ripple 0.2.215 → 0.3.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 +86 -0
- package/package.json +16 -7
- package/src/compiler/errors.js +1 -1
- package/src/compiler/identifier-utils.js +2 -0
- package/src/compiler/index.d.ts +2 -6
- package/src/compiler/phases/1-parse/index.js +171 -233
- package/src/compiler/phases/2-analyze/index.js +216 -16
- package/src/compiler/phases/2-analyze/prune.js +2 -2
- package/src/compiler/phases/3-transform/client/index.js +326 -94
- package/src/compiler/phases/3-transform/segments.js +43 -15
- package/src/compiler/phases/3-transform/server/index.js +71 -21
- package/src/compiler/scope.js +31 -12
- package/src/compiler/source-map-utils.js +4 -6
- package/src/compiler/types/acorn.d.ts +11 -0
- package/src/compiler/types/estree-jsx.d.ts +11 -0
- package/src/compiler/types/estree.d.ts +11 -0
- package/src/compiler/types/import.d.ts +32 -18
- package/src/compiler/types/index.d.ts +75 -23
- package/src/compiler/types/parse.d.ts +7 -10
- package/src/compiler/utils.js +48 -0
- package/src/runtime/array.js +53 -22
- package/src/runtime/date.js +15 -5
- package/src/runtime/index-client.js +41 -7
- package/src/runtime/index-server.js +7 -7
- package/src/runtime/internal/client/bindings.js +2 -2
- package/src/runtime/internal/client/blocks.js +40 -1
- package/src/runtime/internal/client/context.js +8 -0
- package/src/runtime/internal/client/for.js +3 -3
- package/src/runtime/internal/client/index.js +32 -5
- package/src/runtime/internal/client/render.js +20 -8
- package/src/runtime/internal/client/runtime.js +9 -7
- package/src/runtime/internal/client/template.js +1 -1
- package/src/runtime/internal/client/try.js +15 -22
- package/src/runtime/internal/client/utils.js +1 -1
- package/src/runtime/internal/server/context.js +8 -0
- package/src/runtime/internal/server/index.js +99 -6
- package/src/runtime/map.js +7 -7
- package/src/runtime/media-query.js +10 -1
- package/src/runtime/object.js +6 -6
- package/src/runtime/proxy.js +6 -6
- package/src/runtime/set.js +11 -11
- package/src/runtime/url-search-params.js +13 -2
- package/src/runtime/url.js +15 -5
- package/src/utils/builders.js +13 -3
- package/tests/client/array/array.copy-within.test.ripple +11 -11
- package/tests/client/array/array.derived.test.ripple +42 -42
- package/tests/client/array/array.iteration.test.ripple +12 -12
- package/tests/client/array/array.mutations.test.ripple +25 -25
- package/tests/client/array/array.static.test.ripple +103 -106
- package/tests/client/array/array.to-methods.test.ripple +8 -8
- package/tests/client/async-suspend.test.ripple +94 -0
- package/tests/client/basic/basic.attributes.test.ripple +31 -31
- package/tests/client/basic/basic.collections.test.ripple +7 -7
- package/tests/client/basic/basic.components.test.ripple +48 -10
- package/tests/client/basic/basic.errors.test.ripple +111 -30
- package/tests/client/basic/basic.events.test.ripple +11 -11
- package/tests/client/basic/basic.get-set.test.ripple +18 -18
- package/tests/client/basic/basic.reactivity.test.ripple +47 -42
- package/tests/client/basic/basic.rendering.test.ripple +7 -7
- package/tests/client/basic/basic.utilities.test.ripple +4 -4
- package/tests/client/boundaries.test.ripple +7 -7
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +2 -2
- package/tests/client/compiler/compiler.assignments.test.ripple +21 -21
- package/tests/client/compiler/compiler.basic.test.ripple +223 -82
- package/tests/client/compiler/compiler.tracked-access.test.ripple +8 -9
- package/tests/client/composite/composite.dynamic-components.test.ripple +8 -8
- package/tests/client/composite/composite.generics.test.ripple +4 -4
- package/tests/client/composite/composite.props.test.ripple +9 -9
- package/tests/client/composite/composite.reactivity.test.ripple +32 -26
- package/tests/client/composite/composite.render.test.ripple +13 -4
- package/tests/client/computed-properties.test.ripple +3 -3
- package/tests/client/context.test.ripple +3 -3
- package/tests/client/css/global-additional-cases.test.ripple +4 -4
- package/tests/client/css/style-identifier.test.ripple +49 -41
- package/tests/client/date.test.ripple +40 -40
- package/tests/client/dynamic-elements.test.ripple +165 -30
- package/tests/client/events.test.ripple +25 -25
- package/tests/client/for.test.ripple +76 -8
- package/tests/client/function-overload.test.ripple +0 -1
- package/tests/client/head.test.ripple +7 -7
- package/tests/client/html.test.ripple +2 -2
- package/tests/client/input-value.test.ripple +174 -176
- package/tests/client/map.test.ripple +21 -21
- package/tests/client/media-query.test.ripple +4 -4
- package/tests/client/object.test.ripple +12 -12
- package/tests/client/portal.test.ripple +4 -4
- package/tests/client/ref.test.ripple +5 -5
- package/tests/client/return.test.ripple +17 -17
- package/tests/client/set.test.ripple +16 -16
- package/tests/client/svg.test.ripple +6 -7
- package/tests/client/switch.test.ripple +10 -10
- package/tests/client/tracked-expression.test.ripple +1 -3
- package/tests/client/try.test.ripple +56 -4
- package/tests/client/url/url.derived.test.ripple +10 -9
- package/tests/client/url/url.parsing.test.ripple +10 -10
- package/tests/client/url/url.partial-removal.test.ripple +10 -10
- package/tests/client/url/url.reactivity.test.ripple +17 -17
- package/tests/client/url/url.serialization.test.ripple +4 -4
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +11 -10
- package/tests/client/url-search-params/url-search-params.initialization.test.ripple +5 -7
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +13 -13
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +19 -19
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +17 -17
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +5 -5
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +5 -5
- package/tests/hydration/compiled/client/events.js +8 -11
- package/tests/hydration/compiled/client/for.js +20 -23
- package/tests/hydration/compiled/client/head.js +17 -19
- package/tests/hydration/compiled/client/hmr.js +84 -0
- package/tests/hydration/compiled/client/html.js +1 -15
- package/tests/hydration/compiled/client/if-children.js +7 -9
- package/tests/hydration/compiled/client/if.js +5 -7
- package/tests/hydration/compiled/client/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/client/portal.js +1 -1
- package/tests/hydration/compiled/client/reactivity.js +9 -11
- package/tests/hydration/compiled/client/return.js +11 -13
- package/tests/hydration/compiled/client/switch.js +4 -6
- package/tests/hydration/compiled/server/basic.js +0 -1
- package/tests/hydration/compiled/server/composite.js +0 -3
- package/tests/hydration/compiled/server/events.js +8 -12
- package/tests/hydration/compiled/server/for.js +20 -23
- package/tests/hydration/compiled/server/head.js +17 -19
- package/tests/hydration/compiled/server/hmr.js +107 -0
- package/tests/hydration/compiled/server/html.js +1 -35
- package/tests/hydration/compiled/server/if-children.js +7 -11
- package/tests/hydration/compiled/server/if.js +5 -7
- package/tests/hydration/compiled/server/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/server/portal.js +1 -9
- package/tests/hydration/compiled/server/reactivity.js +9 -11
- package/tests/hydration/compiled/server/return.js +11 -13
- package/tests/hydration/compiled/server/switch.js +4 -6
- package/tests/hydration/components/events.ripple +8 -9
- package/tests/hydration/components/for.ripple +20 -21
- package/tests/hydration/components/head.ripple +6 -8
- package/tests/hydration/components/hmr.ripple +34 -0
- package/tests/hydration/components/html.ripple +1 -3
- package/tests/hydration/components/if-children.ripple +7 -8
- package/tests/hydration/components/if.ripple +5 -6
- package/tests/hydration/components/mixed-control-flow.ripple +4 -6
- package/tests/hydration/components/portal.ripple +1 -1
- package/tests/hydration/components/reactivity.ripple +9 -10
- package/tests/hydration/components/return.ripple +11 -12
- package/tests/hydration/components/switch.ripple +6 -8
- package/tests/hydration/hmr.test.js +74 -0
- package/tests/server/await.test.ripple +2 -2
- package/tests/server/basic.attributes.test.ripple +19 -21
- package/tests/server/basic.components.test.ripple +13 -7
- package/tests/server/basic.test.ripple +20 -21
- package/tests/server/compiler.test.ripple +5 -5
- package/tests/server/composite.props.test.ripple +6 -7
- package/tests/server/composite.test.ripple +4 -4
- package/tests/server/context.test.ripple +1 -3
- package/tests/server/dynamic-elements.test.ripple +24 -24
- package/tests/server/head.test.ripple +5 -7
- package/tests/server/style-identifier.test.ripple +16 -17
- package/types/index.d.ts +266 -62
- package/types/server.d.ts +6 -6
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { flushSync,
|
|
1
|
+
import { flushSync, RippleMap } from 'ripple';
|
|
2
2
|
|
|
3
|
-
describe('
|
|
3
|
+
describe('RippleMap', () => {
|
|
4
4
|
it('handles set with update and delete operations with a reactive size var', () => {
|
|
5
5
|
component MapTest() {
|
|
6
|
-
let map =
|
|
7
|
-
let value = track(() => map.get('a'));
|
|
8
|
-
let size = track(() => map.size);
|
|
6
|
+
let map = #ripple.map([['a', 1], ['b', 2], ['c', 3]]);
|
|
7
|
+
let value = #ripple.track(() => map.get('a'));
|
|
8
|
+
let size = #ripple.track(() => map.size);
|
|
9
9
|
|
|
10
10
|
<button onClick={() => map.set('d', 4)}>{'set'}</button>
|
|
11
11
|
<button onClick={() => map.delete('b')}>{'delete'}</button>
|
|
@@ -42,7 +42,7 @@ describe('TrackedMap', () => {
|
|
|
42
42
|
|
|
43
43
|
it('handles clear operation', () => {
|
|
44
44
|
component MapTest() {
|
|
45
|
-
let map =
|
|
45
|
+
let map = #ripple.map([['a', 1], ['b', 2], ['c', 3]]);
|
|
46
46
|
|
|
47
47
|
<button onClick={() => map.clear()}>{'clear'}</button>
|
|
48
48
|
<pre>{map.size}</pre>
|
|
@@ -60,8 +60,8 @@ describe('TrackedMap', () => {
|
|
|
60
60
|
|
|
61
61
|
it('handles has operation and tracks reactive $has', () => {
|
|
62
62
|
component MapTest() {
|
|
63
|
-
let map =
|
|
64
|
-
let has = track(() => map.has('b'));
|
|
63
|
+
let map = #ripple.map([['a', 1], ['b', 2], ['c', 3]]);
|
|
64
|
+
let has = #ripple.track(() => map.has('b'));
|
|
65
65
|
|
|
66
66
|
<button onClick={() => map.delete('b')}>{'delete'}</button>
|
|
67
67
|
<pre>{@has}</pre>
|
|
@@ -80,10 +80,10 @@ describe('TrackedMap', () => {
|
|
|
80
80
|
|
|
81
81
|
it('handles reactivity of keys, values, and entries', () => {
|
|
82
82
|
component MapTest() {
|
|
83
|
-
let map =
|
|
84
|
-
let keys = track(() => Array.from(map.keys()));
|
|
85
|
-
let values = track(() => Array.from(map.values()));
|
|
86
|
-
let entries = track(() => Array.from(map.entries()));
|
|
83
|
+
let map = #ripple.map([['x', 10], ['y', 20]]);
|
|
84
|
+
let keys = #ripple.track(() => Array.from(map.keys()));
|
|
85
|
+
let values = #ripple.track(() => Array.from(map.values()));
|
|
86
|
+
let entries = #ripple.track(() => Array.from(map.entries()));
|
|
87
87
|
|
|
88
88
|
<button onClick={() => map.delete('x')}>{'delete'}</button>
|
|
89
89
|
|
|
@@ -110,7 +110,7 @@ describe('TrackedMap', () => {
|
|
|
110
110
|
|
|
111
111
|
it('toJSON returns correct object', () => {
|
|
112
112
|
component MapTest() {
|
|
113
|
-
let map =
|
|
113
|
+
let map = #ripple.map([['foo', 1], ['bar', 2]]);
|
|
114
114
|
|
|
115
115
|
<pre>{JSON.stringify(map)}</pre>
|
|
116
116
|
}
|
|
@@ -120,9 +120,9 @@ describe('TrackedMap', () => {
|
|
|
120
120
|
expect(container.querySelectorAll('pre')[0].textContent).toBe('[["foo",1],["bar",2]]');
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
it('creates empty
|
|
123
|
+
it('creates empty RippleMap using #ripple.map() shorthand syntax', () => {
|
|
124
124
|
component MapTest() {
|
|
125
|
-
let map =
|
|
125
|
+
let map = #ripple.map();
|
|
126
126
|
|
|
127
127
|
<button onClick={() => map.set('a', 1)}>{'add'}</button>
|
|
128
128
|
<pre>{map.size}</pre>
|
|
@@ -139,10 +139,10 @@ describe('TrackedMap', () => {
|
|
|
139
139
|
expect(container.querySelector('pre').textContent).toBe('1');
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
it('creates
|
|
142
|
+
it('creates RippleMap with initial entries using #ripple.map() shorthand syntax', () => {
|
|
143
143
|
component MapTest() {
|
|
144
|
-
let map =
|
|
145
|
-
let value = track(() => map.get('b'));
|
|
144
|
+
let map = #ripple.map([['a', 1], ['b', 2], ['c', 3]]);
|
|
145
|
+
let value = #ripple.track(() => map.get('b'));
|
|
146
146
|
|
|
147
147
|
<button onClick={() => map.set('b', 10)}>{'update'}</button>
|
|
148
148
|
<pre>{map.size}</pre>
|
|
@@ -161,10 +161,10 @@ describe('TrackedMap', () => {
|
|
|
161
161
|
expect(container.querySelectorAll('pre')[1].textContent).toBe('10');
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
it('handles all operations with #
|
|
164
|
+
it('handles all operations with #ripple.map() shorthand syntax', () => {
|
|
165
165
|
component MapTest() {
|
|
166
|
-
let map =
|
|
167
|
-
let keys = track(() => Array.from(map.keys()));
|
|
166
|
+
let map = #ripple.map([['x', 100], ['y', 200]]);
|
|
167
|
+
let keys = #ripple.track(() => Array.from(map.keys()));
|
|
168
168
|
|
|
169
169
|
<button onClick={() => map.set('z', 300)}>{'add'}</button>
|
|
170
170
|
<button onClick={() => map.delete('x')}>{'delete'}</button>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flushSync
|
|
1
|
+
import { flushSync } from 'ripple';
|
|
2
2
|
|
|
3
3
|
type Callback = (event: MediaQueryListEvent) => void;
|
|
4
4
|
|
|
@@ -51,7 +51,7 @@ describe('MediaQuery', () => {
|
|
|
51
51
|
const media = '(min-width: 600px)';
|
|
52
52
|
|
|
53
53
|
component App() {
|
|
54
|
-
const medium =
|
|
54
|
+
const medium = #ripple.mediaQuery(media);
|
|
55
55
|
|
|
56
56
|
<div>
|
|
57
57
|
<p>{@medium}</p>
|
|
@@ -86,7 +86,7 @@ describe('MediaQuery', () => {
|
|
|
86
86
|
const media = '(min-width: 600px)';
|
|
87
87
|
|
|
88
88
|
component App() {
|
|
89
|
-
let show = track(true);
|
|
89
|
+
let show = #ripple.track(true);
|
|
90
90
|
|
|
91
91
|
if (@show) {
|
|
92
92
|
<Child />
|
|
@@ -96,7 +96,7 @@ describe('MediaQuery', () => {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
component Child() {
|
|
99
|
-
const medium =
|
|
99
|
+
const medium = #ripple.mediaQuery(media);
|
|
100
100
|
|
|
101
101
|
<div>
|
|
102
102
|
<p>{@medium}</p>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { flushSync,
|
|
1
|
+
import { flushSync, RippleObject } from 'ripple';
|
|
2
2
|
import { TRACKED_OBJECT } from '../../src/runtime/internal/client/constants.js';
|
|
3
3
|
|
|
4
|
-
describe('
|
|
4
|
+
describe('RippleObject', () => {
|
|
5
5
|
it('makes new properties reactive', () => {
|
|
6
6
|
component ObjectTest() {
|
|
7
|
-
const obj =
|
|
7
|
+
const obj = #ripple{ a: -1 };
|
|
8
8
|
|
|
9
9
|
obj.a = 0;
|
|
10
10
|
|
|
@@ -33,7 +33,7 @@ describe('TrackedObject', () => {
|
|
|
33
33
|
|
|
34
34
|
it('makes existing object properties reactive', () => {
|
|
35
35
|
component ObjectTest() {
|
|
36
|
-
const obj =
|
|
36
|
+
const obj = #ripple{ a: 0 };
|
|
37
37
|
|
|
38
38
|
<pre>{obj.a}</pre>
|
|
39
39
|
<button
|
|
@@ -60,7 +60,7 @@ describe('TrackedObject', () => {
|
|
|
60
60
|
|
|
61
61
|
it('checks if property exists via the has trap', () => {
|
|
62
62
|
component ObjectTest() {
|
|
63
|
-
const obj =
|
|
63
|
+
const obj = #ripple{ a: -1, b: 1 };
|
|
64
64
|
|
|
65
65
|
obj.a = 0;
|
|
66
66
|
|
|
@@ -76,7 +76,7 @@ describe('TrackedObject', () => {
|
|
|
76
76
|
|
|
77
77
|
it('deletes properties via the delete trap', () => {
|
|
78
78
|
component ObjectTest() {
|
|
79
|
-
const obj = new
|
|
79
|
+
const obj = new RippleObject<{ a?: number; b: number }>({ a: 0, b: 1 });
|
|
80
80
|
|
|
81
81
|
<pre>{String(obj.a)}</pre>
|
|
82
82
|
<button
|
|
@@ -103,7 +103,7 @@ describe('TrackedObject', () => {
|
|
|
103
103
|
|
|
104
104
|
it('checks if non-existent property is reactive when added later', () => {
|
|
105
105
|
component ObjectTest() {
|
|
106
|
-
const obj = new
|
|
106
|
+
const obj = new RippleObject<{ a?: number }>({});
|
|
107
107
|
|
|
108
108
|
<pre>{String(obj.a)}</pre>
|
|
109
109
|
<button
|
|
@@ -130,7 +130,7 @@ describe('TrackedObject', () => {
|
|
|
130
130
|
|
|
131
131
|
it('checks that deeply nested objects are not proxied or reactive', () => {
|
|
132
132
|
component ObjectTest() {
|
|
133
|
-
const obj = new
|
|
133
|
+
const obj = new RippleObject({ a: { b: 1 } });
|
|
134
134
|
|
|
135
135
|
<pre>{String(obj.a.b)}</pre>
|
|
136
136
|
<button
|
|
@@ -156,18 +156,18 @@ describe('TrackedObject', () => {
|
|
|
156
156
|
expect(pre1.textContent).toBe('1');
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
it('checks if TRACKED_OBJECT symbol is present on
|
|
159
|
+
it('checks if TRACKED_OBJECT symbol is present on RippleObject instances', () => {
|
|
160
160
|
component ObjectTest() {
|
|
161
|
-
const obj = new
|
|
161
|
+
const obj = new RippleObject({ a: 0 });
|
|
162
162
|
|
|
163
163
|
// @ts-expect-error TRACKED_OBJECT is internal
|
|
164
164
|
expect(obj[TRACKED_OBJECT]).toBe(true);
|
|
165
165
|
}
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
-
it('uses the hash syntax for creating
|
|
168
|
+
it('uses the hash syntax for creating RippleObject', () => {
|
|
169
169
|
component ObjectTest() {
|
|
170
|
-
const obj = #{ a: 0, b: 1, c: { d: { e: 8 } } };
|
|
170
|
+
const obj = #ripple{ a: 0, b: 1, c: { d: { e: 8 } } };
|
|
171
171
|
|
|
172
172
|
<pre>{obj.a}</pre>
|
|
173
173
|
<pre>{TRACKED_OBJECT in obj}</pre>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Portal,
|
|
1
|
+
import { Portal, flushSync } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('Portal', () => {
|
|
4
4
|
afterEach(() => {
|
|
@@ -46,7 +46,7 @@ describe('Portal', () => {
|
|
|
46
46
|
|
|
47
47
|
it('cleans up portal content when destroyed via conditional rendering', () => {
|
|
48
48
|
component TestPortal() {
|
|
49
|
-
let open = track(true);
|
|
49
|
+
let open = #ripple.track(true);
|
|
50
50
|
|
|
51
51
|
if (@open) {
|
|
52
52
|
<Portal target={document.body}>
|
|
@@ -72,7 +72,7 @@ describe('Portal', () => {
|
|
|
72
72
|
|
|
73
73
|
it('opens and closes portal via conditional rendering', () => {
|
|
74
74
|
component TestPortal() {
|
|
75
|
-
let open = track(false);
|
|
75
|
+
let open = #ripple.track(false);
|
|
76
76
|
|
|
77
77
|
if (@open) {
|
|
78
78
|
<Portal target={document.body}>
|
|
@@ -138,7 +138,7 @@ describe('Portal', () => {
|
|
|
138
138
|
|
|
139
139
|
it('handles portal with reactive content', () => {
|
|
140
140
|
component TestReactivePortal() {
|
|
141
|
-
let count = track(0);
|
|
141
|
+
let count = #ripple.track(0);
|
|
142
142
|
|
|
143
143
|
<Portal target={document.body}>
|
|
144
144
|
<div class="test-portal">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PropsWithExtras } from 'ripple';
|
|
2
2
|
import { describe, it, expect } from 'vitest';
|
|
3
|
-
import { flushSync,
|
|
3
|
+
import { flushSync, RippleArray, createRefKey } from 'ripple';
|
|
4
4
|
|
|
5
5
|
describe('refs', () => {
|
|
6
6
|
it('capture a <div>', () => {
|
|
@@ -25,7 +25,7 @@ describe('refs', () => {
|
|
|
25
25
|
let _node: Child | undefined;
|
|
26
26
|
|
|
27
27
|
component Component() {
|
|
28
|
-
let items =
|
|
28
|
+
let items = RippleArray.from([1, 2, 3]);
|
|
29
29
|
|
|
30
30
|
function componentRef(node: Child) {
|
|
31
31
|
_node = node;
|
|
@@ -34,7 +34,7 @@ describe('refs', () => {
|
|
|
34
34
|
<Child {ref componentRef} {items} />
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
component Child(props: { items:
|
|
37
|
+
component Child(props: { items: RippleArray<number> }) {
|
|
38
38
|
const { items, ...rest } = props;
|
|
39
39
|
<pre {...rest}>{JSON.stringify(items)}</pre>
|
|
40
40
|
<pre>{items.length}</pre>
|
|
@@ -50,7 +50,7 @@ describe('refs', () => {
|
|
|
50
50
|
let logs: string[] = [];
|
|
51
51
|
|
|
52
52
|
component App() {
|
|
53
|
-
let value = track('test');
|
|
53
|
+
let value = #ripple.track('test');
|
|
54
54
|
|
|
55
55
|
function inputRef(node: HTMLInputElement) {
|
|
56
56
|
logs.push('ref called');
|
|
@@ -81,7 +81,7 @@ describe('refs', () => {
|
|
|
81
81
|
let logs: string[] = [];
|
|
82
82
|
|
|
83
83
|
component App() {
|
|
84
|
-
let value = track('test');
|
|
84
|
+
let value = #ripple.track('test');
|
|
85
85
|
|
|
86
86
|
function inputRef(node: HTMLInputElement) {
|
|
87
87
|
logs.push('ref called');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import { flushSync } from 'ripple';
|
|
3
3
|
import { compile } from 'ripple/compiler';
|
|
4
4
|
|
|
5
5
|
describe('returns in prohibited scopes', () => {
|
|
@@ -64,7 +64,7 @@ describe('early return in client components', () => {
|
|
|
64
64
|
|
|
65
65
|
it('reactive: condition changes from false to true hides rest', () => {
|
|
66
66
|
component App() {
|
|
67
|
-
let condition = track(false);
|
|
67
|
+
let condition = #ripple.track(false);
|
|
68
68
|
|
|
69
69
|
<button
|
|
70
70
|
onClick={() => {
|
|
@@ -93,7 +93,7 @@ describe('early return in client components', () => {
|
|
|
93
93
|
|
|
94
94
|
it('reactive: condition changes from true to false shows rest', () => {
|
|
95
95
|
component App() {
|
|
96
|
-
let condition = track(true);
|
|
96
|
+
let condition = #ripple.track(true);
|
|
97
97
|
|
|
98
98
|
<button
|
|
99
99
|
onClick={() => {
|
|
@@ -905,8 +905,8 @@ describe('early return in client components', () => {
|
|
|
905
905
|
|
|
906
906
|
it('reactive: nested return condition changes', () => {
|
|
907
907
|
component App() {
|
|
908
|
-
let a = track(true);
|
|
909
|
-
let b = track(true);
|
|
908
|
+
let a = #ripple.track(true);
|
|
909
|
+
let b = #ripple.track(true);
|
|
910
910
|
|
|
911
911
|
<button
|
|
912
912
|
onClick={() => {
|
|
@@ -940,7 +940,7 @@ describe('early return in client components', () => {
|
|
|
940
940
|
|
|
941
941
|
it('reactive: return in nested element scope', () => {
|
|
942
942
|
component App() {
|
|
943
|
-
let show = track(true);
|
|
943
|
+
let show = #ripple.track(true);
|
|
944
944
|
|
|
945
945
|
<button
|
|
946
946
|
onClick={() => {
|
|
@@ -1214,7 +1214,7 @@ describe('early return in client components', () => {
|
|
|
1214
1214
|
|
|
1215
1215
|
it('reactive: nested return - outer condition changes to false shows rest', () => {
|
|
1216
1216
|
component App() {
|
|
1217
|
-
let a = track(true);
|
|
1217
|
+
let a = #ripple.track(true);
|
|
1218
1218
|
let b = true;
|
|
1219
1219
|
|
|
1220
1220
|
<button
|
|
@@ -1251,7 +1251,7 @@ describe('early return in client components', () => {
|
|
|
1251
1251
|
component App() {
|
|
1252
1252
|
let a = true;
|
|
1253
1253
|
let b = true;
|
|
1254
|
-
let c = track(true);
|
|
1254
|
+
let c = #ripple.track(true);
|
|
1255
1255
|
|
|
1256
1256
|
<button
|
|
1257
1257
|
onClick={() => {
|
|
@@ -2208,10 +2208,10 @@ describe('early return in client components', () => {
|
|
|
2208
2208
|
|
|
2209
2209
|
it('nested reactive: toggling conditions updates DOM', () => {
|
|
2210
2210
|
component App() {
|
|
2211
|
-
let a = track(false);
|
|
2212
|
-
let b = track(false);
|
|
2213
|
-
let c = track(false);
|
|
2214
|
-
let d = track(false);
|
|
2211
|
+
let a = #ripple.track(false);
|
|
2212
|
+
let b = #ripple.track(false);
|
|
2213
|
+
let c = #ripple.track(false);
|
|
2214
|
+
let d = #ripple.track(false);
|
|
2215
2215
|
|
|
2216
2216
|
<button
|
|
2217
2217
|
class="toggle-c"
|
|
@@ -2279,7 +2279,7 @@ describe('early return in client components', () => {
|
|
|
2279
2279
|
() => {
|
|
2280
2280
|
component App() {
|
|
2281
2281
|
let a = true;
|
|
2282
|
-
let b = track(true);
|
|
2282
|
+
let b = #ripple.track(true);
|
|
2283
2283
|
|
|
2284
2284
|
<button
|
|
2285
2285
|
class="toggle"
|
|
@@ -2326,7 +2326,7 @@ describe('early return in client components', () => {
|
|
|
2326
2326
|
|
|
2327
2327
|
it('reactive sibling returns cycle through first, second, and fallback branches', () => {
|
|
2328
2328
|
component App() {
|
|
2329
|
-
let mode = track('first');
|
|
2329
|
+
let mode = #ripple.track('first');
|
|
2330
2330
|
|
|
2331
2331
|
<button
|
|
2332
2332
|
class="toggle"
|
|
@@ -2382,8 +2382,8 @@ describe('early return in client components', () => {
|
|
|
2382
2382
|
|
|
2383
2383
|
it('reactive nested returns with tracked outer and inner flags transition correctly', () => {
|
|
2384
2384
|
component App() {
|
|
2385
|
-
let a = track(true);
|
|
2386
|
-
let b = track(true);
|
|
2385
|
+
let a = #ripple.track(true);
|
|
2386
|
+
let b = #ripple.track(true);
|
|
2387
2387
|
|
|
2388
2388
|
<button
|
|
2389
2389
|
class="toggle-a"
|
|
@@ -2446,7 +2446,7 @@ describe('early return in client components', () => {
|
|
|
2446
2446
|
|
|
2447
2447
|
it('reactive else-if return chain transitions between return and non-return states', () => {
|
|
2448
2448
|
component App() {
|
|
2449
|
-
let status = track(0);
|
|
2449
|
+
let status = #ripple.track(0);
|
|
2450
2450
|
|
|
2451
2451
|
<button
|
|
2452
2452
|
class="toggle"
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { flushSync,
|
|
1
|
+
import { flushSync, RippleSet } from 'ripple';
|
|
2
2
|
|
|
3
|
-
describe('
|
|
3
|
+
describe('RippleSet', () => {
|
|
4
4
|
it('handles add and delete operations', () => {
|
|
5
5
|
component SetTest() {
|
|
6
|
-
let items = new
|
|
6
|
+
let items = new RippleSet([1, 2, 3]);
|
|
7
7
|
|
|
8
8
|
<button onClick={() => items.add(4)}>{'add'}</button>
|
|
9
9
|
<button onClick={() => items.delete(2)}>{'delete'}</button>
|
|
10
10
|
<Child {items} />
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
component Child({ items }: { items:
|
|
13
|
+
component Child({ items }: { items: RippleSet<number> }) {
|
|
14
14
|
<pre>{JSON.stringify(items)}</pre>
|
|
15
15
|
<pre>{items.size}</pre>
|
|
16
16
|
}
|
|
@@ -35,13 +35,13 @@ describe('TrackedSet', () => {
|
|
|
35
35
|
|
|
36
36
|
it('handles clear operation', () => {
|
|
37
37
|
component SetTest() {
|
|
38
|
-
let items = new
|
|
38
|
+
let items = new RippleSet([1, 2, 3]);
|
|
39
39
|
|
|
40
40
|
<button onClick={() => items.clear()}>{'clear'}</button>
|
|
41
41
|
<Child {items} />
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
component Child({ items }: { items:
|
|
44
|
+
component Child({ items }: { items: RippleSet<number> }) {
|
|
45
45
|
<pre>{JSON.stringify(items)}</pre>
|
|
46
46
|
<pre>{items.size}</pre>
|
|
47
47
|
}
|
|
@@ -59,8 +59,8 @@ describe('TrackedSet', () => {
|
|
|
59
59
|
|
|
60
60
|
it('handles has operation', () => {
|
|
61
61
|
component SetTest() {
|
|
62
|
-
let items = new
|
|
63
|
-
let hasValue = track(() => items.has(2));
|
|
62
|
+
let items = new RippleSet([1, 2, 3]);
|
|
63
|
+
let hasValue = #ripple.track(() => items.has(2));
|
|
64
64
|
|
|
65
65
|
<button onClick={() => items.delete(2)}>{'delete'}</button>
|
|
66
66
|
<pre>{@hasValue}</pre>
|
|
@@ -78,9 +78,9 @@ describe('TrackedSet', () => {
|
|
|
78
78
|
expect(container.querySelectorAll('pre')[0].textContent).toBe('false');
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
it('creates empty
|
|
81
|
+
it('creates empty RippleSet using #ripple.set() shorthand syntax', () => {
|
|
82
82
|
component SetTest() {
|
|
83
|
-
let items =
|
|
83
|
+
let items = #ripple.set();
|
|
84
84
|
|
|
85
85
|
<button onClick={() => items.add(1)}>{'add'}</button>
|
|
86
86
|
<pre>{items.size}</pre>
|
|
@@ -97,10 +97,10 @@ describe('TrackedSet', () => {
|
|
|
97
97
|
expect(container.querySelector('pre').textContent).toBe('1');
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
it('creates
|
|
100
|
+
it('creates RippleSet with initial values using #ripple.set() shorthand syntax', () => {
|
|
101
101
|
component SetTest() {
|
|
102
|
-
let items =
|
|
103
|
-
let hasValue = track(() => items.has(3));
|
|
102
|
+
let items = #ripple.set([1, 2, 3, 4]);
|
|
103
|
+
let hasValue = #ripple.track(() => items.has(3));
|
|
104
104
|
|
|
105
105
|
<button onClick={() => items.delete(3)}>{'delete'}</button>
|
|
106
106
|
<pre>{items.size}</pre>
|
|
@@ -120,10 +120,10 @@ describe('TrackedSet', () => {
|
|
|
120
120
|
expect(container.querySelectorAll('pre')[1].textContent).toBe('false');
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
it('handles all operations with #
|
|
123
|
+
it('handles all operations with #ripple.set() shorthand syntax', () => {
|
|
124
124
|
component SetTest() {
|
|
125
|
-
let items =
|
|
126
|
-
let values = track(() => Array.from(items.values()));
|
|
125
|
+
let items = #ripple.set([10, 20, 30]);
|
|
126
|
+
let values = #ripple.track(() => Array.from(items.values()));
|
|
127
127
|
|
|
128
128
|
<button onClick={() => items.add(40)}>{'add'}</button>
|
|
129
129
|
<button onClick={() => items.delete(20)}>{'delete'}</button>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Component,
|
|
2
|
-
import { track } from 'ripple';
|
|
1
|
+
import type { Component, PropsWithChildren, PropsWithExtras } from 'ripple';
|
|
3
2
|
|
|
4
3
|
describe('SVG namespace handling', () => {
|
|
5
4
|
it('should render static SVG elements with correct namespace', () => {
|
|
@@ -290,7 +289,7 @@ describe('SVG namespace handling', () => {
|
|
|
290
289
|
}
|
|
291
290
|
|
|
292
291
|
component App() {
|
|
293
|
-
let dynTag = track('polygon');
|
|
292
|
+
let dynTag = #ripple.track('polygon');
|
|
294
293
|
<SVG>
|
|
295
294
|
<@dynTag points="0,0 30,0 15,10" />
|
|
296
295
|
</SVG>
|
|
@@ -317,7 +316,7 @@ describe('SVG namespace handling', () => {
|
|
|
317
316
|
}
|
|
318
317
|
|
|
319
318
|
component App() {
|
|
320
|
-
let Component = track(() => Polygon);
|
|
319
|
+
let Component = #ripple.track(() => Polygon);
|
|
321
320
|
<SVG>
|
|
322
321
|
<@Component points="0,0 30,0 15,10" />
|
|
323
322
|
</SVG>
|
|
@@ -334,19 +333,19 @@ describe('SVG namespace handling', () => {
|
|
|
334
333
|
|
|
335
334
|
it('should render SVG as a dynamic top element with any dynamic children elements', () => {
|
|
336
335
|
component SVG({ children }: PropsWithChildren<{}>) {
|
|
337
|
-
const tag = track('svg');
|
|
336
|
+
const tag = #ripple.track('svg');
|
|
338
337
|
<@tag width={100} height={50} fill="red" viewBox="0 0 30 10" preserveAspectRatio="none">
|
|
339
338
|
<children />
|
|
340
339
|
</@tag>
|
|
341
340
|
}
|
|
342
341
|
|
|
343
342
|
component Polygon({ points }: PropsWithExtras<{ points: string }>) {
|
|
344
|
-
let dynTag = track('polygon');
|
|
343
|
+
let dynTag = #ripple.track('polygon');
|
|
345
344
|
<@dynTag {points} />
|
|
346
345
|
}
|
|
347
346
|
|
|
348
347
|
component App() {
|
|
349
|
-
let Component = track(() => Polygon);
|
|
348
|
+
let Component = #ripple.track(() => Polygon);
|
|
350
349
|
<SVG>
|
|
351
350
|
<@Component points="0,0 30,0 15,10" />
|
|
352
351
|
</SVG>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { flushSync
|
|
1
|
+
import { flushSync } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('switch statements', () => {
|
|
4
4
|
it('renders simple switch with literal cases', () => {
|
|
5
5
|
component App() {
|
|
6
|
-
let value = track('b');
|
|
6
|
+
let value = #ripple.track('b');
|
|
7
7
|
|
|
8
8
|
<button onClick={() => (@value = 'c')}>{'Change to C'}</button>
|
|
9
9
|
<button onClick={() => (@value = 'a')}>{'Change to A'}</button>
|
|
@@ -38,7 +38,7 @@ describe('switch statements', () => {
|
|
|
38
38
|
|
|
39
39
|
it('renders switch with reactive discriminant', () => {
|
|
40
40
|
component App() {
|
|
41
|
-
let count = track(1);
|
|
41
|
+
let count = #ripple.track(1);
|
|
42
42
|
|
|
43
43
|
<button onClick={() => @count++}>{'Increment'}</button>
|
|
44
44
|
|
|
@@ -70,7 +70,7 @@ describe('switch statements', () => {
|
|
|
70
70
|
|
|
71
71
|
it('renders switch with default clause only', () => {
|
|
72
72
|
component App() {
|
|
73
|
-
let value = track('x');
|
|
73
|
+
let value = #ripple.track('x');
|
|
74
74
|
|
|
75
75
|
<button onClick={() => (@value = 'y')}>{'Change Value'}</button>
|
|
76
76
|
|
|
@@ -91,7 +91,7 @@ describe('switch statements', () => {
|
|
|
91
91
|
|
|
92
92
|
it('renders switch using empty case fall-through', () => {
|
|
93
93
|
component App() {
|
|
94
|
-
let value = track('a');
|
|
94
|
+
let value = #ripple.track('a');
|
|
95
95
|
|
|
96
96
|
<button onClick={() => (@value = 'b')}>{'Change to B'}</button>
|
|
97
97
|
<button onClick={() => (@value = 'c')}>{'Change to C'}</button>
|
|
@@ -133,8 +133,8 @@ describe('switch statements', () => {
|
|
|
133
133
|
|
|
134
134
|
it('renders switch with template content and reacts to tracked changes', () => {
|
|
135
135
|
component App() {
|
|
136
|
-
let status = track('active');
|
|
137
|
-
let message = track('');
|
|
136
|
+
let status = #ripple.track('active');
|
|
137
|
+
let message = #ripple.track('');
|
|
138
138
|
|
|
139
139
|
<button onClick={() => (@status = 'pending')}>{'Pending'}</button>
|
|
140
140
|
<button onClick={() => (@status = 'completed')}>{'Completed'}</button>
|
|
@@ -185,7 +185,7 @@ describe('switch statements', () => {
|
|
|
185
185
|
'renders switch with multiple non-empty fall-through cases and reacts to tracked changes without recreating DOM unnecessarily',
|
|
186
186
|
() => {
|
|
187
187
|
component App() {
|
|
188
|
-
let status = track(0);
|
|
188
|
+
let status = #ripple.track(0);
|
|
189
189
|
<div>
|
|
190
190
|
switch (@status) {
|
|
191
191
|
case -1:
|
|
@@ -253,7 +253,7 @@ describe('switch statements', () => {
|
|
|
253
253
|
'renders a fall-through default in the middle of switch cases and reacts to changes without recreating DOM unnecessarily',
|
|
254
254
|
() => {
|
|
255
255
|
component App() {
|
|
256
|
-
let value = track('x');
|
|
256
|
+
let value = #ripple.track('x');
|
|
257
257
|
|
|
258
258
|
<button onClick={() => (@value = 'a')}>{'Set A'}</button>
|
|
259
259
|
<button onClick={() => (@value = 'b')}>{'Set B'}</button>
|
|
@@ -359,7 +359,7 @@ describe('switch statements', () => {
|
|
|
359
359
|
|
|
360
360
|
it('renders switch with block-scoped cases and break inside blocks', () => {
|
|
361
361
|
component App() {
|
|
362
|
-
let level = track(1);
|
|
362
|
+
let level = #ripple.track(1);
|
|
363
363
|
|
|
364
364
|
<button
|
|
365
365
|
onClick={() => {
|