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
@@ -1,21 +1,23 @@
1
1
  import { track } from 'ripple';
2
2
  import { compile } from '@tsrx/ripple';
3
3
 
4
- describe('{style} directive', () => {
4
+ describe('style refs', () => {
5
5
  describe('basic usage with components', () => {
6
- it('passes scoped class to a child component via {style}', () => {
7
- component Child({ className }: { className: string }) {
8
- <div class={className}>{'styled child'}</div>
6
+ it('passes scoped classes to a child component via a style ref', () => {
7
+ function Child({ className }: { className: string }) {
8
+ return <><div class={className}>{'styled child'}</div></>;
9
9
  }
10
10
 
11
- component Parent() {
12
- <Child className={style 'highlight'} />
13
-
14
- <style>
15
- .highlight {
16
- color: red;
17
- }
18
- </style>
11
+ function Parent() {
12
+ let styles;
13
+ return <>
14
+ <Child className={styles.highlight} />
15
+ <style ref={(s) => (styles = s)}>
16
+ .highlight {
17
+ color: red;
18
+ }
19
+ </style>
20
+ </>;
19
21
  }
20
22
 
21
23
  render(Parent);
@@ -28,23 +30,27 @@ describe('{style} directive', () => {
28
30
  expect(classes.some((cls: string) => cls === 'highlight')).toBe(true);
29
31
  });
30
32
 
31
- it('passes multiple {style} classes to a child component', () => {
32
- component Child({ primary, secondary }: { primary: string; secondary: string }) {
33
- <div class={primary}>{'primary'}</div>
34
- <span class={secondary}>{'secondary'}</span>
33
+ it('passes multiple style ref classes to a child component', () => {
34
+ function Child({ primary, secondary }: { primary: string; secondary: string }) {
35
+ return <>
36
+ <div class={primary}>{'primary'}</div>
37
+ <span class={secondary}>{'secondary'}</span>
38
+ </>;
35
39
  }
36
40
 
37
- component Parent() {
38
- <Child primary={style 'primary'} secondary={style 'secondary'} />
39
-
40
- <style>
41
- .primary {
42
- color: blue;
43
- }
44
- .secondary {
45
- color: gray;
46
- }
47
- </style>
41
+ function Parent() {
42
+ let styles;
43
+ return <>
44
+ <Child primary={styles.primary} secondary={styles.secondary} />
45
+ <style ref={(s) => (styles = s)}>
46
+ .primary {
47
+ color: blue;
48
+ }
49
+ .secondary {
50
+ color: gray;
51
+ }
52
+ </style>
53
+ </>;
48
54
  }
49
55
 
50
56
  render(Parent);
@@ -64,40 +70,45 @@ describe('{style} directive', () => {
64
70
  expect(spanClasses.some((cls: string) => cls === 'secondary')).toBe(true);
65
71
  });
66
72
 
67
- it('allows {style} props on child components with children', () => {
73
+ it('allows style ref classes on child components with children', () => {
68
74
  const source = `
69
- component Child({ className }) {
75
+ function Child({ className }) { return <>
70
76
  <div class={className}>"hello world"</div>
71
- }
72
- component App() {
73
- <Child className={style 'container'}>"hello world"</Child>
74
-
75
- <style>
76
- .container {
77
- color: red;
78
- }
79
- </style>
77
+ </>; }
78
+ function App() {
79
+ let styles;
80
+ return <>
81
+ <Child className={styles.container}>"hello world"</Child>
82
+
83
+ <style ref={(s) => styles = s}>
84
+ .container {
85
+ color: red;
86
+ }
87
+ </style>
88
+ </>;
80
89
  }`;
81
90
 
82
91
  expect(() => compile(source, 'test.tsrx')).not.toThrow();
83
92
  });
84
93
 
85
- it('passes scoped class to a dynamic child component via {style}', () => {
86
- component Child({ cls }: { cls: string }) {
87
- <span class={cls}>{'text'}</span>
94
+ it('passes scoped classes to a dynamic child component via a style ref', () => {
95
+ function Child({ cls }: { cls: string }) {
96
+ return <><span class={cls}>{'text'}</span></>;
88
97
  }
89
98
 
90
- component Parent() {
91
- let dynamic = track(() => Child);
92
- <div class="wrapper">
93
- <@dynamic cls={style 'text'} />
94
- </div>
95
-
96
- <style>
97
- .text {
98
- color: red;
99
- }
100
- </style>
99
+ function Parent() {
100
+ let styles;
101
+ return <>
102
+ let dynamic = track(() => Child);
103
+ <div class="wrapper">
104
+ <@dynamic cls={styles.text} />
105
+ </div>
106
+ <style ref={(s) => (styles = s)}>
107
+ .text {
108
+ color: red;
109
+ }
110
+ </style>
111
+ </>;
101
112
  }
102
113
 
103
114
  render(Parent);
@@ -109,25 +120,28 @@ component App() {
109
120
  expect(classes.some((cls: string) => cls === 'text')).toBe(true);
110
121
  });
111
122
 
112
- it('child can combine its own classes with parent {style} class', () => {
113
- component Card({ className }: { className?: string }) {
114
- <div class={['card-base', className ?? '']}>{'card content'}</div>
115
-
116
- <style>
117
- .card-base {
118
- border: 1px solid black;
119
- }
120
- </style>
123
+ it('child can combine its own classes with a parent style ref class', () => {
124
+ function Card({ className }: { className?: string }) {
125
+ return <>
126
+ <div class={['card-base', className ?? '']}>{'card content'}</div>
127
+ <style>
128
+ .card-base {
129
+ border: 1px solid black;
130
+ }
131
+ </style>
132
+ </>;
121
133
  }
122
134
 
123
- component App() {
124
- <Card className={style 'themed'} />
125
-
126
- <style>
127
- .themed {
128
- background: purple;
129
- }
130
- </style>
135
+ function App() {
136
+ let styles;
137
+ return <>
138
+ <Card className={styles.themed} />
139
+ <style ref={(s) => (styles = s)}>
140
+ .themed {
141
+ background: purple;
142
+ }
143
+ </style>
144
+ </>;
131
145
  }
132
146
 
133
147
  render(App);
@@ -139,24 +153,26 @@ component App() {
139
153
  expect(classes.some((cls: string) => cls === 'themed')).toBe(true);
140
154
  });
141
155
 
142
- it('passes standalone class to child even when it also appears in descendant context', () => {
143
- component Child({ cls }: { cls: string }) {
144
- <span class={cls}>{'text'}</span>
156
+ it('passes a standalone class even when it also appears in descendant context', () => {
157
+ function Child({ cls }: { cls: string }) {
158
+ return <><span class={cls}>{'text'}</span></>;
145
159
  }
146
160
 
147
- component App() {
148
- <div class="parent">
149
- <Child cls={style 'dual'} />
150
- </div>
151
-
152
- <style>
153
- .dual {
154
- color: blue;
155
- }
156
- .parent .dual {
157
- font-weight: bold;
158
- }
159
- </style>
161
+ function App() {
162
+ let styles;
163
+ return <>
164
+ <div class="parent">
165
+ <Child cls={styles.dual} />
166
+ </div>
167
+ <style ref={(s) => (styles = s)}>
168
+ .dual {
169
+ color: blue;
170
+ }
171
+ .parent .dual {
172
+ font-weight: bold;
173
+ }
174
+ </style>
175
+ </>;
160
176
  }
161
177
 
162
178
  render(App);
@@ -169,246 +185,82 @@ component App() {
169
185
  });
170
186
  });
171
187
 
172
- describe('compile errors', () => {
173
- it('errors when {style} is used directly on a DOM element', () => {
188
+ describe('removed syntax', () => {
189
+ it('does not parse the old style directive in attributes', () => {
174
190
  const source = `
175
- component App() {
176
- <div class={style 'box'}>{'content'}</div>
177
-
178
- <style>
179
- .box {
180
- padding: 10px;
181
- }
182
- </style>
183
- }`;
184
- expect(() => compile(source, 'test.tsrx')).toThrow(/cannot be used directly on DOM elements/);
185
- });
186
-
187
- it('errors when {style} is used directly on a DOM element class', () => {
188
- const source = `
189
- component App() {
190
- <div class={style 'container'}>{'content'}</div>
191
-
192
- <style>
193
- .container {
194
- margin: 0 auto;
195
- }
196
- </style>
197
- }`;
198
- expect(() => compile(source, 'test.tsrx')).toThrow(/cannot be used directly on DOM elements/);
199
- });
200
-
201
- it('errors when {style} references a class in a compound selector passed to component', () => {
202
- const source = `
203
- component Child({ cls }) {
204
- <span class={cls}>{'text'}</span>
205
- }
206
- component App() {
207
- <Child cls={style 'special'} />
208
-
209
- <style>
210
- span.special {
211
- color: red;
212
- }
213
- </style>
214
- }`;
215
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
216
- });
217
-
218
- it('errors if descendant class is attempted to be passed in to child component', () => {
219
- const source = `
220
- component Child({ cls }: { cls: string }) {
221
- <span class={cls}>{'text'}</span>
222
- }
223
-
224
- component App() {
225
- <div class="wrapper">
226
- <Child
227
- cls={style 'nested'}
228
- />
229
- </div>
230
-
231
- <style>
232
- .wrapper .nested {
233
- color: red;
234
- }
235
- </style>
236
- }
237
-
238
- render(App);
239
- `;
240
-
241
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
242
- });
243
-
244
- it('errors if combinator class is attempted to be passed in to child component', () => {
245
- const source = `
246
- component Child({ cls }) {
247
- <p class={cls}>{'text'}</p>
248
- }
249
-
250
- component App() {
251
- <div class="parent">
252
- <Child
253
- // @ts-expect-error - cannot use child combinator class as standalone
254
- // @ripple-expect-error - cannot use child combinator class as standalone
255
- cls={style 'child'}
256
- />
257
- </div>
258
-
259
- <style>
260
- .parent > .child {
261
- font-size: 14px;
262
- }
263
- </style>
264
- }
265
-
266
- render(App);
267
- `;
268
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
269
- });
270
-
271
- it('errors if compound class is attempted to be passed in to child component', () => {
272
- const source = `
273
- component Child({ cls }) {
274
- <p class={cls}>{'text'}</p>
275
- }
276
-
277
- component App() {
278
- <div class="parent">
279
- <Child
280
- // @ts-expect-error - cannot use compound class as standalone
281
- // @ripple-expect-error - cannot use compound class as standalone
282
- cls={style 'child'}
283
- />
284
- </div>
285
-
286
- <style>
287
- .parent.child {
288
- font-size: 14px;
289
- }
290
- </style>
291
- }
292
-
293
- render(App);
294
- `;
295
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
296
- });
297
-
298
- it('errors if descendant {style} class is used on a dynamic component', () => {
299
- const source = `
300
-
301
- component Child({ cls }) {
302
- <span class={cls}>{'text'}</span>
303
- }
304
-
305
- component App() {
306
- let dynamic = track(() => Child);
307
- <div class="wrapper">
308
- <@dynamic cls={style 'nested'} />
309
- </div>
310
-
311
- <style>
312
- .wrapper .nested {
313
- color: red;
314
- }
315
- </style>
316
- }
317
-
318
- render(App);
319
- `;
320
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
321
- });
322
-
323
- it('errors when {style} references a class that does not exist in the style block', () => {
324
- const source = `
325
- component Child({ cls }) {
191
+ function Child({ cls }) { return <>
326
192
  <div class={cls}>{'text'}</div>
327
- }
328
- component App() {
329
- <Child cls={style 'missing'} />
330
-
331
- <style>
332
- .other {
333
- color: blue;
334
- }
335
- </style>
336
- }`;
337
- expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
338
- });
339
-
340
- it('errors when {style} is used with a dynamic expression', () => {
341
- const source = `
342
- component Child({ cls }) {
343
- <div class={cls}>{'text'}</div>
344
- }
345
- component App() {
346
- const key = 'highlight';
347
- <Child cls={style 'highlight' + key} />
193
+ </>; }
194
+ function App() { return <>
195
+ <Child cls={style 'highlight'} />
348
196
 
349
197
  <style>
350
198
  .highlight {
351
199
  color: red;
352
200
  }
353
201
  </style>
354
- }`;
355
- expect(() => compile(source, 'test.tsrx')).toThrow(/must be used in the form/);
202
+ </>; }`;
203
+ expect(() => compile(source, 'test.tsrx')).toThrow();
356
204
  });
357
205
 
358
- it('errors when {style} is used as a child expression', () => {
359
- const source = `component App() {
206
+ it('does not parse the old style directive as a child expression', () => {
207
+ const source = `function App() { return <>
360
208
  <div>{style 'foo'}</div>
361
209
  <style>
362
210
  .foo {
363
211
  color: red;
364
212
  }
365
213
  </style>
366
- }`;
367
- expect(() => compile(source, 'test.tsrx')).toThrow(
368
- /can only be used as an element attribute value/,
369
- );
214
+ </>; }`;
215
+ expect(() => compile(source, 'test.tsrx')).toThrow();
370
216
  });
371
217
  });
372
218
 
373
219
  describe('compiler output', () => {
374
- it('inlines scoped class strings for client mode', () => {
220
+ it('emits style class maps for client mode', () => {
375
221
  const source = `
376
- component Child({ cls }) {
222
+ function Child({ cls }) { return <>
377
223
  <div class={cls}>{'text'}</div>
378
- }
379
- export component App() {
380
- <Child cls={style 'highlight'} />
381
-
382
- <style>
383
- .highlight {
384
- color: red;
385
- }
386
- </style>
224
+ </>; }
225
+ export function App() {
226
+ let styles;
227
+ return <>
228
+ <Child cls={styles.highlight} />
229
+
230
+ <style ref={(s) => styles = s}>
231
+ .highlight {
232
+ color: red;
233
+ }
234
+ </style>
235
+ </>;
387
236
  }`;
388
237
  const { code } = compile(source, 'test.tsrx');
389
238
 
390
239
  expect(code).toContain('highlight');
391
- expect(code).toMatch(/tsrx-[a-z0-9]+/);
240
+ expect(code).toMatch(/tsrx-[a-z0-9]+ highlight/);
392
241
  });
393
242
 
394
- it('inlines scoped class strings for server mode', () => {
243
+ it('emits style class maps for server mode', () => {
395
244
  const source = `
396
- component Child({ cls }) {
245
+ function Child({ cls }) { return <>
397
246
  <div class={cls}>{'text'}</div>
398
- }
399
- export component App() {
400
- <Child cls={style 'highlight'} />
401
-
402
- <style>
403
- .highlight {
404
- color: red;
405
- }
406
- </style>
247
+ </>; }
248
+ export function App() {
249
+ let styles;
250
+ return <>
251
+ <Child cls={styles.highlight} />
252
+
253
+ <style ref={(s) => styles = s}>
254
+ .highlight {
255
+ color: red;
256
+ }
257
+ </style>
258
+ </>;
407
259
  }`;
408
260
  const { code } = compile(source, 'test.tsrx', { mode: 'server' });
409
261
 
410
262
  expect(code).toContain('highlight');
411
- expect(code).toMatch(/tsrx-[a-z0-9]+/);
263
+ expect(code).toMatch(/tsrx-[a-z0-9]+ highlight/);
412
264
  });
413
265
  });
414
266
  });