ripple 0.3.72 → 0.3.76

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 (172) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +4 -10
  4. package/src/runtime/dynamic-client.js +33 -0
  5. package/src/runtime/dynamic-server.js +80 -0
  6. package/src/runtime/index-client.js +5 -13
  7. package/src/runtime/index-server.js +2 -0
  8. package/src/runtime/internal/client/blocks.js +6 -27
  9. package/src/runtime/internal/client/composite.js +11 -6
  10. package/src/runtime/internal/client/for.js +80 -5
  11. package/src/runtime/internal/client/index.js +0 -2
  12. package/src/runtime/internal/client/render.js +5 -2
  13. package/src/runtime/internal/client/types.d.ts +0 -10
  14. package/src/runtime/internal/server/index.js +8 -1
  15. package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
  16. package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
  18. package/tests/client/array/array.copy-within.test.tsrx +19 -19
  19. package/tests/client/array/array.derived.test.tsrx +97 -109
  20. package/tests/client/array/array.iteration.test.tsrx +28 -28
  21. package/tests/client/array/array.mutations.test.tsrx +68 -68
  22. package/tests/client/array/array.static.test.tsrx +82 -92
  23. package/tests/client/array/array.to-methods.test.tsrx +15 -15
  24. package/tests/client/async-suspend.test.tsrx +180 -179
  25. package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
  26. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
  27. package/tests/client/basic/basic.attributes.test.tsrx +273 -317
  28. package/tests/client/basic/basic.collections.test.tsrx +55 -61
  29. package/tests/client/basic/basic.components.test.tsrx +198 -220
  30. package/tests/client/basic/basic.errors.test.tsrx +70 -76
  31. package/tests/client/basic/basic.events.test.tsrx +80 -85
  32. package/tests/client/basic/basic.get-set.test.tsrx +54 -64
  33. package/tests/client/basic/basic.hmr.test.tsrx +15 -19
  34. package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
  35. package/tests/client/basic/basic.rendering.test.tsrx +273 -178
  36. package/tests/client/basic/basic.styling.test.tsrx +16 -14
  37. package/tests/client/basic/basic.utilities.test.tsrx +8 -10
  38. package/tests/client/boundaries.test.tsrx +18 -18
  39. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
  40. package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
  41. package/tests/client/compiler/compiler.basic.test.tsrx +357 -288
  42. package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
  43. package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
  44. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  45. package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
  46. package/tests/client/composite/composite.dynamic-components.test.tsrx +62 -47
  47. package/tests/client/composite/composite.generics.test.tsrx +165 -167
  48. package/tests/client/composite/composite.props.test.tsrx +66 -74
  49. package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
  50. package/tests/client/composite/composite.render.test.tsrx +92 -101
  51. package/tests/client/computed-properties.test.tsrx +14 -18
  52. package/tests/client/context.test.tsrx +14 -18
  53. package/tests/client/css/global-additional-cases.test.tsrx +493 -439
  54. package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
  55. package/tests/client/css/global-at-rules.test.tsrx +71 -66
  56. package/tests/client/css/global-basic.test.tsrx +105 -98
  57. package/tests/client/css/global-classes-ids.test.tsrx +128 -114
  58. package/tests/client/css/global-combinators.test.tsrx +83 -78
  59. package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
  60. package/tests/client/css/global-edge-cases.test.tsrx +138 -120
  61. package/tests/client/css/global-keyframes.test.tsrx +108 -96
  62. package/tests/client/css/global-nested.test.tsrx +88 -78
  63. package/tests/client/css/global-pseudo.test.tsrx +104 -98
  64. package/tests/client/css/global-scoping.test.tsrx +145 -125
  65. package/tests/client/css/style-identifier.test.tsrx +65 -72
  66. package/tests/client/date.test.tsrx +83 -83
  67. package/tests/client/dynamic-elements.test.tsrx +318 -299
  68. package/tests/client/events.test.tsrx +252 -266
  69. package/tests/client/for.test.tsrx +120 -127
  70. package/tests/client/head.test.tsrx +74 -48
  71. package/tests/client/html.test.tsrx +37 -49
  72. package/tests/client/input-value.test.tsrx +1125 -1354
  73. package/tests/client/lazy-array.test.tsrx +10 -16
  74. package/tests/client/lazy-destructuring.test.tsrx +169 -221
  75. package/tests/client/map.test.tsrx +39 -41
  76. package/tests/client/media-query.test.tsrx +15 -19
  77. package/tests/client/object.test.tsrx +46 -56
  78. package/tests/client/portal.test.tsrx +31 -37
  79. package/tests/client/ref.test.tsrx +173 -193
  80. package/tests/client/return.test.tsrx +62 -37
  81. package/tests/client/set.test.tsrx +33 -33
  82. package/tests/client/svg.test.tsrx +197 -216
  83. package/tests/client/switch.test.tsrx +201 -191
  84. package/tests/client/track-async-hydration.test.tsrx +14 -18
  85. package/tests/client/tracked-index-access.test.tsrx +18 -28
  86. package/tests/client/try.test.tsrx +494 -619
  87. package/tests/client/tsx.test.tsrx +286 -292
  88. package/tests/client/typescript-generics.test.tsrx +121 -129
  89. package/tests/client/url/url.derived.test.tsrx +21 -25
  90. package/tests/client/url/url.parsing.test.tsrx +35 -35
  91. package/tests/client/url/url.partial-removal.test.tsrx +32 -32
  92. package/tests/client/url/url.reactivity.test.tsrx +68 -72
  93. package/tests/client/url/url.serialization.test.tsrx +8 -8
  94. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
  95. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
  96. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
  97. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
  98. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
  99. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
  100. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
  101. package/tests/hydration/compiled/client/basic.js +390 -319
  102. package/tests/hydration/compiled/client/composite.js +52 -44
  103. package/tests/hydration/compiled/client/for.js +734 -604
  104. package/tests/hydration/compiled/client/head.js +183 -103
  105. package/tests/hydration/compiled/client/html.js +93 -86
  106. package/tests/hydration/compiled/client/if-children.js +95 -71
  107. package/tests/hydration/compiled/client/if.js +113 -89
  108. package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
  109. package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
  110. package/tests/hydration/compiled/client/reactivity.js +26 -24
  111. package/tests/hydration/compiled/client/return.js +8 -42
  112. package/tests/hydration/compiled/client/switch.js +208 -173
  113. package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
  114. package/tests/hydration/compiled/client/try.js +29 -21
  115. package/tests/hydration/compiled/server/basic.js +210 -221
  116. package/tests/hydration/compiled/server/composite.js +13 -14
  117. package/tests/hydration/compiled/server/for.js +427 -444
  118. package/tests/hydration/compiled/server/head.js +199 -189
  119. package/tests/hydration/compiled/server/html.js +33 -41
  120. package/tests/hydration/compiled/server/if-children.js +114 -117
  121. package/tests/hydration/compiled/server/if.js +77 -83
  122. package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
  123. package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
  124. package/tests/hydration/compiled/server/reactivity.js +24 -22
  125. package/tests/hydration/compiled/server/return.js +6 -18
  126. package/tests/hydration/compiled/server/switch.js +179 -176
  127. package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
  128. package/tests/hydration/compiled/server/try.js +31 -35
  129. package/tests/hydration/components/basic.tsrx +216 -258
  130. package/tests/hydration/components/composite.tsrx +32 -42
  131. package/tests/hydration/components/events.tsrx +81 -101
  132. package/tests/hydration/components/for.tsrx +270 -336
  133. package/tests/hydration/components/head.tsrx +43 -39
  134. package/tests/hydration/components/hmr.tsrx +16 -22
  135. package/tests/hydration/components/html-in-template.tsrx +15 -21
  136. package/tests/hydration/components/html.tsrx +442 -526
  137. package/tests/hydration/components/if-children.tsrx +107 -125
  138. package/tests/hydration/components/if.tsrx +68 -90
  139. package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
  140. package/tests/hydration/components/nested-control-flow.tsrx +202 -216
  141. package/tests/hydration/components/portal.tsrx +33 -41
  142. package/tests/hydration/components/reactivity.tsrx +26 -34
  143. package/tests/hydration/components/return.tsrx +4 -6
  144. package/tests/hydration/components/switch.tsrx +73 -78
  145. package/tests/hydration/components/track-async-serialization.tsrx +83 -93
  146. package/tests/hydration/components/try.tsrx +37 -51
  147. package/tests/hydration/switch.test.js +8 -8
  148. package/tests/server/await.test.tsrx +3 -3
  149. package/tests/server/basic.attributes.test.tsrx +117 -162
  150. package/tests/server/basic.components.test.tsrx +164 -194
  151. package/tests/server/basic.test.tsrx +299 -199
  152. package/tests/server/compiler.test.tsrx +142 -72
  153. package/tests/server/composite.props.test.tsrx +54 -58
  154. package/tests/server/composite.test.tsrx +165 -167
  155. package/tests/server/context.test.tsrx +13 -17
  156. package/tests/server/dynamic-elements.test.tsrx +147 -148
  157. package/tests/server/for.test.tsrx +115 -84
  158. package/tests/server/head.test.tsrx +54 -31
  159. package/tests/server/html-nesting-validation.test.tsrx +16 -8
  160. package/tests/server/if.test.tsrx +49 -59
  161. package/tests/server/lazy-destructuring.test.tsrx +288 -366
  162. package/tests/server/return.test.tsrx +58 -36
  163. package/tests/server/streaming-ssr.test.tsrx +4 -4
  164. package/tests/server/style-identifier.test.tsrx +61 -69
  165. package/tests/server/switch.test.tsrx +89 -97
  166. package/tests/server/track-async-serialization.test.tsrx +85 -103
  167. package/tests/server/try.test.tsrx +275 -360
  168. package/tests/utils/ref-types.test.js +72 -0
  169. package/tests/utils/vite-plugin-config.test.js +41 -74
  170. package/types/index.d.ts +29 -4
  171. package/src/runtime/internal/client/compat.js +0 -40
  172. package/tests/utils/compiler-compat-config.test.js +0 -38
@@ -1,89 +1,114 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import { compile } from '@tsrx/ripple';
3
3
 
4
- const TSRX_RETURN_ERROR = 'Return statements are not allowed inside TSRX templates. Move the return before the TSRX return value, or use conditional rendering instead.';
5
-
6
- describe('returns in prohibited scopes', () => {
4
+ describe('returns in restricted scopes', () => {
7
5
  it('throws error when return is used in module scope', () => {
8
6
  expect(
9
7
  () => compile(`
10
8
  return;
11
- function App() { return <>
9
+ function App() @{
12
10
  <div>{'hello'}</div>
13
- </>; }
11
+ }
14
12
  `, 'test.tsrx', {
15
13
  mode: 'client',
16
14
  }),
17
15
  ).toThrow('Return statements are not allowed at the top level of a module.');
18
16
  });
19
17
 
20
- it('throws when return is used inside a TSRX fragment', () => {
18
+ it('allows returns inside regular functions declared in TSRX templates', () => {
21
19
  expect(
22
20
  () => compile(
23
21
  `
24
- function App() {
25
- return <>
26
- if (ready) {
27
- return;
22
+ function App() @{
23
+ function label() {
24
+ return 'ready';
28
25
  }
29
- <div>{'ready'}</div>
30
- </>;
26
+ <div>{label()}</div>
31
27
  }
32
28
  `,
33
29
  'test.tsrx',
34
30
  { mode: 'client' },
35
31
  ),
36
- ).toThrow(TSRX_RETURN_ERROR);
32
+ ).not.toThrow();
37
33
  });
38
34
 
39
- it('throws when return is used inside a TSRX element', () => {
35
+ it('compiles template directives inside templates', () => {
40
36
  expect(
41
37
  () => compile(
42
38
  `
43
- function App() {
44
- return <section>
45
- if (ready) {
46
- return null;
47
- }
48
- <div>{'ready'}</div>
49
- </section>;
50
- }
39
+ function App() @{
40
+ <>
41
+ @if (ready) {
42
+ <div>yielded</div>
43
+ }
44
+ <span>after</span>
45
+ </>
46
+ }
51
47
  `,
52
48
  'test.tsrx',
53
49
  { mode: 'client' },
54
50
  ),
55
- ).toThrow(TSRX_RETURN_ERROR);
51
+ ).not.toThrow();
56
52
  });
53
+ });
57
54
 
58
- it('allows returns inside regular functions declared in TSRX templates', () => {
55
+ describe('function returns in client components', () => {
56
+ it('renders template directive branches alongside outer siblings', () => {
57
+ function App() @{
58
+ const ready = true;
59
+ <>
60
+ @if (ready) {
61
+ <div class="yielded">yielded</div>
62
+ }
63
+ <span class="outer">outer</span>
64
+ </>
65
+ }
66
+
67
+ render(App);
68
+ expect(container.querySelector('.yielded')?.textContent).toBe('yielded');
69
+ expect(container.querySelector('.outer')?.textContent).toBe('outer');
70
+ });
71
+
72
+ it('allows plain JavaScript control flow in setup when rendered output follows', () => {
59
73
  expect(
60
74
  () => compile(
61
75
  `
62
- function App() {
63
- return <>
64
- function label() {
65
- return 'ready';
66
- }
67
- <div>{label()}</div>
68
- </>;
69
- }
70
- `,
76
+ function App() @{
77
+ const items = [1, 2, 3];
78
+ for (const item of items) {
79
+ <div>{item}</div>
80
+ }
81
+ <></>
82
+ }
83
+ `,
71
84
  'test.tsrx',
72
85
  { mode: 'client' },
73
86
  ),
74
87
  ).not.toThrow();
75
88
  });
76
- });
77
89
 
78
- describe('function returns in client components', () => {
90
+ it('renders TSRX return arguments and skips later siblings', () => {
91
+ function App() @{
92
+ const ready = true;
93
+ if (ready) {
94
+ return <div class="returned">returned</div>;
95
+ }
96
+ <span class="after">after</span>
97
+ }
98
+
99
+ render(App);
100
+ expect(container.querySelector('.returned')?.textContent).toBe('returned');
101
+ expect(container.querySelector('.after')).toBeNull();
102
+ });
103
+
79
104
  it('allows guard returns before TSRX output', () => {
80
- function App() {
105
+ function App() @{
81
106
  const ready = true;
82
107
  if (!ready) {
83
108
  return null;
84
109
  }
85
110
 
86
- return <><div class="ready">{'ready'}</div></>;
111
+ <div class="ready">{'ready'}</div>
87
112
  }
88
113
 
89
114
  render(App);
@@ -2,20 +2,20 @@ import { RippleSet, flushSync, track } from 'ripple';
2
2
 
3
3
  describe('RippleSet', () => {
4
4
  it('handles add and delete operations', () => {
5
- function SetTest() {
6
- return <>
7
- let items = new RippleSet([1, 2, 3]);
5
+ function SetTest() @{
6
+ let items = new RippleSet([1, 2, 3]);
7
+ <>
8
8
  <button onClick={() => items.add(4)}>{'add'}</button>
9
9
  <button onClick={() => items.delete(2)}>{'delete'}</button>
10
10
  <Child {items} />
11
- </>;
11
+ </>
12
12
  }
13
13
 
14
- function Child({ items }: { items: RippleSet<number> }) {
15
- return <>
14
+ function Child({ items }: { items: RippleSet<number> }) @{
15
+ <>
16
16
  <pre>{JSON.stringify(items)}</pre>
17
17
  <pre>{items.size}</pre>
18
- </>;
18
+ </>
19
19
  }
20
20
 
21
21
  render(SetTest);
@@ -37,19 +37,19 @@ describe('RippleSet', () => {
37
37
  });
38
38
 
39
39
  it('handles clear operation', () => {
40
- function SetTest() {
41
- return <>
42
- let items = new RippleSet([1, 2, 3]);
40
+ function SetTest() @{
41
+ let items = new RippleSet([1, 2, 3]);
42
+ <>
43
43
  <button onClick={() => items.clear()}>{'clear'}</button>
44
44
  <Child {items} />
45
- </>;
45
+ </>
46
46
  }
47
47
 
48
- function Child({ items }: { items: RippleSet<number> }) {
49
- return <>
48
+ function Child({ items }: { items: RippleSet<number> }) @{
49
+ <>
50
50
  <pre>{JSON.stringify(items)}</pre>
51
51
  <pre>{items.size}</pre>
52
- </>;
52
+ </>
53
53
  }
54
54
 
55
55
  render(SetTest);
@@ -64,13 +64,13 @@ describe('RippleSet', () => {
64
64
  });
65
65
 
66
66
  it('handles has operation', () => {
67
- function SetTest() {
68
- return <>
69
- let items = new RippleSet([1, 2, 3]);
70
- let &[hasValue] = track(() => items.has(2));
67
+ function SetTest() @{
68
+ let items = new RippleSet([1, 2, 3]);
69
+ let &[hasValue] = track(() => items.has(2));
70
+ <>
71
71
  <button onClick={() => items.delete(2)}>{'delete'}</button>
72
72
  <pre>{hasValue}</pre>
73
- </>;
73
+ </>
74
74
  }
75
75
 
76
76
  render(SetTest);
@@ -86,12 +86,12 @@ describe('RippleSet', () => {
86
86
  });
87
87
 
88
88
  it('creates empty RippleSet using RippleSet() shorthand syntax', () => {
89
- function SetTest() {
90
- return <>
91
- let items = RippleSet();
89
+ function SetTest() @{
90
+ let items = new RippleSet();
91
+ <>
92
92
  <button onClick={() => items.add(1)}>{'add'}</button>
93
93
  <pre>{items.size}</pre>
94
- </>;
94
+ </>
95
95
  }
96
96
 
97
97
  render(SetTest);
@@ -106,14 +106,14 @@ describe('RippleSet', () => {
106
106
  });
107
107
 
108
108
  it('creates RippleSet with initial values using RippleSet() shorthand syntax', () => {
109
- function SetTest() {
110
- return <>
111
- let items = RippleSet([1, 2, 3, 4]);
112
- let &[hasValue] = track(() => items.has(3));
109
+ function SetTest() @{
110
+ let items = new RippleSet([1, 2, 3, 4]);
111
+ let &[hasValue] = track(() => items.has(3));
112
+ <>
113
113
  <button onClick={() => items.delete(3)}>{'delete'}</button>
114
114
  <pre>{items.size}</pre>
115
115
  <pre>{hasValue}</pre>
116
- </>;
116
+ </>
117
117
  }
118
118
 
119
119
  render(SetTest);
@@ -130,16 +130,16 @@ describe('RippleSet', () => {
130
130
  });
131
131
 
132
132
  it('handles all operations with RippleSet() shorthand syntax', () => {
133
- function SetTest() {
134
- return <>
135
- let items = RippleSet([10, 20, 30]);
136
- let &[values] = track(() => Array.from(items.values()));
133
+ function SetTest() @{
134
+ let items = new RippleSet([10, 20, 30]);
135
+ let &[values] = track(() => Array.from(items.values()));
136
+ <>
137
137
  <button onClick={() => items.add(40)}>{'add'}</button>
138
138
  <button onClick={() => items.delete(20)}>{'delete'}</button>
139
139
  <button onClick={() => items.clear()}>{'clear'}</button>
140
140
  <pre>{JSON.stringify(values)}</pre>
141
141
  <pre>{items.size}</pre>
142
- </>;
142
+ </>
143
143
  }
144
144
 
145
145
  render(SetTest);