ripple 0.2.78 → 0.2.80

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/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.2.78",
6
+ "version": "0.2.80",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -802,20 +802,35 @@ const visitors = {
802
802
  }
803
803
  }
804
804
 
805
- if (is_spreading) {
805
+ const metadata = { tracking: false, await: false };
806
+ // We visit, but only to gather metadata
807
+ b.call(visit(node.id, { ...state, metadata }));
808
+
809
+ if (metadata.tracking) {
806
810
  state.init.push(
807
811
  b.stmt(
808
812
  b.call(
809
- node.id,
813
+ '_$_.composite',
814
+ b.thunk(visit(node.id, state)),
810
815
  id,
811
- b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block')),
812
- b.id('_$_.active_block'),
816
+ is_spreading
817
+ ? b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block'))
818
+ : b.object(props),
813
819
  ),
814
820
  ),
815
821
  );
816
822
  } else {
817
823
  state.init.push(
818
- b.stmt(b.call(visit(node.id, state), id, b.object(props), b.id('_$_.active_block'))),
824
+ b.stmt(
825
+ b.call(
826
+ visit(node.id, state),
827
+ id,
828
+ is_spreading
829
+ ? b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block'))
830
+ : b.object(props),
831
+ b.id('_$_.active_block'),
832
+ ),
833
+ ),
819
834
  );
820
835
  }
821
836
  }
@@ -0,0 +1,22 @@
1
+ import { branch, destroy_block, render } from './blocks.js';
2
+ import { COMPOSITE_BLOCK } from './constants.js';
3
+ import { active_block } from './runtime.js';
4
+
5
+ export function composite(get_component, node, props) {
6
+ var anchor = node;
7
+ var b = null;
8
+
9
+ render(() => {
10
+ var component = get_component();
11
+
12
+ if (b !== null) {
13
+ destroy_block(b);
14
+ b = null;
15
+ }
16
+
17
+ b = branch(() => {
18
+ var block = active_block;
19
+ component(anchor, props, block);
20
+ });
21
+ }, COMPOSITE_BLOCK);
22
+ }
@@ -5,8 +5,8 @@ export var BRANCH_BLOCK = 1 << 4;
5
5
  export var FOR_BLOCK = 1 << 5;
6
6
  export var TRY_BLOCK = 1 << 6;
7
7
  export var IF_BLOCK = 1 << 7;
8
- export var ASYNC_BLOCK = 1 << 8;
9
- export var COMPAT_BLOCK = 1 << 9;
8
+ export var COMPOSITE_BLOCK = 1 << 8;
9
+ export var ASYNC_BLOCK = 1 << 9;
10
10
  export var CONTAINS_UPDATE = 1 << 10;
11
11
  export var CONTAINS_TEARDOWN = 1 << 11;
12
12
  export var BLOCK_HAS_RUN = 1 << 12;
@@ -16,7 +16,7 @@ export var DEFERRED = 1 << 15;
16
16
  export var PAUSED = 1 << 16;
17
17
  export var DESTROYED = 1 << 17;
18
18
 
19
- export var LOGIC_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK;
19
+ export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK | COMPOSITE_BLOCK;
20
20
 
21
21
  export var UNINITIALIZED = Symbol();
22
22
  /** @type {unique symbol} */
@@ -43,6 +43,8 @@ export {
43
43
  maybe_tracked,
44
44
  } from './runtime.js';
45
45
 
46
+ export { composite } from './composite.js';
47
+
46
48
  export { for_block as for } from './for.js';
47
49
 
48
50
  export { if_block as if } from './if.js';
@@ -114,6 +114,10 @@ export function spread_attrs(attrs, css_hash) {
114
114
 
115
115
  if (typeof value === 'function') continue;
116
116
 
117
+ if (is_tracked_object(value)) {
118
+ value = get(value);
119
+ }
120
+
117
121
  if (name === 'class' && css_hash) {
118
122
  value = (value == null ? '' : value) + ' ' + css_hash;
119
123
  }
@@ -1,6 +1,6 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`basic > basic operations 1`] = `
3
+ exports[`basic client > basic operations 1`] = `
4
4
  <div>
5
5
  <div>
6
6
  0
@@ -18,25 +18,7 @@ exports[`basic > basic operations 1`] = `
18
18
  </div>
19
19
  `;
20
20
 
21
- exports[`basic > correctly renders adjacent text nodes 1`] = `
22
- <div>
23
- <div>
24
- 11
25
- </div>
26
- <div>
27
- 11
28
- </div>
29
- <div>
30
- truetrue
31
- </div>
32
- <div>
33
- truetrue
34
- </div>
35
-
36
- </div>
37
- `;
38
-
39
- exports[`basic > handles boolean attributes with no prop value provides 1`] = `
21
+ exports[`basic client > handles boolean attributes with no prop value provides 1`] = `
40
22
  <div>
41
23
  <div
42
24
  class="container"
@@ -55,7 +37,7 @@ exports[`basic > handles boolean attributes with no prop value provides 1`] = `
55
37
  </div>
56
38
  `;
57
39
 
58
- exports[`basic > render semi-dynamic text 1`] = `
40
+ exports[`basic client > render semi-dynamic text 1`] = `
59
41
  <div>
60
42
  <div>
61
43
  Hello World
@@ -64,7 +46,7 @@ exports[`basic > render semi-dynamic text 1`] = `
64
46
  </div>
65
47
  `;
66
48
 
67
- exports[`basic > render spread props without duplication 1`] = `
49
+ exports[`basic client > render spread props without duplication 1`] = `
68
50
  <div>
69
51
  <div>
70
52
  <input
@@ -78,7 +60,7 @@ exports[`basic > render spread props without duplication 1`] = `
78
60
  </div>
79
61
  `;
80
62
 
81
- exports[`basic > render static attributes 1`] = `
63
+ exports[`basic client > render static attributes 1`] = `
82
64
  <div>
83
65
  <div
84
66
  class="foo"
@@ -91,7 +73,7 @@ exports[`basic > render static attributes 1`] = `
91
73
  </div>
92
74
  `;
93
75
 
94
- exports[`basic > render static text 1`] = `
76
+ exports[`basic client > render static text 1`] = `
95
77
  <div>
96
78
  <div>
97
79
  Hello World
@@ -100,7 +82,7 @@ exports[`basic > render static text 1`] = `
100
82
  </div>
101
83
  `;
102
84
 
103
- exports[`basic > renders simple JS expression logic correctly 1`] = `
85
+ exports[`basic client > renders simple JS expression logic correctly 1`] = `
104
86
  <div>
105
87
  <div>
106
88
  {"0":"Test"}
@@ -112,7 +94,7 @@ exports[`basic > renders simple JS expression logic correctly 1`] = `
112
94
  </div>
113
95
  `;
114
96
 
115
- exports[`basic > should handle lexical scopes correctly 1`] = `
97
+ exports[`basic client > should handle lexical scopes correctly 1`] = `
116
98
  <div>
117
99
  <section>
118
100
  Nested scope variable
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { mount, flushSync, effect, track } from 'ripple';
3
3
  import { compile } from 'ripple/compiler';
4
4
 
5
- describe('basic', () => {
5
+ describe('basic client', () => {
6
6
  let container;
7
7
 
8
8
  function render(component) {
@@ -663,5 +663,41 @@ describe('composite components', () => {
663
663
 
664
664
  render(App);
665
665
  expect(container).toMatchSnapshot();
666
- })
666
+ });
667
+
668
+ it('handles dynamic component switching', () => {
669
+ component Child1() {
670
+ <div>{"I am child 1"}</div>
671
+ }
672
+
673
+ component Child2() {
674
+ <div>{"I am child 2"}</div>
675
+ }
676
+
677
+ component App() {
678
+ let thing = track(() => Child1)
679
+
680
+ <div id="container">
681
+ <@thing />
682
+ </div>
683
+
684
+ <button onClick={() => @thing = @thing === Child1 ? Child2 : Child1}>{"Change Child"}</button>
685
+ }
686
+
687
+ render(App);
688
+ flushSync();
689
+
690
+ expect(container.querySelector('#container').textContent).toBe('I am child 1');
691
+
692
+ const button = container.querySelector('button');
693
+ button.click();
694
+ flushSync();
695
+
696
+ expect(container.querySelector('#container').textContent).toBe('I am child 2');
697
+
698
+ button.click();
699
+ flushSync();
700
+
701
+ expect(container.querySelector('#container').textContent).toBe('I am child 1');
702
+ });
667
703
  });
@@ -0,0 +1,15 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { render } from 'ripple/server';
3
+
4
+ describe('basic client', () => {
5
+ it('render static text', async () => {
6
+ component Basic() {
7
+ <div>{'Hello World'}</div>
8
+ }
9
+
10
+ const { head, body } = await render(Basic);
11
+
12
+ expect(head).toBe('');
13
+ expect(body).toBe('<div>Hello World</div>');
14
+ });
15
+ });
package/types/server.d.ts CHANGED
@@ -0,0 +1,4 @@
1
+
2
+ export declare async function render(
3
+ component: () => void,
4
+ ): { head: string; body: string };