ripple 0.3.2 → 0.3.4

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 (128) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/package.json +2 -2
  3. package/src/compiler/identifier-utils.js +0 -2
  4. package/src/compiler/phases/1-parse/index.js +101 -195
  5. package/src/compiler/phases/2-analyze/index.js +82 -174
  6. package/src/compiler/phases/2-analyze/prune.js +2 -2
  7. package/src/compiler/phases/3-transform/client/index.js +174 -264
  8. package/src/compiler/phases/3-transform/segments.js +0 -22
  9. package/src/compiler/phases/3-transform/server/index.js +185 -42
  10. package/src/compiler/types/index.d.ts +14 -33
  11. package/src/compiler/utils.js +32 -20
  12. package/src/runtime/index-client.js +0 -17
  13. package/src/runtime/internal/client/bindings.js +118 -7
  14. package/src/runtime/internal/client/render.js +5 -1
  15. package/src/runtime/internal/client/runtime.js +1 -1
  16. package/src/runtime/internal/client/types.d.ts +4 -0
  17. package/tests/client/array/array.copy-within.test.ripple +7 -7
  18. package/tests/client/array/array.derived.test.ripple +24 -24
  19. package/tests/client/array/array.iteration.test.ripple +7 -7
  20. package/tests/client/array/array.mutations.test.ripple +17 -17
  21. package/tests/client/array/array.to-methods.test.ripple +4 -4
  22. package/tests/client/async-suspend.test.ripple +3 -3
  23. package/tests/client/basic/basic.attributes.test.ripple +31 -31
  24. package/tests/client/basic/basic.collections.test.ripple +6 -6
  25. package/tests/client/basic/basic.components.test.ripple +8 -8
  26. package/tests/client/basic/basic.errors.test.ripple +31 -34
  27. package/tests/client/basic/basic.events.test.ripple +11 -11
  28. package/tests/client/basic/basic.get-set.test.ripple +18 -18
  29. package/tests/client/basic/basic.reactivity.test.ripple +36 -36
  30. package/tests/client/basic/basic.rendering.test.ripple +7 -7
  31. package/tests/client/basic/basic.utilities.test.ripple +4 -4
  32. package/tests/client/boundaries.test.ripple +7 -7
  33. package/tests/client/compiler/__snapshots__/compiler.typescript.test.ripple.snap +24 -0
  34. package/tests/client/compiler/compiler.assignments.test.ripple +12 -10
  35. package/tests/client/compiler/compiler.basic.test.ripple +58 -60
  36. package/tests/client/compiler/compiler.tracked-access.test.ripple +14 -8
  37. package/tests/client/compiler/compiler.typescript.test.ripple +31 -0
  38. package/tests/client/composite/composite.dynamic-components.test.ripple +6 -6
  39. package/tests/client/composite/composite.props.test.ripple +9 -9
  40. package/tests/client/composite/composite.reactivity.test.ripple +23 -23
  41. package/tests/client/composite/composite.render.test.ripple +52 -4
  42. package/tests/client/computed-properties.test.ripple +3 -3
  43. package/tests/client/context.test.ripple +3 -3
  44. package/tests/client/css/global-additional-cases.test.ripple +5 -2
  45. package/tests/client/css/style-identifier.test.ripple +40 -49
  46. package/tests/client/date.test.ripple +39 -39
  47. package/tests/client/dynamic-elements.test.ripple +37 -37
  48. package/tests/client/events.test.ripple +25 -25
  49. package/tests/client/for.test.ripple +8 -8
  50. package/tests/client/head.test.ripple +7 -7
  51. package/tests/client/html.test.ripple +2 -2
  52. package/tests/client/input-value.test.ripple +376 -177
  53. package/tests/client/lazy-destructuring.test.ripple +185 -0
  54. package/tests/client/map.test.ripple +20 -20
  55. package/tests/client/media-query.test.ripple +4 -4
  56. package/tests/client/object.test.ripple +5 -5
  57. package/tests/client/portal.test.ripple +4 -4
  58. package/tests/client/ref.test.ripple +3 -3
  59. package/tests/client/return.test.ripple +17 -17
  60. package/tests/client/set.test.ripple +10 -10
  61. package/tests/client/svg.test.ripple +6 -5
  62. package/tests/client/switch.test.ripple +10 -10
  63. package/tests/client/tracked-expression.test.ripple +3 -1
  64. package/tests/client/try.test.ripple +4 -4
  65. package/tests/client/url/url.derived.test.ripple +6 -7
  66. package/tests/client/url/url.parsing.test.ripple +9 -9
  67. package/tests/client/url/url.partial-removal.test.ripple +9 -9
  68. package/tests/client/url/url.reactivity.test.ripple +16 -16
  69. package/tests/client/url/url.serialization.test.ripple +3 -3
  70. package/tests/client/url-search-params/url-search-params.derived.test.ripple +7 -8
  71. package/tests/client/url-search-params/url-search-params.initialization.test.ripple +6 -4
  72. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +12 -12
  73. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +18 -18
  74. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +16 -16
  75. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +4 -4
  76. package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +3 -3
  77. package/tests/hydration/build-components.js +4 -10
  78. package/tests/hydration/compiled/client/basic.js +4 -4
  79. package/tests/hydration/compiled/client/events.js +2 -0
  80. package/tests/hydration/compiled/client/for.js +2 -0
  81. package/tests/hydration/compiled/client/head.js +13 -11
  82. package/tests/hydration/compiled/client/hmr.js +4 -2
  83. package/tests/hydration/compiled/client/html.js +82 -95
  84. package/tests/hydration/compiled/client/if-children.js +8 -9
  85. package/tests/hydration/compiled/client/if.js +2 -0
  86. package/tests/hydration/compiled/client/mixed-control-flow.js +4 -2
  87. package/tests/hydration/compiled/client/portal.js +1 -1
  88. package/tests/hydration/compiled/client/reactivity.js +2 -0
  89. package/tests/hydration/compiled/client/return.js +2 -0
  90. package/tests/hydration/compiled/client/switch.js +2 -0
  91. package/tests/hydration/compiled/server/composite.js +2 -2
  92. package/tests/hydration/compiled/server/events.js +2 -0
  93. package/tests/hydration/compiled/server/for.js +2 -0
  94. package/tests/hydration/compiled/server/head.js +13 -11
  95. package/tests/hydration/compiled/server/hmr.js +2 -0
  96. package/tests/hydration/compiled/server/html.js +2 -0
  97. package/tests/hydration/compiled/server/if-children.js +2 -0
  98. package/tests/hydration/compiled/server/if.js +2 -0
  99. package/tests/hydration/compiled/server/mixed-control-flow.js +2 -0
  100. package/tests/hydration/compiled/server/portal.js +1 -1
  101. package/tests/hydration/compiled/server/reactivity.js +2 -0
  102. package/tests/hydration/compiled/server/return.js +2 -0
  103. package/tests/hydration/compiled/server/switch.js +2 -0
  104. package/tests/hydration/components/composite.ripple +1 -1
  105. package/tests/hydration/components/events.ripple +10 -8
  106. package/tests/hydration/components/for.ripple +22 -20
  107. package/tests/hydration/components/head.ripple +8 -6
  108. package/tests/hydration/components/hmr.ripple +3 -1
  109. package/tests/hydration/components/html.ripple +3 -1
  110. package/tests/hydration/components/if-children.ripple +9 -7
  111. package/tests/hydration/components/if.ripple +7 -5
  112. package/tests/hydration/components/mixed-control-flow.ripple +5 -3
  113. package/tests/hydration/components/portal.ripple +2 -2
  114. package/tests/hydration/components/reactivity.ripple +11 -9
  115. package/tests/hydration/components/return.ripple +13 -11
  116. package/tests/hydration/components/switch.ripple +6 -4
  117. package/tests/server/__snapshots__/compiler.test.ripple.snap +22 -0
  118. package/tests/server/await.test.ripple +2 -2
  119. package/tests/server/basic.attributes.test.ripple +21 -19
  120. package/tests/server/basic.components.test.ripple +5 -4
  121. package/tests/server/basic.test.ripple +21 -20
  122. package/tests/server/compiler.test.ripple +36 -5
  123. package/tests/server/composite.props.test.ripple +7 -6
  124. package/tests/server/context.test.ripple +3 -1
  125. package/tests/server/dynamic-elements.test.ripple +24 -24
  126. package/tests/server/head.test.ripple +7 -5
  127. package/tests/server/style-identifier.test.ripple +95 -16
  128. package/types/index.d.ts +4 -1
@@ -1,7 +1,7 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
- export async function Layout(__output, { children }) {
4
+ export async function Layout(__output, __props) {
5
5
  return _$_.async(async () => {
6
6
  _$_.push_component();
7
7
  __output.push('<div');
@@ -10,7 +10,7 @@ export async function Layout(__output, { children }) {
10
10
 
11
11
  {
12
12
  {
13
- const comp = children;
13
+ const comp = __props.children;
14
14
  const args = [__output, {}];
15
15
 
16
16
  if (comp?.async) {
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function ClickCounter(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function StaticForLoop(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function StaticTitle(__output) {
5
7
  _$_.push_component();
6
8
  __output.push('<div');
@@ -12,7 +14,7 @@ export function StaticTitle(__output) {
12
14
 
13
15
  __output.push('</div>');
14
16
  __output.target = 'head';
15
- __output.push('<!--df6gdi-->');
17
+ __output.push('<!--qwqurq-->');
16
18
  __output.push('<title');
17
19
  __output.push('>');
18
20
 
@@ -46,7 +48,7 @@ export function ReactiveTitle(__output) {
46
48
 
47
49
  __output.push('</div>');
48
50
  __output.target = 'head';
49
- __output.push('<!--13wropz-->');
51
+ __output.push('<!--1h8nm28-->');
50
52
  __output.push('<title');
51
53
  __output.push('>');
52
54
 
@@ -70,7 +72,7 @@ export function MultipleHeadElements(__output) {
70
72
 
71
73
  __output.push('</div>');
72
74
  __output.target = 'head';
73
- __output.push('<!--jbv4cs-->');
75
+ __output.push('<!--9v67ol-->');
74
76
  __output.push('<title');
75
77
  __output.push('>');
76
78
 
@@ -105,7 +107,7 @@ export function ReactiveMetaTags(__output) {
105
107
 
106
108
  __output.push('</div>');
107
109
  __output.target = 'head';
108
- __output.push('<!--t794k2-->');
110
+ __output.push('<!--166unm-->');
109
111
  __output.push('<title');
110
112
  __output.push('>');
111
113
 
@@ -136,7 +138,7 @@ export function TitleWithTemplate(__output) {
136
138
 
137
139
  __output.push('</div>');
138
140
  __output.target = 'head';
139
- __output.push('<!--betaue-->');
141
+ __output.push('<!--3o3mh2-->');
140
142
  __output.push('<title');
141
143
  __output.push('>');
142
144
 
@@ -160,7 +162,7 @@ export function EmptyTitle(__output) {
160
162
 
161
163
  __output.push('</div>');
162
164
  __output.target = 'head';
163
- __output.push('<!--11sq4o6-->');
165
+ __output.push('<!--kwo3k6-->');
164
166
  __output.push('<title');
165
167
  __output.push('>');
166
168
 
@@ -188,7 +190,7 @@ export function ConditionalTitle(__output) {
188
190
 
189
191
  __output.push('</div>');
190
192
  __output.target = 'head';
191
- __output.push('<!--xxkmhn-->');
193
+ __output.push('<!--c2i5xr-->');
192
194
  __output.push('<title');
193
195
  __output.push('>');
194
196
 
@@ -223,7 +225,7 @@ export function ComputedTitle(__output) {
223
225
 
224
226
  __output.push('</div>');
225
227
  __output.target = 'head';
226
- __output.push('<!--1hj0can-->');
228
+ __output.push('<!--1h2z3z5-->');
227
229
  __output.push('<title');
228
230
  __output.push('>');
229
231
 
@@ -247,7 +249,7 @@ export function MultipleHeadBlocks(__output) {
247
249
 
248
250
  __output.push('</div>');
249
251
  __output.target = 'head';
250
- __output.push('<!--15ucmy3-->');
252
+ __output.push('<!--14rv3le-->');
251
253
  __output.push('<title');
252
254
  __output.push('>');
253
255
 
@@ -256,7 +258,7 @@ export function MultipleHeadBlocks(__output) {
256
258
  }
257
259
 
258
260
  __output.push('</title>');
259
- __output.push('<!--1xolofp-->');
261
+ __output.push('<!--1eh1mn5-->');
260
262
  __output.push('<meta');
261
263
  __output.push(' name="author"');
262
264
  __output.push(' content="Test Author"');
@@ -276,7 +278,7 @@ export function HeadWithStyle(__output) {
276
278
 
277
279
  __output.push('</div>');
278
280
  __output.target = 'head';
279
- __output.push('<!--q5et2p-->');
281
+ __output.push('<!--1dxk6yg-->');
280
282
  __output.push('<title');
281
283
  __output.push('>');
282
284
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export async function Layout(__output, { children }) {
5
7
  return _$_.async(async () => {
6
8
  _$_.push_component();
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function StaticHtml(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export async function IfWithChildren(__output, { children }) {
5
7
  return _$_.async(async () => {
6
8
  _$_.push_component();
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function IfTruthy(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export async function MixedControlFlowStatic(__output) {
5
7
  return _$_.async(async () => {
6
8
  _$_.push_component();
@@ -1,7 +1,7 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
- import { Portal } from 'ripple/server';
4
+ import { Portal, track } from 'ripple/server';
5
5
 
6
6
  export async function SimplePortal(__output) {
7
7
  return _$_.async(async () => {
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function TrackedState(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function DirectReturn(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,8 @@
1
1
  // @ts-nocheck
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
+ import { track } from 'ripple/server';
5
+
4
6
  export function SwitchStatic(__output) {
5
7
  _$_.push_component();
6
8
 
@@ -1,6 +1,6 @@
1
1
  import type { Component } from 'ripple';
2
2
 
3
- export component Layout({ children }: { children?: Component }) {
3
+ export component Layout(&{ children }: { children?: Component }) {
4
4
  <div class="layout">
5
5
  <children />
6
6
  </div>
@@ -1,7 +1,9 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // Event handling components for hydration testing
2
4
 
3
5
  export component ClickCounter() {
4
- let count = #ripple.track(0);
6
+ let count = track(0);
5
7
  <div>
6
8
  <button
7
9
  class="increment"
@@ -16,7 +18,7 @@ export component ClickCounter() {
16
18
  }
17
19
 
18
20
  export component IncrementDecrement() {
19
- let count = #ripple.track(0);
21
+ let count = track(0);
20
22
  <div>
21
23
  <button
22
24
  class="decrement"
@@ -39,8 +41,8 @@ export component IncrementDecrement() {
39
41
  }
40
42
 
41
43
  export component MultipleEvents() {
42
- let clicks = #ripple.track(0);
43
- let hovers = #ripple.track(0);
44
+ let clicks = track(0);
45
+ let hovers = track(0);
44
46
  <div>
45
47
  <button
46
48
  class="target"
@@ -59,8 +61,8 @@ export component MultipleEvents() {
59
61
  }
60
62
 
61
63
  export component MultiStateUpdate() {
62
- let count = #ripple.track(0);
63
- let lastAction = #ripple.track('none');
64
+ let count = track(0);
65
+ let lastAction = track('none');
64
66
 
65
67
  const handleClick = () => {
66
68
  @count++;
@@ -75,7 +77,7 @@ export component MultiStateUpdate() {
75
77
  }
76
78
 
77
79
  export component ToggleButton() {
78
- let isOn = #ripple.track(false);
80
+ let isOn = track(false);
79
81
  <div>
80
82
  <button
81
83
  class="toggle"
@@ -93,7 +95,7 @@ export component ChildButton(props: { onClick: () => void; label: string }) {
93
95
  }
94
96
 
95
97
  export component ParentWithChildButton() {
96
- let count = #ripple.track(0);
98
+ let count = track(0);
97
99
  <div>
98
100
  <ChildButton
99
101
  onClick={() => {
@@ -1,3 +1,5 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // For loop components for hydration testing
2
4
 
3
5
  export component StaticForLoop() {
@@ -32,7 +34,7 @@ export component KeyedForLoop() {
32
34
  }
33
35
 
34
36
  export component ReactiveForLoopAdd() {
35
- let items = #ripple.track(['A', 'B']);
37
+ let items = track(['A', 'B']);
36
38
  <button
37
39
  class="add"
38
40
  onClick={() => {
@@ -49,7 +51,7 @@ export component ReactiveForLoopAdd() {
49
51
  }
50
52
 
51
53
  export component ReactiveForLoopRemove() {
52
- let items = #ripple.track(['A', 'B', 'C']);
54
+ let items = track(['A', 'B', 'C']);
53
55
  <button
54
56
  class="remove"
55
57
  onClick={() => {
@@ -66,7 +68,7 @@ export component ReactiveForLoopRemove() {
66
68
  }
67
69
 
68
70
  export component ForLoopInteractive() {
69
- let counts = #ripple.track([0, 0, 0]);
71
+ let counts = track([0, 0, 0]);
70
72
  <div>
71
73
  for (const count of @counts; index i) {
72
74
  <div class={`item-${i}`}>
@@ -128,7 +130,7 @@ export component ForLoopComplexObjects() {
128
130
 
129
131
  // Test reordering items in a keyed for loop
130
132
  export component KeyedForLoopReorder() {
131
- let items = #ripple.track([
133
+ let items = track([
132
134
  { id: 1, name: 'First' },
133
135
  { id: 2, name: 'Second' },
134
136
  { id: 3, name: 'Third' },
@@ -150,7 +152,7 @@ export component KeyedForLoopReorder() {
150
152
 
151
153
  // Test for loop with item property updates (keyed)
152
154
  export component KeyedForLoopUpdate() {
153
- let items = #ripple.track([
155
+ let items = track([
154
156
  { id: 1, name: 'Item 1' },
155
157
  { id: 2, name: 'Item 2' },
156
158
  ]);
@@ -171,7 +173,7 @@ export component KeyedForLoopUpdate() {
171
173
 
172
174
  // Test for loop with combined add/remove/reorder
173
175
  export component ForLoopMixedOperations() {
174
- let items = #ripple.track(['A', 'B', 'C', 'D']);
176
+ let items = track(['A', 'B', 'C', 'D']);
175
177
  <button
176
178
  class="shuffle"
177
179
  onClick={() => {
@@ -190,8 +192,8 @@ export component ForLoopMixedOperations() {
190
192
 
191
193
  // Test for loop inside if block (combined control flow)
192
194
  export component ForLoopInsideIf() {
193
- let showList = #ripple.track(true);
194
- let items = #ripple.track(['X', 'Y', 'Z']);
195
+ let showList = track(true);
196
+ let items = track(['X', 'Y', 'Z']);
195
197
  <button
196
198
  class="toggle"
197
199
  onClick={() => {
@@ -219,7 +221,7 @@ export component ForLoopInsideIf() {
219
221
 
220
222
  // Test for loop that transitions from empty to populated
221
223
  export component ForLoopEmptyToPopulated() {
222
- let items = #ripple.track<string[]>([]);
224
+ let items = track<string[]>([]);
223
225
  <button
224
226
  class="populate"
225
227
  onClick={() => {
@@ -237,7 +239,7 @@ export component ForLoopEmptyToPopulated() {
237
239
 
238
240
  // Test for loop that transitions from populated to empty
239
241
  export component ForLoopPopulatedToEmpty() {
240
- let items = #ripple.track(['One', 'Two', 'Three']);
242
+ let items = track(['One', 'Two', 'Three']);
241
243
  <button
242
244
  class="clear"
243
245
  onClick={() => {
@@ -255,7 +257,7 @@ export component ForLoopPopulatedToEmpty() {
255
257
 
256
258
  // Test nested for loops with reactivity
257
259
  export component NestedForLoopReactive() {
258
- let grid = #ripple.track([
260
+ let grid = track([
259
261
  [1, 2],
260
262
  [3, 4],
261
263
  ]);
@@ -328,7 +330,7 @@ export component ForLoopDeeplyNested() {
328
330
 
329
331
  // Test for loop with index that gets updated
330
332
  export component ForLoopIndexUpdate() {
331
- let items = #ripple.track(['First', 'Second', 'Third']);
333
+ let items = track(['First', 'Second', 'Third']);
332
334
  <button
333
335
  class="prepend"
334
336
  onClick={() => {
@@ -346,7 +348,7 @@ export component ForLoopIndexUpdate() {
346
348
 
347
349
  // Test keyed for loop with index
348
350
  export component KeyedForLoopWithIndex() {
349
- let items = #ripple.track([
351
+ let items = track([
350
352
  { id: 'a', value: 'Alpha' },
351
353
  { id: 'b', value: 'Beta' },
352
354
  { id: 'c', value: 'Gamma' },
@@ -368,7 +370,7 @@ export component KeyedForLoopWithIndex() {
368
370
 
369
371
  // Test for loop with sibling elements
370
372
  export component ForLoopWithSiblings() {
371
- let items = #ripple.track(['A', 'B']);
373
+ let items = track(['A', 'B']);
372
374
  <div class="wrapper">
373
375
  <header class="before">{'Before'}</header>
374
376
  for (const item of @items) {
@@ -401,7 +403,7 @@ export component ForLoopItemState() {
401
403
  }
402
404
 
403
405
  component TodoItem(props: { id: number; text: string }) {
404
- let done = #ripple.track(false);
406
+ let done = track(false);
405
407
  <div class={`todo-${props.id}`}>
406
408
  <input
407
409
  type="checkbox"
@@ -427,7 +429,7 @@ export component ForLoopSingleItem() {
427
429
 
428
430
  // Test for loop adding at beginning
429
431
  export component ForLoopAddAtBeginning() {
430
- let items = #ripple.track(['B', 'C']);
432
+ let items = track(['B', 'C']);
431
433
  <button
432
434
  class="prepend"
433
435
  onClick={() => {
@@ -445,7 +447,7 @@ export component ForLoopAddAtBeginning() {
445
447
 
446
448
  // Test for loop adding in the middle
447
449
  export component ForLoopAddInMiddle() {
448
- let items = #ripple.track(['A', 'C']);
450
+ let items = track(['A', 'C']);
449
451
  <button
450
452
  class="insert"
451
453
  onClick={() => {
@@ -465,7 +467,7 @@ export component ForLoopAddInMiddle() {
465
467
 
466
468
  // Test for loop removing from the middle
467
469
  export component ForLoopRemoveFromMiddle() {
468
- let items = #ripple.track(['A', 'B', 'C']);
470
+ let items = track(['A', 'B', 'C']);
469
471
  <button
470
472
  class="remove-middle"
471
473
  onClick={() => {
@@ -493,7 +495,7 @@ export component ForLoopLargeList() {
493
495
 
494
496
  // Test for loop with swap operation
495
497
  export component ForLoopSwap() {
496
- let items = #ripple.track(['A', 'B', 'C', 'D']);
498
+ let items = track(['A', 'B', 'C', 'D']);
497
499
  <button
498
500
  class="swap"
499
501
  onClick={() => {
@@ -513,7 +515,7 @@ export component ForLoopSwap() {
513
515
 
514
516
  // Test for loop with reverse operation
515
517
  export component ForLoopReverse() {
516
- let items = #ripple.track(['A', 'B', 'C', 'D']);
518
+ let items = track(['A', 'B', 'C', 'D']);
517
519
  <button
518
520
  class="reverse"
519
521
  onClick={() => {
@@ -1,3 +1,5 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // Static title
2
4
  export component StaticTitle() {
3
5
  <head>
@@ -9,7 +11,7 @@ export component StaticTitle() {
9
11
 
10
12
  // Reactive title
11
13
  export component ReactiveTitle() {
12
- let title = #ripple.track('Initial Title');
14
+ let title = track('Initial Title');
13
15
 
14
16
  <head>
15
17
  <title>{@title}</title>
@@ -32,7 +34,7 @@ export component MultipleHeadElements() {
32
34
 
33
35
  // Head with reactive meta tags
34
36
  export component ReactiveMetaTags() {
35
- let description = #ripple.track('Initial description');
37
+ let description = track('Initial description');
36
38
 
37
39
  <head>
38
40
  <title>{'My Page'}</title>
@@ -44,7 +46,7 @@ export component ReactiveMetaTags() {
44
46
 
45
47
  // Title with template literal
46
48
  export component TitleWithTemplate() {
47
- let name = #ripple.track('World');
49
+ let name = track('World');
48
50
 
49
51
  <head>
50
52
  <title>{`Hello ${@name}!`}</title>
@@ -63,8 +65,8 @@ export component EmptyTitle() {
63
65
 
64
66
  // Title with conditional content
65
67
  export component ConditionalTitle() {
66
- let showPrefix = #ripple.track(true);
67
- let title = #ripple.track('Main Page');
68
+ let showPrefix = track(true);
69
+ let title = track('Main Page');
68
70
 
69
71
  <head>
70
72
  <title>{@showPrefix ? 'App - ' + @title : @title}</title>
@@ -75,7 +77,7 @@ export component ConditionalTitle() {
75
77
 
76
78
  // Title with computed value
77
79
  export component ComputedTitle() {
78
- let count = #ripple.track(0);
80
+ let count = track(0);
79
81
  let prefix = 'Count: ';
80
82
 
81
83
  <head>
@@ -1,3 +1,5 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // Components for testing HMR re-render after hydration.
2
4
  // The key scenario: a layout wrapper whose root element contains children
3
5
  // that use if/for blocks. After hydration, hydrate_node can be left pointing
@@ -17,7 +19,7 @@ export component Layout({ children }: { children: any }) {
17
19
 
18
20
  // A child component with an if block (the key source of deep hydrate_node)
19
21
  export component Content() {
20
- let visible = #ripple.track(true);
22
+ let visible = track(true);
21
23
 
22
24
  <div class="content">
23
25
  if (@visible) {
@@ -1,3 +1,5 @@
1
+ import { track } from 'ripple';
2
+
1
3
  export component StaticHtml() {
2
4
  const html = '<p><strong>Bold</strong> text</p>';
3
5
  <div>{html html}</div>
@@ -227,7 +229,7 @@ component NavItem({
227
229
  }
228
230
 
229
231
  component SidebarSection({ title, children }: { title: string; children: any }) {
230
- let expanded = #ripple.track(true);
232
+ let expanded = track(true);
231
233
  <section class="sidebar-section">
232
234
  <div class="section-header">
233
235
  <h2>{title}</h2>
@@ -1,8 +1,10 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // Minimal repro for hydration issue with if block containing children
2
4
  // Based on SidebarGroup pattern from website-new
3
5
 
4
6
  export component IfWithChildren({ children }: { children: any }) {
5
- let expanded = #ripple.track(true);
7
+ let expanded = track(true);
6
8
 
7
9
  <div class="container">
8
10
  <div class="header" role="button" onClick={() => (@expanded = !@expanded)}>{'Toggle'}</div>
@@ -27,7 +29,7 @@ export component TestIfWithChildren() {
27
29
 
28
30
  // Simpler variant - if block with static children
29
31
  export component IfWithStaticChildren() {
30
- let expanded = #ripple.track(true);
32
+ let expanded = track(true);
31
33
 
32
34
  <div class="container">
33
35
  <div class="header" role="button" onClick={() => (@expanded = !@expanded)}>{'Toggle'}</div>
@@ -42,7 +44,7 @@ export component IfWithStaticChildren() {
42
44
 
43
45
  // Variant with sibling elements before the if block (like SidebarGroup)
44
46
  export component IfWithSiblingsAndChildren({ children }: { children: any }) {
45
- let expanded = #ripple.track(true);
47
+ let expanded = track(true);
46
48
 
47
49
  <section class="group">
48
50
  <div class="item" role="button" onClick={() => (@expanded = !@expanded)}>
@@ -73,7 +75,7 @@ export component TestIfWithSiblingsAndChildren() {
73
75
  // This tests that hydrate_node is properly restored after processing an element's children
74
76
  // before navigating to a dynamic sibling (if/for/switch)
75
77
  export component ElementWithChildrenThenIf() {
76
- let show = #ripple.track(true);
78
+ let show = track(true);
77
79
 
78
80
  <div class="wrapper">
79
81
  <div class="nested-parent">
@@ -91,7 +93,7 @@ export component ElementWithChildrenThenIf() {
91
93
 
92
94
  // More complex: multiple levels of nesting before if sibling
93
95
  export component DeepNestingThenIf() {
94
- let visible = #ripple.track(true);
96
+ let visible = track(true);
95
97
 
96
98
  <section class="outer">
97
99
  <article class="middle">
@@ -114,7 +116,7 @@ export component DeepNestingThenIf() {
114
116
  // followed by another sibling element. This requires pop() to restore hydrate_node
115
117
  // because we descend into the first element to get the button children.
116
118
  export component DomElementChildrenThenSibling() {
117
- let activeTab = #ripple.track('code');
119
+ let activeTab = track('code');
118
120
 
119
121
  <div class="tabs">
120
122
  <div class="tab-list">
@@ -147,7 +149,7 @@ export component DomElementChildrenThenSibling() {
147
149
  // generate sibling() calls. This was causing incorrect pop() generation before next().
148
150
  // Pattern: <ul> with dynamic <li> children -> static <h2> -> static <p> -> next()
149
151
  export component DomChildrenThenStaticSiblings() {
150
- let count = #ripple.track(0);
152
+ let count = track(0);
151
153
 
152
154
  <div class="container">
153
155
  <ul class="list">
@@ -1,3 +1,5 @@
1
+ import { track } from 'ripple';
2
+
1
3
  // If block components for hydration testing
2
4
 
3
5
  export component IfTruthy() {
@@ -24,7 +26,7 @@ export component IfElse() {
24
26
  }
25
27
 
26
28
  export component ReactiveIf() {
27
- let show = #ripple.track(true);
29
+ let show = track(true);
28
30
  <button
29
31
  class="toggle"
30
32
  onClick={() => {
@@ -39,7 +41,7 @@ export component ReactiveIf() {
39
41
  }
40
42
 
41
43
  export component ReactiveIfElse() {
42
- let isOn = #ripple.track(false);
44
+ let isOn = track(false);
43
45
  <button
44
46
  class="toggle"
45
47
  onClick={() => {
@@ -56,8 +58,8 @@ export component ReactiveIfElse() {
56
58
  }
57
59
 
58
60
  export component NestedIf() {
59
- let outer = #ripple.track(true);
60
- let inner = #ripple.track(true);
61
+ let outer = track(true);
62
+ let inner = track(true);
61
63
  <button
62
64
  class="outer-toggle"
63
65
  onClick={() => {
@@ -85,7 +87,7 @@ export component NestedIf() {
85
87
  }
86
88
 
87
89
  export component IfElseIfChain() {
88
- let status = #ripple.track<'loading' | 'success' | 'error'>('loading');
90
+ let status = track<'loading' | 'success' | 'error'>('loading');
89
91
  <div>
90
92
  <button
91
93
  class="success"