ripple 0.3.128 → 0.4.0
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.
- package/CHANGELOG.md +267 -0
- package/package.json +10 -4
- package/src/runtime/element.js +23 -6
- package/src/runtime/index-client.js +81 -41
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/blocks.js +173 -91
- package/src/runtime/internal/client/component.js +4 -30
- package/src/runtime/internal/client/composite.js +12 -13
- package/src/runtime/internal/client/constants.js +9 -0
- package/src/runtime/internal/client/context.js +12 -19
- package/src/runtime/internal/client/css.js +7 -9
- package/src/runtime/internal/client/events.js +178 -90
- package/src/runtime/internal/client/expression.js +45 -25
- package/src/runtime/internal/client/for.js +409 -129
- package/src/runtime/internal/client/head.js +10 -5
- package/src/runtime/internal/client/html.js +1 -0
- package/src/runtime/internal/client/hydration.js +152 -10
- package/src/runtime/internal/client/if.js +239 -50
- package/src/runtime/internal/client/index.js +4 -12
- package/src/runtime/internal/client/operations.js +40 -61
- package/src/runtime/internal/client/portal.js +163 -85
- package/src/runtime/internal/client/render.js +39 -39
- package/src/runtime/internal/client/rpc.js +3 -3
- package/src/runtime/internal/client/runtime.js +592 -433
- package/src/runtime/internal/client/selector.js +5 -2
- package/src/runtime/internal/client/template.js +133 -158
- package/src/runtime/internal/client/transport.js +38 -0
- package/src/runtime/internal/client/try.js +465 -426
- package/src/runtime/internal/client/types.d.ts +56 -23
- package/src/runtime/internal/client/utils.js +1 -3
- package/src/runtime/internal/server/dynamic.js +20 -21
- package/src/runtime/internal/server/index.js +325 -275
- package/src/runtime/internal/server/rpc.js +3 -2
- package/src/runtime/internal/server/transport.js +16 -0
- package/src/runtime/transport.js +21 -0
- package/tests/client/__snapshots__/for.test.tsrx.snap +0 -5
- package/tests/client/array/array.copy-within.test.tsrx +12 -12
- package/tests/client/array/array.derived.test.tsrx +46 -46
- package/tests/client/array/array.iteration.test.tsrx +10 -10
- package/tests/client/array/array.mutations.test.tsrx +20 -20
- package/tests/client/array/array.static.test.tsrx +11 -11
- package/tests/client/array/array.to-methods.test.tsrx +6 -6
- package/tests/client/async-suspend.test.tsrx +74 -75
- package/tests/client/basic/basic.attributes.test.tsrx +86 -83
- package/tests/client/basic/basic.collections.test.tsrx +12 -12
- package/tests/client/basic/basic.components.test.tsrx +99 -25
- package/tests/client/basic/basic.errors.test.tsrx +18 -18
- package/tests/client/basic/basic.events.test.tsrx +42 -42
- package/tests/client/basic/basic.get-set.test.tsrx +8 -8
- package/tests/client/basic/basic.reactivity.test.tsrx +73 -38
- package/tests/client/basic/basic.rendering.test.tsrx +25 -25
- package/tests/client/basic/basic.utilities.test.tsrx +3 -3
- package/tests/client/boundaries.test.tsrx +8 -8
- package/tests/client/boxed-locals.test.tsrx +452 -0
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +6 -6
- package/tests/client/compiler/compiler.assignments.test.tsrx +9 -73
- package/tests/client/compiler/compiler.attributes.test.tsrx +23 -23
- package/tests/client/compiler/compiler.basic.test.tsrx +15 -60
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +18 -43
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +2 -2
- package/tests/client/composite/__snapshots__/composite.render.test.tsrx.snap +0 -1
- package/tests/client/composite/composite.dynamic-components.test.tsrx +77 -6
- package/tests/client/composite/composite.props.test.tsrx +149 -12
- package/tests/client/composite/composite.reactivity.test.tsrx +51 -52
- package/tests/client/composite/composite.render.test.tsrx +26 -9
- package/tests/client/css/scoped-styles.test.tsrx +8 -8
- package/tests/client/date.test.tsrx +42 -42
- package/tests/client/derived-release.test.tsrx +370 -0
- package/tests/client/dynamic-elements.test.tsrx +45 -45
- package/tests/client/events.test.tsrx +97 -71
- package/tests/client/for-selector.test.tsrx +14 -14
- package/tests/client/for-single-root-items.test.tsrx +118 -3
- package/tests/client/for.test.tsrx +332 -31
- package/tests/client/head.test.tsrx +19 -19
- package/tests/client/html.test.tsrx +11 -9
- package/tests/client/if-block.test.tsrx +80 -0
- package/tests/client/map.test.tsrx +16 -16
- package/tests/client/media-query.test.tsrx +7 -7
- package/tests/client/portal.test.tsrx +224 -26
- package/tests/client/primitive-text.test.tsrx +50 -0
- package/tests/client/prop-kind-switch.test.tsrx +141 -0
- package/tests/client/ref.test.tsrx +17 -17
- package/tests/client/return.test.tsrx +26 -3
- package/tests/client/root-boundary.test.tsrx +42 -0
- package/tests/client/scoped-flush.test.tsrx +8 -8
- package/tests/client/set.test.tsrx +6 -6
- package/tests/client/svg.test.tsrx +11 -11
- package/tests/client/switch.test.tsrx +44 -44
- package/tests/client/track-async-hydration.test.tsrx +4 -4
- package/tests/client/try.test.tsrx +151 -83
- package/tests/client/tsx.test.tsrx +43 -40
- package/tests/client/url/url.derived.test.tsrx +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +2 -2
- package/tests/hydration/basic.test.js +74 -1
- package/tests/hydration/build-components.js +22 -1
- package/tests/hydration/compiled/client/basic.js +1142 -713
- package/tests/hydration/compiled/client/composite.js +151 -100
- package/tests/hydration/compiled/client/events.js +184 -171
- package/tests/hydration/compiled/client/for.js +1472 -1132
- package/tests/hydration/compiled/client/fragment-cursor.js +2341 -0
- package/tests/hydration/compiled/client/head.js +254 -201
- package/tests/hydration/compiled/client/hmr.js +54 -41
- package/tests/hydration/compiled/client/html-in-template.js +54 -39
- package/tests/hydration/compiled/client/html.js +1633 -1263
- package/tests/hydration/compiled/client/if-children.js +420 -270
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +363 -317
- package/tests/hydration/compiled/client/if.js +229 -219
- package/tests/hydration/compiled/client/mixed-control-flow.js +420 -404
- package/tests/hydration/compiled/client/nested-control-flow.js +1326 -1277
- package/tests/hydration/compiled/client/portal.js +87 -95
- package/tests/hydration/compiled/client/reactivity.js +135 -101
- package/tests/hydration/compiled/client/return.js +28 -19
- package/tests/hydration/compiled/client/streaming.js +390 -306
- package/tests/hydration/compiled/client/switch.js +258 -266
- package/tests/hydration/compiled/client/track-async-serialization.js +448 -280
- package/tests/hydration/compiled/client/try.js +173 -129
- package/tests/hydration/compiled/client/typed-text.js +71 -0
- package/tests/hydration/compiled/fixtures/money.js +10 -0
- package/tests/hydration/compiled/server/basic.js +123 -6
- package/tests/hydration/compiled/server/composite.js +16 -30
- package/tests/hydration/compiled/server/events.js +66 -18
- package/tests/hydration/compiled/server/for.js +117 -41
- package/tests/hydration/compiled/server/fragment-cursor.js +1687 -0
- package/tests/hydration/compiled/server/head.js +20 -20
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +70 -238
- package/tests/hydration/compiled/server/if-children.js +107 -15
- package/tests/hydration/compiled/server/if.js +11 -15
- package/tests/hydration/compiled/server/mixed-control-flow.js +8 -8
- package/tests/hydration/compiled/server/portal.js +14 -22
- package/tests/hydration/compiled/server/reactivity.js +14 -14
- package/tests/hydration/compiled/server/streaming.js +19 -19
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/compiled/server/track-async-serialization.js +150 -23
- package/tests/hydration/compiled/server/try.js +8 -8
- package/tests/hydration/compiled/server/typed-text.js +17 -0
- package/tests/hydration/components/basic.tsrx +44 -8
- package/tests/hydration/components/composite.tsrx +2 -2
- package/tests/hydration/components/events.tsrx +25 -25
- package/tests/hydration/components/for.tsrx +115 -67
- package/tests/hydration/components/fragment-cursor.tsrx +650 -0
- package/tests/hydration/components/head.tsrx +16 -16
- package/tests/hydration/components/hmr.tsrx +2 -2
- package/tests/hydration/components/html.tsrx +7 -7
- package/tests/hydration/components/if-children.tsrx +72 -25
- package/tests/hydration/components/if.tsrx +18 -18
- package/tests/hydration/components/mixed-control-flow.tsrx +11 -11
- package/tests/hydration/components/portal.tsrx +3 -3
- package/tests/hydration/components/reactivity.tsrx +16 -16
- package/tests/hydration/components/streaming.tsrx +20 -20
- package/tests/hydration/components/switch.tsrx +20 -20
- package/tests/hydration/components/text-types.ts +4 -0
- package/tests/hydration/components/track-async-serialization.tsrx +80 -26
- package/tests/hydration/components/try.tsrx +8 -8
- package/tests/hydration/components/typed-text.tsrx +22 -0
- package/tests/hydration/fixtures/money.js +10 -0
- package/tests/hydration/for.test.js +36 -0
- package/tests/hydration/fragment-cursor.test.js +111 -0
- package/tests/hydration/if-children.test.js +24 -0
- package/tests/hydration/streaming.test.js +19 -0
- package/tests/hydration/track-async-serialization.test.js +87 -2
- package/tests/hydration/tsconfig.text-types.json +10 -0
- package/tests/hydration/typed-text.test.js +34 -0
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +42 -42
- package/tests/server/basic.components.test.tsrx +64 -8
- package/tests/server/basic.test.tsrx +34 -32
- package/tests/server/compiler.test.tsrx +1 -70
- package/tests/server/composite.props.test.tsrx +6 -6
- package/tests/server/dynamic-elements.test.tsrx +31 -8
- package/tests/server/for.test.tsrx +94 -0
- package/tests/server/head.test.tsrx +11 -11
- package/tests/server/scoped-styles.test.tsrx +2 -2
- package/tests/server/streaming-ssr.test.tsrx +48 -43
- package/tests/server/track-async-serialization.test.tsrx +204 -21
- package/tests/server/try.test.tsrx +48 -48
- package/tests/types/transport.ts +40 -0
- package/tests/utils/vite-plugin-config.test.js +23 -0
- package/types/index.d.ts +48 -7
- package/types/server.d.ts +3 -0
- package/types/transport.d.ts +15 -0
- package/src/runtime/internal/client/switch.js +0 -113
- package/src/utils/errors.js +0 -13
- package/tests/client/lazy-array.test.tsrx +0 -31
- package/tests/client/lazy-destructuring.test.tsrx +0 -438
- package/tests/client/tracked-index-access.test.tsrx +0 -113
- package/tests/server/lazy-destructuring.test.tsrx +0 -595
- package/tests/server/tracked-index-access.test.tsrx +0 -76
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Props, Tracked } from 'ripple';
|
|
1
|
+
import type { Derived, Props, Tracked } from 'ripple';
|
|
2
2
|
import { RippleObject, effect, flushSync, track } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('composite > reactivity', () => {
|
|
@@ -77,28 +77,28 @@ describe('composite > reactivity', () => {
|
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
it('parents and children have isolated state', () => {
|
|
80
|
-
function Button(props: { count: number }) @{
|
|
81
|
-
|
|
80
|
+
function Button(props: { count: Tracked<number> }) @{
|
|
81
|
+
const count = track(() => props.count.value, undefined, true);
|
|
82
82
|
<button
|
|
83
83
|
onClick={() => {
|
|
84
|
-
count++;
|
|
84
|
+
count.value++;
|
|
85
85
|
}}
|
|
86
86
|
>
|
|
87
|
-
{'child: ' + count}
|
|
87
|
+
{'child: ' + count.value}
|
|
88
88
|
</button>
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
function App() @{
|
|
92
|
-
|
|
92
|
+
const count = track(0);
|
|
93
93
|
<div>
|
|
94
94
|
<button
|
|
95
95
|
onClick={() => {
|
|
96
|
-
count++;
|
|
96
|
+
count.value++;
|
|
97
97
|
}}
|
|
98
98
|
>
|
|
99
|
-
{'parent: ' + count}
|
|
99
|
+
{'parent: ' + count.value}
|
|
100
100
|
</button>
|
|
101
|
-
<Button {count} />
|
|
101
|
+
<Button count={count} />
|
|
102
102
|
</div>
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -123,28 +123,28 @@ describe('composite > reactivity', () => {
|
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
it('parents and children have isolated connected state (destructured props)', () => {
|
|
126
|
-
function Button(
|
|
127
|
-
|
|
126
|
+
function Button({ count }: { count: Tracked<number> }) @{
|
|
127
|
+
const local_count = track(() => count.value, undefined, true);
|
|
128
128
|
<button
|
|
129
129
|
onClick={() => {
|
|
130
|
-
local_count++;
|
|
130
|
+
local_count.value++;
|
|
131
131
|
}}
|
|
132
132
|
>
|
|
133
|
-
{'child: ' + local_count}
|
|
133
|
+
{'child: ' + local_count.value}
|
|
134
134
|
</button>
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
function App() @{
|
|
138
|
-
|
|
138
|
+
const count = track(0);
|
|
139
139
|
<div>
|
|
140
140
|
<button
|
|
141
141
|
onClick={() => {
|
|
142
|
-
count++;
|
|
142
|
+
count.value++;
|
|
143
143
|
}}
|
|
144
144
|
>
|
|
145
|
-
{'parent: ' + count}
|
|
145
|
+
{'parent: ' + count.value}
|
|
146
146
|
</button>
|
|
147
|
-
<Button {count} />
|
|
147
|
+
<Button count={count} />
|
|
148
148
|
</div>
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -172,33 +172,27 @@ describe('composite > reactivity', () => {
|
|
|
172
172
|
let logs: string[] = [];
|
|
173
173
|
|
|
174
174
|
function App() @{
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
() => ({
|
|
180
|
-
a,
|
|
181
|
-
b,
|
|
182
|
-
c,
|
|
183
|
-
}),
|
|
184
|
-
);
|
|
175
|
+
const a = track(1);
|
|
176
|
+
const b = track(2);
|
|
177
|
+
const c = track(3);
|
|
178
|
+
const obj = { a, b, c };
|
|
185
179
|
<>
|
|
186
180
|
<Child {...obj} />
|
|
187
181
|
<button
|
|
188
182
|
onClick={() => {
|
|
189
|
-
a++;
|
|
190
|
-
b++;
|
|
191
|
-
c++;
|
|
183
|
+
a.value++;
|
|
184
|
+
b.value++;
|
|
185
|
+
c.value++;
|
|
192
186
|
}}
|
|
193
187
|
>{'Increment all'}</button>
|
|
194
188
|
</>
|
|
195
189
|
}
|
|
196
190
|
|
|
197
|
-
function Child(
|
|
191
|
+
function Child({ a, b, c }: { a: Tracked<number>; b: Tracked<number>; c: Tracked<number> }) @{
|
|
198
192
|
effect(() => {
|
|
199
|
-
logs.push(`Child effect: ${a}, ${b}, ${c}`);
|
|
193
|
+
logs.push(`Child effect: ${a.value}, ${b.value}, ${c.value}`);
|
|
200
194
|
});
|
|
201
|
-
<div>{a + ' ' + b + ' ' + c}</div>
|
|
195
|
+
<div>{a.value + ' ' + b.value + ' ' + c.value}</div>
|
|
202
196
|
}
|
|
203
197
|
|
|
204
198
|
render(App);
|
|
@@ -215,10 +209,10 @@ describe('composite > reactivity', () => {
|
|
|
215
209
|
expect(logs).toEqual(['Child effect: 1, 2, 3', 'Child effect: 2, 3, 4']);
|
|
216
210
|
});
|
|
217
211
|
|
|
218
|
-
it('keeps reactivity for spread props via intermediate components and
|
|
212
|
+
it('keeps reactivity for spread props via intermediate components and destructured props', () => {
|
|
219
213
|
function App() @{
|
|
220
|
-
|
|
221
|
-
<CounterWrapper {count} up={() => count++} down={() => count--} />
|
|
214
|
+
const count = track(0);
|
|
215
|
+
<CounterWrapper count={count} up={() => count.value++} down={() => count.value--} />
|
|
222
216
|
}
|
|
223
217
|
|
|
224
218
|
function CounterWrapper(props: Props) @{
|
|
@@ -227,11 +221,11 @@ describe('composite > reactivity', () => {
|
|
|
227
221
|
</div>
|
|
228
222
|
}
|
|
229
223
|
|
|
230
|
-
function Counter(
|
|
224
|
+
function Counter({ count, up, down, ...rest }: Props) @{
|
|
231
225
|
<>
|
|
232
226
|
<button onClick={() => up()}>{'UP'}</button>
|
|
233
227
|
<button onClick={() => down()}>{'DOWN'}</button>
|
|
234
|
-
<span {...rest}>{`Counter: ${count}`}</span>
|
|
228
|
+
<span {...rest}>{`Counter: ${count.value}`}</span>
|
|
235
229
|
</>
|
|
236
230
|
}
|
|
237
231
|
|
|
@@ -256,46 +250,51 @@ describe('composite > reactivity', () => {
|
|
|
256
250
|
|
|
257
251
|
it('keeps reactivity on elements for element spreads and adds / removes dynamic props', () => {
|
|
258
252
|
function App() @{
|
|
259
|
-
|
|
260
|
-
<CounterWrapper {count} up={() => count++} />
|
|
253
|
+
const count = track(0);
|
|
254
|
+
<CounterWrapper count={count} up={() => count.value++} />
|
|
261
255
|
}
|
|
262
256
|
|
|
263
|
-
function CounterWrapper(props: { count: number
|
|
257
|
+
function CounterWrapper(props: { count: Tracked<number>; up: () => void }) @{
|
|
264
258
|
const more: {
|
|
265
|
-
double:
|
|
259
|
+
double: Derived<number>;
|
|
266
260
|
another?: number;
|
|
267
261
|
extra: number;
|
|
268
262
|
} = new RippleObject({
|
|
269
|
-
double: track(() => props.count * 2),
|
|
263
|
+
double: track(() => props.count.value * 2),
|
|
270
264
|
another: 0,
|
|
271
265
|
extra: 100,
|
|
272
266
|
});
|
|
273
267
|
effect(() => {
|
|
274
|
-
props.count;
|
|
275
|
-
if (
|
|
268
|
+
const count = props.count.value;
|
|
269
|
+
if (count === 1) {
|
|
276
270
|
delete more.another;
|
|
277
|
-
} else if (
|
|
271
|
+
} else if (count === 2) {
|
|
278
272
|
more.another = 0;
|
|
279
273
|
}
|
|
280
274
|
});
|
|
281
275
|
<div>
|
|
282
|
-
<Counter
|
|
276
|
+
<Counter
|
|
277
|
+
{...props}
|
|
278
|
+
double={more.double}
|
|
279
|
+
another={track(() => more.another)}
|
|
280
|
+
extra={more.extra}
|
|
281
|
+
/>
|
|
283
282
|
</div>
|
|
284
283
|
}
|
|
285
284
|
|
|
286
|
-
function Counter(
|
|
285
|
+
function Counter({
|
|
287
286
|
count,
|
|
288
287
|
up,
|
|
289
288
|
...rest
|
|
290
289
|
}: {
|
|
291
|
-
count: number
|
|
290
|
+
count: Tracked<number>;
|
|
292
291
|
up: () => void;
|
|
293
|
-
double:
|
|
294
|
-
another
|
|
292
|
+
double: Derived<number>;
|
|
293
|
+
another: Derived<number | undefined>;
|
|
295
294
|
extra: number;
|
|
296
295
|
}) @{
|
|
297
296
|
<>
|
|
298
|
-
<div {...rest}>{`Counter: ${count} Double: ${rest.double.value}`}</div>
|
|
297
|
+
<div {...rest}>{`Counter: ${count.value} Double: ${rest.double.value}`}</div>
|
|
299
298
|
<button onClick={() => up()}>{'UP'}</button>
|
|
300
299
|
</>
|
|
301
300
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { RippleArray, flushSync, track, type Component } from 'ripple';
|
|
1
|
+
import { RippleArray, flushSync, track, type Component, type Tracked } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('composite > render', () => {
|
|
4
4
|
it('renders composite components', () => {
|
|
5
|
-
function Button(
|
|
6
|
-
<div>{count}</div>
|
|
5
|
+
function Button({ count }: { count: Tracked<number> }) @{
|
|
6
|
+
<div>{count.value}</div>
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function App() @{
|
|
10
|
-
|
|
10
|
+
const count = track(0);
|
|
11
11
|
<>
|
|
12
|
-
<button onClick={() => count++}>{'Increment'}</button>
|
|
13
|
-
<Button {count} />
|
|
12
|
+
<button onClick={() => count.value++}>{'Increment'}</button>
|
|
13
|
+
<Button count={count} />
|
|
14
14
|
</>
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -164,7 +164,7 @@ describe('composite > render', () => {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
it('should not render <undefined> tag when a passed in component is undefined', () => {
|
|
167
|
-
function Child(
|
|
167
|
+
function Child({
|
|
168
168
|
children,
|
|
169
169
|
NonExistent,
|
|
170
170
|
...props
|
|
@@ -176,8 +176,8 @@ describe('composite > render', () => {
|
|
|
176
176
|
<div {...props}>
|
|
177
177
|
{children}
|
|
178
178
|
|
|
179
|
-
<NonExistent />
|
|
180
179
|
// @ts-expect-error - intentionally testing behavior when a component is undefined
|
|
180
|
+
<NonExistent />
|
|
181
181
|
</div>
|
|
182
182
|
}
|
|
183
183
|
|
|
@@ -193,11 +193,28 @@ describe('composite > render', () => {
|
|
|
193
193
|
expect(undefinedTag).toBeNull();
|
|
194
194
|
expect(div.innerHTML).not.toContain('<undefined');
|
|
195
195
|
});
|
|
196
|
+
|
|
197
|
+
it('renders nothing for a local or imported component value that is undefined', () => {
|
|
198
|
+
const pick = (): Component | undefined => undefined;
|
|
199
|
+
|
|
200
|
+
function App() @{
|
|
201
|
+
const Local = pick();
|
|
202
|
+
<div>
|
|
203
|
+
{'before'}
|
|
204
|
+
<Local />
|
|
205
|
+
{'after'}
|
|
206
|
+
</div>
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
render(App);
|
|
210
|
+
|
|
211
|
+
expect(container.querySelector('div').textContent).toBe('beforeafter');
|
|
212
|
+
});
|
|
196
213
|
});
|
|
197
214
|
|
|
198
215
|
describe('scoped styles with children', () => {
|
|
199
216
|
it('generates correct CSS hashes for wrapper and child with empty style in App', () => {
|
|
200
|
-
function Wrapper(
|
|
217
|
+
function Wrapper({ children }: { children?: Component }) @{
|
|
201
218
|
<>
|
|
202
219
|
<div class="green">
|
|
203
220
|
{'Wrapper'}
|
|
@@ -51,9 +51,9 @@ const bundle = <style apply={[two, accent]} />;
|
|
|
51
51
|
describe('sibling-scoped style blocks', () => {
|
|
52
52
|
it('styles the items beside a block and everything below them, never the container', () => {
|
|
53
53
|
function Status() @{
|
|
54
|
-
|
|
54
|
+
const ready = track(false);
|
|
55
55
|
<>
|
|
56
|
-
<button onClick={() => (ready = !ready)}>{'toggle'}</button>
|
|
56
|
+
<button onClick={() => (ready.value = !ready.value)}>{'toggle'}</button>
|
|
57
57
|
<style>
|
|
58
58
|
.status {
|
|
59
59
|
padding: 0.5rem;
|
|
@@ -69,7 +69,7 @@ describe('sibling-scoped style blocks', () => {
|
|
|
69
69
|
}
|
|
70
70
|
</style>
|
|
71
71
|
<h2 id="title" class="title">{'Status'}</h2>
|
|
72
|
-
@if (ready) {
|
|
72
|
+
@if (ready.value) {
|
|
73
73
|
<>
|
|
74
74
|
<style>
|
|
75
75
|
.ok {
|
|
@@ -325,7 +325,7 @@ export function Status({ ready }: { ready: boolean }) @{
|
|
|
325
325
|
);
|
|
326
326
|
|
|
327
327
|
it('adds the scope classes of an element that spreads its props, one token per scope', () => {
|
|
328
|
-
function Button(
|
|
328
|
+
function Button({ ...rest }: { id: string; class?: string }) @{
|
|
329
329
|
<>
|
|
330
330
|
<style>
|
|
331
331
|
button {
|
|
@@ -356,7 +356,7 @@ export function Status({ ready }: { ready: boolean }) @{
|
|
|
356
356
|
});
|
|
357
357
|
|
|
358
358
|
it('keeps the scope classes of a static class when a spread brings its own class', () => {
|
|
359
|
-
function Card(
|
|
359
|
+
function Card({ ...rest }: { class?: string }) @{
|
|
360
360
|
<>
|
|
361
361
|
<style apply={importedTheme}>
|
|
362
362
|
.box {
|
|
@@ -387,15 +387,15 @@ export function Status({ ready }: { ready: boolean }) @{
|
|
|
387
387
|
|
|
388
388
|
it('keeps the scope classes while a dynamic class value changes', () => {
|
|
389
389
|
function App() @{
|
|
390
|
-
|
|
390
|
+
const active = track(false);
|
|
391
391
|
<>
|
|
392
392
|
<style>
|
|
393
393
|
.on {
|
|
394
394
|
color: green;
|
|
395
395
|
}
|
|
396
396
|
</style>
|
|
397
|
-
<button id="toggle" onClick={() => (active = !active)}>{'toggle'}</button>
|
|
398
|
-
<p id="p" class={active ? 'on' : 'off'}>{'p'}</p>
|
|
397
|
+
<button id="toggle" onClick={() => (active.value = !active.value)}>{'toggle'}</button>
|
|
398
|
+
<p id="p" class={active.value ? 'on' : 'off'}>{'p'}</p>
|
|
399
399
|
</>
|
|
400
400
|
}
|
|
401
401
|
|
|
@@ -4,10 +4,10 @@ describe('RippleDate', () => {
|
|
|
4
4
|
it('handles getTime() with reactive updates', () => {
|
|
5
5
|
function DateTest() @{
|
|
6
6
|
let date = new RippleDate(2025, 0, 1);
|
|
7
|
-
|
|
7
|
+
const time = track(() => date.getTime());
|
|
8
8
|
<>
|
|
9
9
|
<button onClick={() => date.setFullYear(2026)}>{'Change Year'}</button>
|
|
10
|
-
<pre>{time}</pre>
|
|
10
|
+
<pre>{time.value}</pre>
|
|
11
11
|
</>
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -27,10 +27,10 @@ describe('RippleDate', () => {
|
|
|
27
27
|
it('handles getFullYear() with reactive updates', () => {
|
|
28
28
|
function DateTest() @{
|
|
29
29
|
let date = new RippleDate(2025, 5, 15);
|
|
30
|
-
|
|
30
|
+
const year = track(() => date.getFullYear());
|
|
31
31
|
<>
|
|
32
32
|
<button onClick={() => date.setFullYear(2030)}>{'Change Year'}</button>
|
|
33
|
-
<pre>{year}</pre>
|
|
33
|
+
<pre>{year.value}</pre>
|
|
34
34
|
</>
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -49,10 +49,10 @@ describe('RippleDate', () => {
|
|
|
49
49
|
it('handles getMonth() with reactive updates', () => {
|
|
50
50
|
function DateTest() @{
|
|
51
51
|
let date = new RippleDate(2025, 0, 15);
|
|
52
|
-
|
|
52
|
+
const month = track(() => date.getMonth());
|
|
53
53
|
<>
|
|
54
54
|
<button onClick={() => date.setMonth(11)}>{'Change to December'}</button>
|
|
55
|
-
<pre>{month}</pre>
|
|
55
|
+
<pre>{month.value}</pre>
|
|
56
56
|
</>
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -71,10 +71,10 @@ describe('RippleDate', () => {
|
|
|
71
71
|
it('handles getDate() with reactive updates', () => {
|
|
72
72
|
function DateTest() @{
|
|
73
73
|
let date = new RippleDate(2025, 0, 1);
|
|
74
|
-
|
|
74
|
+
const day = track(() => date.getDate());
|
|
75
75
|
<>
|
|
76
76
|
<button onClick={() => date.setDate(15)}>{'Change Day'}</button>
|
|
77
|
-
<pre>{day}</pre>
|
|
77
|
+
<pre>{day.value}</pre>
|
|
78
78
|
</>
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -93,10 +93,10 @@ describe('RippleDate', () => {
|
|
|
93
93
|
it('handles getDay() with reactive updates', () => {
|
|
94
94
|
function DateTest() @{
|
|
95
95
|
let date = new RippleDate(2025, 0, 1);
|
|
96
|
-
|
|
96
|
+
const dayOfWeek = track(() => date.getDay());
|
|
97
97
|
<>
|
|
98
98
|
<button onClick={() => date.setDate(2)}>{'Next Day'}</button>
|
|
99
|
-
<pre>{dayOfWeek}</pre>
|
|
99
|
+
<pre>{dayOfWeek.value}</pre>
|
|
100
100
|
</>
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -115,10 +115,10 @@ describe('RippleDate', () => {
|
|
|
115
115
|
it('handles getHours() with reactive updates', () => {
|
|
116
116
|
function DateTest() @{
|
|
117
117
|
let date = new RippleDate(2025, 0, 1, 10, 30, 0);
|
|
118
|
-
|
|
118
|
+
const hours = track(() => date.getHours());
|
|
119
119
|
<>
|
|
120
120
|
<button onClick={() => date.setHours(15)}>{'Change to 3 PM'}</button>
|
|
121
|
-
<pre>{hours}</pre>
|
|
121
|
+
<pre>{hours.value}</pre>
|
|
122
122
|
</>
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -137,10 +137,10 @@ describe('RippleDate', () => {
|
|
|
137
137
|
it('handles getMinutes() with reactive updates', () => {
|
|
138
138
|
function DateTest() @{
|
|
139
139
|
let date = new RippleDate(2025, 0, 1, 10, 15, 0);
|
|
140
|
-
|
|
140
|
+
const minutes = track(() => date.getMinutes());
|
|
141
141
|
<>
|
|
142
142
|
<button onClick={() => date.setMinutes(45)}>{'Change Minutes'}</button>
|
|
143
|
-
<pre>{minutes}</pre>
|
|
143
|
+
<pre>{minutes.value}</pre>
|
|
144
144
|
</>
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -159,10 +159,10 @@ describe('RippleDate', () => {
|
|
|
159
159
|
it('handles getSeconds() with reactive updates', () => {
|
|
160
160
|
function DateTest() @{
|
|
161
161
|
let date = new RippleDate(2025, 0, 1, 10, 15, 30);
|
|
162
|
-
|
|
162
|
+
const seconds = track(() => date.getSeconds());
|
|
163
163
|
<>
|
|
164
164
|
<button onClick={() => date.setSeconds(45)}>{'Change Seconds'}</button>
|
|
165
|
-
<pre>{seconds}</pre>
|
|
165
|
+
<pre>{seconds.value}</pre>
|
|
166
166
|
</>
|
|
167
167
|
}
|
|
168
168
|
|
|
@@ -181,10 +181,10 @@ describe('RippleDate', () => {
|
|
|
181
181
|
it('handles toISOString() with reactive updates', () => {
|
|
182
182
|
function DateTest() @{
|
|
183
183
|
let date = new RippleDate(2025, 0, 1, 12, 0, 0);
|
|
184
|
-
|
|
184
|
+
const isoString = track(() => date.toISOString());
|
|
185
185
|
<>
|
|
186
186
|
<button onClick={() => date.setFullYear(2026)}>{'Change Year'}</button>
|
|
187
|
-
<pre>{isoString}</pre>
|
|
187
|
+
<pre>{isoString.value}</pre>
|
|
188
188
|
</>
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -208,10 +208,10 @@ describe('RippleDate', () => {
|
|
|
208
208
|
it('handles toDateString() with reactive updates', () => {
|
|
209
209
|
function DateTest() @{
|
|
210
210
|
let date = new RippleDate(2025, 0, 1);
|
|
211
|
-
|
|
211
|
+
const dateString = track(() => date.toDateString());
|
|
212
212
|
<>
|
|
213
213
|
<button onClick={() => date.setMonth(11)}>{'Change to December'}</button>
|
|
214
|
-
<pre>{dateString}</pre>
|
|
214
|
+
<pre>{dateString.value}</pre>
|
|
215
215
|
</>
|
|
216
216
|
}
|
|
217
217
|
|
|
@@ -233,10 +233,10 @@ describe('RippleDate', () => {
|
|
|
233
233
|
it('handles valueOf() with reactive updates', () => {
|
|
234
234
|
function DateTest() @{
|
|
235
235
|
let date = new RippleDate(2025, 0, 1);
|
|
236
|
-
|
|
236
|
+
const valueOf = track(() => date.valueOf());
|
|
237
237
|
<>
|
|
238
238
|
<button onClick={() => date.setDate(2)}>{'Next Day'}</button>
|
|
239
|
-
<pre>{valueOf}</pre>
|
|
239
|
+
<pre>{valueOf.value}</pre>
|
|
240
240
|
</>
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -256,29 +256,29 @@ describe('RippleDate', () => {
|
|
|
256
256
|
it('handles multiple get methods reacting to same setTime change', () => {
|
|
257
257
|
function DateTest() @{
|
|
258
258
|
let date = new RippleDate(2025, 0, 1, 10, 30, 15);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
const year = track(() => date.getFullYear());
|
|
260
|
+
const month = track(() => date.getMonth());
|
|
261
|
+
const day = track(() => date.getDate());
|
|
262
|
+
const hours = track(() => date.getHours());
|
|
263
263
|
<>
|
|
264
264
|
<button
|
|
265
265
|
onClick={() => date.setTime(new Date(2026, 5, 15, 14, 45, 30).getTime())}
|
|
266
266
|
>{'Change All'}</button>
|
|
267
267
|
<div>
|
|
268
268
|
{'Year: '}
|
|
269
|
-
{year}
|
|
269
|
+
{year.value}
|
|
270
270
|
</div>
|
|
271
271
|
<div>
|
|
272
272
|
{'Month: '}
|
|
273
|
-
{month}
|
|
273
|
+
{month.value}
|
|
274
274
|
</div>
|
|
275
275
|
<div>
|
|
276
276
|
{'Day: '}
|
|
277
|
-
{day}
|
|
277
|
+
{day.value}
|
|
278
278
|
</div>
|
|
279
279
|
<div>
|
|
280
280
|
{'Hours: '}
|
|
281
|
-
{hours}
|
|
281
|
+
{hours.value}
|
|
282
282
|
</div>
|
|
283
283
|
</>
|
|
284
284
|
}
|
|
@@ -308,26 +308,26 @@ describe('RippleDate', () => {
|
|
|
308
308
|
let dateFromString = new RippleDate('2025-01-01');
|
|
309
309
|
let dateFromNumbers = new RippleDate(2025, 0, 1);
|
|
310
310
|
let dateFromTimestamp = new RippleDate(1735689600000);
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
311
|
+
const nowYear = track(() => dateNow.getFullYear());
|
|
312
|
+
const stringYear = track(() => dateFromString.getFullYear());
|
|
313
|
+
const numbersYear = track(() => dateFromNumbers.getFullYear());
|
|
314
|
+
const timestampYear = track(() => dateFromTimestamp.getFullYear());
|
|
315
315
|
<>
|
|
316
316
|
<div>
|
|
317
317
|
{'Now: '}
|
|
318
|
-
{nowYear}
|
|
318
|
+
{nowYear.value}
|
|
319
319
|
</div>
|
|
320
320
|
<div>
|
|
321
321
|
{'String: '}
|
|
322
|
-
{stringYear}
|
|
322
|
+
{stringYear.value}
|
|
323
323
|
</div>
|
|
324
324
|
<div>
|
|
325
325
|
{'Numbers: '}
|
|
326
|
-
{numbersYear}
|
|
326
|
+
{numbersYear.value}
|
|
327
327
|
</div>
|
|
328
328
|
<div>
|
|
329
329
|
{'Timestamp: '}
|
|
330
|
-
{timestampYear}
|
|
330
|
+
{timestampYear.value}
|
|
331
331
|
</div>
|
|
332
332
|
</>
|
|
333
333
|
}
|
|
@@ -354,17 +354,17 @@ describe('RippleDate', () => {
|
|
|
354
354
|
it('handles get methods with arguments non-memoized', () => {
|
|
355
355
|
function DateTest() @{
|
|
356
356
|
let date = new RippleDate();
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
const localeDateString = track(() => date.toLocaleDateString('en-US'));
|
|
358
|
+
const localeTimeString = track(() => date.toLocaleTimeString('en-US'));
|
|
359
359
|
<>
|
|
360
360
|
<button onClick={() => date.setFullYear(date.getFullYear() + 1)}>{'Next Year'}</button>
|
|
361
361
|
<div>
|
|
362
362
|
{'Date: '}
|
|
363
|
-
{localeDateString}
|
|
363
|
+
{localeDateString.value}
|
|
364
364
|
</div>
|
|
365
365
|
<div>
|
|
366
366
|
{'Time: '}
|
|
367
|
-
{localeTimeString}
|
|
367
|
+
{localeTimeString.value}
|
|
368
368
|
</div>
|
|
369
369
|
</>
|
|
370
370
|
}
|