ripple 0.3.68 → 0.3.70

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 +126 -259
  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 -131
  176. package/tests/server/switch.test.tsrx +91 -85
  177. package/tests/server/track-async-serialization.test.tsrx +105 -85
  178. package/tests/server/try.test.tsrx +374 -280
  179. package/tests/utils/compiler-compat-config.test.js +2 -2
  180. package/tests/utils/runtime-imports.test.js +10 -0
  181. package/types/index.d.ts +8 -0
  182. package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
@@ -2,222 +2,182 @@
2
2
  // Each component tests one specific combination of for / if / switch.
3
3
 
4
4
  // ── for + if (2 items shown, 1 hidden) ────────────────────────────────────────
5
- export component ForIf() {
6
- const items = [
7
- { id: 1, show: true, label: 'One' },
8
- { id: 2, show: true, label: 'Two' },
9
- { id: 3, show: false, label: 'Three' },
10
- ];
11
-
12
- <ul class="for-if">
13
- for (const item of items; key item.id) {
14
- if (item.show) {
15
- <li class={`item item-${item.id}`}>{item.label}</li>
5
+ export function ForIf() {
6
+ return <>
7
+ const items = [
8
+ { id: 1, show: true, label: 'One' },
9
+ { id: 2, show: true, label: 'Two' },
10
+ { id: 3, show: false, label: 'Three' },
11
+ ];
12
+ <ul class="for-if">
13
+ for (const item of items; key item.id) {
14
+ if (item.show) {
15
+ <li class={`item item-${item.id}`}>{item.label}</li>
16
+ }
16
17
  }
17
- }
18
- </ul>
18
+ </ul>
19
+ </>;
19
20
  }
20
21
 
21
22
  // ── for + switch (3 items, alternating cases) ─────────────────────────────────
22
- export component ForSwitch() {
23
- const items = [
24
- { id: 1, kind: 'a' },
25
- { id: 2, kind: 'b' },
26
- { id: 3, kind: 'a' },
27
- ];
28
-
29
- <ul class="for-switch">
30
- for (const item of items; key item.id) {
31
- switch (item.kind) {
32
- case 'a':
33
- <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
34
- break;
35
- default:
36
- <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
37
- }
38
- }
39
- </ul>
40
- }
41
-
42
- // ── if + switch (no for loop) ─────────────────────────────────────────────────
43
- export component IfSwitch() {
44
- const show = true;
45
- const kind = 'a';
46
-
47
- <div class="if-switch">
48
- if (show) {
49
- switch (kind) {
50
- case 'a':
51
- <p class="case-a">{'Case A'}</p>
52
- break;
53
- default:
54
- <p class="case-default">{'Default'}</p>
55
- }
56
- }
57
- </div>
58
- }
59
-
60
- // ── if + switch where if is false ─────────────────────────────────────────────
61
- export component IfSwitchHidden() {
62
- const show = false;
63
- const kind = 'a';
64
-
65
- <div class="if-switch-hidden">
66
- if (show) {
67
- switch (kind) {
68
- case 'a':
69
- <p class="case-a">{'Case A'}</p>
70
- break;
71
- default:
72
- <p class="case-default">{'Default'}</p>
73
- }
74
- }
75
- <p class="after">{'after'}</p>
76
- </div>
77
- }
78
-
79
- // ── for + if + switch, single item (no inter-item cursor advance needed) ───────
80
- export component ForIfSwitchSingle() {
81
- const items = [
82
- { id: 1, kind: 'a', show: true },
83
- ];
84
-
85
- <ul class="for-if-switch-single">
86
- for (const item of items; key item.id) {
87
- if (item.show) {
23
+ export function ForSwitch() {
24
+ return <>
25
+ const items = [
26
+ { id: 1, kind: 'a' },
27
+ { id: 2, kind: 'b' },
28
+ { id: 3, kind: 'a' },
29
+ ];
30
+ <ul class="for-switch">
31
+ for (const item of items; key item.id) {
88
32
  switch (item.kind) {
89
33
  case 'a':
90
34
  <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
91
35
  break;
92
36
  default:
93
- <li class={`item item-${item.id} kind-default`}>{`D-${item.id}`}</li>
37
+ <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
94
38
  }
95
39
  }
96
- }
97
- </ul>
40
+ </ul>
41
+ </>;
98
42
  }
99
43
 
100
- // ── for + if + switch, two items shown (the cursor-advance regression) ─────────
101
- export component ForIfSwitchMulti() {
102
- const items = [
103
- { id: 1, kind: 'a', show: true },
104
- { id: 2, kind: 'b', show: true },
105
- ];
106
-
107
- <ul class="for-if-switch-multi">
108
- for (const item of items; key item.id) {
109
- if (item.show) {
110
- switch (item.kind) {
44
+ // ── if + switch (no for loop) ─────────────────────────────────────────────────
45
+ export function IfSwitch() {
46
+ return <>
47
+ const show = true;
48
+ const kind = 'a';
49
+ <div class="if-switch">
50
+ if (show) {
51
+ switch (kind) {
111
52
  case 'a':
112
- <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
53
+ <p class="case-a">{'Case A'}</p>
113
54
  break;
114
55
  default:
115
- <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
56
+ <p class="case-default">{'Default'}</p>
116
57
  }
117
58
  }
118
- }
119
- </ul>
59
+ </div>
60
+ </>;
120
61
  }
121
62
 
122
- // ── for + if + switch, last item hidden (if=false path between items) ──────────
123
- export component ForIfSwitchWithDisabled() {
124
- const items = [
125
- { id: 1, kind: 'a', show: true },
126
- { id: 2, kind: 'b', show: false },
127
- { id: 3, kind: 'a', show: true },
128
- ];
129
-
130
- <ul class="for-if-switch-disabled">
131
- for (const item of items; key item.id) {
132
- if (item.show) {
133
- switch (item.kind) {
63
+ // ── if + switch where if is false ─────────────────────────────────────────────
64
+ export function IfSwitchHidden() {
65
+ return <>
66
+ const show = false;
67
+ const kind = 'a';
68
+ <div class="if-switch-hidden">
69
+ if (show) {
70
+ switch (kind) {
134
71
  case 'a':
135
- <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
72
+ <p class="case-a">{'Case A'}</p>
136
73
  break;
137
74
  default:
138
- <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
75
+ <p class="case-default">{'Default'}</p>
139
76
  }
140
77
  }
141
- }
142
- </ul>
78
+ <p class="after">{'after'}</p>
79
+ </div>
80
+ </>;
143
81
  }
144
82
 
145
- // ── switch + try (no for/if) ──────────────────────────────────────────────────
146
- export component SwitchTry() {
147
- const kind = 'a';
83
+ // ── for + if + switch, single item (no inter-item cursor advance needed) ───────
84
+ export function ForIfSwitchSingle() {
85
+ return <>
86
+ const items = [
87
+ { id: 1, kind: 'a', show: true },
88
+ ];
89
+ <ul class="for-if-switch-single">
90
+ for (const item of items; key item.id) {
91
+ if (item.show) {
92
+ switch (item.kind) {
93
+ case 'a':
94
+ <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
95
+ break;
96
+ default:
97
+ <li class={`item item-${item.id} kind-default`}>{`D-${item.id}`}</li>
98
+ }
99
+ }
100
+ }
101
+ </ul>
102
+ </>;
103
+ }
148
104
 
149
- <div class="switch-try">
150
- switch (kind) {
151
- case 'a':
152
- try {
153
- <p class="resolved-a">{'A resolved'}</p>
154
- } pending {
155
- <p class="pending-a">{'A pending'}</p>
105
+ // ── for + if + switch, two items shown (the cursor-advance regression) ─────────
106
+ export function ForIfSwitchMulti() {
107
+ return <>
108
+ const items = [
109
+ { id: 1, kind: 'a', show: true },
110
+ { id: 2, kind: 'b', show: true },
111
+ ];
112
+ <ul class="for-if-switch-multi">
113
+ for (const item of items; key item.id) {
114
+ if (item.show) {
115
+ switch (item.kind) {
116
+ case 'a':
117
+ <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
118
+ break;
119
+ default:
120
+ <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
121
+ }
156
122
  }
157
- break;
158
- default:
159
- <p class="default">{'Default'}</p>
160
- }
161
- </div>
123
+ }
124
+ </ul>
125
+ </>;
162
126
  }
163
127
 
164
- // ── for + switch + try (no if) ────────────────────────────────────────────────
165
- export component ForSwitchTry() {
166
- const items = [
167
- { id: 1, kind: 'a' },
168
- { id: 2, kind: 'b' },
169
- ];
128
+ // ── for + if + switch, last item hidden (if=false path between items) ──────────
129
+ export function ForIfSwitchWithDisabled() {
130
+ return <>
131
+ const items = [
132
+ { id: 1, kind: 'a', show: true },
133
+ { id: 2, kind: 'b', show: false },
134
+ { id: 3, kind: 'a', show: true },
135
+ ];
136
+ <ul class="for-if-switch-disabled">
137
+ for (const item of items; key item.id) {
138
+ if (item.show) {
139
+ switch (item.kind) {
140
+ case 'a':
141
+ <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
142
+ break;
143
+ default:
144
+ <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
145
+ }
146
+ }
147
+ }
148
+ </ul>
149
+ </>;
150
+ }
170
151
 
171
- <ul class="for-switch-try">
172
- for (const item of items; key item.id) {
173
- switch (item.kind) {
152
+ // ── switch + try (no for/if) ──────────────────────────────────────────────────
153
+ export function SwitchTry() {
154
+ return <>
155
+ const kind = 'a';
156
+ <div class="switch-try">
157
+ switch (kind) {
174
158
  case 'a':
175
159
  try {
176
- <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
160
+ <p class="resolved-a">{'A resolved'}</p>
177
161
  } pending {
178
- <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
162
+ <p class="pending-a">{'A pending'}</p>
179
163
  }
180
164
  break;
181
165
  default:
182
- try {
183
- <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
184
- } pending {
185
- <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
186
- }
166
+ <p class="default">{'Default'}</p>
187
167
  }
188
- }
189
- </ul>
168
+ </div>
169
+ </>;
190
170
  }
191
171
 
192
- // ── for + if + try (no switch) ────────────────────────────────────────────────
193
- export component ForIfTry() {
194
- const items = [
195
- { id: 1, show: true },
196
- { id: 2, show: true },
197
- ];
198
-
199
- <ul class="for-if-try">
200
- for (const item of items; key item.id) {
201
- if (item.show) {
202
- try {
203
- <li class={`item item-${item.id}`}>{`item-${item.id}`}</li>
204
- } pending {
205
- <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
206
- }
207
- }
208
- }
209
- </ul>
210
- }
211
-
212
- // ── for + if + switch + try, single item ─────────────────────────────────────
213
- export component ForIfSwitchTrySingle() {
214
- const items = [
215
- { id: 1, kind: 'a', show: true },
216
- ];
217
-
218
- <ul class="for-if-switch-try-single">
219
- for (const item of items; key item.id) {
220
- if (item.show) {
172
+ // ── for + switch + try (no if) ────────────────────────────────────────────────
173
+ export function ForSwitchTry() {
174
+ return <>
175
+ const items = [
176
+ { id: 1, kind: 'a' },
177
+ { id: 2, kind: 'b' },
178
+ ];
179
+ <ul class="for-switch-try">
180
+ for (const item of items; key item.id) {
221
181
  switch (item.kind) {
222
182
  case 'a':
223
183
  try {
@@ -228,42 +188,94 @@ export component ForIfSwitchTrySingle() {
228
188
  break;
229
189
  default:
230
190
  try {
231
- <li class={`item item-${item.id} kind-default`}>{`D-${item.id}`}</li>
191
+ <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
232
192
  } pending {
233
193
  <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
234
194
  }
235
195
  }
236
196
  }
237
- }
238
- </ul>
197
+ </ul>
198
+ </>;
239
199
  }
240
200
 
241
- // ── for + if + switch + try, multiple items (matches MixedControlFlowStatic) ──
242
- export component ForIfSwitchTryMulti() {
243
- const items = [
244
- { id: 1, kind: 'a', show: true },
245
- { id: 2, kind: 'b', show: true },
246
- ];
201
+ // ── for + if + try (no switch) ────────────────────────────────────────────────
202
+ export function ForIfTry() {
203
+ return <>
204
+ const items = [
205
+ { id: 1, show: true },
206
+ { id: 2, show: true },
207
+ ];
208
+ <ul class="for-if-try">
209
+ for (const item of items; key item.id) {
210
+ if (item.show) {
211
+ try {
212
+ <li class={`item item-${item.id}`}>{`item-${item.id}`}</li>
213
+ } pending {
214
+ <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
215
+ }
216
+ }
217
+ }
218
+ </ul>
219
+ </>;
220
+ }
247
221
 
248
- <ul class="for-if-switch-try-multi">
249
- for (const item of items; key item.id) {
250
- if (item.show) {
251
- switch (item.kind) {
252
- case 'a':
253
- try {
254
- <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
255
- } pending {
256
- <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
257
- }
258
- break;
259
- default:
260
- try {
261
- <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
262
- } pending {
263
- <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
264
- }
222
+ // ── for + if + switch + try, single item ─────────────────────────────────────
223
+ export function ForIfSwitchTrySingle() {
224
+ return <>
225
+ const items = [
226
+ { id: 1, kind: 'a', show: true },
227
+ ];
228
+ <ul class="for-if-switch-try-single">
229
+ for (const item of items; key item.id) {
230
+ if (item.show) {
231
+ switch (item.kind) {
232
+ case 'a':
233
+ try {
234
+ <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
235
+ } pending {
236
+ <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
237
+ }
238
+ break;
239
+ default:
240
+ try {
241
+ <li class={`item item-${item.id} kind-default`}>{`D-${item.id}`}</li>
242
+ } pending {
243
+ <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
244
+ }
245
+ }
246
+ }
247
+ }
248
+ </ul>
249
+ </>;
250
+ }
251
+
252
+ // ── for + if + switch + try, multiple items (matches MixedControlFlowStatic) ──
253
+ export function ForIfSwitchTryMulti() {
254
+ return <>
255
+ const items = [
256
+ { id: 1, kind: 'a', show: true },
257
+ { id: 2, kind: 'b', show: true },
258
+ ];
259
+ <ul class="for-if-switch-try-multi">
260
+ for (const item of items; key item.id) {
261
+ if (item.show) {
262
+ switch (item.kind) {
263
+ case 'a':
264
+ try {
265
+ <li class={`item item-${item.id} kind-a`}>{`A-${item.id}`}</li>
266
+ } pending {
267
+ <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
268
+ }
269
+ break;
270
+ default:
271
+ try {
272
+ <li class={`item item-${item.id} kind-b`}>{`B-${item.id}`}</li>
273
+ } pending {
274
+ <li class={`pending pending-${item.id}`}>{`pending ${item.id}`}</li>
275
+ }
276
+ }
265
277
  }
266
278
  }
267
- }
268
- </ul>
279
+ </ul>
280
+ </>;
269
281
  }
@@ -2,48 +2,55 @@
2
2
  import { Portal, track } from 'ripple';
3
3
 
4
4
  // Simple portal with static content
5
- export component SimplePortal() {
6
- <div class="container">
7
- <h1>{'Main Content'}</h1>
8
- <Portal target={typeof document !== 'undefined' ? document.body : null}>
9
- <div class="portal-content">{'Portal content'}</div>
10
- </Portal>
11
- </div>
5
+ export function SimplePortal() {
6
+ return <>
7
+ <div class="container">
8
+ <h1>{'Main Content'}</h1>
9
+ <Portal target={typeof document !== 'undefined' ? document.body : null}>
10
+ <div class="portal-content">{'Portal content'}</div>
11
+ </Portal>
12
+ </div>
13
+ </>;
12
14
  }
13
15
 
14
16
  // Portal with conditional rendering
15
- export component ConditionalPortal() {
16
- let &[show] = track(true);
17
-
18
- <div class="container">
19
- <button class="toggle" onClick={() => (show = !show)}>{'Toggle'}</button>
20
- if (show) {
21
- <Portal target={typeof document !== 'undefined' ? document.body : null}>
22
- <div class="portal-content">{'Portal is visible'}</div>
23
- </Portal>
24
- }
25
- </div>
17
+ export function ConditionalPortal() {
18
+ return <>
19
+ let &[show] = track(true);
20
+ <div class="container">
21
+ <button class="toggle" onClick={() => (show = !show)}>{'Toggle'}</button>
22
+ if (show) {
23
+ <Portal target={typeof document !== 'undefined' ? document.body : null}>
24
+ <div class="portal-content">{'Portal is visible'}</div>
25
+ </Portal>
26
+ }
27
+ </div>
28
+ </>;
26
29
  }
27
30
 
28
31
  // Component with portal that shouldn't break on initial load
29
- export component PortalWithMainContent() {
30
- <div>
31
- <div class="main-content">{'Main page content'}</div>
32
- <Portal target={typeof document !== 'undefined' ? document.body : null}>
33
- <div class="portal-content">{'Modal content'}</div>
34
- </Portal>
35
- <div class="footer">{'Footer'}</div>
36
- </div>
32
+ export function PortalWithMainContent() {
33
+ return <>
34
+ <div>
35
+ <div class="main-content">{'Main page content'}</div>
36
+ <Portal target={typeof document !== 'undefined' ? document.body : null}>
37
+ <div class="portal-content">{'Modal content'}</div>
38
+ </Portal>
39
+ <div class="footer">{'Footer'}</div>
40
+ </div>
41
+ </>;
37
42
  }
38
43
 
39
44
  // Nested portals scenario
40
- export component NestedContentWithPortal() {
41
- <div class="outer">
42
- <div class="inner">
43
- <span>{'Nested content'}</span>
45
+ export function NestedContentWithPortal() {
46
+ return <>
47
+ <div class="outer">
48
+ <div class="inner">
49
+ <span>{'Nested content'}</span>
50
+ </div>
51
+ <Portal target={typeof document !== 'undefined' ? document.body : null}>
52
+ <div class="portal-content">{'Portal content'}</div>
53
+ </Portal>
44
54
  </div>
45
- <Portal target={typeof document !== 'undefined' ? document.body : null}>
46
- <div class="portal-content">{'Portal content'}</div>
47
- </Portal>
48
- </div>
55
+ </>;
49
56
  }
@@ -2,41 +2,51 @@ import { track } from 'ripple';
2
2
 
3
3
  // Reactive components for hydration testing
4
4
 
5
- export component TrackedState() {
6
- let &[count] = track(0);
7
- <div class="count">{count}</div>
5
+ export function TrackedState() {
6
+ return <>
7
+ let &[count] = track(0);
8
+ <div class="count">{count}</div>
9
+ </>;
8
10
  }
9
11
 
10
- export component CounterWithInitial(props: { initial: number }) {
11
- let &[count] = track(props.initial);
12
- <div>
13
- <span class="count">{count}</span>
14
- </div>
12
+ export function CounterWithInitial(props: { initial: number }) {
13
+ return <>
14
+ let &[count] = track(props.initial);
15
+ <div>
16
+ <span class="count">{count}</span>
17
+ </div>
18
+ </>;
15
19
  }
16
20
 
17
- export component CounterWrapper() {
18
- <CounterWithInitial initial={5} />
21
+ export function CounterWrapper() {
22
+ return <><CounterWithInitial initial={5} /></>;
19
23
  }
20
24
 
21
- export component ComputedValues() {
22
- let &[a] = track(2);
23
- let &[b] = track(3);
24
- const sum = () => a + b;
25
- <div class="sum">{sum()}</div>
25
+ export function ComputedValues() {
26
+ return <>
27
+ let &[a] = track(2);
28
+ let &[b] = track(3);
29
+ const sum = () => a + b;
30
+ <div class="sum">{sum()}</div>
31
+ </>;
26
32
  }
27
33
 
28
- export component MultipleTracked() {
29
- let &[x] = track(10);
30
- let &[y] = track(20);
31
- let &[z] = track(30);
32
- <div class="x">{x}</div>
33
- <div class="y">{y}</div>
34
- <div class="z">{z}</div>
34
+ export function MultipleTracked() {
35
+ return <>
36
+ let &[x] = track(10);
37
+ let &[y] = track(20);
38
+ let &[z] = track(30);
39
+ <div class="x">{x}</div>
40
+ <div class="y">{y}</div>
41
+ <div class="z">{z}</div>
42
+ </>;
35
43
  }
36
44
 
37
- export component DerivedState() {
38
- let &[firstName] = track('John');
39
- let &[lastName] = track('Doe');
40
- const fullName = () => `${firstName} ${lastName}`;
41
- <div class="name">{fullName()}</div>
45
+ export function DerivedState() {
46
+ return <>
47
+ let &[firstName] = track('John');
48
+ let &[lastName] = track('Doe');
49
+ const fullName = () => `${firstName} ${lastName}`;
50
+ <div class="name">{fullName()}</div>
51
+ </>;
42
52
  }