ripple 0.3.74 → 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.
- package/CHANGELOG.md +50 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +2 -2
- package/src/runtime/dynamic-client.js +33 -0
- package/src/runtime/dynamic-server.js +80 -0
- package/src/runtime/index-client.js +2 -0
- package/src/runtime/index-server.js +2 -0
- package/src/runtime/internal/client/blocks.js +3 -2
- package/src/runtime/internal/client/composite.js +11 -6
- package/src/runtime/internal/client/render.js +5 -2
- package/src/runtime/internal/server/index.js +8 -1
- package/tests/client/basic/basic.components.test.tsrx +2 -2
- package/tests/client/basic/basic.styling.test.tsrx +16 -14
- package/tests/client/composite/composite.dynamic-components.test.tsrx +24 -6
- package/tests/client/css/global-additional-cases.test.tsrx +4 -4
- package/tests/client/css/style-identifier.test.tsrx +4 -4
- package/tests/client/dynamic-elements.test.tsrx +113 -38
- package/tests/client/head.test.tsrx +34 -0
- package/tests/client/svg.test.tsrx +8 -7
- package/tests/server/basic.components.test.tsrx +2 -2
- package/tests/server/basic.test.tsrx +3 -3
- package/tests/server/dynamic-elements.test.tsrx +60 -29
- package/tests/server/head.test.tsrx +23 -0
- package/tests/server/style-identifier.test.tsrx +4 -4
- package/types/index.d.ts +28 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { PropsWithExtras } from 'ripple';
|
|
2
|
-
import { createRefKey, effect, flushSync, track } from 'ripple';
|
|
2
|
+
import { createRefKey, Dynamic, effect, flushSync, track } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('dynamic DOM elements', () => {
|
|
5
5
|
it('renders static dynamic element', () => {
|
|
6
6
|
function App() @{
|
|
7
7
|
let tag = track('div');
|
|
8
|
-
|
|
8
|
+
<Dynamic is={tag}>{'Hello World'}</Dynamic>
|
|
9
9
|
}
|
|
10
10
|
render(App);
|
|
11
11
|
|
|
@@ -14,12 +14,10 @@ describe('dynamic DOM elements', () => {
|
|
|
14
14
|
expect(element.textContent).toBe('Hello World');
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
// The ts errors below are due to limitations in our current tsx generation for dynamic elements.
|
|
18
|
-
// They can be ignored for now. But we'll fix them via jsx() vs <jsx>
|
|
19
17
|
it('renders static dynamic element from a plain object with a tracked property', () => {
|
|
20
18
|
function App() @{
|
|
21
19
|
let obj = { tag: track('div') };
|
|
22
|
-
<obj.tag
|
|
20
|
+
<Dynamic is={obj.tag}>{'Hello World'}</Dynamic>
|
|
23
21
|
}
|
|
24
22
|
render(App);
|
|
25
23
|
|
|
@@ -32,7 +30,7 @@ describe('dynamic DOM elements', () => {
|
|
|
32
30
|
function App() @{
|
|
33
31
|
let obj = track({ tag: track('div') });
|
|
34
32
|
let tag = obj.value.tag;
|
|
35
|
-
|
|
33
|
+
<Dynamic is={tag}>{'Hello World'}</Dynamic>
|
|
36
34
|
}
|
|
37
35
|
render(App);
|
|
38
36
|
|
|
@@ -47,7 +45,7 @@ describe('dynamic DOM elements', () => {
|
|
|
47
45
|
function App() @{
|
|
48
46
|
let obj = track({ tag: track('div') });
|
|
49
47
|
let tag = obj.value['tag'];
|
|
50
|
-
|
|
48
|
+
<Dynamic is={tag}>{'Hello World'}</Dynamic>
|
|
51
49
|
}
|
|
52
50
|
render(App);
|
|
53
51
|
|
|
@@ -66,7 +64,7 @@ describe('dynamic DOM elements', () => {
|
|
|
66
64
|
tag = 'span';
|
|
67
65
|
}}
|
|
68
66
|
>{'Change Tag'}</button>
|
|
69
|
-
|
|
67
|
+
<Dynamic is={tag} id="dynamic">{'Hello World'}</Dynamic>
|
|
70
68
|
</>
|
|
71
69
|
}
|
|
72
70
|
render(App);
|
|
@@ -90,7 +88,7 @@ describe('dynamic DOM elements', () => {
|
|
|
90
88
|
it('renders self-closing dynamic element', () => {
|
|
91
89
|
function App() @{
|
|
92
90
|
let tag = track('input');
|
|
93
|
-
|
|
91
|
+
<Dynamic is={tag} type="text" value="test" />
|
|
94
92
|
}
|
|
95
93
|
render(App);
|
|
96
94
|
|
|
@@ -104,7 +102,12 @@ describe('dynamic DOM elements', () => {
|
|
|
104
102
|
function App() @{
|
|
105
103
|
let tag = track('div');
|
|
106
104
|
let &[className] = track('test-class');
|
|
107
|
-
|
|
105
|
+
<Dynamic
|
|
106
|
+
is={tag}
|
|
107
|
+
class={className}
|
|
108
|
+
id="test"
|
|
109
|
+
data-testid="dynamic-element"
|
|
110
|
+
>{'Content'}</Dynamic>
|
|
108
111
|
}
|
|
109
112
|
render(App);
|
|
110
113
|
|
|
@@ -119,9 +122,9 @@ describe('dynamic DOM elements', () => {
|
|
|
119
122
|
function App() @{
|
|
120
123
|
let outerTag = track('div');
|
|
121
124
|
let innerTag = track('span');
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
<Dynamic is={outerTag} class="outer">
|
|
126
|
+
<Dynamic is={innerTag} class="inner">{'Nested content'}</Dynamic>
|
|
127
|
+
</Dynamic>
|
|
125
128
|
}
|
|
126
129
|
render(App);
|
|
127
130
|
|
|
@@ -138,7 +141,10 @@ describe('dynamic DOM elements', () => {
|
|
|
138
141
|
function App() @{
|
|
139
142
|
let tag = track('div');
|
|
140
143
|
let &[active] = track(true);
|
|
141
|
-
|
|
144
|
+
<Dynamic
|
|
145
|
+
is={tag}
|
|
146
|
+
class={{ active: active, 'dynamic-element': true }}
|
|
147
|
+
>{'Element with class object'}</Dynamic>
|
|
142
148
|
}
|
|
143
149
|
render(App);
|
|
144
150
|
|
|
@@ -151,13 +157,14 @@ describe('dynamic DOM elements', () => {
|
|
|
151
157
|
it('handles dynamic element with style object', () => {
|
|
152
158
|
function App() @{
|
|
153
159
|
let tag = track('span');
|
|
154
|
-
|
|
160
|
+
<Dynamic
|
|
161
|
+
is={tag}
|
|
155
162
|
style={{
|
|
156
163
|
color: 'red',
|
|
157
164
|
fontSize: '16px',
|
|
158
165
|
fontWeight: 'bold',
|
|
159
166
|
}}
|
|
160
|
-
>{'Styled dynamic element'}
|
|
167
|
+
>{'Styled dynamic element'}</Dynamic>
|
|
161
168
|
}
|
|
162
169
|
render(App);
|
|
163
170
|
|
|
@@ -176,7 +183,11 @@ describe('dynamic DOM elements', () => {
|
|
|
176
183
|
'data-testid': 'spread-test',
|
|
177
184
|
class: 'spread-class',
|
|
178
185
|
};
|
|
179
|
-
|
|
186
|
+
<Dynamic
|
|
187
|
+
is={tag}
|
|
188
|
+
{...attrs}
|
|
189
|
+
data-extra="additional"
|
|
190
|
+
>{'Element with spread attributes'}</Dynamic>
|
|
180
191
|
}
|
|
181
192
|
render(App);
|
|
182
193
|
|
|
@@ -193,12 +204,13 @@ describe('dynamic DOM elements', () => {
|
|
|
193
204
|
|
|
194
205
|
function App() @{
|
|
195
206
|
let tag = track('article');
|
|
196
|
-
|
|
207
|
+
<Dynamic
|
|
208
|
+
is={tag}
|
|
197
209
|
ref={(node: HTMLElement) => {
|
|
198
210
|
capturedElement = node;
|
|
199
211
|
}}
|
|
200
212
|
id="ref-test"
|
|
201
|
-
>{'Element with ref'}
|
|
213
|
+
>{'Element with ref'}</Dynamic>
|
|
202
214
|
}
|
|
203
215
|
render(App);
|
|
204
216
|
flushSync();
|
|
@@ -222,7 +234,8 @@ describe('dynamic DOM elements', () => {
|
|
|
222
234
|
refAttrElement = input ?? null;
|
|
223
235
|
anonymousRefElement = state.anonymous ?? null;
|
|
224
236
|
});
|
|
225
|
-
|
|
237
|
+
<Dynamic
|
|
238
|
+
is={tag}
|
|
226
239
|
id="dynamic-ref-combo"
|
|
227
240
|
type="text"
|
|
228
241
|
ref={[
|
|
@@ -264,7 +277,8 @@ describe('dynamic DOM elements', () => {
|
|
|
264
277
|
refAttrElement = input ?? null;
|
|
265
278
|
anonymousRefElement = state.anonymous ?? null;
|
|
266
279
|
});
|
|
267
|
-
|
|
280
|
+
<Dynamic
|
|
281
|
+
is={dynamic}
|
|
268
282
|
ref={[
|
|
269
283
|
input,
|
|
270
284
|
state.anonymous,
|
|
@@ -287,6 +301,65 @@ describe('dynamic DOM elements', () => {
|
|
|
287
301
|
expect(element!.hasAttribute('input_ref')).toBe(false);
|
|
288
302
|
});
|
|
289
303
|
|
|
304
|
+
it('updates forwarded refs when a dynamic component changes', () => {
|
|
305
|
+
let refAttrElement: HTMLInputElement | null = null;
|
|
306
|
+
let anonymousRefElement: HTMLInputElement | null = null;
|
|
307
|
+
let namedRefElement: HTMLInputElement | null = null;
|
|
308
|
+
|
|
309
|
+
function TextInput(props: PropsWithExtras<{}>) @{
|
|
310
|
+
<input id="dynamic-component-text" type="text" {...props} />
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function SearchInput(props: PropsWithExtras<{}>) @{
|
|
314
|
+
<input id="dynamic-component-search" type="search" {...props} />
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function App() @{
|
|
318
|
+
let &[dynamic] = track(() => TextInput);
|
|
319
|
+
<>
|
|
320
|
+
<button
|
|
321
|
+
onClick={() => {
|
|
322
|
+
dynamic = dynamic === TextInput ? SearchInput : TextInput;
|
|
323
|
+
}}
|
|
324
|
+
>{'Change Component'}</button>
|
|
325
|
+
<Dynamic
|
|
326
|
+
is={dynamic}
|
|
327
|
+
ref={[
|
|
328
|
+
(node: HTMLInputElement | null) => {
|
|
329
|
+
refAttrElement = node;
|
|
330
|
+
},
|
|
331
|
+
(node: HTMLInputElement | null) => {
|
|
332
|
+
anonymousRefElement = node;
|
|
333
|
+
},
|
|
334
|
+
(node: HTMLInputElement | null) => {
|
|
335
|
+
namedRefElement = node;
|
|
336
|
+
},
|
|
337
|
+
]}
|
|
338
|
+
/>
|
|
339
|
+
</>
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
render(App);
|
|
343
|
+
flushSync();
|
|
344
|
+
|
|
345
|
+
const button = container.querySelector('button')!;
|
|
346
|
+
const textInput = container.querySelector('#dynamic-component-text');
|
|
347
|
+
expect(textInput).toBeInstanceOf(HTMLInputElement);
|
|
348
|
+
expect(refAttrElement).toBe(textInput);
|
|
349
|
+
expect(anonymousRefElement).toBe(textInput);
|
|
350
|
+
expect(namedRefElement).toBe(textInput);
|
|
351
|
+
|
|
352
|
+
button.click();
|
|
353
|
+
flushSync();
|
|
354
|
+
|
|
355
|
+
const searchInput = container.querySelector('#dynamic-component-search');
|
|
356
|
+
expect(searchInput).toBeInstanceOf(HTMLInputElement);
|
|
357
|
+
expect(container.querySelector('#dynamic-component-text')).toBeNull();
|
|
358
|
+
expect(refAttrElement).toBe(searchInput);
|
|
359
|
+
expect(anonymousRefElement).toBe(searchInput);
|
|
360
|
+
expect(namedRefElement).toBe(searchInput);
|
|
361
|
+
});
|
|
362
|
+
|
|
290
363
|
it('handles dynamic element with createRefKey in spread', () => {
|
|
291
364
|
function App() @{
|
|
292
365
|
let tag = track('header');
|
|
@@ -300,7 +373,7 @@ describe('dynamic DOM elements', () => {
|
|
|
300
373
|
class: 'ref-element',
|
|
301
374
|
[createRefKey()]: elementRef,
|
|
302
375
|
};
|
|
303
|
-
|
|
376
|
+
<Dynamic is={tag} {...dynamicProps}>{'Element with spread ref'}</Dynamic>
|
|
304
377
|
}
|
|
305
378
|
render(App);
|
|
306
379
|
flushSync();
|
|
@@ -324,14 +397,15 @@ describe('dynamic DOM elements', () => {
|
|
|
324
397
|
count++;
|
|
325
398
|
}}
|
|
326
399
|
>{'Increment'}</button>
|
|
327
|
-
|
|
400
|
+
<Dynamic
|
|
401
|
+
is={tag}
|
|
328
402
|
id={count % 2 ? 'even' : 'odd'}
|
|
329
403
|
class={count % 2 ? 'even-class' : 'odd-class'}
|
|
330
404
|
data-count={count}
|
|
331
405
|
>
|
|
332
406
|
{'Count: '}
|
|
333
407
|
{count}
|
|
334
|
-
|
|
408
|
+
</Dynamic>
|
|
335
409
|
</>
|
|
336
410
|
}
|
|
337
411
|
|
|
@@ -371,7 +445,7 @@ describe('dynamic DOM elements', () => {
|
|
|
371
445
|
function App() @{
|
|
372
446
|
let tag = track('div');
|
|
373
447
|
<>
|
|
374
|
-
|
|
448
|
+
<Dynamic is={tag} class="test-class">{'Dynamic element'}</Dynamic>
|
|
375
449
|
<style>
|
|
376
450
|
.test-class {
|
|
377
451
|
color: red;
|
|
@@ -397,7 +471,8 @@ describe('dynamic DOM elements', () => {
|
|
|
397
471
|
let tag = track('button');
|
|
398
472
|
let &[count] = track(0);
|
|
399
473
|
<>
|
|
400
|
-
|
|
474
|
+
<Dynamic
|
|
475
|
+
is={tag}
|
|
401
476
|
class={count % 2 ? 'even' : 'odd'}
|
|
402
477
|
id={count % 2 ? 'even' : 'odd'}
|
|
403
478
|
onClick={() => {
|
|
@@ -406,7 +481,7 @@ describe('dynamic DOM elements', () => {
|
|
|
406
481
|
>
|
|
407
482
|
{'Count: '}
|
|
408
483
|
{count}
|
|
409
|
-
|
|
484
|
+
</Dynamic>
|
|
410
485
|
<style>
|
|
411
486
|
.even {
|
|
412
487
|
background-color: green;
|
|
@@ -470,7 +545,7 @@ describe('dynamic DOM elements', () => {
|
|
|
470
545
|
}>) @{
|
|
471
546
|
const tag = track('button');
|
|
472
547
|
<>
|
|
473
|
-
|
|
548
|
+
<Dynamic is={tag} {...rest}>{rest.class}</Dynamic>
|
|
474
549
|
<style>
|
|
475
550
|
.even {
|
|
476
551
|
background-color: green;
|
|
@@ -528,9 +603,9 @@ describe('dynamic DOM elements', () => {
|
|
|
528
603
|
function App() @{
|
|
529
604
|
let tag = track('div');
|
|
530
605
|
<>
|
|
531
|
-
|
|
606
|
+
<Dynamic is={tag} class="scoped">
|
|
532
607
|
<p>{'Scoped dynamic element'}</p>
|
|
533
|
-
|
|
608
|
+
</Dynamic>
|
|
534
609
|
<style>
|
|
535
610
|
.scoped {
|
|
536
611
|
color: blue;
|
|
@@ -551,9 +626,9 @@ describe('dynamic DOM elements', () => {
|
|
|
551
626
|
function App() @{
|
|
552
627
|
let tag = track('div');
|
|
553
628
|
<>
|
|
554
|
-
|
|
629
|
+
<Dynamic is={tag} class="scoped">
|
|
555
630
|
<p>{'Scoped dynamic element'}</p>
|
|
556
|
-
|
|
631
|
+
</Dynamic>
|
|
557
632
|
<style>
|
|
558
633
|
div {
|
|
559
634
|
color: blue;
|
|
@@ -587,10 +662,10 @@ describe('dynamic DOM elements', () => {
|
|
|
587
662
|
function App() @{
|
|
588
663
|
let tag = track('div');
|
|
589
664
|
<>
|
|
590
|
-
|
|
665
|
+
<Dynamic is={tag} class="scoped">
|
|
591
666
|
<p>{'Scoped dynamic element'}</p>
|
|
592
667
|
<Child />
|
|
593
|
-
|
|
668
|
+
</Dynamic>
|
|
594
669
|
<style>
|
|
595
670
|
div {
|
|
596
671
|
color: blue;
|
|
@@ -633,7 +708,7 @@ describe('dynamic DOM elements', () => {
|
|
|
633
708
|
function App() @{
|
|
634
709
|
let tag = track(() => Child);
|
|
635
710
|
<>
|
|
636
|
-
|
|
711
|
+
<Dynamic is={tag} />
|
|
637
712
|
<style>
|
|
638
713
|
.child {
|
|
639
714
|
color: red;
|
|
@@ -659,7 +734,7 @@ describe('dynamic DOM elements', () => {
|
|
|
659
734
|
|
|
660
735
|
function Button(props: any) @{
|
|
661
736
|
const el = track('button');
|
|
662
|
-
|
|
737
|
+
<Dynamic is={el} {...props} />
|
|
663
738
|
}
|
|
664
739
|
|
|
665
740
|
function App() @{
|
|
@@ -699,7 +774,7 @@ describe('dynamic DOM elements', () => {
|
|
|
699
774
|
|
|
700
775
|
function Button(props: any) @{
|
|
701
776
|
const el = track('button');
|
|
702
|
-
|
|
777
|
+
<Dynamic is={el} {...props} />
|
|
703
778
|
}
|
|
704
779
|
|
|
705
780
|
function App() @{
|
|
@@ -744,7 +819,7 @@ describe('dynamic DOM elements', () => {
|
|
|
744
819
|
|
|
745
820
|
function Button(props: any) @{
|
|
746
821
|
const el = track('button');
|
|
747
|
-
|
|
822
|
+
<Dynamic is={el} {...props} />
|
|
748
823
|
}
|
|
749
824
|
|
|
750
825
|
function App() @{
|
|
@@ -172,6 +172,40 @@ describe('head elements', () => {
|
|
|
172
172
|
expect(document.title).toBe('');
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
+
it('renders external scripts with src attributes from a loop', () => {
|
|
176
|
+
const added: HTMLScriptElement[] = [];
|
|
177
|
+
const scripts = [{ src: '/a.js' }, { src: '/b.js' }];
|
|
178
|
+
|
|
179
|
+
function App() @{
|
|
180
|
+
<head>
|
|
181
|
+
@for (const script of scripts) {
|
|
182
|
+
<script src={script.src} />
|
|
183
|
+
}
|
|
184
|
+
</head>
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
render(App);
|
|
189
|
+
|
|
190
|
+
const head_scripts = Array.from(
|
|
191
|
+
document.head.querySelectorAll('script[src]'),
|
|
192
|
+
) as HTMLScriptElement[];
|
|
193
|
+
|
|
194
|
+
for (const node of head_scripts) {
|
|
195
|
+
if (node.getAttribute('src') === '/a.js' || node.getAttribute('src') === '/b.js') {
|
|
196
|
+
added.push(node);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const srcs = added.map((node) => node.getAttribute('src')).sort();
|
|
201
|
+
expect(srcs).toEqual(['/a.js', '/b.js']);
|
|
202
|
+
} finally {
|
|
203
|
+
for (const node of added) {
|
|
204
|
+
node.remove();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
175
209
|
it('renders title with conditional content', () => {
|
|
176
210
|
function App() @{
|
|
177
211
|
let &[showPrefix] = track(true);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { track } from 'ripple';
|
|
1
|
+
import { Dynamic, track } from 'ripple';
|
|
2
2
|
import type { Component, PropsWithChildren, PropsWithExtras } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('SVG namespace handling', () => {
|
|
@@ -296,7 +296,7 @@ describe('SVG namespace handling', () => {
|
|
|
296
296
|
function App() @{
|
|
297
297
|
let &[dynTag] = track('polygon');
|
|
298
298
|
<SVG>
|
|
299
|
-
|
|
299
|
+
<Dynamic is={dynTag} points="0,0 30,0 15,10" />
|
|
300
300
|
</SVG>
|
|
301
301
|
}
|
|
302
302
|
|
|
@@ -327,7 +327,7 @@ describe('SVG namespace handling', () => {
|
|
|
327
327
|
function App() @{
|
|
328
328
|
let &[Component] = track(() => Polygon);
|
|
329
329
|
<SVG>
|
|
330
|
-
|
|
330
|
+
<Dynamic is={Component} points="0,0 30,0 15,10" />
|
|
331
331
|
</SVG>
|
|
332
332
|
}
|
|
333
333
|
|
|
@@ -343,24 +343,25 @@ describe('SVG namespace handling', () => {
|
|
|
343
343
|
it('should render SVG as a dynamic top element with any dynamic children elements', () => {
|
|
344
344
|
function SVG({ children }: PropsWithChildren<{}>) @{
|
|
345
345
|
let &[tag] = track('svg');
|
|
346
|
-
|
|
346
|
+
<Dynamic
|
|
347
|
+
is={tag}
|
|
347
348
|
width={100}
|
|
348
349
|
height={50}
|
|
349
350
|
fill="red"
|
|
350
351
|
viewBox="0 0 30 10"
|
|
351
352
|
preserveAspectRatio="none"
|
|
352
|
-
>{children}
|
|
353
|
+
>{children}</Dynamic>
|
|
353
354
|
}
|
|
354
355
|
|
|
355
356
|
function Polygon({ points }: PropsWithExtras<{ points: string }>) @{
|
|
356
357
|
let &[dynTag] = track('polygon');
|
|
357
|
-
|
|
358
|
+
<Dynamic is={dynTag} {points} />
|
|
358
359
|
}
|
|
359
360
|
|
|
360
361
|
function App() @{
|
|
361
362
|
let &[Component] = track(() => Polygon);
|
|
362
363
|
<SVG>
|
|
363
|
-
|
|
364
|
+
<Dynamic is={Component} points="0,0 30,0 15,10" />
|
|
364
365
|
</SVG>
|
|
365
366
|
}
|
|
366
367
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { track } from 'ripple';
|
|
1
|
+
import { Dynamic, track } from 'ripple';
|
|
2
2
|
import type {
|
|
3
3
|
Tracked,
|
|
4
4
|
PropsWithChildren,
|
|
@@ -331,7 +331,7 @@ describe('basic server > components & composition', () => {
|
|
|
331
331
|
|
|
332
332
|
function App() @{
|
|
333
333
|
let Content = track(() => Noop);
|
|
334
|
-
|
|
334
|
+
<Dynamic is={Content} />
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
const { body } = await render(App);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fragment, track } from 'ripple';
|
|
1
|
+
import { Dynamic, Fragment, track } from 'ripple';
|
|
2
2
|
import type { Tracked, PropsNoChildren } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('basic client', () => {
|
|
@@ -402,8 +402,8 @@ second
|
|
|
402
402
|
|
|
403
403
|
function Parent() @{
|
|
404
404
|
const count = track(10);
|
|
405
|
-
let
|
|
406
|
-
|
|
405
|
+
let DynamicChild = track(() => Child);
|
|
406
|
+
<Dynamic is={DynamicChild} {count} class={{ test: true }} />
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
const { body } = await render(Parent);
|