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
@@ -105,14 +105,14 @@ describe('use value()', () => {
105
105
  it('should update value on input', () => {
106
106
  const logs: string[] = [];
107
107
 
108
- component App() {
109
- const text = track('');
110
-
111
- effect(() => {
112
- logs.push('text changed', text.value);
113
- });
114
-
115
- <input type="text" {ref bindValue(text)} />
108
+ function App() {
109
+ return <>
110
+ const text = track('');
111
+ effect(() => {
112
+ logs.push('text changed', text.value);
113
+ });
114
+ <input type="text" ref={bindValue(text)} />
115
+ </>;
116
116
  }
117
117
  render(App);
118
118
  flushSync();
@@ -128,14 +128,14 @@ describe('use value()', () => {
128
128
  it('should update value on input with getter and setter', () => {
129
129
  const logs: string[] = [];
130
130
 
131
- component App() {
132
- const text = new RippleObject({ value: '' });
133
-
134
- effect(() => {
135
- logs.push('text changed', text.value);
136
- });
137
-
138
- <input type="text" {ref bindValue(() => text.value, (v) => (text.value = v))} />
131
+ function App() {
132
+ return <>
133
+ const text = new RippleObject({ value: '' });
134
+ effect(() => {
135
+ logs.push('text changed', text.value);
136
+ });
137
+ <input type="text" ref={bindValue(() => text.value, (v) => (text.value = v))} />
138
+ </>;
139
139
  }
140
140
  render(App);
141
141
  flushSync();
@@ -151,14 +151,14 @@ describe('use value()', () => {
151
151
  it('should update value on input with a predefined value', () => {
152
152
  const logs: string[] = [];
153
153
 
154
- component App() {
155
- const text = track('foo');
156
-
157
- effect(() => {
158
- logs.push('text changed', text.value);
159
- });
160
-
161
- <input type="text" {ref bindValue(text)} />
154
+ function App() {
155
+ return <>
156
+ const text = track('foo');
157
+ effect(() => {
158
+ logs.push('text changed', text.value);
159
+ });
160
+ <input type="text" ref={bindValue(text)} />
161
+ </>;
162
162
  }
163
163
  render(App);
164
164
  flushSync();
@@ -175,13 +175,14 @@ describe('use value()', () => {
175
175
  it('should update value on input with a predefined value and with a getter and setter', () => {
176
176
  const logs: string[] = [];
177
177
 
178
- component App() {
179
- const text = new RippleObject({ value: 'foo' });
180
- effect(() => {
181
- logs.push('text changed', text.value);
182
- });
183
-
184
- <input type="text" {ref bindValue(() => text.value, (v) => (text.value = v))} />
178
+ function App() {
179
+ return <>
180
+ const text = new RippleObject({ value: 'foo' });
181
+ effect(() => {
182
+ logs.push('text changed', text.value);
183
+ });
184
+ <input type="text" ref={bindValue(() => text.value, (v) => (text.value = v))} />
185
+ </>;
185
186
  }
186
187
  render(App);
187
188
  flushSync();
@@ -196,13 +197,14 @@ describe('use value()', () => {
196
197
  });
197
198
 
198
199
  it('should update text input element when tracked value changes', () => {
199
- component App() {
200
- const text = track('initial');
201
-
202
- <div>
203
- <input type="text" {ref bindValue(text)} />
204
- <button onClick={() => (text.value = 'updated')}>{'Update'}</button>
205
- </div>
200
+ function App() {
201
+ return <>
202
+ const text = track('initial');
203
+ <div>
204
+ <input type="text" ref={bindValue(text)} />
205
+ <button onClick={() => (text.value = 'updated')}>{'Update'}</button>
206
+ </div>
207
+ </>;
206
208
  }
207
209
  render(App);
208
210
  flushSync();
@@ -219,13 +221,14 @@ describe('use value()', () => {
219
221
  });
220
222
 
221
223
  it('should update text input element when tracked value changes with a getter and setter', () => {
222
- component App() {
223
- const text = new RippleObject({ value: 'initial' });
224
-
225
- <div>
226
- <input type="text" {ref bindValue(() => text.value, (v) => (text.value = v))} />
227
- <button onClick={() => (text.value = 'updated')}>{'Update'}</button>
228
- </div>
224
+ function App() {
225
+ return <>
226
+ const text = new RippleObject({ value: 'initial' });
227
+ <div>
228
+ <input type="text" ref={bindValue(() => text.value, (v) => (text.value = v))} />
229
+ <button onClick={() => (text.value = 'updated')}>{'Update'}</button>
230
+ </div>
231
+ </>;
229
232
  }
230
233
  render(App);
231
234
  flushSync();
@@ -244,14 +247,14 @@ describe('use value()', () => {
244
247
  it('should update checked on input', () => {
245
248
  const logs: (string | boolean)[] = [];
246
249
 
247
- component App() {
248
- const value = track(false);
249
-
250
- effect(() => {
251
- logs.push('checked changed', value.value);
252
- });
253
-
254
- <input type="checkbox" {ref bindChecked(value)} />
250
+ function App() {
251
+ return <>
252
+ const value = track(false);
253
+ effect(() => {
254
+ logs.push('checked changed', value.value);
255
+ });
256
+ <input type="checkbox" ref={bindChecked(value)} />
257
+ </>;
255
258
  }
256
259
  render(App);
257
260
  flushSync();
@@ -268,13 +271,17 @@ describe('use value()', () => {
268
271
  it('should update checked on input with a getter and setter', () => {
269
272
  const logs: (string | boolean)[] = [];
270
273
 
271
- component App() {
272
- const obj = new RippleObject({ value: false });
273
- effect(() => {
274
- logs.push('checked changed', obj.value);
275
- });
276
-
277
- <input type="checkbox" {ref bindChecked(() => obj.value, (v: boolean) => (obj.value = v))} />
274
+ function App() {
275
+ return <>
276
+ const obj = new RippleObject({ value: false });
277
+ effect(() => {
278
+ logs.push('checked changed', obj.value);
279
+ });
280
+ <input
281
+ type="checkbox"
282
+ ref={bindChecked(() => obj.value, (v: boolean) => (obj.value = v))}
283
+ />
284
+ </>;
278
285
  }
279
286
  render(App);
280
287
  flushSync();
@@ -289,13 +296,14 @@ describe('use value()', () => {
289
296
  });
290
297
 
291
298
  it('should update checkbox element when tracked value changes', () => {
292
- component App() {
293
- const value = track(false);
294
-
295
- <div>
296
- <input type="checkbox" {ref bindChecked(value)} />
297
- <button onClick={() => (value.value = true)}>{'Check'}</button>
298
- </div>
299
+ function App() {
300
+ return <>
301
+ const value = track(false);
302
+ <div>
303
+ <input type="checkbox" ref={bindChecked(value)} />
304
+ <button onClick={() => (value.value = true)}>{'Check'}</button>
305
+ </div>
306
+ </>;
299
307
  }
300
308
  render(App);
301
309
  flushSync();
@@ -312,16 +320,17 @@ describe('use value()', () => {
312
320
  });
313
321
 
314
322
  it('should update checkbox element when tracked value changes with a getter and setter', () => {
315
- component App() {
316
- const obj = new RippleObject({ value: false });
317
-
318
- <div>
319
- <input
320
- type="checkbox"
321
- {ref bindChecked(() => obj.value, (v: boolean) => (obj.value = v))}
322
- />
323
- <button onClick={() => (obj.value = true)}>{'Check'}</button>
324
- </div>
323
+ function App() {
324
+ return <>
325
+ const obj = new RippleObject({ value: false });
326
+ <div>
327
+ <input
328
+ type="checkbox"
329
+ ref={bindChecked(() => obj.value, (v: boolean) => (obj.value = v))}
330
+ />
331
+ <button onClick={() => (obj.value = true)}>{'Check'}</button>
332
+ </div>
333
+ </>;
325
334
  }
326
335
  render(App);
327
336
  flushSync();
@@ -340,14 +349,14 @@ describe('use value()', () => {
340
349
  it('should update indeterminate on input', () => {
341
350
  const logs: (string | boolean)[] = [];
342
351
 
343
- component App() {
344
- const value = track(false);
345
-
346
- effect(() => {
347
- logs.push('indeterminate changed', value.value);
348
- });
349
-
350
- <input type="checkbox" {ref bindIndeterminate(value)} />
352
+ function App() {
353
+ return <>
354
+ const value = track(false);
355
+ effect(() => {
356
+ logs.push('indeterminate changed', value.value);
357
+ });
358
+ <input type="checkbox" ref={bindIndeterminate(value)} />
359
+ </>;
351
360
  }
352
361
  render(App);
353
362
  flushSync();
@@ -366,17 +375,17 @@ describe('use value()', () => {
366
375
  it('should update indeterminate on input with a getter and setter', () => {
367
376
  const logs: (string | boolean)[] = [];
368
377
 
369
- component App() {
370
- const obj = new RippleObject({ value: false });
371
-
372
- effect(() => {
373
- logs.push('indeterminate changed', obj.value);
374
- });
375
-
376
- <input
377
- type="checkbox"
378
- {ref bindIndeterminate(() => obj.value, (v: boolean) => (obj.value = v))}
379
- />
378
+ function App() {
379
+ return <>
380
+ const obj = new RippleObject({ value: false });
381
+ effect(() => {
382
+ logs.push('indeterminate changed', obj.value);
383
+ });
384
+ <input
385
+ type="checkbox"
386
+ ref={bindIndeterminate(() => obj.value, (v: boolean) => (obj.value = v))}
387
+ />
388
+ </>;
380
389
  }
381
390
  render(App);
382
391
  flushSync();
@@ -393,13 +402,14 @@ describe('use value()', () => {
393
402
  });
394
403
 
395
404
  it('should update checkbox indeterminate element when tracked value changes', () => {
396
- component App() {
397
- const value = track(false);
398
-
399
- <div>
400
- <input type="checkbox" {ref bindIndeterminate(value)} />
401
- <button onClick={() => (value.value = true)}>{'Set Indeterminate'}</button>
402
- </div>
405
+ function App() {
406
+ return <>
407
+ const value = track(false);
408
+ <div>
409
+ <input type="checkbox" ref={bindIndeterminate(value)} />
410
+ <button onClick={() => (value.value = true)}>{'Set Indeterminate'}</button>
411
+ </div>
412
+ </>;
403
413
  }
404
414
  render(App);
405
415
  flushSync();
@@ -418,16 +428,17 @@ describe('use value()', () => {
418
428
  it(
419
429
  'should update checkbox indeterminate element when tracked value changes with a getter and setter',
420
430
  () => {
421
- component App() {
422
- const obj = new RippleObject({ value: false });
423
-
424
- <div>
425
- <input
426
- type="checkbox"
427
- {ref bindIndeterminate(() => obj.value, (v: boolean) => (obj.value = v))}
428
- />
429
- <button onClick={() => (obj.value = true)}>{'Set Indeterminate'}</button>
430
- </div>
431
+ function App() {
432
+ return <>
433
+ const obj = new RippleObject({ value: false });
434
+ <div>
435
+ <input
436
+ type="checkbox"
437
+ ref={bindIndeterminate(() => obj.value, (v: boolean) => (obj.value = v))}
438
+ />
439
+ <button onClick={() => (obj.value = true)}>{'Set Indeterminate'}</button>
440
+ </div>
441
+ </>;
431
442
  }
432
443
  render(App);
433
444
  flushSync();
@@ -447,18 +458,18 @@ describe('use value()', () => {
447
458
  it('should update select value on change', () => {
448
459
  const logs: string[] = [];
449
460
 
450
- component App() {
451
- const select = track('2');
452
-
453
- effect(() => {
454
- logs.push('select changed', select.value);
455
- });
456
-
457
- <select {ref bindValue(select)}>
458
- <option value="1">{'One'}</option>
459
- <option value="2">{'Two'}</option>
460
- <option value="3">{'Three'}</option>
461
- </select>
461
+ function App() {
462
+ return <>
463
+ const select = track('2');
464
+ effect(() => {
465
+ logs.push('select changed', select.value);
466
+ });
467
+ <select ref={bindValue(select)}>
468
+ <option value="1">{'One'}</option>
469
+ <option value="2">{'Two'}</option>
470
+ <option value="3">{'Three'}</option>
471
+ </select>
472
+ </>;
462
473
  }
463
474
 
464
475
  render(App);
@@ -476,17 +487,18 @@ describe('use value()', () => {
476
487
  it('should update select value on change with a getter and setter', () => {
477
488
  const logs: string[] = [];
478
489
 
479
- component App() {
480
- const select = new RippleObject({ value: '2' });
481
- effect(() => {
482
- logs.push('select changed', select.value);
483
- });
484
-
485
- <select {ref bindValue(() => select.value, (v) => (select.value = v))}>
486
- <option value="1">{'One'}</option>
487
- <option value="2">{'Two'}</option>
488
- <option value="3">{'Three'}</option>
489
- </select>
490
+ function App() {
491
+ return <>
492
+ const select = new RippleObject({ value: '2' });
493
+ effect(() => {
494
+ logs.push('select changed', select.value);
495
+ });
496
+ <select ref={bindValue(() => select.value, (v) => (select.value = v))}>
497
+ <option value="1">{'One'}</option>
498
+ <option value="2">{'Two'}</option>
499
+ <option value="3">{'Three'}</option>
500
+ </select>
501
+ </>;
490
502
  }
491
503
 
492
504
  render(App);
@@ -502,17 +514,18 @@ describe('use value()', () => {
502
514
  });
503
515
 
504
516
  it('should update select element when tracked value changes', () => {
505
- component App() {
506
- const select = track('1');
507
-
508
- <div>
509
- <select {ref bindValue(select)}>
510
- <option value="1">{'One'}</option>
511
- <option value="2">{'Two'}</option>
512
- <option value="3">{'Three'}</option>
513
- </select>
514
- <button onClick={() => (select.value = '3')}>{'Update'}</button>
515
- </div>
517
+ function App() {
518
+ return <>
519
+ const select = track('1');
520
+ <div>
521
+ <select ref={bindValue(select)}>
522
+ <option value="1">{'One'}</option>
523
+ <option value="2">{'Two'}</option>
524
+ <option value="3">{'Three'}</option>
525
+ </select>
526
+ <button onClick={() => (select.value = '3')}>{'Update'}</button>
527
+ </div>
528
+ </>;
516
529
  }
517
530
 
518
531
  render(App);
@@ -530,17 +543,18 @@ describe('use value()', () => {
530
543
  });
531
544
 
532
545
  it('should update select element when tracked value changes with a getter and setter', () => {
533
- component App() {
534
- const select = new RippleObject({ value: '1' });
535
-
536
- <div>
537
- <select {ref bindValue(() => select.value, (v) => (select.value = v))}>
538
- <option value="1">{'One'}</option>
539
- <option value="2">{'Two'}</option>
540
- <option value="3">{'Three'}</option>
541
- </select>
542
- <button onClick={() => (select.value = '3')}>{'Update'}</button>
543
- </div>
546
+ function App() {
547
+ return <>
548
+ const select = new RippleObject({ value: '1' });
549
+ <div>
550
+ <select ref={bindValue(() => select.value, (v) => (select.value = v))}>
551
+ <option value="1">{'One'}</option>
552
+ <option value="2">{'Two'}</option>
553
+ <option value="3">{'Three'}</option>
554
+ </select>
555
+ <button onClick={() => (select.value = '3')}>{'Update'}</button>
556
+ </div>
557
+ </>;
544
558
  }
545
559
 
546
560
  render(App);
@@ -560,18 +574,18 @@ describe('use value()', () => {
560
574
  it('should bind checkbox group', () => {
561
575
  const logs: string[] = [];
562
576
 
563
- component App() {
564
- const selected = track(['b']);
565
-
566
- effect(() => {
567
- logs.push('selected changed', JSON.stringify(selected.value));
568
- });
569
-
570
- <div>
571
- <input type="checkbox" value="a" {ref bindGroup(selected)} />
572
- <input type="checkbox" value="b" {ref bindGroup(selected)} />
573
- <input type="checkbox" value="c" {ref bindGroup(selected)} />
574
- </div>
577
+ function App() {
578
+ return <>
579
+ const selected = track(['b']);
580
+ effect(() => {
581
+ logs.push('selected changed', JSON.stringify(selected.value));
582
+ });
583
+ <div>
584
+ <input type="checkbox" value="a" ref={bindGroup(selected)} />
585
+ <input type="checkbox" value="b" ref={bindGroup(selected)} />
586
+ <input type="checkbox" value="c" ref={bindGroup(selected)} />
587
+ </div>
588
+ </>;
575
589
  }
576
590
 
577
591
  render(App);
@@ -608,30 +622,30 @@ describe('use value()', () => {
608
622
  it('should bind checkbox group with a getter and setter', () => {
609
623
  const logs: string[] = [];
610
624
 
611
- component App() {
612
- const obj = new RippleObject({ selected: ['b'] });
613
-
614
- effect(() => {
615
- logs.push('selected changed', JSON.stringify(obj.selected));
616
- });
617
-
618
- <div>
619
- <input
620
- type="checkbox"
621
- value="a"
622
- {ref bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
623
- />
624
- <input
625
- type="checkbox"
626
- value="b"
627
- {ref bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
628
- />
629
- <input
630
- type="checkbox"
631
- value="c"
632
- {ref bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
633
- />
634
- </div>
625
+ function App() {
626
+ return <>
627
+ const obj = new RippleObject({ selected: ['b'] });
628
+ effect(() => {
629
+ logs.push('selected changed', JSON.stringify(obj.selected));
630
+ });
631
+ <div>
632
+ <input
633
+ type="checkbox"
634
+ value="a"
635
+ ref={bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
636
+ />
637
+ <input
638
+ type="checkbox"
639
+ value="b"
640
+ ref={bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
641
+ />
642
+ <input
643
+ type="checkbox"
644
+ value="c"
645
+ ref={bindGroup(() => obj.selected, (v: string[]) => (obj.selected = v))}
646
+ />
647
+ </div>
648
+ </>;
635
649
  }
636
650
 
637
651
  render(App);
@@ -668,18 +682,18 @@ describe('use value()', () => {
668
682
  it('should bind radio group', () => {
669
683
  const logs: string[] = [];
670
684
 
671
- component App() {
672
- const selected = track('b');
673
-
674
- effect(() => {
675
- logs.push('selected changed', selected.value);
676
- });
677
-
678
- <div>
679
- <input type="radio" name="test" value="a" {ref bindGroup(selected)} />
680
- <input type="radio" name="test" value="b" {ref bindGroup(selected)} />
681
- <input type="radio" name="test" value="c" {ref bindGroup(selected)} />
682
- </div>
685
+ function App() {
686
+ return <>
687
+ const selected = track('b');
688
+ effect(() => {
689
+ logs.push('selected changed', selected.value);
690
+ });
691
+ <div>
692
+ <input type="radio" name="test" value="a" ref={bindGroup(selected)} />
693
+ <input type="radio" name="test" value="b" ref={bindGroup(selected)} />
694
+ <input type="radio" name="test" value="c" ref={bindGroup(selected)} />
695
+ </div>
696
+ </>;
683
697
  }
684
698
 
685
699
  render(App);
@@ -715,33 +729,33 @@ describe('use value()', () => {
715
729
  it('should bind radio group with a getter and setter', () => {
716
730
  const logs: string[] = [];
717
731
 
718
- component App() {
719
- const selected = new RippleObject({ value: 'b' });
720
-
721
- effect(() => {
722
- logs.push('selected changed', selected.value);
723
- });
724
-
725
- <div>
726
- <input
727
- type="radio"
728
- name="test"
729
- value="a"
730
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
731
- />
732
- <input
733
- type="radio"
734
- name="test"
735
- value="b"
736
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
737
- />
738
- <input
739
- type="radio"
740
- name="test"
741
- value="c"
742
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
743
- />
744
- </div>
732
+ function App() {
733
+ return <>
734
+ const selected = new RippleObject({ value: 'b' });
735
+ effect(() => {
736
+ logs.push('selected changed', selected.value);
737
+ });
738
+ <div>
739
+ <input
740
+ type="radio"
741
+ name="test"
742
+ value="a"
743
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
744
+ />
745
+ <input
746
+ type="radio"
747
+ name="test"
748
+ value="b"
749
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
750
+ />
751
+ <input
752
+ type="radio"
753
+ name="test"
754
+ value="c"
755
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
756
+ />
757
+ </div>
758
+ </>;
745
759
  }
746
760
 
747
761
  render(App);
@@ -775,15 +789,16 @@ describe('use value()', () => {
775
789
  });
776
790
 
777
791
  it('should update checkbox group from tracked value change', () => {
778
- component App() {
779
- const selected = track(['a']);
780
-
781
- <div>
782
- <input type="checkbox" value="a" {ref bindGroup(selected)} />
783
- <input type="checkbox" value="b" {ref bindGroup(selected)} />
784
- <input type="checkbox" value="c" {ref bindGroup(selected)} />
785
- <button onClick={() => (selected.value = ['b', 'c'])}>{'Update'}</button>
786
- </div>
792
+ function App() {
793
+ return <>
794
+ const selected = track(['a']);
795
+ <div>
796
+ <input type="checkbox" value="a" ref={bindGroup(selected)} />
797
+ <input type="checkbox" value="b" ref={bindGroup(selected)} />
798
+ <input type="checkbox" value="c" ref={bindGroup(selected)} />
799
+ <button onClick={() => (selected.value = ['b', 'c'])}>{'Update'}</button>
800
+ </div>
801
+ </>;
787
802
  }
788
803
 
789
804
  render(App);
@@ -805,27 +820,28 @@ describe('use value()', () => {
805
820
  });
806
821
 
807
822
  it('should update checkbox group from tracked value change with a getter and setter', () => {
808
- component App() {
809
- const selected = new RippleObject({ value: ['a'] });
810
-
811
- <div>
812
- <input
813
- type="checkbox"
814
- value="a"
815
- {ref bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
816
- />
817
- <input
818
- type="checkbox"
819
- value="b"
820
- {ref bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
821
- />
822
- <input
823
- type="checkbox"
824
- value="c"
825
- {ref bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
826
- />
827
- <button onClick={() => (selected.value = ['b', 'c'])}>{'Update'}</button>
828
- </div>
823
+ function App() {
824
+ return <>
825
+ const selected = new RippleObject({ value: ['a'] });
826
+ <div>
827
+ <input
828
+ type="checkbox"
829
+ value="a"
830
+ ref={bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
831
+ />
832
+ <input
833
+ type="checkbox"
834
+ value="b"
835
+ ref={bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
836
+ />
837
+ <input
838
+ type="checkbox"
839
+ value="c"
840
+ ref={bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
841
+ />
842
+ <button onClick={() => (selected.value = ['b', 'c'])}>{'Update'}</button>
843
+ </div>
844
+ </>;
829
845
  }
830
846
 
831
847
  render(App);
@@ -847,15 +863,16 @@ describe('use value()', () => {
847
863
  });
848
864
 
849
865
  it('should update radio group from tracked value change', () => {
850
- component App() {
851
- const selected = track('a');
852
-
853
- <div>
854
- <input type="radio" name="test" value="a" {ref bindGroup(selected)} />
855
- <input type="radio" name="test" value="b" {ref bindGroup(selected)} />
856
- <input type="radio" name="test" value="c" {ref bindGroup(selected)} />
857
- <button onClick={() => (selected.value = 'c')}>{'Update'}</button>
858
- </div>
866
+ function App() {
867
+ return <>
868
+ const selected = track('a');
869
+ <div>
870
+ <input type="radio" name="test" value="a" ref={bindGroup(selected)} />
871
+ <input type="radio" name="test" value="b" ref={bindGroup(selected)} />
872
+ <input type="radio" name="test" value="c" ref={bindGroup(selected)} />
873
+ <button onClick={() => (selected.value = 'c')}>{'Update'}</button>
874
+ </div>
875
+ </>;
859
876
  }
860
877
 
861
878
  render(App);
@@ -877,30 +894,31 @@ describe('use value()', () => {
877
894
  });
878
895
 
879
896
  it('should update radio group from tracked value change with a getter and setter', () => {
880
- component App() {
881
- const selected = new RippleObject({ value: 'a' });
882
-
883
- <div>
884
- <input
885
- type="radio"
886
- name="test"
887
- value="a"
888
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
889
- />
890
- <input
891
- type="radio"
892
- name="test"
893
- value="b"
894
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
895
- />
896
- <input
897
- type="radio"
898
- name="test"
899
- value="c"
900
- {ref bindGroup(() => selected.value, (v: string) => (selected.value = v))}
901
- />
902
- <button onClick={() => (selected.value = 'c')}>{'Update'}</button>
903
- </div>
897
+ function App() {
898
+ return <>
899
+ const selected = new RippleObject({ value: 'a' });
900
+ <div>
901
+ <input
902
+ type="radio"
903
+ name="test"
904
+ value="a"
905
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
906
+ />
907
+ <input
908
+ type="radio"
909
+ name="test"
910
+ value="b"
911
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
912
+ />
913
+ <input
914
+ type="radio"
915
+ name="test"
916
+ value="c"
917
+ ref={bindGroup(() => selected.value, (v: string) => (selected.value = v))}
918
+ />
919
+ <button onClick={() => (selected.value = 'c')}>{'Update'}</button>
920
+ </div>
921
+ </>;
904
922
  }
905
923
 
906
924
  render(App);
@@ -922,13 +940,14 @@ describe('use value()', () => {
922
940
  });
923
941
 
924
942
  it('should handle checkbox group with initial empty array', () => {
925
- component App() {
926
- const selected = track([]);
927
-
928
- <div>
929
- <input type="checkbox" value="a" {ref bindGroup(selected)} />
930
- <input type="checkbox" value="b" {ref bindGroup(selected)} />
931
- </div>
943
+ function App() {
944
+ return <>
945
+ const selected = track([]);
946
+ <div>
947
+ <input type="checkbox" value="a" ref={bindGroup(selected)} />
948
+ <input type="checkbox" value="b" ref={bindGroup(selected)} />
949
+ </div>
950
+ </>;
932
951
  }
933
952
 
934
953
  render(App);
@@ -948,21 +967,22 @@ describe('use value()', () => {
948
967
  });
949
968
 
950
969
  it('should handle checkbox group with initial empty array with a getter and setter', () => {
951
- component App() {
952
- const selected: RippleObject<{ value: string[] }> = new RippleObject({ value: [] });
953
-
954
- <div>
955
- <input
956
- type="checkbox"
957
- value="a"
958
- {ref bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
959
- />
960
- <input
961
- type="checkbox"
962
- value="b"
963
- {ref bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
964
- />
965
- </div>
970
+ function App() {
971
+ return <>
972
+ const selected: RippleObject<{ value: string[] }> = new RippleObject({ value: [] });
973
+ <div>
974
+ <input
975
+ type="checkbox"
976
+ value="a"
977
+ ref={bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
978
+ />
979
+ <input
980
+ type="checkbox"
981
+ value="b"
982
+ ref={bindGroup(() => selected.value, (v: string[]) => (selected.value = v))}
983
+ />
984
+ </div>
985
+ </>;
966
986
  }
967
987
 
968
988
  render(App);
@@ -982,10 +1002,11 @@ describe('use value()', () => {
982
1002
  });
983
1003
 
984
1004
  it('should handle number input type', () => {
985
- component App() {
986
- const value = track(42);
987
-
988
- <input type="number" {ref bindValue(value)} />
1005
+ function App() {
1006
+ return <>
1007
+ const value = track(42);
1008
+ <input type="number" ref={bindValue(value)} />
1009
+ </>;
989
1010
  }
990
1011
 
991
1012
  render(App);
@@ -1002,10 +1023,11 @@ describe('use value()', () => {
1002
1023
  });
1003
1024
 
1004
1025
  it('should handle number input type with a getter and setter', () => {
1005
- component App() {
1006
- const obj = new RippleObject({ value: 42 });
1007
-
1008
- <input type="number" {ref bindValue(() => obj.value, (v) => (obj.value = v))} />
1026
+ function App() {
1027
+ return <>
1028
+ const obj = new RippleObject({ value: 42 });
1029
+ <input type="number" ref={bindValue(() => obj.value, (v) => (obj.value = v))} />
1030
+ </>;
1009
1031
  }
1010
1032
 
1011
1033
  render(App);
@@ -1022,13 +1044,14 @@ describe('use value()', () => {
1022
1044
  });
1023
1045
 
1024
1046
  it('should update number input element when tracked value changes', () => {
1025
- component App() {
1026
- const value = track(10);
1027
-
1028
- <div>
1029
- <input type="number" {ref bindValue(value)} />
1030
- <button onClick={() => (value.value = 99)}>{'Update'}</button>
1031
- </div>
1047
+ function App() {
1048
+ return <>
1049
+ const value = track(10);
1050
+ <div>
1051
+ <input type="number" ref={bindValue(value)} />
1052
+ <button onClick={() => (value.value = 99)}>{'Update'}</button>
1053
+ </div>
1054
+ </>;
1032
1055
  }
1033
1056
 
1034
1057
  render(App);
@@ -1048,13 +1071,14 @@ describe('use value()', () => {
1048
1071
  it(
1049
1072
  'should update number input element when tracked value changes with a getter and setter',
1050
1073
  () => {
1051
- component App() {
1052
- const obj = new RippleObject({ value: 10 });
1053
-
1054
- <div>
1055
- <input type="number" {ref bindValue(() => obj.value, (v) => (obj.value = v))} />
1056
- <button onClick={() => (obj.value = 99)}>{'Update'}</button>
1057
- </div>
1074
+ function App() {
1075
+ return <>
1076
+ const obj = new RippleObject({ value: 10 });
1077
+ <div>
1078
+ <input type="number" ref={bindValue(() => obj.value, (v) => (obj.value = v))} />
1079
+ <button onClick={() => (obj.value = 99)}>{'Update'}</button>
1080
+ </div>
1081
+ </>;
1058
1082
  }
1059
1083
 
1060
1084
  render(App);
@@ -1073,10 +1097,11 @@ describe('use value()', () => {
1073
1097
  );
1074
1098
 
1075
1099
  it('should handle range input type', () => {
1076
- component App() {
1077
- const value = track(50);
1078
-
1079
- <input type="range" min="0" max="100" {ref bindValue(value)} />
1100
+ function App() {
1101
+ return <>
1102
+ const value = track(50);
1103
+ <input type="range" min="0" max="100" ref={bindValue(value)} />
1104
+ </>;
1080
1105
  }
1081
1106
 
1082
1107
  render(App);
@@ -1093,15 +1118,16 @@ describe('use value()', () => {
1093
1118
  });
1094
1119
 
1095
1120
  it('should handle range input type with a getter and setter', () => {
1096
- component App() {
1097
- const obj = new RippleObject({ value: 50 });
1098
-
1099
- <input
1100
- type="range"
1101
- min="0"
1102
- max="100"
1103
- {ref bindValue(() => obj.value, (v) => (obj.value = v))}
1104
- />
1121
+ function App() {
1122
+ return <>
1123
+ const obj = new RippleObject({ value: 50 });
1124
+ <input
1125
+ type="range"
1126
+ min="0"
1127
+ max="100"
1128
+ ref={bindValue(() => obj.value, (v) => (obj.value = v))}
1129
+ />
1130
+ </>;
1105
1131
  }
1106
1132
 
1107
1133
  render(App);
@@ -1118,13 +1144,14 @@ describe('use value()', () => {
1118
1144
  });
1119
1145
 
1120
1146
  it('should update range input element when tracked value changes', () => {
1121
- component App() {
1122
- const value = track(25);
1123
-
1124
- <div>
1125
- <input type="range" min="0" max="100" {ref bindValue(value)} />
1126
- <button onClick={() => (value.value = 80)}>{'Update'}</button>
1127
- </div>
1147
+ function App() {
1148
+ return <>
1149
+ const value = track(25);
1150
+ <div>
1151
+ <input type="range" min="0" max="100" ref={bindValue(value)} />
1152
+ <button onClick={() => (value.value = 80)}>{'Update'}</button>
1153
+ </div>
1154
+ </>;
1128
1155
  }
1129
1156
 
1130
1157
  render(App);
@@ -1144,18 +1171,19 @@ describe('use value()', () => {
1144
1171
  it(
1145
1172
  'should update range input element when tracked value changes with a getter and setter',
1146
1173
  () => {
1147
- component App() {
1148
- const obj = new RippleObject({ value: 25 });
1149
-
1150
- <div>
1151
- <input
1152
- type="range"
1153
- min="0"
1154
- max="100"
1155
- {ref bindValue(() => obj.value, (v) => (obj.value = v))}
1156
- />
1157
- <button onClick={() => (obj.value = 80)}>{'Update'}</button>
1158
- </div>
1174
+ function App() {
1175
+ return <>
1176
+ const obj = new RippleObject({ value: 25 });
1177
+ <div>
1178
+ <input
1179
+ type="range"
1180
+ min="0"
1181
+ max="100"
1182
+ ref={bindValue(() => obj.value, (v) => (obj.value = v))}
1183
+ />
1184
+ <button onClick={() => (obj.value = 80)}>{'Update'}</button>
1185
+ </div>
1186
+ </>;
1159
1187
  }
1160
1188
 
1161
1189
  render(App);
@@ -1174,10 +1202,11 @@ describe('use value()', () => {
1174
1202
  );
1175
1203
 
1176
1204
  it('should handle empty number input as null', () => {
1177
- component App() {
1178
- const value = track(null);
1179
-
1180
- <input type="number" {ref bindValue(value)} />
1205
+ function App() {
1206
+ return <>
1207
+ const value = track(null);
1208
+ <input type="number" ref={bindValue(value)} />
1209
+ </>;
1181
1210
  }
1182
1211
 
1183
1212
  render(App);
@@ -1194,10 +1223,11 @@ describe('use value()', () => {
1194
1223
  });
1195
1224
 
1196
1225
  it('should handle empty number input as null with a getter and setter', () => {
1197
- component App() {
1198
- const obj = new RippleObject({ value: null });
1199
-
1200
- <input type="number" {ref bindValue(() => obj.value, (v) => (obj.value = v))} />
1226
+ function App() {
1227
+ return <>
1228
+ const obj = new RippleObject({ value: null });
1229
+ <input type="number" ref={bindValue(() => obj.value, (v) => (obj.value = v))} />
1230
+ </>;
1201
1231
  }
1202
1232
 
1203
1233
  render(App);
@@ -1214,10 +1244,11 @@ describe('use value()', () => {
1214
1244
  });
1215
1245
 
1216
1246
  it('should handle date input type', () => {
1217
- component App() {
1218
- const value = track('2025-11-14');
1219
-
1220
- <input type="date" {ref bindValue(value)} />
1247
+ function App() {
1248
+ return <>
1249
+ const value = track('2025-11-14');
1250
+ <input type="date" ref={bindValue(value)} />
1251
+ </>;
1221
1252
  }
1222
1253
 
1223
1254
  render(App);
@@ -1234,10 +1265,11 @@ describe('use value()', () => {
1234
1265
  });
1235
1266
 
1236
1267
  it('should handle date input type with a getter and setter', () => {
1237
- component App() {
1238
- const obj = new RippleObject({ value: '2025-11-14' });
1239
-
1240
- <input type="date" {ref bindValue(() => obj.value, (v) => (obj.value = v))} />
1268
+ function App() {
1269
+ return <>
1270
+ const obj = new RippleObject({ value: '2025-11-14' });
1271
+ <input type="date" ref={bindValue(() => obj.value, (v) => (obj.value = v))} />
1272
+ </>;
1241
1273
  }
1242
1274
 
1243
1275
  render(App);
@@ -1254,13 +1286,14 @@ describe('use value()', () => {
1254
1286
  });
1255
1287
 
1256
1288
  it('should update date input element when tracked value changes', () => {
1257
- component App() {
1258
- const value = track('2025-01-01');
1259
-
1260
- <div>
1261
- <input type="date" {ref bindValue(value)} />
1262
- <button onClick={() => (value.value = '2025-12-31')}>{'Update'}</button>
1263
- </div>
1289
+ function App() {
1290
+ return <>
1291
+ const value = track('2025-01-01');
1292
+ <div>
1293
+ <input type="date" ref={bindValue(value)} />
1294
+ <button onClick={() => (value.value = '2025-12-31')}>{'Update'}</button>
1295
+ </div>
1296
+ </>;
1264
1297
  }
1265
1298
 
1266
1299
  render(App);
@@ -1278,13 +1311,14 @@ describe('use value()', () => {
1278
1311
  });
1279
1312
 
1280
1313
  it('should update date input element when tracked value changes with a getter and setter', () => {
1281
- component App() {
1282
- const obj = new RippleObject({ value: '2025-01-01' });
1283
-
1284
- <div>
1285
- <input type="date" {ref bindValue(() => obj.value, (v) => (obj.value = v))} />
1286
- <button onClick={() => (obj.value = '2025-12-31')}>{'Update'}</button>
1287
- </div>
1314
+ function App() {
1315
+ return <>
1316
+ const obj = new RippleObject({ value: '2025-01-01' });
1317
+ <div>
1318
+ <input type="date" ref={bindValue(() => obj.value, (v) => (obj.value = v))} />
1319
+ <button onClick={() => (obj.value = '2025-12-31')}>{'Update'}</button>
1320
+ </div>
1321
+ </>;
1288
1322
  }
1289
1323
 
1290
1324
  render(App);
@@ -1302,15 +1336,16 @@ describe('use value()', () => {
1302
1336
  });
1303
1337
 
1304
1338
  it('should handle select with multiple attribute', () => {
1305
- component App() {
1306
- const selected = track(['2', '3']);
1307
-
1308
- <select multiple {ref bindValue(selected)}>
1309
- <option value="1">{'One'}</option>
1310
- <option value="2">{'Two'}</option>
1311
- <option value="3">{'Three'}</option>
1312
- <option value="4">{'Four'}</option>
1313
- </select>
1339
+ function App() {
1340
+ return <>
1341
+ const selected = track(['2', '3']);
1342
+ <select multiple ref={bindValue(selected)}>
1343
+ <option value="1">{'One'}</option>
1344
+ <option value="2">{'Two'}</option>
1345
+ <option value="3">{'Three'}</option>
1346
+ <option value="4">{'Four'}</option>
1347
+ </select>
1348
+ </>;
1314
1349
  }
1315
1350
 
1316
1351
  render(App);
@@ -1336,15 +1371,16 @@ describe('use value()', () => {
1336
1371
  });
1337
1372
 
1338
1373
  it('should handle select with multiple attribute with a getter and setter', () => {
1339
- component App() {
1340
- const selected = track(['2', '3']);
1341
-
1342
- <select multiple {ref bindValue(() => selected.value, (v) => (selected.value = v))}>
1343
- <option value="1">{'One'}</option>
1344
- <option value="2">{'Two'}</option>
1345
- <option value="3">{'Three'}</option>
1346
- <option value="4">{'Four'}</option>
1347
- </select>
1374
+ function App() {
1375
+ return <>
1376
+ const selected = track(['2', '3']);
1377
+ <select multiple ref={bindValue(() => selected.value, (v) => (selected.value = v))}>
1378
+ <option value="1">{'One'}</option>
1379
+ <option value="2">{'Two'}</option>
1380
+ <option value="3">{'Three'}</option>
1381
+ <option value="4">{'Four'}</option>
1382
+ </select>
1383
+ </>;
1348
1384
  }
1349
1385
 
1350
1386
  render(App);
@@ -1370,18 +1406,19 @@ describe('use value()', () => {
1370
1406
  });
1371
1407
 
1372
1408
  it('should update multiple select element when tracked value changes', () => {
1373
- component App() {
1374
- const selected = track(['1']);
1375
-
1376
- <div>
1377
- <select multiple {ref bindValue(selected)}>
1378
- <option value="1">{'One'}</option>
1379
- <option value="2">{'Two'}</option>
1380
- <option value="3">{'Three'}</option>
1381
- <option value="4">{'Four'}</option>
1382
- </select>
1383
- <button onClick={() => (selected.value = ['2', '4'])}>{'Update'}</button>
1384
- </div>
1409
+ function App() {
1410
+ return <>
1411
+ const selected = track(['1']);
1412
+ <div>
1413
+ <select multiple ref={bindValue(selected)}>
1414
+ <option value="1">{'One'}</option>
1415
+ <option value="2">{'Two'}</option>
1416
+ <option value="3">{'Three'}</option>
1417
+ <option value="4">{'Four'}</option>
1418
+ </select>
1419
+ <button onClick={() => (selected.value = ['2', '4'])}>{'Update'}</button>
1420
+ </div>
1421
+ </>;
1385
1422
  }
1386
1423
 
1387
1424
  render(App);
@@ -1408,18 +1445,19 @@ describe('use value()', () => {
1408
1445
  it(
1409
1446
  'should update multiple select element when tracked value changes with a getter and setter',
1410
1447
  () => {
1411
- component App() {
1412
- const selected = track(['1']);
1413
-
1414
- <div>
1415
- <select multiple {ref bindValue(() => selected.value, (v) => (selected.value = v))}>
1416
- <option value="1">{'One'}</option>
1417
- <option value="2">{'Two'}</option>
1418
- <option value="3">{'Three'}</option>
1419
- <option value="4">{'Four'}</option>
1420
- </select>
1421
- <button onClick={() => (selected.value = ['2', '4'])}>{'Update'}</button>
1422
- </div>
1448
+ function App() {
1449
+ return <>
1450
+ const selected = track(['1']);
1451
+ <div>
1452
+ <select multiple ref={bindValue(() => selected.value, (v) => (selected.value = v))}>
1453
+ <option value="1">{'One'}</option>
1454
+ <option value="2">{'Two'}</option>
1455
+ <option value="3">{'Three'}</option>
1456
+ <option value="4">{'Four'}</option>
1457
+ </select>
1458
+ <button onClick={() => (selected.value = ['2', '4'])}>{'Update'}</button>
1459
+ </div>
1460
+ </>;
1423
1461
  }
1424
1462
 
1425
1463
  render(App);
@@ -1445,13 +1483,14 @@ describe('use value()', () => {
1445
1483
  );
1446
1484
 
1447
1485
  it('should handle select without initial value and fall back to first option', () => {
1448
- component App() {
1449
- const selected = track();
1450
-
1451
- <select {ref bindValue(selected)}>
1452
- <option value="1">{'One'}</option>
1453
- <option value="2">{'Two'}</option>
1454
- </select>
1486
+ function App() {
1487
+ return <>
1488
+ const selected = track();
1489
+ <select ref={bindValue(selected)}>
1490
+ <option value="1">{'One'}</option>
1491
+ <option value="2">{'Two'}</option>
1492
+ </select>
1493
+ </>;
1455
1494
  }
1456
1495
 
1457
1496
  render(App);
@@ -1465,13 +1504,14 @@ describe('use value()', () => {
1465
1504
  it(
1466
1505
  'should handle select without initial value and fall back to first option with a getter and setter',
1467
1506
  () => {
1468
- component App() {
1469
- const selected = track();
1470
-
1471
- <select {ref bindValue(() => selected.value, (v) => (selected.value = v))}>
1472
- <option value="1">{'One'}</option>
1473
- <option value="2">{'Two'}</option>
1474
- </select>
1507
+ function App() {
1508
+ return <>
1509
+ const selected = track();
1510
+ <select ref={bindValue(() => selected.value, (v) => (selected.value = v))}>
1511
+ <option value="1">{'One'}</option>
1512
+ <option value="2">{'Two'}</option>
1513
+ </select>
1514
+ </>;
1475
1515
  }
1476
1516
 
1477
1517
  render(App);
@@ -1484,13 +1524,14 @@ describe('use value()', () => {
1484
1524
  );
1485
1525
 
1486
1526
  it('should handle select with disabled options', () => {
1487
- component App() {
1488
- const selected = track();
1489
-
1490
- <select {ref bindValue(selected)}>
1491
- <option value="1" disabled>{'One'}</option>
1492
- <option value="2">{'Two'}</option>
1493
- </select>
1527
+ function App() {
1528
+ return <>
1529
+ const selected = track();
1530
+ <select ref={bindValue(selected)}>
1531
+ <option value="1" disabled>{'One'}</option>
1532
+ <option value="2">{'Two'}</option>
1533
+ </select>
1534
+ </>;
1494
1535
  }
1495
1536
 
1496
1537
  render(App);
@@ -1502,13 +1543,14 @@ describe('use value()', () => {
1502
1543
  });
1503
1544
 
1504
1545
  it('should handle select with disabled options with a getter and setter', () => {
1505
- component App() {
1506
- const selected = track();
1507
-
1508
- <select {ref bindValue(() => selected.value, (v) => (selected.value = v))}>
1509
- <option value="1" disabled>{'One'}</option>
1510
- <option value="2">{'Two'}</option>
1511
- </select>
1546
+ function App() {
1547
+ return <>
1548
+ const selected = track();
1549
+ <select ref={bindValue(() => selected.value, (v) => (selected.value = v))}>
1550
+ <option value="1" disabled>{'One'}</option>
1551
+ <option value="2">{'Two'}</option>
1552
+ </select>
1553
+ </>;
1512
1554
  }
1513
1555
 
1514
1556
  render(App);
@@ -1520,14 +1562,15 @@ describe('use value()', () => {
1520
1562
  });
1521
1563
 
1522
1564
  it('should preselect numeric option values in select bindValue', () => {
1523
- component App() {
1524
- const selected = track(2);
1525
-
1526
- <select {ref bindValue(selected)}>
1527
- <option value={1}>{'One'}</option>
1528
- <option value={2}>{'Two'}</option>
1529
- <option value={3}>{'Three'}</option>
1530
- </select>
1565
+ function App() {
1566
+ return <>
1567
+ const selected = track(2);
1568
+ <select ref={bindValue(selected)}>
1569
+ <option value={1}>{'One'}</option>
1570
+ <option value={2}>{'Two'}</option>
1571
+ <option value={3}>{'Three'}</option>
1572
+ </select>
1573
+ </>;
1531
1574
  }
1532
1575
 
1533
1576
  render(App);
@@ -1542,14 +1585,15 @@ describe('use value()', () => {
1542
1585
  });
1543
1586
 
1544
1587
  it('should preselect numeric option values in select bindValue with a getter and setter', () => {
1545
- component App() {
1546
- const selected = track(2);
1547
-
1548
- <select {ref bindValue(() => selected.value, (v) => (selected.value = v))}>
1549
- <option value={1}>{'One'}</option>
1550
- <option value={2}>{'Two'}</option>
1551
- <option value={3}>{'Three'}</option>
1552
- </select>
1588
+ function App() {
1589
+ return <>
1590
+ const selected = track(2);
1591
+ <select ref={bindValue(() => selected.value, (v) => (selected.value = v))}>
1592
+ <option value={1}>{'One'}</option>
1593
+ <option value={2}>{'Two'}</option>
1594
+ <option value={3}>{'Three'}</option>
1595
+ </select>
1596
+ </>;
1553
1597
  }
1554
1598
 
1555
1599
  render(App);
@@ -1566,18 +1610,18 @@ describe('use value()', () => {
1566
1610
  it('should preserve numeric select values on change', () => {
1567
1611
  const logs: number[] = [];
1568
1612
 
1569
- component App() {
1570
- const selected = track(2);
1571
-
1572
- effect(() => {
1573
- logs.push(selected.value);
1574
- });
1575
-
1576
- <select {ref bindValue(selected)}>
1577
- <option value={1}>{'One'}</option>
1578
- <option value={2}>{'Two'}</option>
1579
- <option value={3}>{'Three'}</option>
1580
- </select>
1613
+ function App() {
1614
+ return <>
1615
+ const selected = track(2);
1616
+ effect(() => {
1617
+ logs.push(selected.value);
1618
+ });
1619
+ <select ref={bindValue(selected)}>
1620
+ <option value={1}>{'One'}</option>
1621
+ <option value={2}>{'Two'}</option>
1622
+ <option value={3}>{'Three'}</option>
1623
+ </select>
1624
+ </>;
1581
1625
  }
1582
1626
 
1583
1627
  render(App);
@@ -1593,21 +1637,22 @@ describe('use value()', () => {
1593
1637
  });
1594
1638
 
1595
1639
  it('should reselect tracked value when matching option is added later', async () => {
1596
- component App() {
1597
- const selected = track(5);
1598
- const options = RippleArray([
1599
- { id: 1, text: 'One' },
1600
- { id: 2, text: 'Two' },
1601
- ]);
1602
-
1603
- <div>
1604
- <select {ref bindValue(selected)}>
1605
- for (const option of options) {
1606
- <option value={option.id}>{option.text}</option>
1607
- }
1608
- </select>
1609
- <button onClick={() => options.push({ id: 5, text: 'Five' })}>{'Add'}</button>
1610
- </div>
1640
+ function App() {
1641
+ return <>
1642
+ const selected = track(5);
1643
+ const options = RippleArray([
1644
+ { id: 1, text: 'One' },
1645
+ { id: 2, text: 'Two' },
1646
+ ]);
1647
+ <div>
1648
+ <select ref={bindValue(selected)}>
1649
+ for (const option of options) {
1650
+ <option value={option.id}>{option.text}</option>
1651
+ }
1652
+ </select>
1653
+ <button onClick={() => options.push({ id: 5, text: 'Five' })}>{'Add'}</button>
1654
+ </div>
1655
+ </>;
1611
1656
  }
1612
1657
 
1613
1658
  render(App);
@@ -1628,25 +1673,25 @@ describe('use value()', () => {
1628
1673
  });
1629
1674
 
1630
1675
  it('should reselect tracked value when option lists are replaced later', async () => {
1631
- component App() {
1632
- const selected = track(22);
1633
- const options = RippleArray([
1634
- { id: 1, text: 'One' },
1635
- ]);
1636
-
1637
- effect(() => {
1638
- const timeout = setTimeout(() => {
1639
- options.splice(0, options.length, { id: 21, text: 'Tokyo' }, { id: 22, text: 'Osaka' });
1640
- }, 0);
1641
-
1642
- return () => clearTimeout(timeout);
1643
- });
1644
-
1645
- <select {ref bindValue(selected)}>
1646
- for (const option of options) {
1647
- <option value={option.id}>{option.text}</option>
1648
- }
1649
- </select>
1676
+ function App() {
1677
+ return <>
1678
+ const selected = track(22);
1679
+ const options = RippleArray([
1680
+ { id: 1, text: 'One' },
1681
+ ]);
1682
+ effect(() => {
1683
+ const timeout = setTimeout(() => {
1684
+ options.splice(0, options.length, { id: 21, text: 'Tokyo' }, { id: 22, text: 'Osaka' });
1685
+ }, 0);
1686
+
1687
+ return () => clearTimeout(timeout);
1688
+ });
1689
+ <select ref={bindValue(selected)}>
1690
+ for (const option of options) {
1691
+ <option value={option.id}>{option.text}</option>
1692
+ }
1693
+ </select>
1694
+ </>;
1650
1695
  }
1651
1696
 
1652
1697
  render(App);
@@ -1661,22 +1706,23 @@ describe('use value()', () => {
1661
1706
  });
1662
1707
 
1663
1708
  it('should accurately reflect values mutated through a tracked setter', () => {
1664
- component App() {
1665
- let value = track(
1666
- '',
1667
- (val) => {
1668
- return val;
1669
- },
1670
- (next) => {
1671
- if (next.includes('c')) {
1672
- next = next.replace(/c/g, '');
1673
- }
1674
- return next;
1675
- },
1676
- );
1677
-
1678
- <input type="text" {ref bindValue(value)} />
1679
- <div>{value.value}</div>
1709
+ function App() {
1710
+ return <>
1711
+ let value = track(
1712
+ '',
1713
+ (val) => {
1714
+ return val;
1715
+ },
1716
+ (next) => {
1717
+ if (next.includes('c')) {
1718
+ next = next.replace(/c/g, '');
1719
+ }
1720
+ return next;
1721
+ },
1722
+ );
1723
+ <input type="text" ref={bindValue(value)} />
1724
+ <div>{value.value}</div>
1725
+ </>;
1680
1726
  }
1681
1727
 
1682
1728
  render(App);
@@ -1697,22 +1743,23 @@ describe('use value()', () => {
1697
1743
  });
1698
1744
 
1699
1745
  it('should accurately reflect values when a getter modifies value', () => {
1700
- component App() {
1701
- let value = track(
1702
- '',
1703
- (val) => {
1704
- if (val.includes('c')) {
1705
- val = val.replace(/c/g, '');
1706
- }
1707
- return val;
1708
- },
1709
- (next) => {
1710
- return next;
1711
- },
1712
- );
1713
-
1714
- <input type="text" {ref bindValue(value)} />
1715
- <div>{value.value}</div>
1746
+ function App() {
1747
+ return <>
1748
+ let value = track(
1749
+ '',
1750
+ (val) => {
1751
+ if (val.includes('c')) {
1752
+ val = val.replace(/c/g, '');
1753
+ }
1754
+ return val;
1755
+ },
1756
+ (next) => {
1757
+ return next;
1758
+ },
1759
+ );
1760
+ <input type="text" ref={bindValue(value)} />
1761
+ <div>{value.value}</div>
1762
+ </>;
1716
1763
  }
1717
1764
 
1718
1765
  render(App);
@@ -1733,22 +1780,23 @@ describe('use value()', () => {
1733
1780
  });
1734
1781
 
1735
1782
  it('should always prefer what getter returns even if setter mutates next', () => {
1736
- component App() {
1737
- let value = track(
1738
- '',
1739
- (val) => {
1740
- return val.replace(/[c,b]+/g, '');
1741
- },
1742
- (next) => {
1743
- if (next.includes('c')) {
1744
- next = next.replace(/c/g, '');
1745
- }
1746
- return next;
1747
- },
1748
- );
1749
-
1750
- <input type="text" {ref bindValue(value)} />
1751
- <div>{value.value}</div>
1783
+ function App() {
1784
+ return <>
1785
+ let value = track(
1786
+ '',
1787
+ (val) => {
1788
+ return val.replace(/[c,b]+/g, '');
1789
+ },
1790
+ (next) => {
1791
+ if (next.includes('c')) {
1792
+ next = next.replace(/c/g, '');
1793
+ }
1794
+ return next;
1795
+ },
1796
+ );
1797
+ <input type="text" ref={bindValue(value)} />
1798
+ <div>{value.value}</div>
1799
+ </>;
1752
1800
  }
1753
1801
 
1754
1802
  render(App);
@@ -1771,31 +1819,32 @@ describe('use value()', () => {
1771
1819
  it(
1772
1820
  'should accurately reflect values mutated through an effect even after a setter mutation',
1773
1821
  () => {
1774
- component App() {
1775
- let value = track(
1776
- '',
1777
- (val) => {
1778
- return val;
1779
- },
1780
- (next) => {
1781
- if (next.includes('c')) {
1782
- next = next.replace(/c/g, '');
1783
- }
1784
- return next;
1785
- },
1786
- );
1787
-
1788
- effect(() => {
1789
- value.value;
1790
-
1791
- untrack(() => {
1792
- if (value.value.includes('a')) {
1793
- value.value = value.value.replace(/a/g, '');
1794
- }
1822
+ function App() {
1823
+ return <>
1824
+ let value = track(
1825
+ '',
1826
+ (val) => {
1827
+ return val;
1828
+ },
1829
+ (next) => {
1830
+ if (next.includes('c')) {
1831
+ next = next.replace(/c/g, '');
1832
+ }
1833
+ return next;
1834
+ },
1835
+ );
1836
+ effect(() => {
1837
+ value.value;
1838
+
1839
+ untrack(() => {
1840
+ if (value.value.includes('a')) {
1841
+ value.value = value.value.replace(/a/g, '');
1842
+ }
1843
+ });
1795
1844
  });
1796
- });
1797
- <input type="text" {ref bindValue(value)} />
1798
- <div>{value.value}</div>
1845
+ <input type="text" ref={bindValue(value)} />
1846
+ <div>{value.value}</div>
1847
+ </>;
1799
1848
  }
1800
1849
 
1801
1850
  render(App);
@@ -1817,21 +1866,22 @@ describe('use value()', () => {
1817
1866
  );
1818
1867
 
1819
1868
  it('should accurately reflect values mutated through a tracked setter via bind accessors', () => {
1820
- component App() {
1821
- let value = track('');
1822
- const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1823
- () => {
1824
- return value.value;
1825
- },
1826
- (v: string) => {
1827
- if (v.includes('c')) {
1828
- v = v.replace(/c/g, '');
1829
- }
1830
- value.value = v;
1831
- },
1832
- ];
1833
-
1834
- <input type="text" {ref bindValue(...value_accessors)} />
1869
+ function App() {
1870
+ return <>
1871
+ let value = track('');
1872
+ const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1873
+ () => {
1874
+ return value.value;
1875
+ },
1876
+ (v: string) => {
1877
+ if (v.includes('c')) {
1878
+ v = v.replace(/c/g, '');
1879
+ }
1880
+ value.value = v;
1881
+ },
1882
+ ];
1883
+ <input type="text" ref={bindValue(...value_accessors)} />
1884
+ </>;
1835
1885
  }
1836
1886
 
1837
1887
  render(App);
@@ -1849,21 +1899,22 @@ describe('use value()', () => {
1849
1899
  });
1850
1900
 
1851
1901
  it('should prefer what getter returns via bind accessors', () => {
1852
- component App() {
1853
- let value = track('');
1854
- const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1855
- () => {
1856
- if (value.value.includes('c')) {
1857
- return value.value.replace(/c/g, '');
1858
- }
1859
- return value.value;
1860
- },
1861
- (v: string) => {
1862
- value.value = v;
1863
- },
1864
- ];
1865
-
1866
- <input type="text" {ref bindValue(...value_accessors)} />
1902
+ function App() {
1903
+ return <>
1904
+ let value = track('');
1905
+ const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1906
+ () => {
1907
+ if (value.value.includes('c')) {
1908
+ return value.value.replace(/c/g, '');
1909
+ }
1910
+ return value.value;
1911
+ },
1912
+ (v: string) => {
1913
+ value.value = v;
1914
+ },
1915
+ ];
1916
+ <input type="text" ref={bindValue(...value_accessors)} />
1917
+ </>;
1867
1918
  }
1868
1919
 
1869
1920
  render(App);
@@ -1883,21 +1934,22 @@ describe('use value()', () => {
1883
1934
  it(
1884
1935
  'should always prefer what getter returns even if setter mutates next via bind accessors',
1885
1936
  () => {
1886
- component App() {
1887
- let value = track('');
1888
- const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1889
- () => {
1890
- return value.value.replace(/[c,b]+/g, '');
1891
- },
1892
- (v: string) => {
1893
- if (v.includes('c')) {
1894
- v = v.replace(/c/g, '');
1895
- }
1896
- value.value = v;
1897
- },
1898
- ];
1899
-
1900
- <input type="text" {ref bindValue(...value_accessors)} />
1937
+ function App() {
1938
+ return <>
1939
+ let value = track('');
1940
+ const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1941
+ () => {
1942
+ return value.value.replace(/[c,b]+/g, '');
1943
+ },
1944
+ (v: string) => {
1945
+ if (v.includes('c')) {
1946
+ v = v.replace(/c/g, '');
1947
+ }
1948
+ value.value = v;
1949
+ },
1950
+ ];
1951
+ <input type="text" ref={bindValue(...value_accessors)} />
1952
+ </>;
1901
1953
  }
1902
1954
 
1903
1955
  render(App);
@@ -1918,30 +1970,31 @@ describe('use value()', () => {
1918
1970
  it(
1919
1971
  'should accurately reflect values mutated through an effect even after a setter mutation via bind accessors',
1920
1972
  () => {
1921
- component App() {
1922
- let value = track('');
1923
- const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1924
- () => {
1925
- return value.value;
1926
- },
1927
- (v: string) => {
1928
- if (v.includes('c')) {
1929
- v = v.replace(/c/g, '');
1930
- }
1931
- value.value = v;
1932
- },
1933
- ];
1934
-
1935
- effect(() => {
1936
- value.value;
1937
-
1938
- untrack(() => {
1939
- if (value.value.includes('a')) {
1940
- value.value = value.value.replace(/a/g, '');
1941
- }
1973
+ function App() {
1974
+ return <>
1975
+ let value = track('');
1976
+ const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1977
+ () => {
1978
+ return value.value;
1979
+ },
1980
+ (v: string) => {
1981
+ if (v.includes('c')) {
1982
+ v = v.replace(/c/g, '');
1983
+ }
1984
+ value.value = v;
1985
+ },
1986
+ ];
1987
+ effect(() => {
1988
+ value.value;
1989
+
1990
+ untrack(() => {
1991
+ if (value.value.includes('a')) {
1992
+ value.value = value.value.replace(/a/g, '');
1993
+ }
1994
+ });
1942
1995
  });
1943
- });
1944
- <input type="text" {ref bindValue(...value_accessors)} />
1996
+ <input type="text" ref={bindValue(...value_accessors)} />
1997
+ </>;
1945
1998
  }
1946
1999
 
1947
2000
  render(App);
@@ -1962,19 +2015,20 @@ describe('use value()', () => {
1962
2015
  it(
1963
2016
  'should keep the input.value unchanged and synced with the tracked when the setter blocks updates to the tracked via bind accessors',
1964
2017
  () => {
1965
- component App() {
1966
- let value = track('');
1967
- const value_accessors: [GetFunction<string>, SetFunction<string>] = [
1968
- () => {
1969
- return value.value;
1970
- },
1971
- (v: string) => {
1972
- // no update
1973
- },
1974
- ];
1975
-
1976
- <input type="text" {ref bindValue(...value_accessors)} />
1977
- <div>{value.value}</div>
2018
+ function App() {
2019
+ return <>
2020
+ let value = track('');
2021
+ const value_accessors: [GetFunction<string>, SetFunction<string>] = [
2022
+ () => {
2023
+ return value.value;
2024
+ },
2025
+ (v: string) => {
2026
+ // no update
2027
+ },
2028
+ ];
2029
+ <input type="text" ref={bindValue(...value_accessors)} />
2030
+ <div>{value.value}</div>
2031
+ </>;
1978
2032
  }
1979
2033
 
1980
2034
  render(App);
@@ -1997,19 +2051,20 @@ describe('use value()', () => {
1997
2051
  it(
1998
2052
  'should keep the input.value unchanged and synced with the tracked when the setter blocks updates to the tracked via track get / set',
1999
2053
  () => {
2000
- component App() {
2001
- let value = track(
2002
- '',
2003
- (v) => {
2004
- return v;
2005
- },
2006
- () => {
2007
- return '';
2008
- },
2009
- );
2010
-
2011
- <input type="text" {ref bindValue(value)} />
2012
- <div>{value.value}</div>
2054
+ function App() {
2055
+ return <>
2056
+ let value = track(
2057
+ '',
2058
+ (v) => {
2059
+ return v;
2060
+ },
2061
+ () => {
2062
+ return '';
2063
+ },
2064
+ );
2065
+ <input type="text" ref={bindValue(value)} />
2066
+ <div>{value.value}</div>
2067
+ </>;
2013
2068
  }
2014
2069
 
2015
2070
  render(App);
@@ -2034,14 +2089,14 @@ describe('bindClientWidth and bindClientHeight', () => {
2034
2089
  it('should bind element clientWidth', () => {
2035
2090
  const logs: number[] = [];
2036
2091
 
2037
- component App() {
2038
- const width = track(0);
2039
-
2040
- effect(() => {
2041
- logs.push(width.value);
2042
- });
2043
-
2044
- <div {ref bindClientWidth(width)} />
2092
+ function App() {
2093
+ return <>
2094
+ const width = track(0);
2095
+ effect(() => {
2096
+ logs.push(width.value);
2097
+ });
2098
+ <div ref={bindClientWidth(width)} />
2099
+ </>;
2045
2100
  }
2046
2101
 
2047
2102
  render(App);
@@ -2065,14 +2120,14 @@ describe('bindClientWidth and bindClientHeight', () => {
2065
2120
  it('should bind element clientWidth with a getter and setter', () => {
2066
2121
  const logs: number[] = [];
2067
2122
 
2068
- component App() {
2069
- const width = new RippleObject({ value: 0 });
2070
-
2071
- effect(() => {
2072
- logs.push(width.value);
2073
- });
2074
-
2075
- <div {ref bindClientWidth(() => width.value, (v: number) => (width.value = v))} />
2123
+ function App() {
2124
+ return <>
2125
+ const width = new RippleObject({ value: 0 });
2126
+ effect(() => {
2127
+ logs.push(width.value);
2128
+ });
2129
+ <div ref={bindClientWidth(() => width.value, (v: number) => (width.value = v))} />
2130
+ </>;
2076
2131
  }
2077
2132
 
2078
2133
  render(App);
@@ -2096,14 +2151,14 @@ describe('bindClientWidth and bindClientHeight', () => {
2096
2151
  it('should bind element clientHeight', () => {
2097
2152
  const logs: number[] = [];
2098
2153
 
2099
- component App() {
2100
- const height = track(0);
2101
-
2102
- effect(() => {
2103
- logs.push(height.value);
2104
- });
2105
-
2106
- <div {ref bindClientHeight(height)} />
2154
+ function App() {
2155
+ return <>
2156
+ const height = track(0);
2157
+ effect(() => {
2158
+ logs.push(height.value);
2159
+ });
2160
+ <div ref={bindClientHeight(height)} />
2161
+ </>;
2107
2162
  }
2108
2163
 
2109
2164
  render(App);
@@ -2127,13 +2182,14 @@ describe('bindClientWidth and bindClientHeight', () => {
2127
2182
  it('should bind element clientHeight with a getter and setter', () => {
2128
2183
  const logs: number[] = [];
2129
2184
 
2130
- component App() {
2131
- const height = new RippleObject({ value: 0 });
2132
- effect(() => {
2133
- logs.push(height.value);
2134
- });
2135
-
2136
- <div {ref bindClientHeight(() => height.value, (v: number) => (height.value = v))} />
2185
+ function App() {
2186
+ return <>
2187
+ const height = new RippleObject({ value: 0 });
2188
+ effect(() => {
2189
+ logs.push(height.value);
2190
+ });
2191
+ <div ref={bindClientHeight(() => height.value, (v: number) => (height.value = v))} />
2192
+ </>;
2137
2193
  }
2138
2194
 
2139
2195
  render(App);
@@ -2159,14 +2215,14 @@ describe('bindOffsetWidth and bindOffsetHeight', () => {
2159
2215
  it('should bind element offsetWidth', () => {
2160
2216
  const logs: number[] = [];
2161
2217
 
2162
- component App() {
2163
- const width = track(0);
2164
-
2165
- effect(() => {
2166
- logs.push(width.value);
2167
- });
2168
-
2169
- <div {ref bindOffsetWidth(width)} />
2218
+ function App() {
2219
+ return <>
2220
+ const width = track(0);
2221
+ effect(() => {
2222
+ logs.push(width.value);
2223
+ });
2224
+ <div ref={bindOffsetWidth(width)} />
2225
+ </>;
2170
2226
  }
2171
2227
 
2172
2228
  render(App);
@@ -2190,14 +2246,14 @@ describe('bindOffsetWidth and bindOffsetHeight', () => {
2190
2246
  it('should bind element offsetWidth with a getter and setter', () => {
2191
2247
  const logs: number[] = [];
2192
2248
 
2193
- component App() {
2194
- const width = new RippleObject({ value: 0 });
2195
-
2196
- effect(() => {
2197
- logs.push(width.value);
2198
- });
2199
-
2200
- <div {ref bindOffsetWidth(() => width.value, (v: number) => (width.value = v))} />
2249
+ function App() {
2250
+ return <>
2251
+ const width = new RippleObject({ value: 0 });
2252
+ effect(() => {
2253
+ logs.push(width.value);
2254
+ });
2255
+ <div ref={bindOffsetWidth(() => width.value, (v: number) => (width.value = v))} />
2256
+ </>;
2201
2257
  }
2202
2258
 
2203
2259
  render(App);
@@ -2221,14 +2277,14 @@ describe('bindOffsetWidth and bindOffsetHeight', () => {
2221
2277
  it('should bind element offsetHeight', () => {
2222
2278
  const logs: number[] = [];
2223
2279
 
2224
- component App() {
2225
- const height = track(0);
2226
-
2227
- effect(() => {
2228
- logs.push(height.value);
2229
- });
2230
-
2231
- <div {ref bindOffsetHeight(height)} />
2280
+ function App() {
2281
+ return <>
2282
+ const height = track(0);
2283
+ effect(() => {
2284
+ logs.push(height.value);
2285
+ });
2286
+ <div ref={bindOffsetHeight(height)} />
2287
+ </>;
2232
2288
  }
2233
2289
 
2234
2290
  render(App);
@@ -2252,13 +2308,14 @@ describe('bindOffsetWidth and bindOffsetHeight', () => {
2252
2308
  it('should bind element offsetHeight with a getter and setter', () => {
2253
2309
  const logs: number[] = [];
2254
2310
 
2255
- component App() {
2256
- const height = new RippleObject({ value: 0 });
2257
- effect(() => {
2258
- logs.push(height.value);
2259
- });
2260
-
2261
- <div {ref bindOffsetHeight(() => height.value, (v: number) => (height.value = v))} />
2311
+ function App() {
2312
+ return <>
2313
+ const height = new RippleObject({ value: 0 });
2314
+ effect(() => {
2315
+ logs.push(height.value);
2316
+ });
2317
+ <div ref={bindOffsetHeight(() => height.value, (v: number) => (height.value = v))} />
2318
+ </>;
2262
2319
  }
2263
2320
 
2264
2321
  render(App);
@@ -2284,14 +2341,14 @@ describe('bindContentRect', () => {
2284
2341
  it('should bind element contentRect', () => {
2285
2342
  const logs: DOMRectReadOnly[] = [];
2286
2343
 
2287
- component App() {
2288
- const rect = track(null);
2289
-
2290
- effect(() => {
2291
- if (rect.value) logs.push(rect.value);
2292
- });
2293
-
2294
- <div {ref bindContentRect(rect)} />
2344
+ function App() {
2345
+ return <>
2346
+ const rect = track(null);
2347
+ effect(() => {
2348
+ if (rect.value) logs.push(rect.value);
2349
+ });
2350
+ <div ref={bindContentRect(rect)} />
2351
+ </>;
2295
2352
  }
2296
2353
 
2297
2354
  render(App);
@@ -2314,20 +2371,21 @@ describe('bindContentRect', () => {
2314
2371
  it('should bind element contentRect with a getter and setter', () => {
2315
2372
  const logs: DOMRectReadOnly[] = [];
2316
2373
 
2317
- component App() {
2318
- const rect: RippleObject<{ value: DOMRectReadOnly | null }> = new RippleObject({
2319
- value: null,
2320
- });
2321
- effect(() => {
2322
- if (rect.value) logs.push(rect.value);
2323
- });
2324
-
2325
- <div
2326
- {ref bindContentRect<null | DOMRectReadOnly>(
2327
- () => rect.value,
2328
- (v: DOMRectReadOnly) => (rect.value = v),
2329
- )}
2330
- />
2374
+ function App() {
2375
+ return <>
2376
+ const rect: RippleObject<{ value: DOMRectReadOnly | null }> = new RippleObject({
2377
+ value: null,
2378
+ });
2379
+ effect(() => {
2380
+ if (rect.value) logs.push(rect.value);
2381
+ });
2382
+ <div
2383
+ ref={bindContentRect<null | DOMRectReadOnly>(
2384
+ () => rect.value,
2385
+ (v: DOMRectReadOnly) => (rect.value = v),
2386
+ )}
2387
+ />
2388
+ </>;
2331
2389
  }
2332
2390
 
2333
2391
  render(App);
@@ -2352,14 +2410,14 @@ describe('bindContentBoxSize', () => {
2352
2410
  it('should bind element contentBoxSize', () => {
2353
2411
  const logs: any[] = [];
2354
2412
 
2355
- component App() {
2356
- const boxSize = track(null);
2357
-
2358
- effect(() => {
2359
- if (boxSize.value) logs.push(boxSize.value);
2360
- });
2361
-
2362
- <div {ref bindContentBoxSize(boxSize)} />
2413
+ function App() {
2414
+ return <>
2415
+ const boxSize = track(null);
2416
+ effect(() => {
2417
+ if (boxSize.value) logs.push(boxSize.value);
2418
+ });
2419
+ <div ref={bindContentBoxSize(boxSize)} />
2420
+ </>;
2363
2421
  }
2364
2422
 
2365
2423
  render(App);
@@ -2385,21 +2443,21 @@ describe('bindContentBoxSize', () => {
2385
2443
  { blockSize: 200, inlineSize: 300 },
2386
2444
  ];
2387
2445
 
2388
- component App() {
2389
- const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2390
- value: null,
2391
- });
2392
-
2393
- effect(() => {
2394
- if (boxSize.value) logs.push(boxSize.value);
2395
- });
2396
-
2397
- <div
2398
- {ref bindContentBoxSize<null | typeof mockBoxSize>(
2399
- () => boxSize.value,
2400
- (v: typeof mockBoxSize) => (boxSize.value = v),
2401
- )}
2402
- />
2446
+ function App() {
2447
+ return <>
2448
+ const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2449
+ value: null,
2450
+ });
2451
+ effect(() => {
2452
+ if (boxSize.value) logs.push(boxSize.value);
2453
+ });
2454
+ <div
2455
+ ref={bindContentBoxSize<null | typeof mockBoxSize>(
2456
+ () => boxSize.value,
2457
+ (v: typeof mockBoxSize) => (boxSize.value = v),
2458
+ )}
2459
+ />
2460
+ </>;
2403
2461
  }
2404
2462
 
2405
2463
  render(App);
@@ -2421,14 +2479,14 @@ describe('bindBorderBoxSize', () => {
2421
2479
  it('should bind element borderBoxSize', () => {
2422
2480
  const logs: any[] = [];
2423
2481
 
2424
- component App() {
2425
- const boxSize = track(null);
2426
-
2427
- effect(() => {
2428
- if (boxSize.value) logs.push(boxSize.value);
2429
- });
2430
-
2431
- <div {ref bindBorderBoxSize(boxSize)} />
2482
+ function App() {
2483
+ return <>
2484
+ const boxSize = track(null);
2485
+ effect(() => {
2486
+ if (boxSize.value) logs.push(boxSize.value);
2487
+ });
2488
+ <div ref={bindBorderBoxSize(boxSize)} />
2489
+ </>;
2432
2490
  }
2433
2491
 
2434
2492
  render(App);
@@ -2454,21 +2512,21 @@ describe('bindBorderBoxSize', () => {
2454
2512
  { blockSize: 220, inlineSize: 320 },
2455
2513
  ];
2456
2514
 
2457
- component App() {
2458
- const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2459
- value: null,
2460
- });
2461
-
2462
- effect(() => {
2463
- if (boxSize.value) logs.push(boxSize.value);
2464
- });
2465
-
2466
- <div
2467
- {ref bindBorderBoxSize<null | typeof mockBoxSize>(
2468
- () => boxSize.value,
2469
- (v: typeof mockBoxSize) => (boxSize.value = v),
2470
- )}
2471
- />
2515
+ function App() {
2516
+ return <>
2517
+ const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2518
+ value: null,
2519
+ });
2520
+ effect(() => {
2521
+ if (boxSize.value) logs.push(boxSize.value);
2522
+ });
2523
+ <div
2524
+ ref={bindBorderBoxSize<null | typeof mockBoxSize>(
2525
+ () => boxSize.value,
2526
+ (v: typeof mockBoxSize) => (boxSize.value = v),
2527
+ )}
2528
+ />
2529
+ </>;
2472
2530
  }
2473
2531
 
2474
2532
  render(App);
@@ -2490,14 +2548,14 @@ describe('bindDevicePixelContentBoxSize', () => {
2490
2548
  it('should bind element devicePixelContentBoxSize', () => {
2491
2549
  const logs: any[] = [];
2492
2550
 
2493
- component App() {
2494
- const boxSize = track(null);
2495
-
2496
- effect(() => {
2497
- if (boxSize.value) logs.push(boxSize.value);
2498
- });
2499
-
2500
- <div {ref bindDevicePixelContentBoxSize(boxSize)} />
2551
+ function App() {
2552
+ return <>
2553
+ const boxSize = track(null);
2554
+ effect(() => {
2555
+ if (boxSize.value) logs.push(boxSize.value);
2556
+ });
2557
+ <div ref={bindDevicePixelContentBoxSize(boxSize)} />
2558
+ </>;
2501
2559
  }
2502
2560
 
2503
2561
  render(App);
@@ -2523,21 +2581,21 @@ describe('bindDevicePixelContentBoxSize', () => {
2523
2581
  { blockSize: 400, inlineSize: 600 },
2524
2582
  ];
2525
2583
 
2526
- component App() {
2527
- const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2528
- value: null,
2529
- });
2530
-
2531
- effect(() => {
2532
- if (boxSize.value) logs.push(boxSize.value);
2533
- });
2534
-
2535
- <div
2536
- {ref bindDevicePixelContentBoxSize<null | typeof mockBoxSize>(
2537
- () => boxSize.value,
2538
- (v: typeof mockBoxSize) => (boxSize.value = v),
2539
- )}
2540
- />
2584
+ function App() {
2585
+ return <>
2586
+ const boxSize: RippleObject<{ value: typeof mockBoxSize | null }> = new RippleObject({
2587
+ value: null,
2588
+ });
2589
+ effect(() => {
2590
+ if (boxSize.value) logs.push(boxSize.value);
2591
+ });
2592
+ <div
2593
+ ref={bindDevicePixelContentBoxSize<null | typeof mockBoxSize>(
2594
+ () => boxSize.value,
2595
+ (v: typeof mockBoxSize) => (boxSize.value = v),
2596
+ )}
2597
+ />
2598
+ </>;
2541
2599
  }
2542
2600
 
2543
2601
  render(App);
@@ -2559,14 +2617,14 @@ describe('bindInnerHTML', () => {
2559
2617
  it('should bind element innerHTML', () => {
2560
2618
  const logs: string[] = [];
2561
2619
 
2562
- component App() {
2563
- const html = track('<strong>Hello</strong>');
2564
-
2565
- effect(() => {
2566
- logs.push(html.value);
2567
- });
2568
-
2569
- <div contenteditable="true" {ref bindInnerHTML(html)} />
2620
+ function App() {
2621
+ return <>
2622
+ const html = track('<strong>Hello</strong>');
2623
+ effect(() => {
2624
+ logs.push(html.value);
2625
+ });
2626
+ <div contenteditable="true" ref={bindInnerHTML(html)} />
2627
+ </>;
2570
2628
  }
2571
2629
 
2572
2630
  render(App);
@@ -2585,17 +2643,17 @@ describe('bindInnerHTML', () => {
2585
2643
  it('should bind element innerHTML', () => {
2586
2644
  const logs: string[] = [];
2587
2645
 
2588
- component App() {
2589
- const html = new RippleObject({ value: '<strong>Hello</strong>' });
2590
-
2591
- effect(() => {
2592
- logs.push(html.value);
2593
- });
2594
-
2595
- <div
2596
- contenteditable="true"
2597
- {ref bindInnerHTML(() => html.value, (v: string) => (html.value = v))}
2598
- />
2646
+ function App() {
2647
+ return <>
2648
+ const html = new RippleObject({ value: '<strong>Hello</strong>' });
2649
+ effect(() => {
2650
+ logs.push(html.value);
2651
+ });
2652
+ <div
2653
+ contenteditable="true"
2654
+ ref={bindInnerHTML(() => html.value, (v: string) => (html.value = v))}
2655
+ />
2656
+ </>;
2599
2657
  }
2600
2658
 
2601
2659
  render(App);
@@ -2612,13 +2670,14 @@ describe('bindInnerHTML', () => {
2612
2670
  });
2613
2671
 
2614
2672
  it('should update innerHTML when tracked value changes', () => {
2615
- component App() {
2616
- const html = track('<p>Initial</p>');
2617
-
2618
- <div>
2619
- <div contenteditable="true" {ref bindInnerHTML(html)} />
2620
- <button onClick={() => (html.value = '<p>Updated</p>')}>{'Update'}</button>
2621
- </div>
2673
+ function App() {
2674
+ return <>
2675
+ const html = track('<p>Initial</p>');
2676
+ <div>
2677
+ <div contenteditable="true" ref={bindInnerHTML(html)} />
2678
+ <button onClick={() => (html.value = '<p>Updated</p>')}>{'Update'}</button>
2679
+ </div>
2680
+ </>;
2622
2681
  }
2623
2682
 
2624
2683
  render(App);
@@ -2636,16 +2695,17 @@ describe('bindInnerHTML', () => {
2636
2695
  });
2637
2696
 
2638
2697
  it('should update innerHTML when tracked value changes with a getter and setter', () => {
2639
- component App() {
2640
- const html = new RippleObject({ value: '<p>Initial</p>' });
2641
-
2642
- <div>
2643
- <div
2644
- contenteditable="true"
2645
- {ref bindInnerHTML(() => html.value, (v: string) => (html.value = v))}
2646
- />
2647
- <button onClick={() => (html.value = '<p>Updated</p>')}>{'Update'}</button>
2648
- </div>
2698
+ function App() {
2699
+ return <>
2700
+ const html = new RippleObject({ value: '<p>Initial</p>' });
2701
+ <div>
2702
+ <div
2703
+ contenteditable="true"
2704
+ ref={bindInnerHTML(() => html.value, (v: string) => (html.value = v))}
2705
+ />
2706
+ <button onClick={() => (html.value = '<p>Updated</p>')}>{'Update'}</button>
2707
+ </div>
2708
+ </>;
2649
2709
  }
2650
2710
 
2651
2711
  render(App);
@@ -2663,10 +2723,11 @@ describe('bindInnerHTML', () => {
2663
2723
  });
2664
2724
 
2665
2725
  it('should handle null innerHTML value', () => {
2666
- component App() {
2667
- const html = track(null);
2668
-
2669
- <div contenteditable="true" {ref bindInnerHTML(html)} />
2726
+ function App() {
2727
+ return <>
2728
+ const html = track(null);
2729
+ <div contenteditable="true" ref={bindInnerHTML(html)} />
2730
+ </>;
2670
2731
  }
2671
2732
 
2672
2733
  render(App);
@@ -2678,13 +2739,14 @@ describe('bindInnerHTML', () => {
2678
2739
  });
2679
2740
 
2680
2741
  it('should handle null innerHTML value with a getter and setter', () => {
2681
- component App() {
2682
- const html: RippleObject<{ value: null | string }> = new RippleObject({ value: null });
2683
-
2684
- <div
2685
- contenteditable="true"
2686
- {ref bindInnerHTML(() => html.value, (v: string | null) => (html.value = v))}
2687
- />
2742
+ function App() {
2743
+ return <>
2744
+ const html: RippleObject<{ value: null | string }> = new RippleObject({ value: null });
2745
+ <div
2746
+ contenteditable="true"
2747
+ ref={bindInnerHTML(() => html.value, (v: string | null) => (html.value = v))}
2748
+ />
2749
+ </>;
2688
2750
  }
2689
2751
 
2690
2752
  render(App);
@@ -2700,14 +2762,14 @@ describe('bindInnerText', () => {
2700
2762
  it('should bind element innerText', () => {
2701
2763
  const logs: string[] = [];
2702
2764
 
2703
- component App() {
2704
- const text = track('Hello World');
2705
-
2706
- effect(() => {
2707
- logs.push(text.value);
2708
- });
2709
-
2710
- <div contenteditable="true" {ref bindInnerText(text)} />
2765
+ function App() {
2766
+ return <>
2767
+ const text = track('Hello World');
2768
+ effect(() => {
2769
+ logs.push(text.value);
2770
+ });
2771
+ <div contenteditable="true" ref={bindInnerText(text)} />
2772
+ </>;
2711
2773
  }
2712
2774
 
2713
2775
  render(App);
@@ -2726,16 +2788,17 @@ describe('bindInnerText', () => {
2726
2788
  it('should bind element innerText with a getter and setter', () => {
2727
2789
  const logs: string[] = [];
2728
2790
 
2729
- component App() {
2730
- const text = new RippleObject({ value: 'Hello World' });
2731
- effect(() => {
2732
- logs.push(text.value);
2733
- });
2734
-
2735
- <div
2736
- contenteditable="true"
2737
- {ref bindInnerText(() => text.value, (v: string) => (text.value = v))}
2738
- />
2791
+ function App() {
2792
+ return <>
2793
+ const text = new RippleObject({ value: 'Hello World' });
2794
+ effect(() => {
2795
+ logs.push(text.value);
2796
+ });
2797
+ <div
2798
+ contenteditable="true"
2799
+ ref={bindInnerText(() => text.value, (v: string) => (text.value = v))}
2800
+ />
2801
+ </>;
2739
2802
  }
2740
2803
 
2741
2804
  render(App);
@@ -2752,13 +2815,14 @@ describe('bindInnerText', () => {
2752
2815
  });
2753
2816
 
2754
2817
  it('should update innerText when tracked value changes', () => {
2755
- component App() {
2756
- const text = track('Before');
2757
-
2758
- <div>
2759
- <div contenteditable="true" {ref bindInnerText(text)} />
2760
- <button onClick={() => (text.value = 'After')}>{'Update'}</button>
2761
- </div>
2818
+ function App() {
2819
+ return <>
2820
+ const text = track('Before');
2821
+ <div>
2822
+ <div contenteditable="true" ref={bindInnerText(text)} />
2823
+ <button onClick={() => (text.value = 'After')}>{'Update'}</button>
2824
+ </div>
2825
+ </>;
2762
2826
  }
2763
2827
 
2764
2828
  render(App);
@@ -2776,16 +2840,17 @@ describe('bindInnerText', () => {
2776
2840
  });
2777
2841
 
2778
2842
  it('should update innerText when tracked value changes with a getter and setter', () => {
2779
- component App() {
2780
- const text = new RippleObject({ value: 'Before' });
2781
-
2782
- <div>
2783
- <div
2784
- contenteditable="true"
2785
- {ref bindInnerText(() => text.value, (v: string) => (text.value = v))}
2786
- />
2787
- <button onClick={() => (text.value = 'After')}>{'Update'}</button>
2788
- </div>
2843
+ function App() {
2844
+ return <>
2845
+ const text = new RippleObject({ value: 'Before' });
2846
+ <div>
2847
+ <div
2848
+ contenteditable="true"
2849
+ ref={bindInnerText(() => text.value, (v: string) => (text.value = v))}
2850
+ />
2851
+ <button onClick={() => (text.value = 'After')}>{'Update'}</button>
2852
+ </div>
2853
+ </>;
2789
2854
  }
2790
2855
 
2791
2856
  render(App);
@@ -2807,14 +2872,14 @@ describe('bindTextContent', () => {
2807
2872
  it('should bind element textContent', () => {
2808
2873
  const logs: string[] = [];
2809
2874
 
2810
- component App() {
2811
- const text = track('Sample text');
2812
-
2813
- effect(() => {
2814
- logs.push(text.value);
2815
- });
2816
-
2817
- <div contenteditable="true" {ref bindTextContent(text)} />
2875
+ function App() {
2876
+ return <>
2877
+ const text = track('Sample text');
2878
+ effect(() => {
2879
+ logs.push(text.value);
2880
+ });
2881
+ <div contenteditable="true" ref={bindTextContent(text)} />
2882
+ </>;
2818
2883
  }
2819
2884
 
2820
2885
  render(App);
@@ -2833,17 +2898,17 @@ describe('bindTextContent', () => {
2833
2898
  it('should bind element textContent with a getter and setter', () => {
2834
2899
  const logs: string[] = [];
2835
2900
 
2836
- component App() {
2837
- const text = new RippleObject({ value: 'Sample text' });
2838
-
2839
- effect(() => {
2840
- logs.push(text.value);
2841
- });
2842
-
2843
- <div
2844
- contenteditable="true"
2845
- {ref bindTextContent(() => text.value, (v: string) => (text.value = v))}
2846
- />
2901
+ function App() {
2902
+ return <>
2903
+ const text = new RippleObject({ value: 'Sample text' });
2904
+ effect(() => {
2905
+ logs.push(text.value);
2906
+ });
2907
+ <div
2908
+ contenteditable="true"
2909
+ ref={bindTextContent(() => text.value, (v: string) => (text.value = v))}
2910
+ />
2911
+ </>;
2847
2912
  }
2848
2913
 
2849
2914
  render(App);
@@ -2860,13 +2925,14 @@ describe('bindTextContent', () => {
2860
2925
  });
2861
2926
 
2862
2927
  it('should update textContent when tracked value changes', () => {
2863
- component App() {
2864
- const text = track('Start');
2865
-
2866
- <div>
2867
- <div contenteditable="true" {ref bindTextContent(text)} />
2868
- <button onClick={() => (text.value = 'End')}>{'Update'}</button>
2869
- </div>
2928
+ function App() {
2929
+ return <>
2930
+ const text = track('Start');
2931
+ <div>
2932
+ <div contenteditable="true" ref={bindTextContent(text)} />
2933
+ <button onClick={() => (text.value = 'End')}>{'Update'}</button>
2934
+ </div>
2935
+ </>;
2870
2936
  }
2871
2937
 
2872
2938
  render(App);
@@ -2884,16 +2950,17 @@ describe('bindTextContent', () => {
2884
2950
  });
2885
2951
 
2886
2952
  it('should update textContent when tracked value changes with a getter and setter', () => {
2887
- component App() {
2888
- const text = new RippleObject({ value: 'Start' });
2889
-
2890
- <div>
2891
- <div
2892
- contenteditable="true"
2893
- {ref bindTextContent(() => text.value, (v: string) => (text.value = v))}
2894
- />
2895
- <button onClick={() => (text.value = 'End')}>{'Update'}</button>
2896
- </div>
2953
+ function App() {
2954
+ return <>
2955
+ const text = new RippleObject({ value: 'Start' });
2956
+ <div>
2957
+ <div
2958
+ contenteditable="true"
2959
+ ref={bindTextContent(() => text.value, (v: string) => (text.value = v))}
2960
+ />
2961
+ <button onClick={() => (text.value = 'End')}>{'Update'}</button>
2962
+ </div>
2963
+ </>;
2897
2964
  }
2898
2965
 
2899
2966
  render(App);
@@ -2911,10 +2978,11 @@ describe('bindTextContent', () => {
2911
2978
  });
2912
2979
 
2913
2980
  it('should handle null textContent value', () => {
2914
- component App() {
2915
- const text = track(null);
2916
-
2917
- <div contenteditable="true" {ref bindTextContent(text)} />
2981
+ function App() {
2982
+ return <>
2983
+ const text = track(null);
2984
+ <div contenteditable="true" ref={bindTextContent(text)} />
2985
+ </>;
2918
2986
  }
2919
2987
 
2920
2988
  render(App);
@@ -2926,16 +2994,17 @@ describe('bindTextContent', () => {
2926
2994
  });
2927
2995
 
2928
2996
  it('should handle null textContent value with a getter and setter', () => {
2929
- component App() {
2930
- const text: RippleObject<{ value: string | null }> = new RippleObject({ value: null });
2931
-
2932
- <div
2933
- contenteditable="true"
2934
- {ref bindTextContent<string | null>(
2935
- () => text.value,
2936
- (v: string | null) => (text.value = v),
2937
- )}
2938
- />
2997
+ function App() {
2998
+ return <>
2999
+ const text: RippleObject<{ value: string | null }> = new RippleObject({ value: null });
3000
+ <div
3001
+ contenteditable="true"
3002
+ ref={bindTextContent<string | null>(
3003
+ () => text.value,
3004
+ (v: string | null) => (text.value = v),
3005
+ )}
3006
+ />
3007
+ </>;
2939
3008
  }
2940
3009
 
2941
3010
  render(App);
@@ -2951,14 +3020,14 @@ describe('bindNode', () => {
2951
3020
  it('should update tracked value with element reference', () => {
2952
3021
  let capturedNode: HTMLElement | null = null;
2953
3022
 
2954
- component App() {
2955
- const nodeRef = track(null);
2956
-
2957
- effect(() => {
2958
- capturedNode = nodeRef.value;
2959
- });
2960
-
2961
- <div {ref bindNode(nodeRef)} />
3023
+ function App() {
3024
+ return <>
3025
+ const nodeRef = track(null);
3026
+ effect(() => {
3027
+ capturedNode = nodeRef.value;
3028
+ });
3029
+ <div ref={bindNode(nodeRef)} />
3030
+ </>;
2962
3031
  }
2963
3032
 
2964
3033
  render(App);
@@ -2971,16 +3040,16 @@ describe('bindNode', () => {
2971
3040
  it('should update tracked value with element reference and with a getter and setter', () => {
2972
3041
  let capturedNode: HTMLElement | null = null;
2973
3042
 
2974
- component App() {
2975
- const nodeRef: RippleObject<{ value: HTMLElement | null }> = new RippleObject({
2976
- value: null,
2977
- });
2978
-
2979
- effect(() => {
2980
- capturedNode = nodeRef.value;
2981
- });
2982
-
2983
- <div {ref bindNode(() => nodeRef.value, (v: HTMLElement | null) => (nodeRef.value = v))} />
3043
+ function App() {
3044
+ return <>
3045
+ const nodeRef: RippleObject<{ value: HTMLElement | null }> = new RippleObject({
3046
+ value: null,
3047
+ });
3048
+ effect(() => {
3049
+ capturedNode = nodeRef.value;
3050
+ });
3051
+ <div ref={bindNode(() => nodeRef.value, (v: HTMLElement | null) => (nodeRef.value = v))} />
3052
+ </>;
2984
3053
  }
2985
3054
 
2986
3055
  render(App);
@@ -2991,21 +3060,22 @@ describe('bindNode', () => {
2991
3060
  });
2992
3061
 
2993
3062
  it('should allow access to bound element', () => {
2994
- component App() {
2995
- const inputRef = track<HTMLInputElement | null>(null);
2996
-
2997
- <div>
2998
- <input type="text" {ref bindNode(inputRef)} />
2999
- <button
3000
- onClick={() => {
3001
- if (inputRef.value) {
3002
- inputRef.value.value = 'Set by ref';
3003
- }
3004
- }}
3005
- >
3006
- {'Set Value'}
3007
- </button>
3008
- </div>
3063
+ function App() {
3064
+ return <>
3065
+ const inputRef = track<HTMLInputElement | null>(null);
3066
+ <div>
3067
+ <input type="text" ref={bindNode(inputRef)} />
3068
+ <button
3069
+ onClick={() => {
3070
+ if (inputRef.value) {
3071
+ inputRef.value.value = 'Set by ref';
3072
+ }
3073
+ }}
3074
+ >
3075
+ {'Set Value'}
3076
+ </button>
3077
+ </div>
3078
+ </>;
3009
3079
  }
3010
3080
 
3011
3081
  render(App);
@@ -3023,26 +3093,27 @@ describe('bindNode', () => {
3023
3093
  });
3024
3094
 
3025
3095
  it('should allow access to bound element with a getter and setter', () => {
3026
- component App() {
3027
- const inputRef: RippleObject<{ node: HTMLInputElement | null }> = new RippleObject({
3028
- node: null,
3029
- });
3030
-
3031
- <div>
3032
- <input
3033
- type="text"
3034
- {ref bindNode(() => inputRef.node, (v: HTMLInputElement | null) => (inputRef.node = v))}
3035
- />
3036
- <button
3037
- onClick={() => {
3038
- if (inputRef.node) {
3039
- inputRef.node.value = 'Set by ref';
3040
- }
3041
- }}
3042
- >
3043
- {'Set Value'}
3044
- </button>
3045
- </div>
3096
+ function App() {
3097
+ return <>
3098
+ const inputRef: RippleObject<{ node: HTMLInputElement | null }> = new RippleObject({
3099
+ node: null,
3100
+ });
3101
+ <div>
3102
+ <input
3103
+ type="text"
3104
+ ref={bindNode(() => inputRef.node, (v: HTMLInputElement | null) => (inputRef.node = v))}
3105
+ />
3106
+ <button
3107
+ onClick={() => {
3108
+ if (inputRef.node) {
3109
+ inputRef.node.value = 'Set by ref';
3110
+ }
3111
+ }}
3112
+ >
3113
+ {'Set Value'}
3114
+ </button>
3115
+ </div>
3116
+ </>;
3046
3117
  }
3047
3118
 
3048
3119
  render(App);
@@ -3064,15 +3135,15 @@ describe('bindFiles', () => {
3064
3135
  it('should bind files from file input', () => {
3065
3136
  const logs: FileList[] = [];
3066
3137
 
3067
- component App() {
3068
- const files = track(null);
3069
-
3070
- effect(() => {
3071
- files.value;
3072
- if (files.value) logs.push(files.value);
3073
- });
3074
-
3075
- <input type="file" multiple {ref bindFiles(files)} />
3138
+ function App() {
3139
+ return <>
3140
+ const files = track(null);
3141
+ effect(() => {
3142
+ files.value;
3143
+ if (files.value) logs.push(files.value);
3144
+ });
3145
+ <input type="file" multiple ref={bindFiles(files)} />
3146
+ </>;
3076
3147
  }
3077
3148
 
3078
3149
  render(App);
@@ -3105,19 +3176,19 @@ describe('bindFiles', () => {
3105
3176
  it('should bind files from file input with a getter and setter', () => {
3106
3177
  const logs: FileList[] = [];
3107
3178
 
3108
- component App() {
3109
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3110
-
3111
- effect(() => {
3112
- files.items;
3113
- if (files.items) logs.push(files.items);
3114
- });
3115
-
3116
- <input
3117
- type="file"
3118
- multiple
3119
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3120
- />
3179
+ function App() {
3180
+ return <>
3181
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3182
+ effect(() => {
3183
+ files.items;
3184
+ if (files.items) logs.push(files.items);
3185
+ });
3186
+ <input
3187
+ type="file"
3188
+ multiple
3189
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3190
+ />
3191
+ </>;
3121
3192
  }
3122
3193
 
3123
3194
  render(App);
@@ -3150,14 +3221,14 @@ describe('bindFiles', () => {
3150
3221
  it('should update tracked value when files are selected', () => {
3151
3222
  let capturedFiles: FileList | null = null;
3152
3223
 
3153
- component App() {
3154
- const files = track<FileList | null>(null);
3155
-
3156
- effect(() => {
3157
- capturedFiles = files.value;
3158
- });
3159
-
3160
- <input type="file" {ref bindFiles(files)} />
3224
+ function App() {
3225
+ return <>
3226
+ const files = track<FileList | null>(null);
3227
+ effect(() => {
3228
+ capturedFiles = files.value;
3229
+ });
3230
+ <input type="file" ref={bindFiles(files)} />
3231
+ </>;
3161
3232
  }
3162
3233
 
3163
3234
  render(App);
@@ -3185,17 +3256,17 @@ describe('bindFiles', () => {
3185
3256
  it('should update tracked value when files are selected with a getter and setter', () => {
3186
3257
  let capturedFiles: FileList | null = null;
3187
3258
 
3188
- component App() {
3189
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3190
-
3191
- effect(() => {
3192
- capturedFiles = files.items;
3193
- });
3194
-
3195
- <input
3196
- type="file"
3197
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3198
- />
3259
+ function App() {
3260
+ return <>
3261
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3262
+ effect(() => {
3263
+ capturedFiles = files.items;
3264
+ });
3265
+ <input
3266
+ type="file"
3267
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3268
+ />
3269
+ </>;
3199
3270
  }
3200
3271
 
3201
3272
  render(App);
@@ -3223,27 +3294,27 @@ describe('bindFiles', () => {
3223
3294
  it('should allow clearing files via input.files', () => {
3224
3295
  let capturedFiles: FileList | null = null;
3225
3296
 
3226
- component App() {
3227
- const files = track<FileList | null>(null);
3228
- const input = track<HTMLInputElement | null>(null);
3229
-
3230
- effect(() => {
3231
- capturedFiles = files.value;
3232
- });
3233
-
3234
- <div>
3235
- <input type="file" {ref bindFiles<FileList>(files)} {ref bindNode(input)} />
3236
- <button
3237
- onClick={() => {
3238
- if (input.value) {
3239
- input.value.files = new DataTransfer().files;
3240
- input.value.dispatchEvent(new Event('change', { bubbles: true }));
3241
- }
3242
- }}
3243
- >
3244
- {'Clear'}
3245
- </button>
3246
- </div>
3297
+ function App() {
3298
+ return <>
3299
+ const files = track<FileList | null>(null);
3300
+ const input = track<HTMLInputElement | null>(null);
3301
+ effect(() => {
3302
+ capturedFiles = files.value;
3303
+ });
3304
+ <div>
3305
+ <input type="file" ref={bindFiles<FileList>(files)} ref={bindNode(input)} />
3306
+ <button
3307
+ onClick={() => {
3308
+ if (input.value) {
3309
+ input.value.files = new DataTransfer().files;
3310
+ input.value.dispatchEvent(new Event('change', { bubbles: true }));
3311
+ }
3312
+ }}
3313
+ >
3314
+ {'Clear'}
3315
+ </button>
3316
+ </div>
3317
+ </>;
3247
3318
  }
3248
3319
 
3249
3320
  render(App);
@@ -3276,31 +3347,31 @@ describe('bindFiles', () => {
3276
3347
  it('should allow clearing files via input.files with a getter and setter', () => {
3277
3348
  let capturedFiles: FileList | null = null;
3278
3349
 
3279
- component App() {
3280
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3281
- const input = track<HTMLInputElement | null>(null);
3282
-
3283
- effect(() => {
3284
- capturedFiles = files.items;
3285
- });
3286
-
3287
- <div>
3288
- <input
3289
- type="file"
3290
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3291
- {ref bindNode(input)}
3292
- />
3293
- <button
3294
- onClick={() => {
3295
- if (input.value) {
3296
- input.value.files = new DataTransfer().files;
3297
- input.value.dispatchEvent(new Event('change', { bubbles: true }));
3298
- }
3299
- }}
3300
- >
3301
- {'Clear'}
3302
- </button>
3303
- </div>
3350
+ function App() {
3351
+ return <>
3352
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3353
+ const input = track<HTMLInputElement | null>(null);
3354
+ effect(() => {
3355
+ capturedFiles = files.items;
3356
+ });
3357
+ <div>
3358
+ <input
3359
+ type="file"
3360
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3361
+ ref={bindNode(input)}
3362
+ />
3363
+ <button
3364
+ onClick={() => {
3365
+ if (input.value) {
3366
+ input.value.files = new DataTransfer().files;
3367
+ input.value.dispatchEvent(new Event('change', { bubbles: true }));
3368
+ }
3369
+ }}
3370
+ >
3371
+ {'Clear'}
3372
+ </button>
3373
+ </div>
3374
+ </>;
3304
3375
  }
3305
3376
 
3306
3377
  render(App);
@@ -3333,17 +3404,17 @@ describe('bindFiles', () => {
3333
3404
  it('should handle multiple file selections', () => {
3334
3405
  const fileCounts: number[] = [];
3335
3406
 
3336
- component App() {
3337
- const files = track<FileList | null>(null);
3338
-
3339
- effect(() => {
3340
- files.value;
3341
- if (files.value) {
3342
- fileCounts.push(files.value.length);
3343
- }
3344
- });
3345
-
3346
- <input type="file" multiple {ref bindFiles(files)} />
3407
+ function App() {
3408
+ return <>
3409
+ const files = track<FileList | null>(null);
3410
+ effect(() => {
3411
+ files.value;
3412
+ if (files.value) {
3413
+ fileCounts.push(files.value.length);
3414
+ }
3415
+ });
3416
+ <input type="file" multiple ref={bindFiles(files)} />
3417
+ </>;
3347
3418
  }
3348
3419
 
3349
3420
  render(App);
@@ -3382,20 +3453,21 @@ describe('bindFiles', () => {
3382
3453
  it('should handle multiple file selections with a getter and setter', () => {
3383
3454
  const fileCounts: number[] = [];
3384
3455
 
3385
- component App() {
3386
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3387
- effect(() => {
3388
- files.items;
3389
- if (files.items) {
3390
- fileCounts.push(files.items.length);
3391
- }
3392
- });
3393
-
3394
- <input
3395
- type="file"
3396
- multiple
3397
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3398
- />
3456
+ function App() {
3457
+ return <>
3458
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3459
+ effect(() => {
3460
+ files.items;
3461
+ if (files.items) {
3462
+ fileCounts.push(files.items.length);
3463
+ }
3464
+ });
3465
+ <input
3466
+ type="file"
3467
+ multiple
3468
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3469
+ />
3470
+ </>;
3399
3471
  }
3400
3472
 
3401
3473
  render(App);
@@ -3434,17 +3506,17 @@ describe('bindFiles', () => {
3434
3506
  it('should handle file input without multiple attribute', () => {
3435
3507
  let capturedFile: File | null = null;
3436
3508
 
3437
- component App() {
3438
- const files = track<FileList | null>(null);
3439
-
3440
- effect(() => {
3441
- files.value;
3442
- if (files.value && files.value.length > 0) {
3443
- capturedFile = files.value[0];
3444
- }
3445
- });
3446
-
3447
- <input type="file" {ref bindFiles(files)} />
3509
+ function App() {
3510
+ return <>
3511
+ const files = track<FileList | null>(null);
3512
+ effect(() => {
3513
+ files.value;
3514
+ if (files.value && files.value.length > 0) {
3515
+ capturedFile = files.value[0];
3516
+ }
3517
+ });
3518
+ <input type="file" ref={bindFiles(files)} />
3519
+ </>;
3448
3520
  }
3449
3521
 
3450
3522
  render(App);
@@ -3471,19 +3543,20 @@ describe('bindFiles', () => {
3471
3543
  it('should handle file input without multiple attribute with a getter and setter', () => {
3472
3544
  let capturedFile: File | null = null;
3473
3545
 
3474
- component App() {
3475
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3476
- effect(() => {
3477
- files.items;
3478
- if (files.items && files.items.length > 0) {
3479
- capturedFile = files.items[0];
3480
- }
3481
- });
3482
-
3483
- <input
3484
- type="file"
3485
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3486
- />
3546
+ function App() {
3547
+ return <>
3548
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3549
+ effect(() => {
3550
+ files.items;
3551
+ if (files.items && files.items.length > 0) {
3552
+ capturedFile = files.items[0];
3553
+ }
3554
+ });
3555
+ <input
3556
+ type="file"
3557
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3558
+ />
3559
+ </>;
3487
3560
  }
3488
3561
 
3489
3562
  render(App);
@@ -3510,14 +3583,14 @@ describe('bindFiles', () => {
3510
3583
  it('should handle empty file selection', () => {
3511
3584
  const logs: (FileList | null)[] = [];
3512
3585
 
3513
- component App() {
3514
- const files = track(null);
3515
-
3516
- effect(() => {
3517
- logs.push(files.value);
3518
- });
3519
-
3520
- <input type="file" {ref bindFiles(files)} />
3586
+ function App() {
3587
+ return <>
3588
+ const files = track(null);
3589
+ effect(() => {
3590
+ logs.push(files.value);
3591
+ });
3592
+ <input type="file" ref={bindFiles(files)} />
3593
+ </>;
3521
3594
  }
3522
3595
 
3523
3596
  render(App);
@@ -3552,16 +3625,17 @@ describe('bindFiles', () => {
3552
3625
  it('should handle empty file selection with a getter and setter', () => {
3553
3626
  const logs: (FileList | null)[] = [];
3554
3627
 
3555
- component App() {
3556
- const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3557
- effect(() => {
3558
- logs.push(files.items);
3559
- });
3560
-
3561
- <input
3562
- type="file"
3563
- {ref bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3564
- />
3628
+ function App() {
3629
+ return <>
3630
+ const files: RippleObject<{ items: FileList | null }> = new RippleObject({ items: null });
3631
+ effect(() => {
3632
+ logs.push(files.items);
3633
+ });
3634
+ <input
3635
+ type="file"
3636
+ ref={bindFiles(() => files.items, (v: FileList | null) => (files.items = v))}
3637
+ />
3638
+ </>;
3565
3639
  }
3566
3640
 
3567
3641
  render(App);
@@ -3597,9 +3671,8 @@ describe('bindFiles', () => {
3597
3671
  describe('error handling', () => {
3598
3672
  it('should throw error when bindValue receives non-tracked object', () => {
3599
3673
  expect(() => {
3600
- component App() {
3601
- // @ts-expect-error invalid argument
3602
- <input type="text" {ref bindValue({ value: 'not tracked' })} />
3674
+ function App() {
3675
+ return <><input type="text" ref={bindValue({ value: 'not tracked' })} /></>;
3603
3676
  }
3604
3677
  render(App);
3605
3678
  }).toThrow('bindValue() argument is not a tracked object');
@@ -3607,9 +3680,8 @@ describe('error handling', () => {
3607
3680
 
3608
3681
  it('should throw error when bindChecked receives non-tracked object', () => {
3609
3682
  expect(() => {
3610
- component App() {
3611
- // @ts-expect-error invalid argument
3612
- <input type="checkbox" {ref bindChecked({ value: false })} />
3683
+ function App() {
3684
+ return <><input type="checkbox" ref={bindChecked({ value: false })} /></>;
3613
3685
  }
3614
3686
  render(App);
3615
3687
  }).toThrow('bindChecked() argument is not a tracked object');
@@ -3617,9 +3689,8 @@ describe('error handling', () => {
3617
3689
 
3618
3690
  it('should throw error when bindIndeterminate receives non-tracked object', () => {
3619
3691
  expect(() => {
3620
- component App() {
3621
- // @ts-expect-error invalid argument
3622
- <input type="checkbox" {ref bindIndeterminate({ value: false })} />
3692
+ function App() {
3693
+ return <><input type="checkbox" ref={bindIndeterminate({ value: false })} /></>;
3623
3694
  }
3624
3695
  render(App);
3625
3696
  }).toThrow('bindIndeterminate() argument is not a tracked object');
@@ -3627,9 +3698,8 @@ describe('error handling', () => {
3627
3698
 
3628
3699
  it('should throw error when bindGroup receives non-tracked object', () => {
3629
3700
  expect(() => {
3630
- component App() {
3631
- // @ts-expect-error invalid argument
3632
- <input type="checkbox" value="a" {ref bindGroup({ value: [] })} />
3701
+ function App() {
3702
+ return <><input type="checkbox" value="a" ref={bindGroup({ value: [] })} /></>;
3633
3703
  }
3634
3704
  render(App);
3635
3705
  }).toThrow('bindGroup() argument is not a tracked object');
@@ -3637,9 +3707,8 @@ describe('error handling', () => {
3637
3707
 
3638
3708
  it('should throw error when bindClientWidth receives non-tracked object', () => {
3639
3709
  expect(() => {
3640
- component App() {
3641
- // @ts-expect-error invalid argument
3642
- <div {ref bindClientWidth({ value: 0 })} />
3710
+ function App() {
3711
+ return <><div ref={bindClientWidth({ value: 0 })} /></>;
3643
3712
  }
3644
3713
  render(App);
3645
3714
  }).toThrow('bindClientWidth() argument is not a tracked object');
@@ -3647,9 +3716,8 @@ describe('error handling', () => {
3647
3716
 
3648
3717
  it('should throw error when bindClientHeight receives non-tracked object', () => {
3649
3718
  expect(() => {
3650
- component App() {
3651
- // @ts-expect-error invalid argument
3652
- <div {ref bindClientHeight({ value: 0 })} />
3719
+ function App() {
3720
+ return <><div ref={bindClientHeight({ value: 0 })} /></>;
3653
3721
  }
3654
3722
  render(App);
3655
3723
  }).toThrow('bindClientHeight() argument is not a tracked object');
@@ -3657,9 +3725,8 @@ describe('error handling', () => {
3657
3725
 
3658
3726
  it('should throw error when bindOffsetWidth receives non-tracked object', () => {
3659
3727
  expect(() => {
3660
- component App() {
3661
- // @ts-expect-error invalid argument
3662
- <div {ref bindOffsetWidth({ value: 0 })} />
3728
+ function App() {
3729
+ return <><div ref={bindOffsetWidth({ value: 0 })} /></>;
3663
3730
  }
3664
3731
  render(App);
3665
3732
  }).toThrow('bindOffsetWidth() argument is not a tracked object');
@@ -3667,9 +3734,8 @@ describe('error handling', () => {
3667
3734
 
3668
3735
  it('should throw error when bindOffsetHeight receives non-tracked object', () => {
3669
3736
  expect(() => {
3670
- component App() {
3671
- // @ts-expect-error invalid argument
3672
- <div {ref bindOffsetHeight({ value: 0 })} />
3737
+ function App() {
3738
+ return <><div ref={bindOffsetHeight({ value: 0 })} /></>;
3673
3739
  }
3674
3740
  render(App);
3675
3741
  }).toThrow('bindOffsetHeight() argument is not a tracked object');
@@ -3677,9 +3743,8 @@ describe('error handling', () => {
3677
3743
 
3678
3744
  it('should throw error when bindContentRect receives non-tracked object', () => {
3679
3745
  expect(() => {
3680
- component App() {
3681
- // @ts-expect-error invalid argument
3682
- <div {ref bindContentRect({ value: null })} />
3746
+ function App() {
3747
+ return <><div ref={bindContentRect({ value: null })} /></>;
3683
3748
  }
3684
3749
  render(App);
3685
3750
  }).toThrow('bindContentRect() argument is not a tracked object');
@@ -3687,9 +3752,8 @@ describe('error handling', () => {
3687
3752
 
3688
3753
  it('should throw error when bindContentBoxSize receives non-tracked object', () => {
3689
3754
  expect(() => {
3690
- component App() {
3691
- // @ts-expect-error invalid argument
3692
- <div {ref bindContentBoxSize({ value: null })} />
3755
+ function App() {
3756
+ return <><div ref={bindContentBoxSize({ value: null })} /></>;
3693
3757
  }
3694
3758
  render(App);
3695
3759
  }).toThrow('bindContentBoxSize() argument is not a tracked object');
@@ -3697,9 +3761,8 @@ describe('error handling', () => {
3697
3761
 
3698
3762
  it('should throw error when bindBorderBoxSize receives non-tracked object', () => {
3699
3763
  expect(() => {
3700
- component App() {
3701
- // @ts-expect-error invalid argument
3702
- <div {ref bindBorderBoxSize({ value: null })} />
3764
+ function App() {
3765
+ return <><div ref={bindBorderBoxSize({ value: null })} /></>;
3703
3766
  }
3704
3767
  render(App);
3705
3768
  }).toThrow('bindBorderBoxSize() argument is not a tracked object');
@@ -3707,9 +3770,8 @@ describe('error handling', () => {
3707
3770
 
3708
3771
  it('should throw error when bindDevicePixelContentBoxSize receives non-tracked object', () => {
3709
3772
  expect(() => {
3710
- component App() {
3711
- // @ts-expect-error invalid argument
3712
- <div {ref bindDevicePixelContentBoxSize({ value: null })} />
3773
+ function App() {
3774
+ return <><div ref={bindDevicePixelContentBoxSize({ value: null })} /></>;
3713
3775
  }
3714
3776
  render(App);
3715
3777
  }).toThrow('bindDevicePixelContentBoxSize() argument is not a tracked object');
@@ -3717,9 +3779,8 @@ describe('error handling', () => {
3717
3779
 
3718
3780
  it('should throw error when bindInnerHTML receives non-tracked object', () => {
3719
3781
  expect(() => {
3720
- component App() {
3721
- // @ts-expect-error invalid argument
3722
- <div {ref bindInnerHTML({ value: '' })} />
3782
+ function App() {
3783
+ return <><div ref={bindInnerHTML({ value: '' })} /></>;
3723
3784
  }
3724
3785
  render(App);
3725
3786
  }).toThrow('bindInnerHTML() argument is not a tracked object');
@@ -3727,9 +3788,8 @@ describe('error handling', () => {
3727
3788
 
3728
3789
  it('should throw error when bindInnerText receives non-tracked object', () => {
3729
3790
  expect(() => {
3730
- component App() {
3731
- // @ts-expect-error invalid argument
3732
- <div {ref bindInnerText({ value: '' })} />
3791
+ function App() {
3792
+ return <><div ref={bindInnerText({ value: '' })} /></>;
3733
3793
  }
3734
3794
  render(App);
3735
3795
  }).toThrow('bindInnerText() argument is not a tracked object');
@@ -3737,9 +3797,8 @@ describe('error handling', () => {
3737
3797
 
3738
3798
  it('should throw error when bindTextContent receives non-tracked object', () => {
3739
3799
  expect(() => {
3740
- component App() {
3741
- // @ts-expect-error invalid argument
3742
- <div {ref bindTextContent({ value: '' })} />
3800
+ function App() {
3801
+ return <><div ref={bindTextContent({ value: '' })} /></>;
3743
3802
  }
3744
3803
  render(App);
3745
3804
  }).toThrow('bindTextContent() argument is not a tracked object');
@@ -3747,9 +3806,8 @@ describe('error handling', () => {
3747
3806
 
3748
3807
  it('should throw error when bindNode receives non-tracked object', () => {
3749
3808
  expect(() => {
3750
- component App() {
3751
- // @ts-expect-error invalid argument
3752
- <div {ref bindNode({ value: null })} />
3809
+ function App() {
3810
+ return <><div ref={bindNode({ value: null })} /></>;
3753
3811
  }
3754
3812
  render(App);
3755
3813
  }).toThrow('bindNode() argument is not a tracked object');
@@ -3757,9 +3815,8 @@ describe('error handling', () => {
3757
3815
 
3758
3816
  it('should throw error when bindFiles receives non-tracked object', () => {
3759
3817
  expect(() => {
3760
- component App() {
3761
- // @ts-expect-error invalid argument
3762
- <input type="file" {ref bindFiles({ value: null })} />
3818
+ function App() {
3819
+ return <><input type="file" ref={bindFiles({ value: null })} /></>;
3763
3820
  }
3764
3821
  render(App);
3765
3822
  }).toThrow('bindFiles() argument is not a tracked object');
@@ -3767,9 +3824,11 @@ describe('error handling', () => {
3767
3824
 
3768
3825
  it('should throw error when bindValue receives a getter but not a setter', () => {
3769
3826
  expect(() => {
3770
- component App() {
3771
- const value = track('');
3772
- <input type="text" {ref bindValue(() => value.value)} />
3827
+ function App() {
3828
+ return <>
3829
+ const value = track('');
3830
+ <input type="text" ref={bindValue(() => value.value)} />
3831
+ </>;
3773
3832
  }
3774
3833
  render(App);
3775
3834
  }).toThrow(
@@ -3779,10 +3838,12 @@ describe('error handling', () => {
3779
3838
 
3780
3839
  it('should throw error when bindValue receives a getter and setter not a function', () => {
3781
3840
  expect(() => {
3782
- component App() {
3783
- const value = track('');
3784
- // @ts-expect-error invalid argument
3785
- <input type="text" {ref bindValue(() => value.value, 5)} />
3841
+ function App() {
3842
+ return <>
3843
+ const value = track('');
3844
+ // @ts-expect-error invalid argument
3845
+ <input type="text" ref={bindValue(() => value.value, 5)} />
3846
+ </>;
3786
3847
  }
3787
3848
  render(App);
3788
3849
  }).toThrow(
@@ -3794,13 +3855,14 @@ describe('error handling', () => {
3794
3855
  'should throw error when bindValue on select multiple receives a non-array tracked value',
3795
3856
  () => {
3796
3857
  expect(() => {
3797
- component App() {
3798
- const value = track('2');
3799
-
3800
- <select multiple {ref bindValue(value)}>
3801
- <option value="1">{'One'}</option>
3802
- <option value="2">{'Two'}</option>
3803
- </select>
3858
+ function App() {
3859
+ return <>
3860
+ const value = track('2');
3861
+ <select multiple ref={bindValue(value)}>
3862
+ <option value="1">{'One'}</option>
3863
+ <option value="2">{'Two'}</option>
3864
+ </select>
3865
+ </>;
3804
3866
  }
3805
3867
 
3806
3868
  render(App);
@@ -3815,13 +3877,14 @@ describe('error handling', () => {
3815
3877
  'should throw error when bindValue on select multiple receives a non-array getter value',
3816
3878
  () => {
3817
3879
  expect(() => {
3818
- component App() {
3819
- const value = track('2');
3820
-
3821
- <select multiple {ref bindValue(() => value.value, (v) => (value.value = v))}>
3822
- <option value="1">{'One'}</option>
3823
- <option value="2">{'Two'}</option>
3824
- </select>
3880
+ function App() {
3881
+ return <>
3882
+ const value = track('2');
3883
+ <select multiple ref={bindValue(() => value.value, (v) => (value.value = v))}>
3884
+ <option value="1">{'One'}</option>
3885
+ <option value="2">{'Two'}</option>
3886
+ </select>
3887
+ </>;
3825
3888
  }
3826
3889
 
3827
3890
  render(App);
@@ -3836,8 +3899,8 @@ describe('error handling', () => {
3836
3899
  'should throw error when bindChecked receives non-tracked object with a getter but not a setter',
3837
3900
  () => {
3838
3901
  expect(() => {
3839
- component App() {
3840
- <input type="checkbox" {ref bindChecked(() => false)} />
3902
+ function App() {
3903
+ return <><input type="checkbox" ref={bindChecked(() => false)} /></>;
3841
3904
  }
3842
3905
  render(App);
3843
3906
  }).toThrow(
@@ -3850,9 +3913,8 @@ describe('error handling', () => {
3850
3913
  'should throw error when bindChecked receives non-tracked object with a getter and setter not a function',
3851
3914
  () => {
3852
3915
  expect(() => {
3853
- component App() {
3854
- // @ts-expect-error invalid argument
3855
- <input type="checkbox" {ref bindChecked(() => false, true)} />
3916
+ function App() {
3917
+ return <><input type="checkbox" ref={bindChecked(() => false, true)} /></>;
3856
3918
  }
3857
3919
  render(App);
3858
3920
  }).toThrow(
@@ -3865,9 +3927,8 @@ describe('error handling', () => {
3865
3927
  'should throw error when bindIndeterminate receives non-tracked object with a getter and setter not a function',
3866
3928
  () => {
3867
3929
  expect(() => {
3868
- component App() {
3869
- // @ts-expect-error invalid argument
3870
- <input type="checkbox" {ref bindIndeterminate(() => false, true)} />
3930
+ function App() {
3931
+ return <><input type="checkbox" ref={bindIndeterminate(() => false, true)} /></>;
3871
3932
  }
3872
3933
  render(App);
3873
3934
  }).toThrow(
@@ -3880,9 +3941,8 @@ describe('error handling', () => {
3880
3941
  'should throw error when bindGroup receives non-tracked object with a getter and setter not a function',
3881
3942
  () => {
3882
3943
  expect(() => {
3883
- component App() {
3884
- // @ts-expect-error invalid argument
3885
- <input type="checkbox" value="a" {ref bindGroup(() => [], true)} />
3944
+ function App() {
3945
+ return <><input type="checkbox" value="a" ref={bindGroup(() => [], true)} /></>;
3886
3946
  }
3887
3947
  render(App);
3888
3948
  }).toThrow(
@@ -3895,9 +3955,8 @@ describe('error handling', () => {
3895
3955
  'should throw error when bindClientWidth receives non-tracked object with a getter and setter not a function',
3896
3956
  () => {
3897
3957
  expect(() => {
3898
- component App() {
3899
- // @ts-expect-error invalid argument
3900
- <div {ref bindClientWidth(() => 0, true)} />
3958
+ function App() {
3959
+ return <><div ref={bindClientWidth(() => 0, true)} /></>;
3901
3960
  }
3902
3961
  render(App);
3903
3962
  }).toThrow(
@@ -3910,9 +3969,8 @@ describe('error handling', () => {
3910
3969
  'should throw error when bindClientHeight receives non-tracked object with a getter and setter not a function',
3911
3970
  () => {
3912
3971
  expect(() => {
3913
- component App() {
3914
- // @ts-expect-error invalid argument
3915
- <div {ref bindClientHeight(() => 0, true)} />
3972
+ function App() {
3973
+ return <><div ref={bindClientHeight(() => 0, true)} /></>;
3916
3974
  }
3917
3975
  render(App);
3918
3976
  }).toThrow(
@@ -3925,9 +3983,8 @@ describe('error handling', () => {
3925
3983
  'should throw error when bindOffsetWidth receives non-tracked object with a getter and setter not a function',
3926
3984
  () => {
3927
3985
  expect(() => {
3928
- component App() {
3929
- // @ts-expect-error invalid argument
3930
- <div {ref bindOffsetWidth(() => 0, true)} />
3986
+ function App() {
3987
+ return <><div ref={bindOffsetWidth(() => 0, true)} /></>;
3931
3988
  }
3932
3989
  render(App);
3933
3990
  }).toThrow(
@@ -3940,9 +3997,8 @@ describe('error handling', () => {
3940
3997
  'should throw error when bindOffsetHeight receives non-tracked object with a getter and setter not a function',
3941
3998
  () => {
3942
3999
  expect(() => {
3943
- component App() {
3944
- // @ts-expect-error invalid argument
3945
- <div {ref bindOffsetHeight(() => 0, true)} />
4000
+ function App() {
4001
+ return <><div ref={bindOffsetHeight(() => 0, true)} /></>;
3946
4002
  }
3947
4003
  render(App);
3948
4004
  }).toThrow(
@@ -3955,9 +4011,8 @@ describe('error handling', () => {
3955
4011
  'should throw error when bindContentRect receives non-tracked object with a getter and setter not a function',
3956
4012
  () => {
3957
4013
  expect(() => {
3958
- component App() {
3959
- // @ts-expect-error invalid argument
3960
- <div {ref bindContentRect(() => null, true)} />
4014
+ function App() {
4015
+ return <><div ref={bindContentRect(() => null, true)} /></>;
3961
4016
  }
3962
4017
  render(App);
3963
4018
  }).toThrow(
@@ -3970,9 +4025,8 @@ describe('error handling', () => {
3970
4025
  'should throw error when bindContentBoxSize receives non-tracked object with a getter and setter not a function',
3971
4026
  () => {
3972
4027
  expect(() => {
3973
- component App() {
3974
- // @ts-expect-error invalid argument
3975
- <div {ref bindContentBoxSize(() => null, true)} />
4028
+ function App() {
4029
+ return <><div ref={bindContentBoxSize(() => null, true)} /></>;
3976
4030
  }
3977
4031
  render(App);
3978
4032
  }).toThrow(
@@ -3985,9 +4039,8 @@ describe('error handling', () => {
3985
4039
  'should throw error when bindBorderBoxSize receives non-tracked object with a getter and setter not a function',
3986
4040
  () => {
3987
4041
  expect(() => {
3988
- component App() {
3989
- // @ts-expect-error invalid argument
3990
- <div {ref bindBorderBoxSize(() => null, true)} />
4042
+ function App() {
4043
+ return <><div ref={bindBorderBoxSize(() => null, true)} /></>;
3991
4044
  }
3992
4045
  render(App);
3993
4046
  }).toThrow(
@@ -4000,9 +4053,8 @@ describe('error handling', () => {
4000
4053
  'should throw error when bindDevicePixelContentBoxSize receives non-tracked object with a getter and setter not a function',
4001
4054
  () => {
4002
4055
  expect(() => {
4003
- component App() {
4004
- // @ts-expect-error invalid argument
4005
- <div {ref bindDevicePixelContentBoxSize(() => null, true)} />
4056
+ function App() {
4057
+ return <><div ref={bindDevicePixelContentBoxSize(() => null, true)} /></>;
4006
4058
  }
4007
4059
  render(App);
4008
4060
  }).toThrow(
@@ -4015,9 +4067,8 @@ describe('error handling', () => {
4015
4067
  'should throw error when bindInnerHTML receives non-tracked object with a getter and setter not a function',
4016
4068
  () => {
4017
4069
  expect(() => {
4018
- component App() {
4019
- // @ts-expect-error invalid argument
4020
- <div {ref bindInnerHTML(() => '', true)} />
4070
+ function App() {
4071
+ return <><div ref={bindInnerHTML(() => '', true)} /></>;
4021
4072
  }
4022
4073
  render(App);
4023
4074
  }).toThrow(
@@ -4030,9 +4081,8 @@ describe('error handling', () => {
4030
4081
  'should throw error when bindInnerText receives non-tracked object with a getter and setter not a function',
4031
4082
  () => {
4032
4083
  expect(() => {
4033
- component App() {
4034
- // @ts-expect-error invalid argument
4035
- <div {ref bindInnerText(() => '', true)} />
4084
+ function App() {
4085
+ return <><div ref={bindInnerText(() => '', true)} /></>;
4036
4086
  }
4037
4087
  render(App);
4038
4088
  }).toThrow(
@@ -4045,9 +4095,8 @@ describe('error handling', () => {
4045
4095
  'should throw error when bindTextContent receives non-tracked object with a getter and setter not a function',
4046
4096
  () => {
4047
4097
  expect(() => {
4048
- component App() {
4049
- // @ts-expect-error invalid argument
4050
- <div {ref bindTextContent(() => '', true)} />
4098
+ function App() {
4099
+ return <><div ref={bindTextContent(() => '', true)} /></>;
4051
4100
  }
4052
4101
  render(App);
4053
4102
  }).toThrow(
@@ -4060,9 +4109,8 @@ describe('error handling', () => {
4060
4109
  'should throw error when bindNode receives non-tracked object with a getter and setter not a function',
4061
4110
  () => {
4062
4111
  expect(() => {
4063
- component App() {
4064
- // @ts-expect-error invalid argument
4065
- <div {ref bindNode(() => null, true)} />
4112
+ function App() {
4113
+ return <><div ref={bindNode(() => null, true)} /></>;
4066
4114
  }
4067
4115
  render(App);
4068
4116
  }).toThrow(
@@ -4075,9 +4123,8 @@ describe('error handling', () => {
4075
4123
  'should throw error when bindFiles receives non-tracked object with a getter and setter not a function',
4076
4124
  () => {
4077
4125
  expect(() => {
4078
- component App() {
4079
- // @ts-expect-error invalid argument
4080
- <input type="file" {ref bindFiles(() => null, true)} />
4126
+ function App() {
4127
+ return <><input type="file" ref={bindFiles(() => null, true)} /></>;
4081
4128
  }
4082
4129
  render(App);
4083
4130
  }).toThrow(