ripple 0.3.49 → 0.3.52
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 +36 -0
- package/package.json +4 -4
- package/tests/client/tsx.test.tsrx +114 -25
- package/tests/server/basic.test.tsrx +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.52
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
[[`2010290`](https://github.com/Ripple-TS/ripple/commit/20102904d68951b47dce3958f88ddd1fc150e7a1)]:
|
|
9
|
+
- @tsrx/core@0.1.2
|
|
10
|
+
- ripple@0.3.52
|
|
11
|
+
- @tsrx/ripple@0.1.2
|
|
12
|
+
|
|
13
|
+
## 0.3.51
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [`f1b1f94`](https://github.com/Ripple-TS/ripple/commit/f1b1f9475553cbe3632a5cc9794a8f54615c29f2)
|
|
18
|
+
Thanks [@leonidaz](https://github.com/leonidaz)! - Patch packages currently
|
|
19
|
+
versioned at 0.3.50 to fix the bump that caused major 1.0.0 release with a minor
|
|
20
|
+
changeset.
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
[[`0fdf340`](https://github.com/Ripple-TS/ripple/commit/0fdf3408417a7565a00304b766e958b438b3c834),
|
|
24
|
+
[`f1b1f94`](https://github.com/Ripple-TS/ripple/commit/f1b1f9475553cbe3632a5cc9794a8f54615c29f2)]:
|
|
25
|
+
- @tsrx/core@0.1.1
|
|
26
|
+
- ripple@0.3.51
|
|
27
|
+
- @tsrx/ripple@0.1.1
|
|
28
|
+
|
|
29
|
+
## 0.3.50
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Updated dependencies
|
|
34
|
+
[[`2a85e9b`](https://github.com/Ripple-TS/ripple/commit/2a85e9bb73f4d82f2bd2273c33735b4dc7b82d5f)]:
|
|
35
|
+
- @tsrx/core@0.1.0
|
|
36
|
+
- @tsrx/ripple@0.1.0
|
|
37
|
+
- ripple@0.3.50
|
|
38
|
+
|
|
3
39
|
## 0.3.49
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.52",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"esm-env": "^1.2.2",
|
|
77
77
|
"@types/estree": "^1.0.8",
|
|
78
78
|
"@types/estree-jsx": "^1.0.5",
|
|
79
|
-
"@tsrx/core": "0.
|
|
80
|
-
"@tsrx/ripple": "0.
|
|
79
|
+
"@tsrx/core": "0.1.2",
|
|
80
|
+
"@tsrx/ripple": "0.1.2"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@types/node": "^24.3.0",
|
|
@@ -87,6 +87,6 @@
|
|
|
87
87
|
"vscode-languageserver-types": "^3.17.5"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
|
-
"ripple": "0.3.
|
|
90
|
+
"ripple": "0.3.52"
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -108,7 +108,10 @@ describe('tsx expression', () => {
|
|
|
108
108
|
|
|
109
109
|
it('renders a tsx element with multiple children', () => {
|
|
110
110
|
component App() {
|
|
111
|
-
const el = <tsx
|
|
111
|
+
const el = <tsx>
|
|
112
|
+
<div>first</div>
|
|
113
|
+
<div>second</div>
|
|
114
|
+
</tsx>;
|
|
112
115
|
{el}
|
|
113
116
|
}
|
|
114
117
|
render(App);
|
|
@@ -209,6 +212,7 @@ describe('tsx expression', () => {
|
|
|
209
212
|
const el = <tsx>just text</tsx>;
|
|
210
213
|
{el}
|
|
211
214
|
}
|
|
215
|
+
|
|
212
216
|
render(App);
|
|
213
217
|
expect(container.textContent).toBe('just text');
|
|
214
218
|
});
|
|
@@ -220,6 +224,7 @@ describe('tsx expression', () => {
|
|
|
220
224
|
</tsx>;
|
|
221
225
|
{el}
|
|
222
226
|
}
|
|
227
|
+
|
|
223
228
|
render(App);
|
|
224
229
|
const div = container.querySelector('div');
|
|
225
230
|
expect(div.id).toBe('my-id');
|
|
@@ -231,10 +236,12 @@ describe('tsx expression', () => {
|
|
|
231
236
|
it('renders tsx element with dynamic attribute values', () => {
|
|
232
237
|
component App() {
|
|
233
238
|
let &[name] = track('initial');
|
|
239
|
+
|
|
234
240
|
const el = <tsx><div id={name} class={'cls-' + name}>content</div></tsx>;
|
|
235
241
|
{el}
|
|
236
242
|
<button onClick={() => (name = 'updated')}>{'update'}</button>
|
|
237
243
|
}
|
|
244
|
+
|
|
238
245
|
render(App);
|
|
239
246
|
const div = container.querySelector('div');
|
|
240
247
|
expect(div.id).toBe('initial');
|
|
@@ -249,6 +256,7 @@ describe('tsx expression', () => {
|
|
|
249
256
|
it('renders tsx element with event handlers', () => {
|
|
250
257
|
component App() {
|
|
251
258
|
let &[clicked] = track(false);
|
|
259
|
+
|
|
252
260
|
const el = <tsx>
|
|
253
261
|
<button onClick={() => (clicked = true)}>
|
|
254
262
|
{'click me'}
|
|
@@ -257,6 +265,7 @@ describe('tsx expression', () => {
|
|
|
257
265
|
{el}
|
|
258
266
|
<div class="status">{clicked ? 'clicked' : 'not clicked'}</div>
|
|
259
267
|
}
|
|
268
|
+
|
|
260
269
|
render(App);
|
|
261
270
|
expect(container.querySelector('.status').textContent).toBe('not clicked');
|
|
262
271
|
|
|
@@ -268,6 +277,7 @@ describe('tsx expression', () => {
|
|
|
268
277
|
it('renders tsx element with boolean attributes', () => {
|
|
269
278
|
component App() {
|
|
270
279
|
let &[isDisabled] = track(true);
|
|
280
|
+
|
|
271
281
|
const el = <tsx>
|
|
272
282
|
<button disabled={isDisabled}>
|
|
273
283
|
{'btn'}
|
|
@@ -276,6 +286,7 @@ describe('tsx expression', () => {
|
|
|
276
286
|
{el}
|
|
277
287
|
<button class="toggle" onClick={() => (isDisabled = !isDisabled)}>{'toggle'}</button>
|
|
278
288
|
}
|
|
289
|
+
|
|
279
290
|
render(App);
|
|
280
291
|
expect(container.querySelector('button:not(.toggle)').disabled).toBe(true);
|
|
281
292
|
|
|
@@ -287,10 +298,12 @@ describe('tsx expression', () => {
|
|
|
287
298
|
it('renders tsx element with style attribute', () => {
|
|
288
299
|
component App() {
|
|
289
300
|
let &[color] = track('red');
|
|
301
|
+
|
|
290
302
|
const el = <tsx><div style={'color: ' + color}>styled</div></tsx>;
|
|
291
303
|
{el}
|
|
292
304
|
<button onClick={() => (color = 'blue')}>{'change color'}</button>
|
|
293
305
|
}
|
|
306
|
+
|
|
294
307
|
render(App);
|
|
295
308
|
expect(container.querySelector('div').style.color).toBe('red');
|
|
296
309
|
|
|
@@ -302,6 +315,7 @@ describe('tsx expression', () => {
|
|
|
302
315
|
it('renders tsx element with multiple dynamic attributes', () => {
|
|
303
316
|
component App() {
|
|
304
317
|
let &[index] = track(0);
|
|
318
|
+
|
|
305
319
|
const el = <tsx>
|
|
306
320
|
<div id={'item-' + index} class={'item pos-' + index} data-index={index} title={'Item ' +
|
|
307
321
|
index}>
|
|
@@ -311,6 +325,7 @@ describe('tsx expression', () => {
|
|
|
311
325
|
{el}
|
|
312
326
|
<button onClick={() => index++}>{'next'}</button>
|
|
313
327
|
}
|
|
328
|
+
|
|
314
329
|
render(App);
|
|
315
330
|
const div = container.querySelector('div');
|
|
316
331
|
expect(div.id).toBe('item-0');
|
|
@@ -334,6 +349,7 @@ describe('tsx expression', () => {
|
|
|
334
349
|
component App() {
|
|
335
350
|
<Wrapper content={<tsx><span class="inner">direct prop</span></tsx>} />
|
|
336
351
|
}
|
|
352
|
+
|
|
337
353
|
render(App);
|
|
338
354
|
const wrapper = container.querySelector('.wrapper');
|
|
339
355
|
expect(wrapper).toBeTruthy();
|
|
@@ -355,6 +371,7 @@ describe('tsx expression', () => {
|
|
|
355
371
|
children={<tsx><p>Card content here</p></tsx>}
|
|
356
372
|
/>
|
|
357
373
|
}
|
|
374
|
+
|
|
358
375
|
render(App);
|
|
359
376
|
const card = container.querySelector('.card');
|
|
360
377
|
expect(card.querySelector('.card-title .bold').textContent).toBe('Title');
|
|
@@ -363,17 +380,14 @@ describe('tsx expression', () => {
|
|
|
363
380
|
|
|
364
381
|
it('renders tsx from function defined outside component', () => {
|
|
365
382
|
function createBadge(label: string) {
|
|
366
|
-
return <tsx>
|
|
367
|
-
<span class="badge">
|
|
368
|
-
{label}
|
|
369
|
-
</span>
|
|
370
|
-
</tsx>;
|
|
383
|
+
return <tsx><span class="badge">{label}</span></tsx>;
|
|
371
384
|
}
|
|
372
385
|
|
|
373
386
|
component App() {
|
|
374
387
|
const badge = createBadge('New');
|
|
375
388
|
{badge}
|
|
376
389
|
}
|
|
390
|
+
|
|
377
391
|
render(App);
|
|
378
392
|
expect(container.querySelector('.badge')).toBeTruthy();
|
|
379
393
|
expect(container.querySelector('.badge').textContent).toBe('New');
|
|
@@ -381,11 +395,7 @@ describe('tsx expression', () => {
|
|
|
381
395
|
|
|
382
396
|
it('renders tsx from function with multiple elements', () => {
|
|
383
397
|
function createListItem(item: string) {
|
|
384
|
-
return <tsx>
|
|
385
|
-
<li class="list-item">
|
|
386
|
-
{item}
|
|
387
|
-
</li>
|
|
388
|
-
</tsx>;
|
|
398
|
+
return <tsx><li class="list-item">{item}</li></tsx>;
|
|
389
399
|
}
|
|
390
400
|
|
|
391
401
|
component App() {
|
|
@@ -396,6 +406,7 @@ describe('tsx expression', () => {
|
|
|
396
406
|
}
|
|
397
407
|
</ul>
|
|
398
408
|
}
|
|
409
|
+
|
|
399
410
|
render(App);
|
|
400
411
|
const listItems = container.querySelectorAll('.list-item');
|
|
401
412
|
expect(listItems.length).toBe(3);
|
|
@@ -416,9 +427,7 @@ describe('tsx expression', () => {
|
|
|
416
427
|
function itemRenderer(item: string) {
|
|
417
428
|
return <tsx>
|
|
418
429
|
<li>
|
|
419
|
-
<span class="item-content">
|
|
420
|
-
{item}
|
|
421
|
-
</span>
|
|
430
|
+
<span class="item-content">{item}</span>
|
|
422
431
|
</li>
|
|
423
432
|
</tsx>;
|
|
424
433
|
}
|
|
@@ -426,6 +435,7 @@ describe('tsx expression', () => {
|
|
|
426
435
|
component App() {
|
|
427
436
|
<List items={['One', 'Two', 'Three']} renderItem={itemRenderer} />
|
|
428
437
|
}
|
|
438
|
+
|
|
429
439
|
render(App);
|
|
430
440
|
const items = container.querySelectorAll('.item-content');
|
|
431
441
|
expect(items.length).toBe(3);
|
|
@@ -438,9 +448,7 @@ describe('tsx expression', () => {
|
|
|
438
448
|
function createCounter(label: string, getCount: () => number) {
|
|
439
449
|
return <tsx>
|
|
440
450
|
<div class="counter-display">
|
|
441
|
-
<span class="label">
|
|
442
|
-
{label}
|
|
443
|
-
</span>
|
|
451
|
+
<span class="label">{label}</span>
|
|
444
452
|
<span class="count">
|
|
445
453
|
{getCount()}
|
|
446
454
|
</span>
|
|
@@ -450,10 +458,12 @@ describe('tsx expression', () => {
|
|
|
450
458
|
|
|
451
459
|
component App() {
|
|
452
460
|
let &[count] = track(0);
|
|
461
|
+
|
|
453
462
|
const counterElement = createCounter('Count:', () => count);
|
|
454
463
|
{counterElement}
|
|
455
464
|
<button onClick={() => count++}>{'increment'}</button>
|
|
456
465
|
}
|
|
466
|
+
|
|
457
467
|
render(App);
|
|
458
468
|
expect(container.querySelector('.label').textContent).toBe('Count:');
|
|
459
469
|
expect(container.querySelector('.count').textContent).toBe('0');
|
|
@@ -472,9 +482,7 @@ describe('tsx expression', () => {
|
|
|
472
482
|
return <tsx>
|
|
473
483
|
<button class="icon-button">
|
|
474
484
|
{createIcon(icon)}
|
|
475
|
-
<span class="btn-label">
|
|
476
|
-
{label}
|
|
477
|
-
</span>
|
|
485
|
+
<span class="btn-label">{label}</span>
|
|
478
486
|
</button>
|
|
479
487
|
</tsx>;
|
|
480
488
|
}
|
|
@@ -483,6 +491,7 @@ describe('tsx expression', () => {
|
|
|
483
491
|
const btn = createButton('save', 'Save');
|
|
484
492
|
{btn}
|
|
485
493
|
}
|
|
494
|
+
|
|
486
495
|
render(App);
|
|
487
496
|
const button = container.querySelector('.icon-button');
|
|
488
497
|
expect(button).toBeTruthy();
|
|
@@ -502,6 +511,7 @@ describe('tsx expression', () => {
|
|
|
502
511
|
<Alert message="No icon" />
|
|
503
512
|
<Alert icon={<tsx><span class="custom-icon">✓</span></tsx>} message="Custom icon" />
|
|
504
513
|
}
|
|
514
|
+
|
|
505
515
|
render(App);
|
|
506
516
|
const alerts = container.querySelectorAll('.alert');
|
|
507
517
|
expect(alerts[0].querySelector('.message').textContent).toBe('No icon');
|
|
@@ -511,11 +521,7 @@ describe('tsx expression', () => {
|
|
|
511
521
|
|
|
512
522
|
it('renders tsx stored in array via function', () => {
|
|
513
523
|
function createItem(className: string, content: string) {
|
|
514
|
-
return <tsx>
|
|
515
|
-
<div class={className}>
|
|
516
|
-
{content}
|
|
517
|
-
</div>
|
|
518
|
-
</tsx>;
|
|
524
|
+
return <tsx><div class={className}>{content}</div></tsx>;
|
|
519
525
|
}
|
|
520
526
|
|
|
521
527
|
component App() {
|
|
@@ -531,6 +537,7 @@ describe('tsx expression', () => {
|
|
|
531
537
|
}
|
|
532
538
|
</div>
|
|
533
539
|
}
|
|
540
|
+
|
|
534
541
|
render(App);
|
|
535
542
|
const container_el = container.querySelector('.container');
|
|
536
543
|
expect(container_el.querySelector('.item-a').textContent).toBe('A');
|
|
@@ -554,6 +561,7 @@ describe('tsx expression', () => {
|
|
|
554
561
|
<button class="set-success" onClick={() => (status = 'success')}>{'Success'}</button>
|
|
555
562
|
<button class="set-error" onClick={() => (status = 'error')}>{'Error'}</button>
|
|
556
563
|
}
|
|
564
|
+
|
|
557
565
|
render(App);
|
|
558
566
|
expect(container.querySelector('.default')).toBeTruthy();
|
|
559
567
|
|
|
@@ -568,3 +576,84 @@ describe('tsx expression', () => {
|
|
|
568
576
|
expect(container.querySelector('.success')).toBeFalsy();
|
|
569
577
|
});
|
|
570
578
|
});
|
|
579
|
+
|
|
580
|
+
describe('tsrx expression', () => {
|
|
581
|
+
it('renders native double-quoted text in an assigned fragment', () => {
|
|
582
|
+
component App() {
|
|
583
|
+
const el = <tsrx>
|
|
584
|
+
<div>"Hello world"</div>
|
|
585
|
+
</tsrx>;
|
|
586
|
+
{el}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
render(App);
|
|
590
|
+
|
|
591
|
+
const div = container.querySelector('div');
|
|
592
|
+
expect(div).toBeTruthy();
|
|
593
|
+
expect(div.textContent).toBe('Hello world');
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
it('runs setup statements before native template output', () => {
|
|
597
|
+
component App() {
|
|
598
|
+
const el = <tsrx>
|
|
599
|
+
const label = 'from setup';
|
|
600
|
+
<div>{label}</div>
|
|
601
|
+
</tsrx>;
|
|
602
|
+
{el}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
render(App);
|
|
606
|
+
|
|
607
|
+
expect(container.querySelector('div').textContent).toBe('from setup');
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('updates reactive expressions inside native fragments', () => {
|
|
611
|
+
component App() {
|
|
612
|
+
let &[count] = track(0);
|
|
613
|
+
|
|
614
|
+
const el = <tsrx>
|
|
615
|
+
<div>{'count: ' + count}</div>
|
|
616
|
+
</tsrx>;
|
|
617
|
+
{el}
|
|
618
|
+
<button onClick={() => count++}>{'increment'}</button>
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
render(App);
|
|
622
|
+
|
|
623
|
+
expect(container.querySelector('div').textContent).toBe('count: 0');
|
|
624
|
+
container.querySelector('button').click();
|
|
625
|
+
flushSync();
|
|
626
|
+
expect(container.querySelector('div').textContent).toBe('count: 1');
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it('renders native control flow inside an assigned fragment', () => {
|
|
630
|
+
component App() {
|
|
631
|
+
const el = <tsrx>
|
|
632
|
+
if (true) {
|
|
633
|
+
<span>"visible"</span>
|
|
634
|
+
}
|
|
635
|
+
</tsrx>;
|
|
636
|
+
{el}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
render(App);
|
|
640
|
+
|
|
641
|
+
expect(container.querySelector('span').textContent).toBe('visible');
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
it('renders fragments returned from helpers outside components', () => {
|
|
645
|
+
function makeFragment(label: string) {
|
|
646
|
+
return <tsrx>
|
|
647
|
+
<span>{label}</span>
|
|
648
|
+
</tsrx>;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
component App() {
|
|
652
|
+
{makeFragment('from helper')}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
render(App);
|
|
656
|
+
|
|
657
|
+
expect(container.querySelector('span').textContent).toBe('from helper');
|
|
658
|
+
});
|
|
659
|
+
});
|
|
@@ -40,6 +40,21 @@ second"</pre>
|
|
|
40
40
|
);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
it('renders inline tsrx fragments', async () => {
|
|
44
|
+
component Basic() {
|
|
45
|
+
const content = <tsrx>
|
|
46
|
+
const label = 'Server';
|
|
47
|
+
<span>{label}</span>
|
|
48
|
+
</tsrx>;
|
|
49
|
+
|
|
50
|
+
<div>{content}</div>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { body } = await render(Basic);
|
|
54
|
+
|
|
55
|
+
expect(body).toBeHtml('<div><span>Server</span></div>');
|
|
56
|
+
});
|
|
57
|
+
|
|
43
58
|
it('renders tracked state updates', async () => {
|
|
44
59
|
component Counter() {
|
|
45
60
|
let &[count] = track(0);
|