ripple 0.3.8 → 0.3.10
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 +19 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +38 -172
- package/src/compiler/phases/2-analyze/index.js +308 -115
- package/src/compiler/phases/2-analyze/prune.js +13 -5
- package/src/compiler/phases/3-transform/client/index.js +197 -213
- package/src/compiler/phases/3-transform/segments.js +0 -7
- package/src/compiler/phases/3-transform/server/index.js +77 -170
- package/src/compiler/types/acorn.d.ts +1 -1
- package/src/compiler/types/estree.d.ts +1 -1
- package/src/compiler/types/import.d.ts +0 -2
- package/src/compiler/types/index.d.ts +14 -18
- package/src/compiler/types/parse.d.ts +3 -9
- package/src/compiler/utils.js +154 -21
- package/src/runtime/element.js +39 -0
- package/src/runtime/index-client.js +2 -13
- package/src/runtime/index-server.js +2 -2
- package/src/runtime/internal/client/bindings.js +3 -1
- package/src/runtime/internal/client/composite.js +11 -6
- package/src/runtime/internal/client/events.js +1 -1
- package/src/runtime/internal/client/expression.js +218 -0
- package/src/runtime/internal/client/head.js +3 -4
- package/src/runtime/internal/client/index.js +4 -1
- package/src/runtime/internal/client/portal.js +12 -6
- package/src/runtime/internal/client/runtime.js +0 -52
- package/src/runtime/internal/server/index.js +57 -56
- package/tests/client/basic/basic.components.test.ripple +85 -87
- package/tests/client/basic/basic.errors.test.ripple +28 -4
- package/tests/client/basic/basic.reactivity.test.ripple +10 -155
- package/tests/client/basic/basic.rendering.test.ripple +23 -8
- package/tests/client/capture-error.js +12 -0
- package/tests/client/compiler/compiler.basic.test.ripple +107 -18
- package/tests/client/composite/composite.props.test.ripple +5 -9
- package/tests/client/composite/composite.reactivity.test.ripple +35 -36
- package/tests/client/composite/composite.render.test.ripple +45 -13
- package/tests/client/css/global-additional-cases.test.ripple +3 -3
- package/tests/client/dynamic-elements.test.ripple +3 -4
- package/tests/client/lazy-destructuring.test.ripple +69 -12
- package/tests/client/svg.test.ripple +4 -4
- package/tests/hydration/basic.test.js +23 -0
- package/tests/hydration/compiled/client/basic.js +118 -66
- package/tests/hydration/compiled/client/composite.js +90 -37
- package/tests/hydration/compiled/client/events.js +18 -18
- package/tests/hydration/compiled/client/for.js +62 -62
- package/tests/hydration/compiled/client/head.js +10 -10
- package/tests/hydration/compiled/client/hmr.js +13 -10
- package/tests/hydration/compiled/client/html.js +274 -236
- package/tests/hydration/compiled/client/if-children.js +41 -35
- package/tests/hydration/compiled/client/if.js +2 -2
- package/tests/hydration/compiled/client/mixed-control-flow.js +12 -12
- package/tests/hydration/compiled/client/nested-control-flow.js +46 -46
- package/tests/hydration/compiled/client/portal.js +8 -8
- package/tests/hydration/compiled/client/reactivity.js +14 -14
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/try.js +4 -4
- package/tests/hydration/compiled/server/basic.js +64 -31
- package/tests/hydration/compiled/server/composite.js +62 -29
- package/tests/hydration/compiled/server/hmr.js +24 -37
- package/tests/hydration/compiled/server/html.js +472 -611
- package/tests/hydration/compiled/server/if-children.js +77 -103
- package/tests/hydration/compiled/server/portal.js +8 -8
- package/tests/hydration/components/basic.ripple +15 -5
- package/tests/hydration/components/composite.ripple +13 -1
- package/tests/hydration/components/hmr.ripple +1 -3
- package/tests/hydration/components/html.ripple +13 -35
- package/tests/hydration/components/if-children.ripple +4 -8
- package/tests/hydration/composite.test.js +11 -0
- package/tests/server/basic.attributes.test.ripple +50 -0
- package/tests/server/basic.components.test.ripple +22 -28
- package/tests/server/basic.test.ripple +12 -0
- package/tests/server/compiler.test.ripple +43 -4
- package/tests/server/composite.props.test.ripple +5 -9
- package/tests/server/dynamic-elements.test.ripple +3 -4
- package/tests/server/lazy-destructuring.test.ripple +68 -12
- package/tests/server/style-identifier.test.ripple +2 -4
- package/tsconfig.typecheck.json +4 -0
- package/types/index.d.ts +9 -21
- package/tests/client/__snapshots__/tracked-expression.test.ripple.snap +0 -34
- package/tests/client/tracked-expression.test.ripple +0 -26
|
@@ -10,17 +10,15 @@ import type {
|
|
|
10
10
|
describe('basic server > components & composition', () => {
|
|
11
11
|
it('renders with component composition and children', async () => {
|
|
12
12
|
component Card(props: PropsWithChildren<{}>) {
|
|
13
|
-
<div class="card">
|
|
14
|
-
<props.children />
|
|
15
|
-
</div>
|
|
13
|
+
<div class="card">{props.children}</div>
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
component Basic() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
component children() {
|
|
18
|
+
<p>{'Card content here'}</p>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
<Card {children} />
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
const { body } = await render(Basic);
|
|
@@ -37,16 +35,16 @@ describe('basic server > components & composition', () => {
|
|
|
37
35
|
component Card(props: PropsWithChildrenOptional<{ test: Component }>) {
|
|
38
36
|
<div class="card">
|
|
39
37
|
// @ts-expect-error - ripple automatically handles falsy children
|
|
40
|
-
|
|
38
|
+
{props.children}
|
|
41
39
|
</div>
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
component Basic() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
component test() {
|
|
44
|
+
<p>{'Card content here'}</p>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
<Card {test} />
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
const { body } = await render(Basic);
|
|
@@ -62,9 +60,7 @@ describe('basic server > components & composition', () => {
|
|
|
62
60
|
|
|
63
61
|
it('renders a component when children is set a component prop', async () => {
|
|
64
62
|
component Card(props: PropsWithChildren<{}>) {
|
|
65
|
-
<div class="card">
|
|
66
|
-
<props.children />
|
|
67
|
-
</div>
|
|
63
|
+
<div class="card">{props.children}</div>
|
|
68
64
|
}
|
|
69
65
|
|
|
70
66
|
component Basic() {
|
|
@@ -174,21 +170,19 @@ describe('basic server > components & composition', () => {
|
|
|
174
170
|
<span>{'Hello from Span'}</span>
|
|
175
171
|
},
|
|
176
172
|
button: component({ children }: PropsWithChildren<{}>) {
|
|
177
|
-
<button>
|
|
178
|
-
<children />
|
|
179
|
-
</button>
|
|
173
|
+
<button>{children}</button>
|
|
180
174
|
},
|
|
181
175
|
};
|
|
182
176
|
|
|
183
177
|
component App() {
|
|
178
|
+
component children() {
|
|
179
|
+
<span>{'Click me!'}</span>
|
|
180
|
+
}
|
|
181
|
+
|
|
184
182
|
<div>
|
|
185
183
|
<h1>{'Component as Property Test'}</h1>
|
|
186
184
|
<UI.span />
|
|
187
|
-
<UI.button
|
|
188
|
-
component children() {
|
|
189
|
-
<span>{'Click me!'}</span>
|
|
190
|
-
}
|
|
191
|
-
</UI.button>
|
|
185
|
+
<UI.button {children} />
|
|
192
186
|
</div>
|
|
193
187
|
}
|
|
194
188
|
|
|
@@ -207,13 +201,13 @@ describe('basic server > components & composition', () => {
|
|
|
207
201
|
|
|
208
202
|
it('handles empty string children', async () => {
|
|
209
203
|
component Button({ children }: PropsWithChildren<{}>) {
|
|
210
|
-
|
|
204
|
+
{children}
|
|
211
205
|
}
|
|
212
206
|
|
|
213
207
|
component App() {
|
|
214
|
-
let
|
|
208
|
+
let content = '';
|
|
215
209
|
<Button>{''}</Button>
|
|
216
|
-
<Button>{
|
|
210
|
+
<Button>{content}</Button>
|
|
217
211
|
}
|
|
218
212
|
|
|
219
213
|
const { body } = await render(App);
|
|
@@ -13,6 +13,18 @@ describe('basic client', () => {
|
|
|
13
13
|
expect(body).toBeHtml('<div>Hello World</div>');
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
it('renders explicit text interpolation as escaped text', async () => {
|
|
17
|
+
component Basic() {
|
|
18
|
+
let markup = '<span>Not HTML</span>';
|
|
19
|
+
|
|
20
|
+
<div>{text markup}</div>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { body } = await render(Basic);
|
|
24
|
+
|
|
25
|
+
expect(body).toBeHtml('<div><span>Not HTML</span></div>');
|
|
26
|
+
});
|
|
27
|
+
|
|
16
28
|
it('renders tracked state updates', async () => {
|
|
17
29
|
component Counter() {
|
|
18
30
|
let &[count] = track(0);
|
|
@@ -78,9 +78,7 @@ export component Layout({ children }) {
|
|
|
78
78
|
<div>{children}</div>
|
|
79
79
|
}`;
|
|
80
80
|
|
|
81
|
-
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
82
|
-
'`children` cannot be rendered using text interpolation. Use `<children />` instead.',
|
|
83
|
-
);
|
|
81
|
+
expect(() => compile(source, 'test.ripple', { mode: 'server' })).not.toThrow();
|
|
84
82
|
});
|
|
85
83
|
|
|
86
84
|
it('throws error for interpolating props.children as text in SSR mode', () => {
|
|
@@ -89,10 +87,51 @@ export component Layout(props) {
|
|
|
89
87
|
<div>{props.children}</div>
|
|
90
88
|
}`;
|
|
91
89
|
|
|
90
|
+
expect(() => compile(source, 'test.ripple', { mode: 'server' })).not.toThrow();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('throws error for calling children as a function in SSR mode', () => {
|
|
94
|
+
const source = `
|
|
95
|
+
export component Layout({ children }) {
|
|
96
|
+
{children()}
|
|
97
|
+
}`;
|
|
98
|
+
|
|
92
99
|
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
93
|
-
'`children` cannot be
|
|
100
|
+
'`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
|
|
94
101
|
);
|
|
95
102
|
});
|
|
103
|
+
|
|
104
|
+
it('throws error for calling props.children as a function in SSR mode', () => {
|
|
105
|
+
const source = `
|
|
106
|
+
export component Layout(props) {
|
|
107
|
+
{props.children()}
|
|
108
|
+
}`;
|
|
109
|
+
|
|
110
|
+
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
111
|
+
'`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('merges explicit children prop with implicit children in SSR output', () => {
|
|
116
|
+
const source = `
|
|
117
|
+
component Card(props) {
|
|
118
|
+
<div>{props.children}</div>
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export component App() {
|
|
122
|
+
const fallback = 'fallback';
|
|
123
|
+
|
|
124
|
+
<Card children={fallback}>
|
|
125
|
+
<span>{'content'}</span>
|
|
126
|
+
</Card>
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const result = compile(source, 'test.ripple', { mode: 'server' }).js.code;
|
|
131
|
+
|
|
132
|
+
expect((result.match(/children:/g) || []).length).toBe(1);
|
|
133
|
+
expect(result).toContain('children: _$_.normalize_children(fallback) ?? _$_.ripple_element(');
|
|
134
|
+
});
|
|
96
135
|
});
|
|
97
136
|
|
|
98
137
|
describe('compiler server block tests', () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { track
|
|
1
|
+
import { track } from 'ripple';
|
|
2
2
|
import type { Tracked, Props } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('composite > props', () => {
|
|
@@ -79,11 +79,8 @@ describe('composite > props', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
it('correctly retains prop accessors and reactivity when using rest props', async () => {
|
|
82
|
-
component Button(
|
|
83
|
-
|
|
84
|
-
<button {...rest.value}>
|
|
85
|
-
<@children />
|
|
86
|
-
</button>
|
|
82
|
+
component Button(&{ children, ...rest }: Props) {
|
|
83
|
+
<button {...rest}>{children}</button>
|
|
87
84
|
<style>
|
|
88
85
|
.on {
|
|
89
86
|
color: blue;
|
|
@@ -94,10 +91,9 @@ describe('composite > props', () => {
|
|
|
94
91
|
</style>
|
|
95
92
|
}
|
|
96
93
|
|
|
97
|
-
component Toggle(
|
|
98
|
-
const [pressed, rest] = trackSplit(props, ['pressed']);
|
|
94
|
+
component Toggle(&{ pressed, ...rest }: { pressed: Tracked<boolean> }) {
|
|
99
95
|
const onClick = () => (pressed.value = !pressed.value);
|
|
100
|
-
<Button {...rest
|
|
96
|
+
<Button {...rest} class={pressed.value ? 'on' : 'off'} {onClick}>{'button 1'}</Button>
|
|
101
97
|
<Button class={pressed.value ? 'on' : 'off'} {onClick}>{'button 2'}</Button>
|
|
102
98
|
}
|
|
103
99
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PropsWithExtras } from 'ripple';
|
|
2
|
-
import { createRefKey, track
|
|
2
|
+
import { createRefKey, track } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('server dynamic DOM elements', () => {
|
|
5
5
|
it('renders static dynamic element', async () => {
|
|
@@ -258,13 +258,12 @@ describe('server dynamic DOM elements', () => {
|
|
|
258
258
|
});
|
|
259
259
|
|
|
260
260
|
it('handles spread attributes with class and CSS scoping', async () => {
|
|
261
|
-
component DynamicButton(
|
|
261
|
+
component DynamicButton(&{ ...rest }: PropsWithExtras<{
|
|
262
262
|
class: string;
|
|
263
263
|
id: string;
|
|
264
264
|
}>) {
|
|
265
265
|
const tag = track('button');
|
|
266
|
-
|
|
267
|
-
<@tag {...rest.value}>{rest.value.class}</@tag>
|
|
266
|
+
<@tag {...rest}>{rest.class}</@tag>
|
|
268
267
|
|
|
269
268
|
<style>
|
|
270
269
|
.even {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Tracked } from 'ripple';
|
|
2
|
+
import { track } from 'ripple';
|
|
2
3
|
|
|
3
4
|
describe('lazy destructuring', () => {
|
|
4
5
|
it('supports tracked value getter and setter', async () => {
|
|
@@ -30,7 +31,7 @@ describe('lazy destructuring', () => {
|
|
|
30
31
|
|
|
31
32
|
it('supports default values in lazy object destructuring', async () => {
|
|
32
33
|
component Test() {
|
|
33
|
-
const obj = { a: 5 };
|
|
34
|
+
const obj: { a: number; b?: number } = { a: 5 };
|
|
34
35
|
const &{ a, b = 99 } = obj;
|
|
35
36
|
<pre>{`${a}-${b}`}</pre>
|
|
36
37
|
}
|
|
@@ -39,6 +40,20 @@ describe('lazy destructuring', () => {
|
|
|
39
40
|
expect(body).toBeHtml('<pre>5-99</pre>');
|
|
40
41
|
});
|
|
41
42
|
|
|
43
|
+
it('supports nested lazy destructuring in non-lazy component params', async () => {
|
|
44
|
+
component Inner({ something: &[first, second] }: { something: Tracked<number> }) {
|
|
45
|
+
first = second.value + 1;
|
|
46
|
+
<pre>{`${first}-${second.value}`}</pre>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
component Test() {
|
|
50
|
+
<Inner something={track(1)} />
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { body } = await render(Test);
|
|
54
|
+
expect(body).toBeHtml('<pre>2-2</pre>');
|
|
55
|
+
});
|
|
56
|
+
|
|
42
57
|
it('supports let lazy destructuring with assignment writeback', async () => {
|
|
43
58
|
component Test() {
|
|
44
59
|
const obj = { a: 1, b: 2 };
|
|
@@ -106,26 +121,67 @@ describe('lazy destructuring', () => {
|
|
|
106
121
|
expect(body).toBeHtml('<pre>15-105</pre>');
|
|
107
122
|
});
|
|
108
123
|
|
|
109
|
-
it('supports
|
|
124
|
+
it('supports nested lazy destructuring in non-lazy function params', async () => {
|
|
110
125
|
component Test() {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
<
|
|
126
|
+
const something = track(1);
|
|
127
|
+
|
|
128
|
+
function getInfo({ something: &[first, second] }: { something: Tracked<number> }) {
|
|
129
|
+
first = second.value + 1;
|
|
130
|
+
return `${first}-${second.value}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
<pre>{getInfo({ something })}</pre>
|
|
114
134
|
}
|
|
115
135
|
|
|
116
136
|
const { body } = await render(Test);
|
|
117
|
-
expect(body).toBeHtml('<pre>
|
|
137
|
+
expect(body).toBeHtml('<pre>2-2</pre>');
|
|
118
138
|
});
|
|
119
139
|
|
|
120
|
-
it(
|
|
140
|
+
it(
|
|
141
|
+
'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy component params',
|
|
142
|
+
async () => {
|
|
143
|
+
component Inner({ values: [head, ...&{ 0: first_rest, length: rest_length }] }) {
|
|
144
|
+
const before = `${first_rest}-${rest_length}`;
|
|
145
|
+
rest_length = 0;
|
|
146
|
+
<pre>{`${head}-${before}-${first_rest}-${rest_length}`}</pre>
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
component Test() {
|
|
150
|
+
<Inner values={[10, 20, 30]} />
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const { body } = await render(Test);
|
|
154
|
+
expect(body).toBeHtml('<pre>10-20-2-undefined-0</pre>');
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
it(
|
|
159
|
+
'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy function params',
|
|
160
|
+
async () => {
|
|
161
|
+
component Test() {
|
|
162
|
+
function getInfo({ values: [head, ...&{ 0: first_rest, length: rest_length }] }) {
|
|
163
|
+
const before = `${first_rest}-${rest_length}`;
|
|
164
|
+
rest_length = 0;
|
|
165
|
+
return `${head}-${before}-${first_rest}-${rest_length}`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
<pre>{getInfo({ values: [5, 6, 7] })}</pre>
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const { body } = await render(Test);
|
|
172
|
+
expect(body).toBeHtml('<pre>5-6-2-undefined-0</pre>');
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
it('supports member access on lazy destructured objects', async () => {
|
|
121
177
|
component Test() {
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
<pre>{`${
|
|
178
|
+
const obj = { user: { name: 'Alice', age: 30 } };
|
|
179
|
+
const &{ user } = obj;
|
|
180
|
+
<pre>{`${user.name}-${user.age}`}</pre>
|
|
125
181
|
}
|
|
126
182
|
|
|
127
183
|
const { body } = await render(Test);
|
|
128
|
-
expect(body).toBeHtml('<pre>
|
|
184
|
+
expect(body).toBeHtml('<pre>Alice-30</pre>');
|
|
129
185
|
});
|
|
130
186
|
|
|
131
187
|
it('supports rest in lazy array destructuring for tracked tuples (iterable)', async () => {
|
|
@@ -190,7 +190,7 @@ describe('#style identifier (server)', () => {
|
|
|
190
190
|
component Wrapper({ children }) {
|
|
191
191
|
<div class="green">
|
|
192
192
|
{'Wrapper'}
|
|
193
|
-
|
|
193
|
+
{children}
|
|
194
194
|
</div>
|
|
195
195
|
|
|
196
196
|
<style>
|
|
@@ -235,9 +235,7 @@ describe('#style identifier (server)', () => {
|
|
|
235
235
|
|
|
236
236
|
it('applies caller scoped hash to slotted children through dynamic components', async () => {
|
|
237
237
|
component Wrapper({ children }) {
|
|
238
|
-
<section>
|
|
239
|
-
<children />
|
|
240
|
-
</section>
|
|
238
|
+
<section>{children}</section>
|
|
241
239
|
}
|
|
242
240
|
|
|
243
241
|
component App() {
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export type Component<T = Record<string, any>> = (props: T) => void;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
declare const RIPPLE_ELEMENT: unique symbol;
|
|
4
|
+
|
|
5
|
+
export type RippleElement = {
|
|
6
|
+
readonly render: Function;
|
|
7
|
+
readonly [RIPPLE_ELEMENT]: true;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** Type for implicit children fragments rendered with `{children}`. */
|
|
11
|
+
export type Children = RippleElement;
|
|
5
12
|
|
|
6
13
|
export type CompatApi = {
|
|
7
14
|
createRoot: () => void;
|
|
@@ -176,19 +183,6 @@ export type PropsNoChildren<T extends object = {}> = Expand<T>;
|
|
|
176
183
|
|
|
177
184
|
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
|
178
185
|
|
|
179
|
-
type WrapTracked<V> = V extends Tracked<any> ? V : Tracked<V>;
|
|
180
|
-
|
|
181
|
-
type PickKeys<T, K extends readonly (keyof T)[]> = {
|
|
182
|
-
[I in keyof K]: WrapTracked<T[K[I] & keyof T]>;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
type RestKeys<T, K extends readonly (keyof T)[]> = Expand<Omit<T, K[number]>>;
|
|
186
|
-
|
|
187
|
-
type SplitResult<T extends Props, K extends readonly (keyof T)[]> = [
|
|
188
|
-
...PickKeys<T, K>,
|
|
189
|
-
Tracked<RestKeys<T, K>>,
|
|
190
|
-
];
|
|
191
|
-
|
|
192
186
|
export function get<V>(tracked: Tracked<V>): V;
|
|
193
187
|
|
|
194
188
|
export function set<V>(tracked: Tracked<V>, value: V): void;
|
|
@@ -204,11 +198,6 @@ export function track<V>(
|
|
|
204
198
|
// Overload for non-function values
|
|
205
199
|
export function track<V>(value?: V, get?: (v: V) => V, set?: (next: V, prev: V) => V): Tracked<V>;
|
|
206
200
|
|
|
207
|
-
export function trackSplit<V extends Props, const K extends readonly (keyof V)[]>(
|
|
208
|
-
value: V,
|
|
209
|
-
splitKeys: K,
|
|
210
|
-
): SplitResult<V, K>;
|
|
211
|
-
|
|
212
201
|
export interface AddEventOptions extends ExtendedEventOptions {
|
|
213
202
|
customName?: string;
|
|
214
203
|
}
|
|
@@ -568,7 +557,6 @@ export interface RippleNamespace {
|
|
|
568
557
|
urlSearchParams: RippleURLSearchParamsCallable;
|
|
569
558
|
untrack: typeof untrack;
|
|
570
559
|
track: typeof track;
|
|
571
|
-
trackSplit: typeof trackSplit;
|
|
572
560
|
style: Record<string, string>;
|
|
573
561
|
server: ServerBlock;
|
|
574
562
|
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
-
|
|
3
|
-
exports[`TrackedExpression tests > should handle the syntax correctly 1`] = `
|
|
4
|
-
<div>
|
|
5
|
-
<div>
|
|
6
|
-
0
|
|
7
|
-
</div>
|
|
8
|
-
<div>
|
|
9
|
-
4
|
|
10
|
-
</div>
|
|
11
|
-
<div>
|
|
12
|
-
1
|
|
13
|
-
</div>
|
|
14
|
-
<div>
|
|
15
|
-
2
|
|
16
|
-
</div>
|
|
17
|
-
<div>
|
|
18
|
-
2
|
|
19
|
-
</div>
|
|
20
|
-
<div>
|
|
21
|
-
3
|
|
22
|
-
</div>
|
|
23
|
-
<div>
|
|
24
|
-
4
|
|
25
|
-
</div>
|
|
26
|
-
<div>
|
|
27
|
-
false
|
|
28
|
-
</div>
|
|
29
|
-
<div>
|
|
30
|
-
true
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
</div>
|
|
34
|
-
`;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { track } from 'ripple';
|
|
2
|
-
|
|
3
|
-
describe('TrackedExpression tests', () => {
|
|
4
|
-
it('should handle the syntax correctly', () => {
|
|
5
|
-
component App() {
|
|
6
|
-
let count = track(0);
|
|
7
|
-
|
|
8
|
-
function get_count() {
|
|
9
|
-
return count;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
<div>{@(count)}</div>
|
|
13
|
-
<div>{@(get_count())}</div>
|
|
14
|
-
<div>{++@(count)}</div>
|
|
15
|
-
<div>{++@(get_count())}</div>
|
|
16
|
-
<div>{@(count)++}</div>
|
|
17
|
-
<div>{@(get_count())++}</div>
|
|
18
|
-
<div>{@(count)}</div>
|
|
19
|
-
<div>{!@(count)}</div>
|
|
20
|
-
<div>{!!@(count)}</div>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
render(App);
|
|
24
|
-
expect(container).toMatchSnapshot();
|
|
25
|
-
});
|
|
26
|
-
});
|