ripple 0.3.67 → 0.3.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +2 -2
  4. package/src/runtime/element.js +1 -1
  5. package/src/runtime/index-client.js +11 -11
  6. package/src/runtime/index-server.js +7 -4
  7. package/src/runtime/internal/client/bindings.js +1 -1
  8. package/src/runtime/internal/client/blocks.js +13 -4
  9. package/src/runtime/internal/client/component.js +55 -0
  10. package/src/runtime/internal/client/composite.js +4 -2
  11. package/src/runtime/internal/client/expression.js +65 -7
  12. package/src/runtime/internal/client/hmr.js +54 -43
  13. package/src/runtime/internal/client/index.js +5 -1
  14. package/src/runtime/internal/client/portal.js +70 -69
  15. package/src/runtime/internal/client/render.js +3 -0
  16. package/src/runtime/internal/server/index.js +92 -8
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
  18. package/tests/client/array/array.copy-within.test.tsrx +33 -31
  19. package/tests/client/array/array.derived.test.tsrx +186 -169
  20. package/tests/client/array/array.iteration.test.tsrx +40 -37
  21. package/tests/client/array/array.mutations.test.tsrx +113 -101
  22. package/tests/client/array/array.static.test.tsrx +119 -101
  23. package/tests/client/array/array.to-methods.test.tsrx +24 -21
  24. package/tests/client/async-suspend.test.tsrx +247 -246
  25. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
  26. package/tests/client/basic/basic.attributes.test.tsrx +428 -423
  27. package/tests/client/basic/basic.collections.test.tsrx +109 -102
  28. package/tests/client/basic/basic.components.test.tsrx +323 -205
  29. package/tests/client/basic/basic.errors.test.tsrx +91 -91
  30. package/tests/client/basic/basic.events.test.tsrx +114 -115
  31. package/tests/client/basic/basic.get-set.test.tsrx +97 -87
  32. package/tests/client/basic/basic.hmr.test.tsrx +19 -16
  33. package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
  34. package/tests/client/basic/basic.rendering.test.tsrx +272 -182
  35. package/tests/client/basic/basic.styling.test.tsrx +23 -22
  36. package/tests/client/basic/basic.utilities.test.tsrx +10 -8
  37. package/tests/client/boundaries.test.tsrx +26 -26
  38. package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
  39. package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
  40. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
  41. package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
  42. package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
  43. package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
  44. package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
  45. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  46. package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
  47. package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
  48. package/tests/client/composite/composite.generics.test.tsrx +168 -192
  49. package/tests/client/composite/composite.props.test.tsrx +97 -81
  50. package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
  51. package/tests/client/composite/composite.render.test.tsrx +122 -105
  52. package/tests/client/computed-properties.test.tsrx +28 -28
  53. package/tests/client/context.test.tsrx +21 -21
  54. package/tests/client/css/global-additional-cases.test.tsrx +58 -58
  55. package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
  56. package/tests/client/css/global-at-rules.test.tsrx +10 -10
  57. package/tests/client/css/global-basic.test.tsrx +14 -14
  58. package/tests/client/css/global-classes-ids.test.tsrx +14 -14
  59. package/tests/client/css/global-combinators.test.tsrx +10 -10
  60. package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
  61. package/tests/client/css/global-edge-cases.test.tsrx +18 -18
  62. package/tests/client/css/global-keyframes.test.tsrx +12 -12
  63. package/tests/client/css/global-nested.test.tsrx +10 -10
  64. package/tests/client/css/global-pseudo.test.tsrx +12 -12
  65. package/tests/client/css/global-scoping.test.tsrx +20 -20
  66. package/tests/client/css/style-identifier.test.tsrx +143 -291
  67. package/tests/client/date.test.tsrx +146 -133
  68. package/tests/client/dynamic-elements.test.tsrx +398 -365
  69. package/tests/client/events.test.tsrx +292 -290
  70. package/tests/client/for.test.tsrx +156 -153
  71. package/tests/client/head.test.tsrx +105 -96
  72. package/tests/client/html.test.tsrx +122 -26
  73. package/tests/client/input-value.test.tsrx +1361 -1314
  74. package/tests/client/lazy-array.test.tsrx +16 -13
  75. package/tests/client/lazy-destructuring.test.tsrx +257 -213
  76. package/tests/client/map.test.tsrx +65 -60
  77. package/tests/client/media-query.test.tsrx +22 -20
  78. package/tests/client/object.test.tsrx +87 -81
  79. package/tests/client/portal.test.tsrx +57 -51
  80. package/tests/client/ref.test.tsrx +233 -202
  81. package/tests/client/return.test.tsrx +71 -2560
  82. package/tests/client/set.test.tsrx +54 -45
  83. package/tests/client/svg.test.tsrx +216 -186
  84. package/tests/client/switch.test.tsrx +194 -193
  85. package/tests/client/track-async-hydration.test.tsrx +18 -14
  86. package/tests/client/tracked-index-access.test.tsrx +28 -18
  87. package/tests/client/try.test.tsrx +675 -548
  88. package/tests/client/tsx.test.tsrx +373 -311
  89. package/tests/client/typescript-generics.test.tsrx +145 -145
  90. package/tests/client/url/url.derived.test.tsrx +33 -28
  91. package/tests/client/url/url.parsing.test.tsrx +61 -51
  92. package/tests/client/url/url.partial-removal.test.tsrx +56 -48
  93. package/tests/client/url/url.reactivity.test.tsrx +142 -125
  94. package/tests/client/url/url.serialization.test.tsrx +13 -11
  95. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
  96. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
  97. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
  98. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
  99. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
  100. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
  101. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
  102. package/tests/hydration/basic.test.js +3 -3
  103. package/tests/hydration/compiled/client/basic.js +586 -651
  104. package/tests/hydration/compiled/client/composite.js +79 -104
  105. package/tests/hydration/compiled/client/events.js +140 -148
  106. package/tests/hydration/compiled/client/for.js +1005 -1018
  107. package/tests/hydration/compiled/client/head.js +124 -134
  108. package/tests/hydration/compiled/client/hmr.js +41 -48
  109. package/tests/hydration/compiled/client/html-in-template.js +38 -41
  110. package/tests/hydration/compiled/client/html.js +970 -1314
  111. package/tests/hydration/compiled/client/if-children.js +234 -249
  112. package/tests/hydration/compiled/client/if.js +182 -189
  113. package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
  114. package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
  115. package/tests/hydration/compiled/client/portal.js +65 -85
  116. package/tests/hydration/compiled/client/reactivity.js +84 -90
  117. package/tests/hydration/compiled/client/return.js +38 -1939
  118. package/tests/hydration/compiled/client/switch.js +218 -224
  119. package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
  120. package/tests/hydration/compiled/client/try.js +123 -132
  121. package/tests/hydration/compiled/server/basic.js +773 -831
  122. package/tests/hydration/compiled/server/composite.js +166 -191
  123. package/tests/hydration/compiled/server/events.js +170 -184
  124. package/tests/hydration/compiled/server/for.js +851 -909
  125. package/tests/hydration/compiled/server/head.js +206 -216
  126. package/tests/hydration/compiled/server/hmr.js +64 -72
  127. package/tests/hydration/compiled/server/html-in-template.js +42 -76
  128. package/tests/hydration/compiled/server/html.js +1362 -1667
  129. package/tests/hydration/compiled/server/if-children.js +419 -445
  130. package/tests/hydration/compiled/server/if.js +194 -208
  131. package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
  132. package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
  133. package/tests/hydration/compiled/server/portal.js +152 -160
  134. package/tests/hydration/compiled/server/reactivity.js +94 -106
  135. package/tests/hydration/compiled/server/return.js +28 -2172
  136. package/tests/hydration/compiled/server/switch.js +274 -286
  137. package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
  138. package/tests/hydration/compiled/server/try.js +167 -185
  139. package/tests/hydration/components/basic.tsrx +320 -272
  140. package/tests/hydration/components/composite.tsrx +44 -32
  141. package/tests/hydration/components/events.tsrx +101 -91
  142. package/tests/hydration/components/for.tsrx +510 -452
  143. package/tests/hydration/components/head.tsrx +87 -80
  144. package/tests/hydration/components/hmr.tsrx +22 -17
  145. package/tests/hydration/components/html-in-template.tsrx +22 -17
  146. package/tests/hydration/components/html.tsrx +525 -443
  147. package/tests/hydration/components/if-children.tsrx +158 -148
  148. package/tests/hydration/components/if.tsrx +109 -95
  149. package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
  150. package/tests/hydration/components/nested-control-flow.tsrx +215 -203
  151. package/tests/hydration/components/portal.tsrx +41 -34
  152. package/tests/hydration/components/reactivity.tsrx +37 -27
  153. package/tests/hydration/components/return.tsrx +12 -556
  154. package/tests/hydration/components/switch.tsrx +120 -114
  155. package/tests/hydration/components/track-async-serialization.tsrx +107 -91
  156. package/tests/hydration/components/try.tsrx +55 -40
  157. package/tests/hydration/html.test.js +4 -4
  158. package/tests/hydration/return.test.js +13 -532
  159. package/tests/server/await.test.tsrx +3 -3
  160. package/tests/server/basic.attributes.test.tsrx +264 -195
  161. package/tests/server/basic.components.test.tsrx +296 -169
  162. package/tests/server/basic.test.tsrx +300 -198
  163. package/tests/server/compiler.test.tsrx +62 -60
  164. package/tests/server/composite.props.test.tsrx +77 -63
  165. package/tests/server/composite.test.tsrx +168 -192
  166. package/tests/server/context.test.tsrx +18 -12
  167. package/tests/server/dynamic-elements.test.tsrx +197 -180
  168. package/tests/server/for.test.tsrx +85 -78
  169. package/tests/server/head.test.tsrx +50 -43
  170. package/tests/server/html-nesting-validation.test.tsrx +8 -8
  171. package/tests/server/if.test.tsrx +57 -51
  172. package/tests/server/lazy-destructuring.test.tsrx +366 -294
  173. package/tests/server/return.test.tsrx +76 -1355
  174. package/tests/server/streaming-ssr.test.tsrx +4 -75
  175. package/tests/server/style-identifier.test.tsrx +169 -148
  176. package/tests/server/switch.test.tsrx +91 -85
  177. package/tests/server/track-async-serialization.test.tsrx +105 -85
  178. package/tests/server/try.test.tsrx +374 -280
  179. package/tests/utils/compiler-compat-config.test.js +2 -2
  180. package/tests/utils/runtime-imports.test.js +10 -0
  181. package/types/index.d.ts +8 -0
  182. package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
@@ -3,191 +3,201 @@ import { track } from 'ripple';
3
3
  // Minimal repro for hydration issue with if block containing children
4
4
  // Based on SidebarGroup pattern from website-new
5
5
 
6
- export component IfWithChildren({ children }: { children: any }) {
7
- let &[expanded] = track(true);
8
-
9
- <div class="container">
10
- <div class="header" role="button" onClick={() => (expanded = !expanded)}>{'Toggle'}</div>
11
- if (expanded) {
12
- <div class="content">{children}</div>
13
- }
14
- </div>
6
+ export function IfWithChildren({ children }: { children: any }) {
7
+ return <>
8
+ let &[expanded] = track(true);
9
+ <div class="container">
10
+ <div class="header" role="button" onClick={() => (expanded = !expanded)}>{'Toggle'}</div>
11
+ if (expanded) {
12
+ <div class="content">{children}</div>
13
+ }
14
+ </div>
15
+ </>;
15
16
  }
16
17
 
17
- export component ChildItem({ text: label }: { text: string }) {
18
- <div class="item">{label}</div>
18
+ export function ChildItem({ text: label }: { text: string }) {
19
+ return <><div class="item">{label}</div></>;
19
20
  }
20
21
 
21
- export component TestIfWithChildren() {
22
- <IfWithChildren>
23
- <ChildItem text="Item 1" />
24
- <ChildItem text="Item 2" />
25
- </IfWithChildren>
22
+ export function TestIfWithChildren() {
23
+ return <>
24
+ <IfWithChildren>
25
+ <ChildItem text="Item 1" />
26
+ <ChildItem text="Item 2" />
27
+ </IfWithChildren>
28
+ </>;
26
29
  }
27
30
 
28
31
  // Simpler variant - if block with static children
29
- export component IfWithStaticChildren() {
30
- let &[expanded] = track(true);
31
-
32
- <div class="container">
33
- <div class="header" role="button" onClick={() => (expanded = !expanded)}>{'Toggle'}</div>
34
- if (expanded) {
35
- <div class="content">
36
- <span>{'Static child 1'}</span>
37
- <span>{'Static child 2'}</span>
38
- </div>
39
- }
40
- </div>
32
+ export function IfWithStaticChildren() {
33
+ return <>
34
+ let &[expanded] = track(true);
35
+ <div class="container">
36
+ <div class="header" role="button" onClick={() => (expanded = !expanded)}>{'Toggle'}</div>
37
+ if (expanded) {
38
+ <div class="content">
39
+ <span>{'Static child 1'}</span>
40
+ <span>{'Static child 2'}</span>
41
+ </div>
42
+ }
43
+ </div>
44
+ </>;
41
45
  }
42
46
 
43
47
  // Variant with sibling elements before the if block (like SidebarGroup)
44
- export component IfWithSiblingsAndChildren({ children }: { children: any }) {
45
- let &[expanded] = track(true);
46
-
47
- <section class="group">
48
- <div class="item" role="button" onClick={() => (expanded = !expanded)}>
49
- <div class="indicator" />
50
- <h2 class="text">{'Title'}</h2>
51
- <div class="caret">
52
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
53
- <path d="m9 18 6-6-6-6" />
54
- </svg>
48
+ export function IfWithSiblingsAndChildren({ children }: { children: any }) {
49
+ return <>
50
+ let &[expanded] = track(true);
51
+ <section class="group">
52
+ <div class="item" role="button" onClick={() => (expanded = !expanded)}>
53
+ <div class="indicator" />
54
+ <h2 class="text">{'Title'}</h2>
55
+ <div class="caret">
56
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
57
+ <path d="m9 18 6-6-6-6" />
58
+ </svg>
59
+ </div>
55
60
  </div>
56
- </div>
57
- if (expanded) {
58
- <div class="items">{children}</div>
59
- }
60
- </section>
61
+ if (expanded) {
62
+ <div class="items">{children}</div>
63
+ }
64
+ </section>
65
+ </>;
61
66
  }
62
67
 
63
- export component TestIfWithSiblingsAndChildren() {
64
- <IfWithSiblingsAndChildren>
65
- <ChildItem text="Item A" />
66
- <ChildItem text="Item B" />
67
- </IfWithSiblingsAndChildren>
68
+ export function TestIfWithSiblingsAndChildren() {
69
+ return <>
70
+ <IfWithSiblingsAndChildren>
71
+ <ChildItem text="Item A" />
72
+ <ChildItem text="Item B" />
73
+ </IfWithSiblingsAndChildren>
74
+ </>;
68
75
  }
69
76
 
70
77
  // Test case for hydration pop bug: element with nested children followed by dynamic if sibling
71
78
  // This tests that hydrate_node is properly restored after processing an element's children
72
79
  // before navigating to a dynamic sibling (if/for/switch)
73
- export component ElementWithChildrenThenIf() {
74
- let &[show] = track(true);
75
-
76
- <div class="wrapper">
77
- <div class="nested-parent">
78
- <div class="nested-child">
79
- <span class="deep">{'Deep content'}</span>
80
+ export function ElementWithChildrenThenIf() {
81
+ return <>
82
+ let &[show] = track(true);
83
+ <div class="wrapper">
84
+ <div class="nested-parent">
85
+ <div class="nested-child">
86
+ <span class="deep">{'Deep content'}</span>
87
+ </div>
80
88
  </div>
89
+ if (show) {
90
+ <div class="conditional">{'Conditional content'}</div>
91
+ }
81
92
  </div>
82
- if (show) {
83
- <div class="conditional">{'Conditional content'}</div>
84
- }
85
- </div>
86
-
87
- <button class="toggle" onClick={() => (show = !show)}>{'Toggle'}</button>
93
+ <button class="toggle" onClick={() => (show = !show)}>{'Toggle'}</button>
94
+ </>;
88
95
  }
89
96
 
90
97
  // More complex: multiple levels of nesting before if sibling
91
- export component DeepNestingThenIf() {
92
- let &[visible] = track(true);
93
-
94
- <section class="outer">
95
- <article class="middle">
96
- <div class="inner">
97
- <p class="leaf">
98
- <strong>{'Bold'}</strong>
99
- <em>{'Italic'}</em>
100
- </p>
101
- </div>
102
- </article>
103
- if (visible) {
104
- <footer class="footer">{'Footer'}</footer>
105
- }
106
- </section>
107
-
108
- <button class="btn" onClick={() => (visible = !visible)}>{'Toggle'}</button>
98
+ export function DeepNestingThenIf() {
99
+ return <>
100
+ let &[visible] = track(true);
101
+ <section class="outer">
102
+ <article class="middle">
103
+ <div class="inner">
104
+ <p class="leaf">
105
+ <strong>{'Bold'}</strong>
106
+ <em>{'Italic'}</em>
107
+ </p>
108
+ </div>
109
+ </article>
110
+ if (visible) {
111
+ <footer class="footer">{'Footer'}</footer>
112
+ }
113
+ </section>
114
+ <button class="btn" onClick={() => (visible = !visible)}>{'Toggle'}</button>
115
+ </>;
109
116
  }
110
117
 
111
118
  // Test case for CodeBlock pattern: element with only DOM element children (like buttons)
112
119
  // followed by another sibling element. This requires pop() to restore hydrate_node
113
120
  // because we descend into the first element to get the button children.
114
- export component DomElementChildrenThenSibling() {
115
- let &[activeTab] = track('code');
116
-
117
- <div class="tabs">
118
- <div class="tab-list">
119
- <button
120
- class="tab"
121
- aria-selected={activeTab === 'code' ? 'true' : 'false'}
122
- onClick={() => (activeTab = 'code')}
123
- >
124
- {'Code'}
125
- </button>
126
- <button
127
- class="tab"
128
- aria-selected={activeTab === 'preview' ? 'true' : 'false'}
129
- onClick={() => (activeTab = 'preview')}
130
- >
131
- {'Preview'}
132
- </button>
133
- </div>
134
- <div class="panel">
135
- if (activeTab === 'code') {
136
- <pre class="code">{'const x = 1;'}</pre>
137
- } else {
138
- <div class="preview">{'Preview content'}</div>
139
- }
121
+ export function DomElementChildrenThenSibling() {
122
+ return <>
123
+ let &[activeTab] = track('code');
124
+ <div class="tabs">
125
+ <div class="tab-list">
126
+ <button
127
+ class="tab"
128
+ aria-selected={activeTab === 'code' ? 'true' : 'false'}
129
+ onClick={() => (activeTab = 'code')}
130
+ >
131
+ {'Code'}
132
+ </button>
133
+ <button
134
+ class="tab"
135
+ aria-selected={activeTab === 'preview' ? 'true' : 'false'}
136
+ onClick={() => (activeTab = 'preview')}
137
+ >
138
+ {'Preview'}
139
+ </button>
140
+ </div>
141
+ <div class="panel">
142
+ if (activeTab === 'code') {
143
+ <pre class="code">{'const x = 1;'}</pre>
144
+ } else {
145
+ <div class="preview">{'Preview content'}</div>
146
+ }
147
+ </div>
140
148
  </div>
141
- </div>
149
+ </>;
142
150
  }
143
151
 
144
152
  // Test case for element with DOM children followed by static siblings that don't
145
153
  // generate sibling() calls. This was causing incorrect pop() generation before next().
146
154
  // Pattern: <ul> with dynamic <li> children -> static <h2> -> static <p> -> next()
147
- export component DomChildrenThenStaticSiblings() {
148
- let &[count] = track(0);
149
-
150
- <div class="container">
151
- <ul class="list">
152
- <li class="item">
153
- {'Item count: '}
154
- {count}
155
- </li>
156
- <li class="item">{'Another item'}</li>
157
- </ul>
158
- <h2 class="heading">{'Static Heading'}</h2>
159
- <p class="para">{'Static paragraph'}</p>
160
- </div>
161
-
162
- <button class="inc" onClick={() => count++}>{'Increment'}</button>
155
+ export function DomChildrenThenStaticSiblings() {
156
+ return <>
157
+ let &[count] = track(0);
158
+ <div class="container">
159
+ <ul class="list">
160
+ <li class="item">
161
+ {'Item count: '}
162
+ {count}
163
+ </li>
164
+ <li class="item">{'Another item'}</li>
165
+ </ul>
166
+ <h2 class="heading">{'Static Heading'}</h2>
167
+ <p class="para">{'Static paragraph'}</p>
168
+ </div>
169
+ <button class="inc" onClick={() => count++}>{'Increment'}</button>
170
+ </>;
163
171
  }
164
172
 
165
173
  // Test case for completely static element children followed by static siblings.
166
174
  // Pattern from introduction page: <ul> with static <li> (strong, code, text)
167
175
  // followed by static <h2> and <p>. No pop() should be generated for these.
168
- export component StaticListThenStaticSiblings() {
169
- <div class="wrapper">
170
- <ul class="features">
171
- <li>
172
- <strong>{'Feature One'}</strong>
173
- {': Description of feature one with '}
174
- <code>{'code'}</code>
175
- {' reference'}
176
- </li>
177
- <li>
178
- <strong>{'Feature Two'}</strong>
179
- {': Another feature description'}
180
- </li>
181
- <li>
182
- <strong>{'Feature Three'}</strong>
183
- {': Third feature'}
184
- </li>
185
- </ul>
186
- <h2 class="section-heading">{'Section Heading'}</h2>
187
- <p class="section-content">
188
- {'Static paragraph with '}
189
- <a href="/link">{'a link'}</a>
190
- {' and more text.'}
191
- </p>
192
- </div>
176
+ export function StaticListThenStaticSiblings() {
177
+ return <>
178
+ <div class="wrapper">
179
+ <ul class="features">
180
+ <li>
181
+ <strong>{'Feature One'}</strong>
182
+ {': Description of feature one with '}
183
+ <code>{'code'}</code>
184
+ {' reference'}
185
+ </li>
186
+ <li>
187
+ <strong>{'Feature Two'}</strong>
188
+ {': Another feature description'}
189
+ </li>
190
+ <li>
191
+ <strong>{'Feature Three'}</strong>
192
+ {': Third feature'}
193
+ </li>
194
+ </ul>
195
+ <h2 class="section-heading">{'Section Heading'}</h2>
196
+ <p class="section-content">
197
+ {'Static paragraph with '}
198
+ <a href="/link">{'a link'}</a>
199
+ {' and more text.'}
200
+ </p>
201
+ </div>
202
+ </>;
193
203
  }
@@ -2,123 +2,137 @@ import { track } from 'ripple';
2
2
 
3
3
  // If block components for hydration testing
4
4
 
5
- export component IfTruthy() {
6
- const show = true;
7
- if (show) {
8
- <div class="shown">{'Visible'}</div>
9
- }
10
- }
11
-
12
- export component IfFalsy() {
13
- const show = false;
14
- if (show) {
15
- <div class="shown">{'Visible'}</div>
16
- }
17
- }
18
-
19
- export component IfElse() {
20
- const isLoggedIn = true;
21
- if (isLoggedIn) {
22
- <div class="logged-in">{'Welcome back!'}</div>
23
- } else {
24
- <div class="logged-out">{'Please log in'}</div>
25
- }
5
+ export function IfTruthy() {
6
+ return <>
7
+ const show = true;
8
+ if (show) {
9
+ <div class="shown">{'Visible'}</div>
10
+ }
11
+ </>;
26
12
  }
27
13
 
28
- export component ReactiveIf() {
29
- let &[show] = track(true);
30
- <button
31
- class="toggle"
32
- onClick={() => {
33
- show = !show;
34
- }}
35
- >
36
- {'Toggle'}
37
- </button>
38
- if (show) {
39
- <div class="content">{'Content visible'}</div>
40
- }
14
+ export function IfFalsy() {
15
+ return <>
16
+ const show = false;
17
+ if (show) {
18
+ <div class="shown">{'Visible'}</div>
19
+ }
20
+ </>;
41
21
  }
42
22
 
43
- export component ReactiveIfElse() {
44
- let &[isOn] = track(false);
45
- <button
46
- class="toggle"
47
- onClick={() => {
48
- isOn = !isOn;
49
- }}
50
- >
51
- {'Toggle'}
52
- </button>
53
- if (isOn) {
54
- <div class="on">{'ON'}</div>
55
- } else {
56
- <div class="off">{'OFF'}</div>
57
- }
23
+ export function IfElse() {
24
+ return <>
25
+ const isLoggedIn = true;
26
+ if (isLoggedIn) {
27
+ <div class="logged-in">{'Welcome back!'}</div>
28
+ } else {
29
+ <div class="logged-out">{'Please log in'}</div>
30
+ }
31
+ </>;
58
32
  }
59
33
 
60
- export component NestedIf() {
61
- let &[outer] = track(true);
62
- let &[inner] = track(true);
63
- <button
64
- class="outer-toggle"
65
- onClick={() => {
66
- outer = !outer;
67
- }}
68
- >
69
- {'Outer'}
70
- </button>
71
- <button
72
- class="inner-toggle"
73
- onClick={() => {
74
- inner = !inner;
75
- }}
76
- >
77
- {'Inner'}
78
- </button>
79
- if (outer) {
80
- <div class="outer-content">
81
- {'Outer'}
82
- if (inner) {
83
- <span class="inner-content">{'Inner'}</span>
84
- }
85
- </div>
86
- }
34
+ export function ReactiveIf() {
35
+ return <>
36
+ let &[show] = track(true);
37
+ <button
38
+ class="toggle"
39
+ onClick={() => {
40
+ show = !show;
41
+ }}
42
+ >
43
+ {'Toggle'}
44
+ </button>
45
+ if (show) {
46
+ <div class="content">{'Content visible'}</div>
47
+ }
48
+ </>;
87
49
  }
88
50
 
89
- export component IfElseIfChain() {
90
- let &[status] = track<'loading' | 'success' | 'error'>('loading');
91
- <div>
51
+ export function ReactiveIfElse() {
52
+ return <>
53
+ let &[isOn] = track(false);
92
54
  <button
93
- class="success"
55
+ class="toggle"
94
56
  onClick={() => {
95
- status = 'success';
57
+ isOn = !isOn;
96
58
  }}
97
59
  >
98
- {'Success'}
60
+ {'Toggle'}
99
61
  </button>
62
+ if (isOn) {
63
+ <div class="on">{'ON'}</div>
64
+ } else {
65
+ <div class="off">{'OFF'}</div>
66
+ }
67
+ </>;
68
+ }
69
+
70
+ export function NestedIf() {
71
+ return <>
72
+ let &[outer] = track(true);
73
+ let &[inner] = track(true);
100
74
  <button
101
- class="error"
75
+ class="outer-toggle"
102
76
  onClick={() => {
103
- status = 'error';
77
+ outer = !outer;
104
78
  }}
105
79
  >
106
- {'Error'}
80
+ {'Outer'}
107
81
  </button>
108
82
  <button
109
- class="loading"
83
+ class="inner-toggle"
110
84
  onClick={() => {
111
- status = 'loading';
85
+ inner = !inner;
112
86
  }}
113
87
  >
114
- {'Loading'}
88
+ {'Inner'}
115
89
  </button>
116
- if (status === 'loading') {
117
- <div class="state">{'Loading...'}</div>
118
- } else if (status === 'success') {
119
- <div class="state">{'Success!'}</div>
120
- } else {
121
- <div class="state">{'Error occurred'}</div>
90
+ if (outer) {
91
+ <div class="outer-content">
92
+ {'Outer'}
93
+ if (inner) {
94
+ <span class="inner-content">{'Inner'}</span>
95
+ }
96
+ </div>
122
97
  }
123
- </div>
98
+ </>;
99
+ }
100
+
101
+ export function IfElseIfChain() {
102
+ return <>
103
+ let &[status] = track<'loading' | 'success' | 'error'>('loading');
104
+ <div>
105
+ <button
106
+ class="success"
107
+ onClick={() => {
108
+ status = 'success';
109
+ }}
110
+ >
111
+ {'Success'}
112
+ </button>
113
+ <button
114
+ class="error"
115
+ onClick={() => {
116
+ status = 'error';
117
+ }}
118
+ >
119
+ {'Error'}
120
+ </button>
121
+ <button
122
+ class="loading"
123
+ onClick={() => {
124
+ status = 'loading';
125
+ }}
126
+ >
127
+ {'Loading'}
128
+ </button>
129
+ if (status === 'loading') {
130
+ <div class="state">{'Loading...'}</div>
131
+ } else if (status === 'success') {
132
+ <div class="state">{'Success!'}</div>
133
+ } else {
134
+ <div class="state">{'Error occurred'}</div>
135
+ }
136
+ </div>
137
+ </>;
124
138
  }