ripple 0.3.67 → 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 +57 -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
@@ -3,8 +3,8 @@ import { RippleArray, RippleObject, flushSync, track } from 'ripple';
3
3
 
4
4
  describe('basic client > attribute rendering', () => {
5
5
  it('render static attributes', () => {
6
- component Basic() {
7
- <div class="foo" id="bar" style="color: red;">{'Hello World'}</div>
6
+ function Basic() {
7
+ return <><div class="foo" id="bar" style="color: red;">{'Hello World'}</div></>;
8
8
  }
9
9
 
10
10
  render(Basic);
@@ -13,23 +13,23 @@ describe('basic client > attribute rendering', () => {
13
13
  });
14
14
 
15
15
  it('render dynamic class attribute', () => {
16
- component Basic() {
17
- let &[active] = track(false);
18
-
19
- <button
20
- onClick={() => {
21
- active = !active;
22
- }}
23
- >
24
- {'Toggle'}
25
- </button>
26
- <div class={active ? 'active' : 'inactive'}>{'Dynamic Class'}</div>
27
-
28
- <style>
29
- .active {
30
- color: green;
31
- }
32
- </style>
16
+ function Basic() {
17
+ return <>
18
+ let &[active] = track(false);
19
+ <button
20
+ onClick={() => {
21
+ active = !active;
22
+ }}
23
+ >
24
+ {'Toggle'}
25
+ </button>
26
+ <div class={active ? 'active' : 'inactive'}>{'Dynamic Class'}</div>
27
+ <style>
28
+ .active {
29
+ color: green;
30
+ }
31
+ </style>
32
+ </>;
33
33
  }
34
34
 
35
35
  render(Basic);
@@ -51,29 +51,30 @@ describe('basic client > attribute rendering', () => {
51
51
  });
52
52
 
53
53
  it('render class attribute with array, nested array, nested object', () => {
54
- component Basic() {
55
- <div
56
- class={[
57
- 'foo',
58
- 'bar',
59
- true && 'baz',
60
- false && 'aaa',
61
- null && 'bbb',
62
- [
63
- 'ccc',
64
- 'ddd',
65
- { eee: true, fff: false },
66
- ],
67
- ]}
68
- >
69
- {'Class Array'}
70
- </div>
71
-
72
- <style>
73
- .foo {
74
- color: red;
75
- }
76
- </style>
54
+ function Basic() {
55
+ return <>
56
+ <div
57
+ class={[
58
+ 'foo',
59
+ 'bar',
60
+ true && 'baz',
61
+ false && 'aaa',
62
+ null && 'bbb',
63
+ [
64
+ 'ccc',
65
+ 'ddd',
66
+ { eee: true, fff: false },
67
+ ],
68
+ ]}
69
+ >
70
+ {'Class Array'}
71
+ </div>
72
+ <style>
73
+ .foo {
74
+ color: red;
75
+ }
76
+ </style>
77
+ </>;
77
78
  }
78
79
 
79
80
  render(Basic);
@@ -93,23 +94,23 @@ describe('basic client > attribute rendering', () => {
93
94
  });
94
95
 
95
96
  it('render dynamic class object', () => {
96
- component Basic() {
97
- let &[active] = track(false);
98
-
99
- <button
100
- onClick={() => {
101
- active = !active;
102
- }}
103
- >
104
- {'Toggle'}
105
- </button>
106
- <div class={{ active: active, inactive: !active }}>{'Dynamic Class'}</div>
107
-
108
- <style>
109
- .active {
110
- color: green;
111
- }
112
- </style>
97
+ function Basic() {
98
+ return <>
99
+ let &[active] = track(false);
100
+ <button
101
+ onClick={() => {
102
+ active = !active;
103
+ }}
104
+ >
105
+ {'Toggle'}
106
+ </button>
107
+ <div class={{ active: active, inactive: !active }}>{'Dynamic Class'}</div>
108
+ <style>
109
+ .active {
110
+ color: green;
111
+ }
112
+ </style>
113
+ </>;
113
114
  }
114
115
 
115
116
  render(Basic);
@@ -134,21 +135,21 @@ describe('basic client > attribute rendering', () => {
134
135
  });
135
136
 
136
137
  it('applies scoped ripple class to multiple elements with dynamic class expressions', () => {
137
- component Basic() {
138
- let &[selected] = track(1);
139
-
140
- <div class={selected === 0 ? 'selected' : ''}>{`div 1`}</div>
141
- <div class={selected === 0 ? 'selected' : ''}>{`div 2`}</div>
142
-
143
- <style>
144
- div {
145
- background: green;
146
- color: white;
147
- }
148
- div.selected {
149
- background: indigo;
150
- }
151
- </style>
138
+ function Basic() {
139
+ return <>
140
+ let &[selected] = track(1);
141
+ <div class={selected === 0 ? 'selected' : ''}>{`div 1`}</div>
142
+ <div class={selected === 0 ? 'selected' : ''}>{`div 2`}</div>
143
+ <style>
144
+ div {
145
+ background: green;
146
+ color: white;
147
+ }
148
+ div.selected {
149
+ background: indigo;
150
+ }
151
+ </style>
152
+ </>;
152
153
  }
153
154
 
154
155
  render(Basic);
@@ -163,17 +164,18 @@ describe('basic client > attribute rendering', () => {
163
164
  });
164
165
 
165
166
  it('render dynamic id attribute', () => {
166
- component Basic() {
167
- let &[count] = track(0);
168
-
169
- <button
170
- onClick={() => {
171
- count++;
172
- }}
173
- >
174
- {'Increment'}
175
- </button>
176
- <div id={`item-${count}`}>{'Dynamic ID'}</div>
167
+ function Basic() {
168
+ return <>
169
+ let &[count] = track(0);
170
+ <button
171
+ onClick={() => {
172
+ count++;
173
+ }}
174
+ >
175
+ {'Increment'}
176
+ </button>
177
+ <div id={`item-${count}`}>{'Dynamic ID'}</div>
178
+ </>;
177
179
  }
178
180
 
179
181
  render(Basic);
@@ -195,17 +197,18 @@ describe('basic client > attribute rendering', () => {
195
197
  });
196
198
 
197
199
  it('render dynamic style attribute', () => {
198
- component Basic() {
199
- let &[color] = track('red');
200
-
201
- <button
202
- onClick={() => {
203
- color = color === 'red' ? 'blue' : 'red';
204
- }}
205
- >
206
- {'Change Color'}
207
- </button>
208
- <div style={`color: ${color}; font-weight: bold;`}>{'Dynamic Style'}</div>
200
+ function Basic() {
201
+ return <>
202
+ let &[color] = track('red');
203
+ <button
204
+ onClick={() => {
205
+ color = color === 'red' ? 'blue' : 'red';
206
+ }}
207
+ >
208
+ {'Change Color'}
209
+ </button>
210
+ <div style={`color: ${color}; font-weight: bold;`}>{'Dynamic Style'}</div>
211
+ </>;
209
212
  }
210
213
 
211
214
  render(Basic);
@@ -224,17 +227,18 @@ describe('basic client > attribute rendering', () => {
224
227
  });
225
228
 
226
229
  it('render style attribute as dynamic object', () => {
227
- component Basic() {
228
- let &[color] = track('red');
229
-
230
- <button
231
- onClick={() => {
232
- color = color === 'red' ? 'blue' : 'red';
233
- }}
234
- >
235
- {'Change Color'}
236
- </button>
237
- <div style={{ color: color, fontWeight: 'bold' }}>{'Dynamic Style'}</div>
230
+ function Basic() {
231
+ return <>
232
+ let &[color] = track('red');
233
+ <button
234
+ onClick={() => {
235
+ color = color === 'red' ? 'blue' : 'red';
236
+ }}
237
+ >
238
+ {'Change Color'}
239
+ </button>
240
+ <div style={{ color: color, fontWeight: 'bold' }}>{'Dynamic Style'}</div>
241
+ </>;
238
242
  }
239
243
 
240
244
  render(Basic);
@@ -253,15 +257,15 @@ describe('basic client > attribute rendering', () => {
253
257
  });
254
258
 
255
259
  it('render tracked variable as style attribute', () => {
256
- component Basic() {
257
- let &[style] = track({ color: 'red', fontWeight: 'bold' });
258
-
259
- function toggleColor() {
260
- style = { ...style, color: style.color === 'red' ? 'blue' : 'red' };
261
- }
262
-
263
- <button onClick={toggleColor}>{'Change Color'}</button>
264
- <div {style}>{'Dynamic Style'}</div>
260
+ function Basic() {
261
+ return <>
262
+ let &[style] = track({ color: 'red', fontWeight: 'bold' });
263
+ function toggleColor() {
264
+ style = { ...style, color: style.color === 'red' ? 'blue' : 'red' };
265
+ }
266
+ <button onClick={toggleColor}>{'Change Color'}</button>
267
+ <div {style}>{'Dynamic Style'}</div>
268
+ </>;
265
269
  }
266
270
 
267
271
  render(Basic);
@@ -280,15 +284,15 @@ describe('basic client > attribute rendering', () => {
280
284
  });
281
285
 
282
286
  it('render tracked object as style attribute', () => {
283
- component Basic() {
284
- let style = new RippleObject({ color: 'red', fontWeight: 'bold' });
285
-
286
- function toggleColor() {
287
- style.color = style.color === 'red' ? 'blue' : 'red';
288
- }
289
-
290
- <button onClick={toggleColor}>{'Change Color'}</button>
291
- <div style={{ color: style.color, fontWeight: style.fontWeight }}>{'Dynamic Style'}</div>
287
+ function Basic() {
288
+ return <>
289
+ let style = new RippleObject({ color: 'red', fontWeight: 'bold' });
290
+ function toggleColor() {
291
+ style.color = style.color === 'red' ? 'blue' : 'red';
292
+ }
293
+ <button onClick={toggleColor}>{'Change Color'}</button>
294
+ <div style={{ color: style.color, fontWeight: style.fontWeight }}>{'Dynamic Style'}</div>
295
+ </>;
292
296
  }
293
297
 
294
298
  render(Basic);
@@ -307,13 +311,14 @@ describe('basic client > attribute rendering', () => {
307
311
  });
308
312
 
309
313
  it('render spread attributes with style and class', () => {
310
- component Basic() {
311
- const attributes = {
312
- style: { color: 'red', fontWeight: 'bold' },
313
- class: ['foo', false && 'bar'],
314
- };
315
-
316
- <div {...attributes}>{'Attributes with style and class'}</div>
314
+ function Basic() {
315
+ return <>
316
+ const attributes = {
317
+ style: { color: 'red', fontWeight: 'bold' },
318
+ class: ['foo', false && 'bar'],
319
+ };
320
+ <div {...attributes}>{'Attributes with style and class'}</div>
321
+ </>;
317
322
  }
318
323
 
319
324
  render(Basic);
@@ -328,12 +333,13 @@ describe('basic client > attribute rendering', () => {
328
333
  });
329
334
 
330
335
  it('render spread props without duplication', () => {
331
- component App() {
332
- const checkBoxProp = { name: 'car' };
333
-
334
- <div>
335
- <input {...checkBoxProp} type="checkbox" id="vehicle1" value="Bike" />
336
- </div>
336
+ function App() {
337
+ return <>
338
+ const checkBoxProp = { name: 'car' };
339
+ <div>
340
+ <input {...checkBoxProp} type="checkbox" id="vehicle1" value="Bike" />
341
+ </div>
342
+ </>;
337
343
  }
338
344
 
339
345
  render(App);
@@ -353,19 +359,20 @@ describe('basic client > attribute rendering', () => {
353
359
  });
354
360
 
355
361
  it('render dynamic boolean attributes', () => {
356
- component Basic() {
357
- let &[disabled] = track(false);
358
- let &[checked] = track(false);
359
-
360
- <button
361
- onClick={() => {
362
- disabled = !disabled;
363
- checked = !checked;
364
- }}
365
- >
366
- {'Toggle'}
367
- </button>
368
- <input type="checkbox" {disabled} {checked} />
362
+ function Basic() {
363
+ return <>
364
+ let &[disabled] = track(false);
365
+ let &[checked] = track(false);
366
+ <button
367
+ onClick={() => {
368
+ disabled = !disabled;
369
+ checked = !checked;
370
+ }}
371
+ >
372
+ {'Toggle'}
373
+ </button>
374
+ <input type="checkbox" {disabled} {checked} />
375
+ </>;
369
376
  }
370
377
 
371
378
  render(Basic);
@@ -384,21 +391,22 @@ describe('basic client > attribute rendering', () => {
384
391
  });
385
392
 
386
393
  it('render multiple dynamic attributes', () => {
387
- component Basic() {
388
- let &[theme] = track('light');
389
- let &[size] = track('medium');
390
-
391
- <button
392
- onClick={() => {
393
- theme = theme === 'light' ? 'dark' : 'light';
394
- size = size === 'medium' ? 'large' : 'medium';
395
- }}
396
- >
397
- {'Toggle Theme & Size'}
398
- </button>
399
- <div class={`theme-${theme} size-${size}`} data-theme={theme} data-size={size}>
400
- {'Multiple Dynamic Attributes'}
401
- </div>
394
+ function Basic() {
395
+ return <>
396
+ let &[theme] = track('light');
397
+ let &[size] = track('medium');
398
+ <button
399
+ onClick={() => {
400
+ theme = theme === 'light' ? 'dark' : 'light';
401
+ size = size === 'medium' ? 'large' : 'medium';
402
+ }}
403
+ >
404
+ {'Toggle Theme & Size'}
405
+ </button>
406
+ <div class={`theme-${theme} size-${size}`} data-theme={theme} data-size={size}>
407
+ {'Multiple Dynamic Attributes'}
408
+ </div>
409
+ </>;
402
410
  }
403
411
 
404
412
  render(Basic);
@@ -419,24 +427,25 @@ describe('basic client > attribute rendering', () => {
419
427
  });
420
428
 
421
429
  it('render conditional attributes', () => {
422
- component Basic() {
423
- let &[showTitle] = track(false);
424
- let &[showAria] = track(false);
425
-
426
- <button
427
- onClick={() => {
428
- showTitle = !showTitle;
429
- showAria = !showAria;
430
- }}
431
- >
432
- {'Toggle Attributes'}
433
- </button>
434
- <div
435
- title={showTitle ? 'This is a title' : undefined}
436
- aria-label={showAria ? 'Accessible label' : undefined}
437
- >
438
- {'Conditional Attributes'}
439
- </div>
430
+ function Basic() {
431
+ return <>
432
+ let &[showTitle] = track(false);
433
+ let &[showAria] = track(false);
434
+ <button
435
+ onClick={() => {
436
+ showTitle = !showTitle;
437
+ showAria = !showAria;
438
+ }}
439
+ >
440
+ {'Toggle Attributes'}
441
+ </button>
442
+ <div
443
+ title={showTitle ? 'This is a title' : undefined}
444
+ aria-label={showAria ? 'Accessible label' : undefined}
445
+ >
446
+ {'Conditional Attributes'}
447
+ </div>
448
+ </>;
440
449
  }
441
450
 
442
451
  render(Basic);
@@ -461,24 +470,25 @@ describe('basic client > attribute rendering', () => {
461
470
  });
462
471
 
463
472
  it('render spread attributes', () => {
464
- component Basic() {
465
- let &[attrs] = track<TestAttributes>({
466
- class: 'initial',
467
- id: 'test-1',
468
- });
469
-
470
- <button
471
- onClick={() => {
472
- attrs = {
473
- class: 'updated',
474
- id: 'test-2',
475
- 'data-extra': 'value',
476
- };
477
- }}
478
- >
479
- {'Update Attributes'}
480
- </button>
481
- <div {...attrs}>{'Spread Attributes'}</div>
473
+ function Basic() {
474
+ return <>
475
+ let &[attrs] = track<TestAttributes>({
476
+ class: 'initial',
477
+ id: 'test-1',
478
+ });
479
+ <button
480
+ onClick={() => {
481
+ attrs = {
482
+ class: 'updated',
483
+ id: 'test-2',
484
+ 'data-extra': 'value',
485
+ };
486
+ }}
487
+ >
488
+ {'Update Attributes'}
489
+ </button>
490
+ <div {...attrs}>{'Spread Attributes'}</div>
491
+ </>;
482
492
  }
483
493
 
484
494
  render(Basic);
@@ -499,16 +509,16 @@ describe('basic client > attribute rendering', () => {
499
509
  });
500
510
 
501
511
  it('renders with reactive attributes with nested reactive attributes', () => {
502
- component App() {
503
- let &[value] = track('parent-class');
504
-
505
- <p class={value}>{'Colored parent value'}</p>
506
-
507
- <div>
508
- let &[nested] = track('nested-class');
509
-
510
- <p class={nested}>{'Colored nested value'}</p>
511
- </div>
512
+ function App() {
513
+ return <>
514
+ let &[value] = track('parent-class');
515
+ <p class={value}>{'Colored parent value'}</p>
516
+ <div>
517
+ let &[nested] = track('nested-class');
518
+
519
+ <p class={nested}>{'Colored nested value'}</p>
520
+ </div>
521
+ </>;
512
522
  }
513
523
 
514
524
  render(App);
@@ -520,11 +530,13 @@ describe('basic client > attribute rendering', () => {
520
530
  });
521
531
 
522
532
  it('handles boolean attributes with no prop value provides', () => {
523
- component App() {
524
- <div class="container">
525
- <button onClick={() => console.log('clicked!')} disabled>{'Button'}</button>
526
- <input type="checkbox" checked />
527
- </div>
533
+ function App() {
534
+ return <>
535
+ <div class="container">
536
+ <button onClick={() => console.log('clicked!')} disabled>{'Button'}</button>
537
+ <input type="checkbox" checked />
538
+ </div>
539
+ </>;
528
540
  }
529
541
 
530
542
  render(App);
@@ -532,14 +544,15 @@ describe('basic client > attribute rendering', () => {
532
544
  });
533
545
 
534
546
  it('handles boolean props correctly', () => {
535
- component App() {
536
- <div data-disabled />
537
-
538
- <Child isDisabled />
547
+ function App() {
548
+ return <>
549
+ <div data-disabled />
550
+ <Child isDisabled />
551
+ </>;
539
552
  }
540
553
 
541
- component Child({ isDisabled }: { isDisabled: boolean }) {
542
- <input disabled={isDisabled} />
554
+ function Child({ isDisabled }: { isDisabled: boolean }) {
555
+ return <><input disabled={isDisabled} /></>;
543
556
  }
544
557
 
545
558
  render(App);
@@ -547,30 +560,29 @@ describe('basic client > attribute rendering', () => {
547
560
  });
548
561
 
549
562
  it('handles reactive event handler changes', () => {
550
- component Basic() {
551
- let &[count] = track(0);
552
- let &[mode] = track<'increment' | 'decrement'>('increment');
553
-
554
- const incrementHandler = () => {
555
- count++;
556
- };
557
-
558
- const decrementHandler = () => {
559
- count--;
560
- };
561
-
562
- <button
563
- onClick={() => {
564
- mode = mode === 'increment' ? 'decrement' : 'increment';
565
- }}
566
- class="toggle-mode"
567
- >
568
- {'Toggle Mode'}
569
- </button>
570
- <button onClick={mode === 'increment' ? incrementHandler : decrementHandler} class="action">
571
- {mode === 'increment' ? '+' : '-'}
572
- </button>
573
- <div class="count">{count}</div>
563
+ function Basic() {
564
+ return <>
565
+ let &[count] = track(0);
566
+ let &[mode] = track<'increment' | 'decrement'>('increment');
567
+ const incrementHandler = () => {
568
+ count++;
569
+ };
570
+ const decrementHandler = () => {
571
+ count--;
572
+ };
573
+ <button
574
+ onClick={() => {
575
+ mode = mode === 'increment' ? 'decrement' : 'increment';
576
+ }}
577
+ class="toggle-mode"
578
+ >
579
+ {'Toggle Mode'}
580
+ </button>
581
+ <button onClick={mode === 'increment' ? incrementHandler : decrementHandler} class="action">
582
+ {mode === 'increment' ? '+' : '-'}
583
+ </button>
584
+ <div class="count">{count}</div>
585
+ </>;
574
586
  }
575
587
 
576
588
  render(Basic);
@@ -604,24 +616,23 @@ describe('basic client > attribute rendering', () => {
604
616
  });
605
617
 
606
618
  it('handles events with capture option', () => {
607
- component Basic() {
608
- let captureOrder: RippleArray<string> = new RippleArray();
609
-
610
- const handleCaptureClick = {
611
- handleEvent() {
612
- captureOrder.push('capture');
613
- },
614
- capture: true,
615
- };
616
-
617
- const handleBubbleClick = () => {
618
- captureOrder.push('bubble');
619
- };
620
-
621
- <div onClick={handleCaptureClick} class="outer">
622
- <button onClick={handleBubbleClick} class="inner">{'Click'}</button>
623
- <div class="order">{captureOrder.join(' -> ')}</div>
624
- </div>
619
+ function Basic() {
620
+ return <>
621
+ let captureOrder: RippleArray<string> = new RippleArray();
622
+ const handleCaptureClick = {
623
+ handleEvent() {
624
+ captureOrder.push('capture');
625
+ },
626
+ capture: true,
627
+ };
628
+ const handleBubbleClick = () => {
629
+ captureOrder.push('bubble');
630
+ };
631
+ <div onClick={handleCaptureClick} class="outer">
632
+ <button onClick={handleBubbleClick} class="inner">{'Click'}</button>
633
+ <div class="order">{captureOrder.join(' -> ')}</div>
634
+ </div>
635
+ </>;
625
636
  }
626
637
 
627
638
  render(Basic);
@@ -638,21 +649,20 @@ describe('basic client > attribute rendering', () => {
638
649
  });
639
650
 
640
651
  it('handles events with Capture suffix in the name', () => {
641
- component Basic() {
642
- let captureOrder: RippleArray<string> = new RippleArray();
643
-
644
- const handleCaptureClick = () => {
645
- captureOrder.push('capture');
646
- };
647
-
648
- const handleBubbleClick = () => {
649
- captureOrder.push('bubble');
650
- };
651
-
652
- <div onClickCapture={handleCaptureClick} class="outer">
653
- <button onClick={handleBubbleClick} class="inner">{'Click'}</button>
654
- <div class="order">{captureOrder.join(' -> ')}</div>
655
- </div>
652
+ function Basic() {
653
+ return <>
654
+ let captureOrder: RippleArray<string> = new RippleArray();
655
+ const handleCaptureClick = () => {
656
+ captureOrder.push('capture');
657
+ };
658
+ const handleBubbleClick = () => {
659
+ captureOrder.push('bubble');
660
+ };
661
+ <div onClickCapture={handleCaptureClick} class="outer">
662
+ <button onClick={handleBubbleClick} class="inner">{'Click'}</button>
663
+ <div class="order">{captureOrder.join(' -> ')}</div>
664
+ </div>
665
+ </>;
656
666
  }
657
667
 
658
668
  render(Basic);
@@ -669,20 +679,20 @@ describe('basic client > attribute rendering', () => {
669
679
  });
670
680
 
671
681
  it('handles custom events with customName option', () => {
672
- component Basic() {
673
- let &[customEventCount] = track(0);
674
-
675
- const handleCustom = {
676
- handleEvent(event: CustomEvent) {
677
- customEventCount += event.detail.value;
678
- },
679
- customName: 'MyCustomEvent',
680
- };
681
-
682
- <div>
683
- <div onMyCustomEvent={handleCustom} class="custom-target">{'Custom'}</div>
684
- <div class="custom-count">{customEventCount}</div>
685
- </div>
682
+ function Basic() {
683
+ return <>
684
+ let &[customEventCount] = track(0);
685
+ const handleCustom = {
686
+ handleEvent(event: CustomEvent) {
687
+ customEventCount += event.detail.value;
688
+ },
689
+ customName: 'MyCustomEvent',
690
+ };
691
+ <div>
692
+ <div onMyCustomEvent={handleCustom} class="custom-target">{'Custom'}</div>
693
+ <div class="custom-count">{customEventCount}</div>
694
+ </div>
695
+ </>;
686
696
  }
687
697
 
688
698
  render(Basic);
@@ -704,27 +714,26 @@ describe('basic client > attribute rendering', () => {
704
714
  });
705
715
 
706
716
  it('handles events with delegated: false option to bypass delegation', () => {
707
- component Basic() {
708
- let &[delegatedCount] = track(0);
709
- let &[nonDelegatedCount] = track(0);
710
-
711
- const delegatedHandler = () => {
712
- delegatedCount++;
713
- };
714
-
715
- const nonDelegatedHandler = {
716
- handleEvent() {
717
- nonDelegatedCount++;
718
- },
719
- delegated: false,
720
- };
721
-
722
- <div>
723
- <button onClick={delegatedHandler} class="delegated-btn">{'Delegated'}</button>
724
- <button onClick={nonDelegatedHandler} class="non-delegated-btn">{'Non-Delegated'}</button>
725
- <div class="delegated-count">{delegatedCount}</div>
726
- <div class="non-delegated-count">{nonDelegatedCount}</div>
727
- </div>
717
+ function Basic() {
718
+ return <>
719
+ let &[delegatedCount] = track(0);
720
+ let &[nonDelegatedCount] = track(0);
721
+ const delegatedHandler = () => {
722
+ delegatedCount++;
723
+ };
724
+ const nonDelegatedHandler = {
725
+ handleEvent() {
726
+ nonDelegatedCount++;
727
+ },
728
+ delegated: false,
729
+ };
730
+ <div>
731
+ <button onClick={delegatedHandler} class="delegated-btn">{'Delegated'}</button>
732
+ <button onClick={nonDelegatedHandler} class="non-delegated-btn">{'Non-Delegated'}</button>
733
+ <div class="delegated-count">{delegatedCount}</div>
734
+ <div class="non-delegated-count">{nonDelegatedCount}</div>
735
+ </div>
736
+ </>;
728
737
  }
729
738
 
730
739
  render(Basic);
@@ -753,34 +762,33 @@ describe('basic client > attribute rendering', () => {
753
762
  const delegatedClicks: number[] = [];
754
763
  const nonDelegatedClicks: number[] = [];
755
764
 
756
- component Basic() {
757
- const makeDelegatedHandler = (id: number) => () => {
758
- delegatedClicks.push(id);
759
- };
760
-
761
- const makeNonDelegatedHandler = (id: number) => ({
762
- handleEvent() {
763
- nonDelegatedClicks.push(id);
764
- },
765
- delegated: false,
766
- });
767
-
768
- const buttonIds = [0, 1, 2, 3, 4];
769
-
770
- <div>
771
- <div class="delegated-buttons">
772
- for (const i of buttonIds) {
773
- <button onClick={makeDelegatedHandler(i)} class={`delegated-${i}`}>{`D${i}`}</button>
774
- }
775
- </div>
776
- <div class="non-delegated-buttons">
777
- for (const i of buttonIds) {
778
- <button onClick={makeNonDelegatedHandler(i)} class={`non-delegated-${i}`}>
779
- {`ND${i}`}
780
- </button>
781
- }
765
+ function Basic() {
766
+ return <>
767
+ const makeDelegatedHandler = (id: number) => () => {
768
+ delegatedClicks.push(id);
769
+ };
770
+ const makeNonDelegatedHandler = (id: number) => ({
771
+ handleEvent() {
772
+ nonDelegatedClicks.push(id);
773
+ },
774
+ delegated: false,
775
+ });
776
+ const buttonIds = [0, 1, 2, 3, 4];
777
+ <div>
778
+ <div class="delegated-buttons">
779
+ for (const i of buttonIds) {
780
+ <button onClick={makeDelegatedHandler(i)} class={`delegated-${i}`}>{`D${i}`}</button>
781
+ }
782
+ </div>
783
+ <div class="non-delegated-buttons">
784
+ for (const i of buttonIds) {
785
+ <button onClick={makeNonDelegatedHandler(i)} class={`non-delegated-${i}`}>
786
+ {`ND${i}`}
787
+ </button>
788
+ }
789
+ </div>
782
790
  </div>
783
- </div>
791
+ </>;
784
792
  }
785
793
 
786
794
  render(Basic);
@@ -818,26 +826,25 @@ describe('basic client > attribute rendering', () => {
818
826
  });
819
827
 
820
828
  it('handles events defined as function directly vs as object', () => {
821
- component Basic() {
822
- let &[functionCount] = track(0);
823
- let &[objectCount] = track(0);
824
-
825
- const functionHandler = () => {
826
- functionCount++;
827
- };
828
-
829
- const objectHandler = {
830
- handleEvent() {
831
- objectCount++;
832
- },
833
- };
834
-
835
- <div>
836
- <button onClick={functionHandler} class="function-btn">{'Function'}</button>
837
- <button onClick={objectHandler} class="object-btn">{'Object'}</button>
838
- <div class="function-count">{functionCount}</div>
839
- <div class="object-count">{objectCount}</div>
840
- </div>
829
+ function Basic() {
830
+ return <>
831
+ let &[functionCount] = track(0);
832
+ let &[objectCount] = track(0);
833
+ const functionHandler = () => {
834
+ functionCount++;
835
+ };
836
+ const objectHandler = {
837
+ handleEvent() {
838
+ objectCount++;
839
+ },
840
+ };
841
+ <div>
842
+ <button onClick={functionHandler} class="function-btn">{'Function'}</button>
843
+ <button onClick={objectHandler} class="object-btn">{'Object'}</button>
844
+ <div class="function-count">{functionCount}</div>
845
+ <div class="object-count">{objectCount}</div>
846
+ </div>
847
+ </>;
841
848
  }
842
849
 
843
850
  render(Basic);
@@ -871,47 +878,46 @@ describe('basic client > attribute rendering', () => {
871
878
  });
872
879
 
873
880
  it('handles passive event option', () => {
874
- component Basic() {
875
- let &[passiveDefaultPrevented] = track<boolean | null>(null);
876
- let &[nonPassiveDefaultPrevented] = track<boolean | null>(null);
877
-
878
- const passiveHandler = {
879
- handleEvent(event: Event) {
880
- event.preventDefault();
881
- // In passive listeners, preventDefault() is ignored
882
- passiveDefaultPrevented = event.defaultPrevented;
883
- },
884
- passive: true,
885
- delegated: false, // Need to ensure it's not delegated to test passive properly
886
- };
887
-
888
- const nonPassiveHandler = {
889
- handleEvent(event: Event) {
890
- event.preventDefault();
891
- // In non-passive listeners, preventDefault() works
892
- nonPassiveDefaultPrevented = event.defaultPrevented;
893
- },
894
- delegated: false,
895
- };
896
-
897
- <div>
898
- <div onWheel={passiveHandler} class="passive-target">{'Passive'}</div>
899
- <div onWheel={nonPassiveHandler} class="non-passive-target">{'Non-Passive'}</div>
900
- <div class="passive-result">
901
- {passiveDefaultPrevented === null
902
- ? 'not-tested'
903
- : passiveDefaultPrevented
904
- ? 'prevented'
905
- : 'not-prevented'}
906
- </div>
907
- <div class="non-passive-result">
908
- {nonPassiveDefaultPrevented === null
909
- ? 'not-tested'
910
- : nonPassiveDefaultPrevented
911
- ? 'prevented'
912
- : 'not-prevented'}
881
+ function Basic() {
882
+ return <>
883
+ let &[passiveDefaultPrevented] = track<boolean | null>(null);
884
+ let &[nonPassiveDefaultPrevented] = track<boolean | null>(null);
885
+ const passiveHandler = {
886
+ handleEvent(event: Event) {
887
+ event.preventDefault();
888
+ // In passive listeners, preventDefault() is ignored
889
+ passiveDefaultPrevented = event.defaultPrevented;
890
+ },
891
+ passive: true,
892
+ delegated: false, // Need to ensure it's not delegated to test passive properly
893
+ };
894
+ const nonPassiveHandler = {
895
+ handleEvent(event: Event) {
896
+ event.preventDefault();
897
+ // In non-passive listeners, preventDefault() works
898
+ nonPassiveDefaultPrevented = event.defaultPrevented;
899
+ },
900
+ delegated: false,
901
+ };
902
+ <div>
903
+ <div onWheel={passiveHandler} class="passive-target">{'Passive'}</div>
904
+ <div onWheel={nonPassiveHandler} class="non-passive-target">{'Non-Passive'}</div>
905
+ <div class="passive-result">
906
+ {passiveDefaultPrevented === null
907
+ ? 'not-tested'
908
+ : passiveDefaultPrevented
909
+ ? 'prevented'
910
+ : 'not-prevented'}
911
+ </div>
912
+ <div class="non-passive-result">
913
+ {nonPassiveDefaultPrevented === null
914
+ ? 'not-tested'
915
+ : nonPassiveDefaultPrevented
916
+ ? 'prevented'
917
+ : 'not-prevented'}
918
+ </div>
913
919
  </div>
914
- </div>
920
+ </>;
915
921
  }
916
922
 
917
923
  render(Basic);
@@ -936,27 +942,26 @@ describe('basic client > attribute rendering', () => {
936
942
  });
937
943
 
938
944
  it('handles once option to fire event only once', () => {
939
- component Basic() {
940
- let &[onceCount] = track(0);
941
- let &[regularCount] = track(0);
942
-
943
- const onceHandler = {
944
- handleEvent() {
945
- onceCount++;
946
- },
947
- once: true,
948
- };
949
-
950
- const regularHandler = () => {
951
- regularCount++;
952
- };
953
-
954
- <div>
955
- <button onClick={onceHandler} class="once-btn">{'Once'}</button>
956
- <button onClick={regularHandler} class="regular-btn">{'Regular'}</button>
957
- <div class="once-count">{onceCount}</div>
958
- <div class="regular-count">{regularCount}</div>
959
- </div>
945
+ function Basic() {
946
+ return <>
947
+ let &[onceCount] = track(0);
948
+ let &[regularCount] = track(0);
949
+ const onceHandler = {
950
+ handleEvent() {
951
+ onceCount++;
952
+ },
953
+ once: true,
954
+ };
955
+ const regularHandler = () => {
956
+ regularCount++;
957
+ };
958
+ <div>
959
+ <button onClick={onceHandler} class="once-btn">{'Once'}</button>
960
+ <button onClick={regularHandler} class="regular-btn">{'Regular'}</button>
961
+ <div class="once-count">{onceCount}</div>
962
+ <div class="regular-count">{regularCount}</div>
963
+ </div>
964
+ </>;
960
965
  }
961
966
 
962
967
  render(Basic);