ripple 0.3.72 → 0.3.74

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 (165) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +2 -8
  4. package/src/runtime/index-client.js +3 -13
  5. package/src/runtime/internal/client/blocks.js +3 -25
  6. package/src/runtime/internal/client/for.js +80 -5
  7. package/src/runtime/internal/client/index.js +0 -2
  8. package/src/runtime/internal/client/types.d.ts +0 -10
  9. package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
  10. package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
  11. package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
  12. package/tests/client/array/array.copy-within.test.tsrx +19 -19
  13. package/tests/client/array/array.derived.test.tsrx +97 -109
  14. package/tests/client/array/array.iteration.test.tsrx +28 -28
  15. package/tests/client/array/array.mutations.test.tsrx +68 -68
  16. package/tests/client/array/array.static.test.tsrx +82 -92
  17. package/tests/client/array/array.to-methods.test.tsrx +15 -15
  18. package/tests/client/async-suspend.test.tsrx +180 -179
  19. package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
  20. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
  21. package/tests/client/basic/basic.attributes.test.tsrx +273 -317
  22. package/tests/client/basic/basic.collections.test.tsrx +55 -61
  23. package/tests/client/basic/basic.components.test.tsrx +196 -218
  24. package/tests/client/basic/basic.errors.test.tsrx +70 -76
  25. package/tests/client/basic/basic.events.test.tsrx +80 -85
  26. package/tests/client/basic/basic.get-set.test.tsrx +54 -64
  27. package/tests/client/basic/basic.hmr.test.tsrx +15 -19
  28. package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
  29. package/tests/client/basic/basic.rendering.test.tsrx +273 -178
  30. package/tests/client/basic/basic.utilities.test.tsrx +8 -10
  31. package/tests/client/boundaries.test.tsrx +18 -18
  32. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
  33. package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
  34. package/tests/client/compiler/compiler.basic.test.tsrx +357 -288
  35. package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
  36. package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
  37. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  38. package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
  39. package/tests/client/composite/composite.dynamic-components.test.tsrx +41 -44
  40. package/tests/client/composite/composite.generics.test.tsrx +165 -167
  41. package/tests/client/composite/composite.props.test.tsrx +66 -74
  42. package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
  43. package/tests/client/composite/composite.render.test.tsrx +92 -101
  44. package/tests/client/computed-properties.test.tsrx +14 -18
  45. package/tests/client/context.test.tsrx +14 -18
  46. package/tests/client/css/global-additional-cases.test.tsrx +491 -437
  47. package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
  48. package/tests/client/css/global-at-rules.test.tsrx +71 -66
  49. package/tests/client/css/global-basic.test.tsrx +105 -98
  50. package/tests/client/css/global-classes-ids.test.tsrx +128 -114
  51. package/tests/client/css/global-combinators.test.tsrx +83 -78
  52. package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
  53. package/tests/client/css/global-edge-cases.test.tsrx +138 -120
  54. package/tests/client/css/global-keyframes.test.tsrx +108 -96
  55. package/tests/client/css/global-nested.test.tsrx +88 -78
  56. package/tests/client/css/global-pseudo.test.tsrx +104 -98
  57. package/tests/client/css/global-scoping.test.tsrx +145 -125
  58. package/tests/client/css/style-identifier.test.tsrx +62 -69
  59. package/tests/client/date.test.tsrx +83 -83
  60. package/tests/client/dynamic-elements.test.tsrx +227 -283
  61. package/tests/client/events.test.tsrx +252 -266
  62. package/tests/client/for.test.tsrx +120 -127
  63. package/tests/client/head.test.tsrx +40 -48
  64. package/tests/client/html.test.tsrx +37 -49
  65. package/tests/client/input-value.test.tsrx +1125 -1354
  66. package/tests/client/lazy-array.test.tsrx +10 -16
  67. package/tests/client/lazy-destructuring.test.tsrx +169 -221
  68. package/tests/client/map.test.tsrx +39 -41
  69. package/tests/client/media-query.test.tsrx +15 -19
  70. package/tests/client/object.test.tsrx +46 -56
  71. package/tests/client/portal.test.tsrx +31 -37
  72. package/tests/client/ref.test.tsrx +173 -193
  73. package/tests/client/return.test.tsrx +62 -37
  74. package/tests/client/set.test.tsrx +33 -33
  75. package/tests/client/svg.test.tsrx +195 -215
  76. package/tests/client/switch.test.tsrx +201 -191
  77. package/tests/client/track-async-hydration.test.tsrx +14 -18
  78. package/tests/client/tracked-index-access.test.tsrx +18 -28
  79. package/tests/client/try.test.tsrx +494 -619
  80. package/tests/client/tsx.test.tsrx +286 -292
  81. package/tests/client/typescript-generics.test.tsrx +121 -129
  82. package/tests/client/url/url.derived.test.tsrx +21 -25
  83. package/tests/client/url/url.parsing.test.tsrx +35 -35
  84. package/tests/client/url/url.partial-removal.test.tsrx +32 -32
  85. package/tests/client/url/url.reactivity.test.tsrx +68 -72
  86. package/tests/client/url/url.serialization.test.tsrx +8 -8
  87. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
  88. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
  89. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
  90. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
  91. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
  92. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
  93. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
  94. package/tests/hydration/compiled/client/basic.js +390 -319
  95. package/tests/hydration/compiled/client/composite.js +52 -44
  96. package/tests/hydration/compiled/client/for.js +734 -604
  97. package/tests/hydration/compiled/client/head.js +183 -103
  98. package/tests/hydration/compiled/client/html.js +93 -86
  99. package/tests/hydration/compiled/client/if-children.js +95 -71
  100. package/tests/hydration/compiled/client/if.js +113 -89
  101. package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
  102. package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
  103. package/tests/hydration/compiled/client/reactivity.js +26 -24
  104. package/tests/hydration/compiled/client/return.js +8 -42
  105. package/tests/hydration/compiled/client/switch.js +208 -173
  106. package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
  107. package/tests/hydration/compiled/client/try.js +29 -21
  108. package/tests/hydration/compiled/server/basic.js +210 -221
  109. package/tests/hydration/compiled/server/composite.js +13 -14
  110. package/tests/hydration/compiled/server/for.js +427 -444
  111. package/tests/hydration/compiled/server/head.js +199 -189
  112. package/tests/hydration/compiled/server/html.js +33 -41
  113. package/tests/hydration/compiled/server/if-children.js +114 -117
  114. package/tests/hydration/compiled/server/if.js +77 -83
  115. package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
  116. package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
  117. package/tests/hydration/compiled/server/reactivity.js +24 -22
  118. package/tests/hydration/compiled/server/return.js +6 -18
  119. package/tests/hydration/compiled/server/switch.js +179 -176
  120. package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
  121. package/tests/hydration/compiled/server/try.js +31 -35
  122. package/tests/hydration/components/basic.tsrx +216 -258
  123. package/tests/hydration/components/composite.tsrx +32 -42
  124. package/tests/hydration/components/events.tsrx +81 -101
  125. package/tests/hydration/components/for.tsrx +270 -336
  126. package/tests/hydration/components/head.tsrx +43 -39
  127. package/tests/hydration/components/hmr.tsrx +16 -22
  128. package/tests/hydration/components/html-in-template.tsrx +15 -21
  129. package/tests/hydration/components/html.tsrx +442 -526
  130. package/tests/hydration/components/if-children.tsrx +107 -125
  131. package/tests/hydration/components/if.tsrx +68 -90
  132. package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
  133. package/tests/hydration/components/nested-control-flow.tsrx +202 -216
  134. package/tests/hydration/components/portal.tsrx +33 -41
  135. package/tests/hydration/components/reactivity.tsrx +26 -34
  136. package/tests/hydration/components/return.tsrx +4 -6
  137. package/tests/hydration/components/switch.tsrx +73 -78
  138. package/tests/hydration/components/track-async-serialization.tsrx +83 -93
  139. package/tests/hydration/components/try.tsrx +37 -51
  140. package/tests/hydration/switch.test.js +8 -8
  141. package/tests/server/await.test.tsrx +3 -3
  142. package/tests/server/basic.attributes.test.tsrx +117 -162
  143. package/tests/server/basic.components.test.tsrx +163 -193
  144. package/tests/server/basic.test.tsrx +298 -198
  145. package/tests/server/compiler.test.tsrx +142 -72
  146. package/tests/server/composite.props.test.tsrx +54 -58
  147. package/tests/server/composite.test.tsrx +165 -167
  148. package/tests/server/context.test.tsrx +13 -17
  149. package/tests/server/dynamic-elements.test.tsrx +103 -135
  150. package/tests/server/for.test.tsrx +115 -84
  151. package/tests/server/head.test.tsrx +31 -31
  152. package/tests/server/html-nesting-validation.test.tsrx +16 -8
  153. package/tests/server/if.test.tsrx +49 -59
  154. package/tests/server/lazy-destructuring.test.tsrx +288 -366
  155. package/tests/server/return.test.tsrx +58 -36
  156. package/tests/server/streaming-ssr.test.tsrx +4 -4
  157. package/tests/server/style-identifier.test.tsrx +58 -66
  158. package/tests/server/switch.test.tsrx +89 -97
  159. package/tests/server/track-async-serialization.test.tsrx +85 -103
  160. package/tests/server/try.test.tsrx +275 -360
  161. package/tests/utils/ref-types.test.js +72 -0
  162. package/tests/utils/vite-plugin-config.test.js +41 -74
  163. package/types/index.d.ts +1 -0
  164. package/src/runtime/internal/client/compat.js +0 -40
  165. package/tests/utils/compiler-compat-config.test.js +0 -38
@@ -3,11 +3,9 @@ import { createRefKey, effect, flushSync, track } from 'ripple';
3
3
 
4
4
  describe('dynamic DOM elements', () => {
5
5
  it('renders static dynamic element', () => {
6
- function App() {
7
- return <>
8
- let tag = track('div');
9
- <@tag>{'Hello World'}</@tag>
10
- </>;
6
+ function App() @{
7
+ let tag = track('div');
8
+ <@tag>{'Hello World'}</@tag>
11
9
  }
12
10
  render(App);
13
11
 
@@ -19,11 +17,9 @@ describe('dynamic DOM elements', () => {
19
17
  // The ts errors below are due to limitations in our current tsx generation for dynamic elements.
20
18
  // They can be ignored for now. But we'll fix them via jsx() vs <jsx>
21
19
  it('renders static dynamic element from a plain object with a tracked property', () => {
22
- function App() {
23
- return <>
24
- let obj = { tag: track('div') };
25
- <obj.tag.value>{'Hello World'}</obj.tag.value>
26
- </>;
20
+ function App() @{
21
+ let obj = { tag: track('div') };
22
+ <obj.tag.value>{'Hello World'}</obj.tag.value>
27
23
  }
28
24
  render(App);
29
25
 
@@ -33,12 +29,10 @@ describe('dynamic DOM elements', () => {
33
29
  });
34
30
 
35
31
  it('renders static dynamic element from a tracked object with a tracked property', () => {
36
- function App() {
37
- return <>
38
- let obj = track({ tag: track('div') });
39
- let tag = obj.value.tag;
40
- <@tag>{'Hello World'}</@tag>
41
- </>;
32
+ function App() @{
33
+ let obj = track({ tag: track('div') });
34
+ let tag = obj.value.tag;
35
+ <@tag>{'Hello World'}</@tag>
42
36
  }
43
37
  render(App);
44
38
 
@@ -50,12 +44,10 @@ describe('dynamic DOM elements', () => {
50
44
  it(
51
45
  'renders static dynamic element from a tracked object with a computed tracked property',
52
46
  () => {
53
- function App() {
54
- return <>
55
- let obj = track({ tag: track('div') });
56
- let tag = obj.value['tag'];
57
- <@tag>{'Hello World'}</@tag>
58
- </>;
47
+ function App() @{
48
+ let obj = track({ tag: track('div') });
49
+ let tag = obj.value['tag'];
50
+ <@tag>{'Hello World'}</@tag>
59
51
  }
60
52
  render(App);
61
53
 
@@ -66,18 +58,16 @@ describe('dynamic DOM elements', () => {
66
58
  );
67
59
 
68
60
  it('renders reactive dynamic element', () => {
69
- function App() {
70
- return <>
71
- let &[tag] = track('div');
61
+ function App() @{
62
+ let &[tag] = track('div');
63
+ <>
72
64
  <button
73
65
  onClick={() => {
74
66
  tag = 'span';
75
67
  }}
76
- >
77
- {'Change Tag'}
78
- </button>
68
+ >{'Change Tag'}</button>
79
69
  <@tag id="dynamic">{'Hello World'}</@tag>
80
- </>;
70
+ </>
81
71
  }
82
72
  render(App);
83
73
 
@@ -98,11 +88,9 @@ describe('dynamic DOM elements', () => {
98
88
  });
99
89
 
100
90
  it('renders self-closing dynamic element', () => {
101
- function App() {
102
- return <>
103
- let tag = track('input');
104
- <@tag type="text" value="test" />
105
- </>;
91
+ function App() @{
92
+ let tag = track('input');
93
+ <@tag type="text" value="test" />
106
94
  }
107
95
  render(App);
108
96
 
@@ -113,12 +101,10 @@ describe('dynamic DOM elements', () => {
113
101
  });
114
102
 
115
103
  it('handles dynamic element with attributes', () => {
116
- function App() {
117
- return <>
118
- let tag = track('div');
119
- let &[className] = track('test-class');
120
- <@tag class={className} id="test" data-testid="dynamic-element">{'Content'}</@tag>
121
- </>;
104
+ function App() @{
105
+ let tag = track('div');
106
+ let &[className] = track('test-class');
107
+ <@tag class={className} id="test" data-testid="dynamic-element">{'Content'}</@tag>
122
108
  }
123
109
  render(App);
124
110
 
@@ -130,14 +116,12 @@ describe('dynamic DOM elements', () => {
130
116
  });
131
117
 
132
118
  it('handles nested dynamic elements', () => {
133
- function App() {
134
- return <>
135
- let outerTag = track('div');
136
- let innerTag = track('span');
137
- <@outerTag class="outer">
138
- <@innerTag class="inner">{'Nested content'}</@innerTag>
139
- </@outerTag>
140
- </>;
119
+ function App() @{
120
+ let outerTag = track('div');
121
+ let innerTag = track('span');
122
+ <@outerTag class="outer">
123
+ <@innerTag class="inner">{'Nested content'}</@innerTag>
124
+ </@outerTag>
141
125
  }
142
126
  render(App);
143
127
 
@@ -151,14 +135,10 @@ describe('dynamic DOM elements', () => {
151
135
  });
152
136
 
153
137
  it('handles dynamic element with class object', () => {
154
- function App() {
155
- return <>
156
- let tag = track('div');
157
- let &[active] = track(true);
158
- <@tag class={{ active: active, 'dynamic-element': true }}>
159
- {'Element with class object'}
160
- </@tag>
161
- </>;
138
+ function App() @{
139
+ let tag = track('div');
140
+ let &[active] = track(true);
141
+ <@tag class={{ active: active, 'dynamic-element': true }}>{'Element with class object'}</@tag>
162
142
  }
163
143
  render(App);
164
144
 
@@ -169,19 +149,15 @@ describe('dynamic DOM elements', () => {
169
149
  });
170
150
 
171
151
  it('handles dynamic element with style object', () => {
172
- function App() {
173
- return <>
174
- let tag = track('span');
175
- <@tag
176
- style={{
177
- color: 'red',
178
- fontSize: '16px',
179
- fontWeight: 'bold',
180
- }}
181
- >
182
- {'Styled dynamic element'}
183
- </@tag>
184
- </>;
152
+ function App() @{
153
+ let tag = track('span');
154
+ <@tag
155
+ style={{
156
+ color: 'red',
157
+ fontSize: '16px',
158
+ fontWeight: 'bold',
159
+ }}
160
+ >{'Styled dynamic element'}</@tag>
185
161
  }
186
162
  render(App);
187
163
 
@@ -193,16 +169,14 @@ describe('dynamic DOM elements', () => {
193
169
  });
194
170
 
195
171
  it('handles dynamic element with spread attributes', () => {
196
- function App() {
197
- return <>
198
- let tag = track('section');
199
- const attrs = {
200
- id: 'spread-section',
201
- 'data-testid': 'spread-test',
202
- class: 'spread-class',
203
- };
204
- <@tag {...attrs} data-extra="additional">{'Element with spread attributes'}</@tag>
205
- </>;
172
+ function App() @{
173
+ let tag = track('section');
174
+ const attrs = {
175
+ id: 'spread-section',
176
+ 'data-testid': 'spread-test',
177
+ class: 'spread-class',
178
+ };
179
+ <@tag {...attrs} data-extra="additional">{'Element with spread attributes'}</@tag>
206
180
  }
207
181
  render(App);
208
182
 
@@ -217,18 +191,14 @@ describe('dynamic DOM elements', () => {
217
191
  it('handles dynamic element with ref', () => {
218
192
  let capturedElement: HTMLElement | null = null;
219
193
 
220
- function App() {
221
- return <>
222
- let tag = track('article');
223
- <@tag
224
- ref={(node: HTMLElement) => {
225
- capturedElement = node;
226
- }}
227
- id="ref-test"
228
- >
229
- {'Element with ref'}
230
- </@tag>
231
- </>;
194
+ function App() @{
195
+ let tag = track('article');
196
+ <@tag
197
+ ref={(node: HTMLElement) => {
198
+ capturedElement = node;
199
+ }}
200
+ id="ref-test"
201
+ >{'Element with ref'}</@tag>
232
202
  }
233
203
  render(App);
234
204
  flushSync();
@@ -244,27 +214,25 @@ describe('dynamic DOM elements', () => {
244
214
  let anonymousRefElement: HTMLInputElement | null = null;
245
215
  let namedRefElement: HTMLInputElement | null = null;
246
216
 
247
- function App() {
248
- return <>
249
- let tag = track('input');
250
- let input: HTMLInputElement | undefined;
251
- const state: { anonymous?: HTMLInputElement } = {};
252
- <@tag
253
- id="dynamic-ref-combo"
254
- type="text"
255
- ref={[
256
- input,
257
- state.anonymous,
258
- (node: HTMLInputElement | null) => {
259
- namedRefElement = node;
260
- },
261
- ]}
262
- />
263
- effect(() => {
264
- refAttrElement = input ?? null;
265
- anonymousRefElement = state.anonymous ?? null;
266
- });
267
- </>;
217
+ function App() @{
218
+ let tag = track('input');
219
+ let input: HTMLInputElement | undefined;
220
+ const state: { anonymous?: HTMLInputElement } = {};
221
+ effect(() => {
222
+ refAttrElement = input ?? null;
223
+ anonymousRefElement = state.anonymous ?? null;
224
+ });
225
+ <@tag
226
+ id="dynamic-ref-combo"
227
+ type="text"
228
+ ref={[
229
+ input,
230
+ state.anonymous,
231
+ (node: HTMLInputElement | null) => {
232
+ namedRefElement = node;
233
+ },
234
+ ]}
235
+ />
268
236
  }
269
237
 
270
238
  render(App);
@@ -284,29 +252,27 @@ describe('dynamic DOM elements', () => {
284
252
  let anonymousRefElement: HTMLInputElement | null = null;
285
253
  let namedRefElement: HTMLInputElement | null = null;
286
254
 
287
- function Child(props: PropsWithExtras<{}>) {
288
- return <><input id="dynamic-component-ref-combo" type="text" {...props} /></>;
289
- }
290
-
291
- function App() {
292
- return <>
293
- let dynamic = track(() => Child);
294
- let input: HTMLInputElement | undefined;
295
- const state: { anonymous?: HTMLInputElement } = {};
296
- <@dynamic
297
- ref={[
298
- input,
299
- state.anonymous,
300
- (node: HTMLInputElement | null) => {
301
- namedRefElement = node;
302
- },
303
- ]}
304
- />
305
- effect(() => {
306
- refAttrElement = input ?? null;
307
- anonymousRefElement = state.anonymous ?? null;
308
- });
309
- </>;
255
+ function Child(props: PropsWithExtras<{}>) @{
256
+ <input id="dynamic-component-ref-combo" type="text" {...props} />
257
+ }
258
+
259
+ function App() @{
260
+ let dynamic = track(() => Child);
261
+ let input: HTMLInputElement | undefined;
262
+ const state: { anonymous?: HTMLInputElement } = {};
263
+ effect(() => {
264
+ refAttrElement = input ?? null;
265
+ anonymousRefElement = state.anonymous ?? null;
266
+ });
267
+ <@dynamic
268
+ ref={[
269
+ input,
270
+ state.anonymous,
271
+ (node: HTMLInputElement | null) => {
272
+ namedRefElement = node;
273
+ },
274
+ ]}
275
+ />
310
276
  }
311
277
 
312
278
  render(App);
@@ -322,21 +288,19 @@ describe('dynamic DOM elements', () => {
322
288
  });
323
289
 
324
290
  it('handles dynamic element with createRefKey in spread', () => {
325
- function App() {
326
- return <>
327
- let tag = track('header');
328
- function elementRef(node: HTMLElement) {
329
- // Set an attribute on the element to prove ref was called
330
- node.setAttribute('data-spread-ref-called', 'true');
331
- node.setAttribute('data-spread-ref-tag', node.tagName.toLowerCase());
332
- }
333
- const dynamicProps = {
334
- id: 'spread-ref-test',
335
- class: 'ref-element',
336
- [createRefKey()]: elementRef,
337
- };
338
- <@tag {...dynamicProps}>{'Element with spread ref'}</@tag>
339
- </>;
291
+ function App() @{
292
+ let tag = track('header');
293
+ function elementRef(node: HTMLElement) {
294
+ // Set an attribute on the element to prove ref was called
295
+ node.setAttribute('data-spread-ref-called', 'true');
296
+ node.setAttribute('data-spread-ref-tag', node.tagName.toLowerCase());
297
+ }
298
+ const dynamicProps = {
299
+ id: 'spread-ref-test',
300
+ class: 'ref-element',
301
+ [createRefKey()]: elementRef,
302
+ };
303
+ <@tag {...dynamicProps}>{'Element with spread ref'}</@tag>
340
304
  }
341
305
  render(App);
342
306
  flushSync();
@@ -351,17 +315,15 @@ describe('dynamic DOM elements', () => {
351
315
  });
352
316
 
353
317
  it('has reactive attributes on dynamic elements', () => {
354
- function App() {
355
- return <>
356
- let tag = track('div');
357
- let &[count] = track(0);
318
+ function App() @{
319
+ let tag = track('div');
320
+ let &[count] = track(0);
321
+ <>
358
322
  <button
359
323
  onClick={() => {
360
324
  count++;
361
325
  }}
362
- >
363
- {'Increment'}
364
- </button>
326
+ >{'Increment'}</button>
365
327
  <@tag
366
328
  id={count % 2 ? 'even' : 'odd'}
367
329
  class={count % 2 ? 'even-class' : 'odd-class'}
@@ -370,7 +332,7 @@ describe('dynamic DOM elements', () => {
370
332
  {'Count: '}
371
333
  {count}
372
334
  </@tag>
373
- </>;
335
+ </>
374
336
  }
375
337
 
376
338
  render(App);
@@ -406,16 +368,16 @@ describe('dynamic DOM elements', () => {
406
368
  });
407
369
 
408
370
  it('applies scoped CSS to dynamic elements', () => {
409
- function App() {
410
- return <>
411
- let tag = track('div');
371
+ function App() @{
372
+ let tag = track('div');
373
+ <>
412
374
  <@tag class="test-class">{'Dynamic element'}</@tag>
413
375
  <style>
414
376
  .test-class {
415
377
  color: red;
416
378
  }
417
379
  </style>
418
- </>;
380
+ </>
419
381
  }
420
382
 
421
383
  render(App);
@@ -431,10 +393,10 @@ describe('dynamic DOM elements', () => {
431
393
  });
432
394
 
433
395
  it('applies scoped CSS to dynamic elements with reactive classes', () => {
434
- function App() {
435
- return <>
436
- let tag = track('button');
437
- let &[count] = track(0);
396
+ function App() @{
397
+ let tag = track('button');
398
+ let &[count] = track(0);
399
+ <>
438
400
  <@tag
439
401
  class={count % 2 ? 'even' : 'odd'}
440
402
  id={count % 2 ? 'even' : 'odd'}
@@ -455,7 +417,7 @@ describe('dynamic DOM elements', () => {
455
417
  color: white;
456
418
  }
457
419
  </style>
458
- </>;
420
+ </>
459
421
  }
460
422
 
461
423
  render(App);
@@ -505,9 +467,9 @@ describe('dynamic DOM elements', () => {
505
467
  class: string;
506
468
  id: string;
507
469
  onClick: EventListener;
508
- }>) {
509
- return <>
510
- const tag = track('button');
470
+ }>) @{
471
+ const tag = track('button');
472
+ <>
511
473
  <@tag {...rest}>{rest.class}</@tag>
512
474
  <style>
513
475
  .even {
@@ -517,20 +479,18 @@ describe('dynamic DOM elements', () => {
517
479
  background-color: red;
518
480
  }
519
481
  </style>
520
- </>;
482
+ </>
521
483
  }
522
484
 
523
- function App() {
524
- return <>
525
- let &[count] = track(0);
526
- <DynamicButton
527
- class={count % 2 ? 'even' : 'odd'}
528
- id={count % 2 ? 'even' : 'odd'}
529
- onClick={() => {
530
- count++;
531
- }}
532
- />
533
- </>;
485
+ function App() @{
486
+ let &[count] = track(0);
487
+ <DynamicButton
488
+ class={count % 2 ? 'even' : 'odd'}
489
+ id={count % 2 ? 'even' : 'odd'}
490
+ onClick={() => {
491
+ count++;
492
+ }}
493
+ />
534
494
  }
535
495
 
536
496
  render(App);
@@ -565,9 +525,9 @@ describe('dynamic DOM elements', () => {
565
525
  });
566
526
 
567
527
  it('adds scoping class to dynamic elements', () => {
568
- function App() {
569
- return <>
570
- let tag = track('div');
528
+ function App() @{
529
+ let tag = track('div');
530
+ <>
571
531
  <@tag class="scoped">
572
532
  <p>{'Scoped dynamic element'}</p>
573
533
  </@tag>
@@ -576,7 +536,7 @@ describe('dynamic DOM elements', () => {
576
536
  color: blue;
577
537
  }
578
538
  </style>
579
- </>;
539
+ </>
580
540
  }
581
541
  render(App);
582
542
 
@@ -588,9 +548,9 @@ describe('dynamic DOM elements', () => {
588
548
  });
589
549
 
590
550
  it('adds scoping class to dynamic elements when selector targets by tag name', () => {
591
- function App() {
592
- return <>
593
- let tag = track('div');
551
+ function App() @{
552
+ let tag = track('div');
553
+ <>
594
554
  <@tag class="scoped">
595
555
  <p>{'Scoped dynamic element'}</p>
596
556
  </@tag>
@@ -599,7 +559,7 @@ describe('dynamic DOM elements', () => {
599
559
  color: blue;
600
560
  }
601
561
  </style>
602
- </>;
562
+ </>
603
563
  }
604
564
  render(App);
605
565
 
@@ -611,8 +571,8 @@ describe('dynamic DOM elements', () => {
611
571
  });
612
572
 
613
573
  it('doesn\'t add scoping class to components inside dynamic element', () => {
614
- function Child() {
615
- return <>
574
+ function Child() @{
575
+ <>
616
576
  <div class="child">
617
577
  <p>{'I am a child component'}</p>
618
578
  </div>
@@ -621,12 +581,12 @@ describe('dynamic DOM elements', () => {
621
581
  color: blue;
622
582
  }
623
583
  </style>
624
- </>;
584
+ </>
625
585
  }
626
586
 
627
- function App() {
628
- return <>
629
- let tag = track('div');
587
+ function App() @{
588
+ let tag = track('div');
589
+ <>
630
590
  <@tag class="scoped">
631
591
  <p>{'Scoped dynamic element'}</p>
632
592
  <Child />
@@ -636,7 +596,7 @@ describe('dynamic DOM elements', () => {
636
596
  color: blue;
637
597
  }
638
598
  </style>
639
- </>;
599
+ </>
640
600
  }
641
601
  render(App);
642
602
 
@@ -657,8 +617,8 @@ describe('dynamic DOM elements', () => {
657
617
  });
658
618
 
659
619
  it('doesn\'t add scoping class to dynamically rendered component', () => {
660
- function Child() {
661
- return <>
620
+ function Child() @{
621
+ <>
662
622
  <div class="child">
663
623
  <p>{'I am a child component'}</p>
664
624
  </div>
@@ -667,19 +627,19 @@ describe('dynamic DOM elements', () => {
667
627
  color: green;
668
628
  }
669
629
  </style>
670
- </>;
630
+ </>
671
631
  }
672
632
 
673
- function App() {
674
- return <>
675
- let tag = track(() => Child);
633
+ function App() @{
634
+ let tag = track(() => Child);
635
+ <>
676
636
  <@tag />
677
637
  <style>
678
638
  .child {
679
639
  color: red;
680
640
  }
681
641
  </style>
682
- </>;
642
+ </>
683
643
  }
684
644
  render(App);
685
645
 
@@ -697,29 +657,23 @@ describe('dynamic DOM elements', () => {
697
657
  let capturedElement: HTMLElement | null = null;
698
658
  let refCallCount = 0;
699
659
 
700
- function Button(props: any) {
701
- return <>
702
- const el = track('button');
703
- <@el {...props} />
704
- </>;
660
+ function Button(props: any) @{
661
+ const el = track('button');
662
+ <@el {...props} />
705
663
  }
706
664
 
707
- function App() {
708
- return <>
709
- let &[active] = track(false);
710
- <Button
711
- data-active={String(active)}
712
- onClick={() => {
713
- active = !active;
714
- }}
715
- ref={(el: HTMLElement) => {
716
- capturedElement = el;
717
- refCallCount++;
718
- }}
719
- >
720
- {'content'}
721
- </Button>
722
- </>;
665
+ function App() @{
666
+ let &[active] = track(false);
667
+ <Button
668
+ data-active={String(active)}
669
+ onClick={() => {
670
+ active = !active;
671
+ }}
672
+ ref={(el: HTMLElement) => {
673
+ capturedElement = el;
674
+ refCallCount++;
675
+ }}
676
+ >{'content'}</Button>
723
677
  }
724
678
 
725
679
  render(App);
@@ -743,34 +697,30 @@ describe('dynamic DOM elements', () => {
743
697
  it('handles ref on dynamic element with spread props containing reactive values', () => {
744
698
  let capturedElement: HTMLElement | null = null;
745
699
 
746
- function Button(props: any) {
747
- return <>
748
- const el = track('button');
749
- <@el {...props} />
750
- </>;
751
- }
752
-
753
- function App() {
754
- return <>
755
- let &[active] = track(false);
756
- let &[buttonProps] = track(
757
- () => ({
758
- 'data-active': active,
759
- }),
760
- );
761
- <Button
762
- {...buttonProps}
763
- onClick={() => {
764
- active = !active;
765
- }}
766
- ref={(el: HTMLElement) => {
767
- capturedElement = el;
768
- }}
769
- >
770
- {'content: '}
771
- {active}
772
- </Button>
773
- </>;
700
+ function Button(props: any) @{
701
+ const el = track('button');
702
+ <@el {...props} />
703
+ }
704
+
705
+ function App() @{
706
+ let &[active] = track(false);
707
+ let &[buttonProps] = track(
708
+ () => ({
709
+ 'data-active': active,
710
+ }),
711
+ );
712
+ <Button
713
+ {...buttonProps}
714
+ onClick={() => {
715
+ active = !active;
716
+ }}
717
+ ref={(el: HTMLElement) => {
718
+ capturedElement = el;
719
+ }}
720
+ >
721
+ {'content: '}
722
+ {active}
723
+ </Button>
774
724
  }
775
725
 
776
726
  render(App);
@@ -792,32 +742,26 @@ describe('dynamic DOM elements', () => {
792
742
  let refCallCount = 0;
793
743
  let capturedElement: HTMLElement | null = null;
794
744
 
795
- function Button(props: any) {
796
- return <>
797
- const el = track('button');
798
- <@el {...props} />
799
- </>;
745
+ function Button(props: any) @{
746
+ const el = track('button');
747
+ <@el {...props} />
800
748
  }
801
749
 
802
- function App() {
803
- return <>
804
- let &[active] = track(false);
805
- <Button
806
- data-active={String(active)}
807
- onClick={() => {
808
- active = !active;
809
- }}
810
- ref={(el: HTMLElement) => {
811
- capturedElement = el;
812
- refCallCount++;
813
- return () => {
814
- cleanupCount++;
815
- };
816
- }}
817
- >
818
- {'content'}
819
- </Button>
820
- </>;
750
+ function App() @{
751
+ let &[active] = track(false);
752
+ <Button
753
+ data-active={String(active)}
754
+ onClick={() => {
755
+ active = !active;
756
+ }}
757
+ ref={(el: HTMLElement) => {
758
+ capturedElement = el;
759
+ refCallCount++;
760
+ return () => {
761
+ cleanupCount++;
762
+ };
763
+ }}
764
+ >{'content'}</Button>
821
765
  }
822
766
 
823
767
  render(App);
@@ -837,16 +781,16 @@ describe('dynamic DOM elements', () => {
837
781
  });
838
782
 
839
783
  it('should remove and add back a text node in a conditional statement with a tracked', () => {
840
- function App() {
841
- return <>
842
- let &[b] = track(true);
784
+ function App() @{
785
+ let &[b] = track(true);
786
+ <>
843
787
  <div>
844
- if (b) {
845
- {'Inside if'}
788
+ @if (b) {
789
+ <>Inside if</>
846
790
  }
847
791
  </div>
848
792
  <button onClick={() => (b = !b)}>{'Toggle b'}</button>
849
- </>;
793
+ </>
850
794
  }
851
795
 
852
796
  render(App);