ripple 0.3.68 → 0.3.70
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 +57 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +2 -2
- package/src/runtime/element.js +1 -1
- package/src/runtime/index-client.js +11 -11
- package/src/runtime/index-server.js +7 -4
- package/src/runtime/internal/client/bindings.js +1 -1
- package/src/runtime/internal/client/blocks.js +13 -4
- package/src/runtime/internal/client/component.js +55 -0
- package/src/runtime/internal/client/composite.js +4 -2
- package/src/runtime/internal/client/expression.js +65 -7
- package/src/runtime/internal/client/hmr.js +54 -43
- package/src/runtime/internal/client/index.js +5 -1
- package/src/runtime/internal/client/portal.js +70 -69
- package/src/runtime/internal/client/render.js +3 -0
- package/src/runtime/internal/server/index.js +92 -8
- package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
- package/tests/client/array/array.copy-within.test.tsrx +33 -31
- package/tests/client/array/array.derived.test.tsrx +186 -169
- package/tests/client/array/array.iteration.test.tsrx +40 -37
- package/tests/client/array/array.mutations.test.tsrx +113 -101
- package/tests/client/array/array.static.test.tsrx +119 -101
- package/tests/client/array/array.to-methods.test.tsrx +24 -21
- package/tests/client/async-suspend.test.tsrx +247 -246
- package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
- package/tests/client/basic/basic.attributes.test.tsrx +428 -423
- package/tests/client/basic/basic.collections.test.tsrx +109 -102
- package/tests/client/basic/basic.components.test.tsrx +323 -205
- package/tests/client/basic/basic.errors.test.tsrx +91 -91
- package/tests/client/basic/basic.events.test.tsrx +114 -115
- package/tests/client/basic/basic.get-set.test.tsrx +97 -87
- package/tests/client/basic/basic.hmr.test.tsrx +19 -16
- package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
- package/tests/client/basic/basic.rendering.test.tsrx +272 -182
- package/tests/client/basic/basic.styling.test.tsrx +23 -22
- package/tests/client/basic/basic.utilities.test.tsrx +10 -8
- package/tests/client/boundaries.test.tsrx +26 -26
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
- package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
- package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
- package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
- package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
- package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
- package/tests/client/composite/composite.generics.test.tsrx +168 -192
- package/tests/client/composite/composite.props.test.tsrx +97 -81
- package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
- package/tests/client/composite/composite.render.test.tsrx +122 -105
- package/tests/client/computed-properties.test.tsrx +28 -28
- package/tests/client/context.test.tsrx +21 -21
- package/tests/client/css/global-additional-cases.test.tsrx +58 -58
- package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
- package/tests/client/css/global-at-rules.test.tsrx +10 -10
- package/tests/client/css/global-basic.test.tsrx +14 -14
- package/tests/client/css/global-classes-ids.test.tsrx +14 -14
- package/tests/client/css/global-combinators.test.tsrx +10 -10
- package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
- package/tests/client/css/global-edge-cases.test.tsrx +18 -18
- package/tests/client/css/global-keyframes.test.tsrx +12 -12
- package/tests/client/css/global-nested.test.tsrx +10 -10
- package/tests/client/css/global-pseudo.test.tsrx +12 -12
- package/tests/client/css/global-scoping.test.tsrx +20 -20
- package/tests/client/css/style-identifier.test.tsrx +126 -259
- package/tests/client/date.test.tsrx +146 -133
- package/tests/client/dynamic-elements.test.tsrx +398 -365
- package/tests/client/events.test.tsrx +292 -290
- package/tests/client/for.test.tsrx +156 -153
- package/tests/client/head.test.tsrx +105 -96
- package/tests/client/html.test.tsrx +122 -26
- package/tests/client/input-value.test.tsrx +1361 -1314
- package/tests/client/lazy-array.test.tsrx +16 -13
- package/tests/client/lazy-destructuring.test.tsrx +257 -213
- package/tests/client/map.test.tsrx +65 -60
- package/tests/client/media-query.test.tsrx +22 -20
- package/tests/client/object.test.tsrx +87 -81
- package/tests/client/portal.test.tsrx +57 -51
- package/tests/client/ref.test.tsrx +233 -202
- package/tests/client/return.test.tsrx +71 -2560
- package/tests/client/set.test.tsrx +54 -45
- package/tests/client/svg.test.tsrx +216 -186
- package/tests/client/switch.test.tsrx +194 -193
- package/tests/client/track-async-hydration.test.tsrx +18 -14
- package/tests/client/tracked-index-access.test.tsrx +28 -18
- package/tests/client/try.test.tsrx +675 -548
- package/tests/client/tsx.test.tsrx +373 -311
- package/tests/client/typescript-generics.test.tsrx +145 -145
- package/tests/client/url/url.derived.test.tsrx +33 -28
- package/tests/client/url/url.parsing.test.tsrx +61 -51
- package/tests/client/url/url.partial-removal.test.tsrx +56 -48
- package/tests/client/url/url.reactivity.test.tsrx +142 -125
- package/tests/client/url/url.serialization.test.tsrx +13 -11
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
- package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
- package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
- package/tests/hydration/basic.test.js +3 -3
- package/tests/hydration/compiled/client/basic.js +586 -651
- package/tests/hydration/compiled/client/composite.js +79 -104
- package/tests/hydration/compiled/client/events.js +140 -148
- package/tests/hydration/compiled/client/for.js +1005 -1018
- package/tests/hydration/compiled/client/head.js +124 -134
- package/tests/hydration/compiled/client/hmr.js +41 -48
- package/tests/hydration/compiled/client/html-in-template.js +38 -41
- package/tests/hydration/compiled/client/html.js +970 -1314
- package/tests/hydration/compiled/client/if-children.js +234 -249
- package/tests/hydration/compiled/client/if.js +182 -189
- package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
- package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
- package/tests/hydration/compiled/client/portal.js +65 -85
- package/tests/hydration/compiled/client/reactivity.js +84 -90
- package/tests/hydration/compiled/client/return.js +38 -1939
- package/tests/hydration/compiled/client/switch.js +218 -224
- package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
- package/tests/hydration/compiled/client/try.js +123 -132
- package/tests/hydration/compiled/server/basic.js +773 -831
- package/tests/hydration/compiled/server/composite.js +166 -191
- package/tests/hydration/compiled/server/events.js +170 -184
- package/tests/hydration/compiled/server/for.js +851 -909
- package/tests/hydration/compiled/server/head.js +206 -216
- package/tests/hydration/compiled/server/hmr.js +64 -72
- package/tests/hydration/compiled/server/html-in-template.js +42 -76
- package/tests/hydration/compiled/server/html.js +1362 -1667
- package/tests/hydration/compiled/server/if-children.js +419 -445
- package/tests/hydration/compiled/server/if.js +194 -208
- package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
- package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
- package/tests/hydration/compiled/server/portal.js +152 -160
- package/tests/hydration/compiled/server/reactivity.js +94 -106
- package/tests/hydration/compiled/server/return.js +28 -2172
- package/tests/hydration/compiled/server/switch.js +274 -286
- package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
- package/tests/hydration/compiled/server/try.js +167 -185
- package/tests/hydration/components/basic.tsrx +320 -272
- package/tests/hydration/components/composite.tsrx +44 -32
- package/tests/hydration/components/events.tsrx +101 -91
- package/tests/hydration/components/for.tsrx +510 -452
- package/tests/hydration/components/head.tsrx +87 -80
- package/tests/hydration/components/hmr.tsrx +22 -17
- package/tests/hydration/components/html-in-template.tsrx +22 -17
- package/tests/hydration/components/html.tsrx +525 -443
- package/tests/hydration/components/if-children.tsrx +158 -148
- package/tests/hydration/components/if.tsrx +109 -95
- package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
- package/tests/hydration/components/nested-control-flow.tsrx +215 -203
- package/tests/hydration/components/portal.tsrx +41 -34
- package/tests/hydration/components/reactivity.tsrx +37 -27
- package/tests/hydration/components/return.tsrx +12 -556
- package/tests/hydration/components/switch.tsrx +120 -114
- package/tests/hydration/components/track-async-serialization.tsrx +107 -91
- package/tests/hydration/components/try.tsrx +55 -40
- package/tests/hydration/html.test.js +4 -4
- package/tests/hydration/return.test.js +13 -532
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +264 -195
- package/tests/server/basic.components.test.tsrx +296 -169
- package/tests/server/basic.test.tsrx +300 -198
- package/tests/server/compiler.test.tsrx +62 -60
- package/tests/server/composite.props.test.tsrx +77 -63
- package/tests/server/composite.test.tsrx +168 -192
- package/tests/server/context.test.tsrx +18 -12
- package/tests/server/dynamic-elements.test.tsrx +197 -180
- package/tests/server/for.test.tsrx +85 -78
- package/tests/server/head.test.tsrx +50 -43
- package/tests/server/html-nesting-validation.test.tsrx +8 -8
- package/tests/server/if.test.tsrx +57 -51
- package/tests/server/lazy-destructuring.test.tsrx +366 -294
- package/tests/server/return.test.tsrx +76 -1355
- package/tests/server/streaming-ssr.test.tsrx +4 -75
- package/tests/server/style-identifier.test.tsrx +169 -131
- package/tests/server/switch.test.tsrx +91 -85
- package/tests/server/track-async-serialization.test.tsrx +105 -85
- package/tests/server/try.test.tsrx +374 -280
- package/tests/utils/compiler-compat-config.test.js +2 -2
- package/tests/utils/runtime-imports.test.js +10 -0
- package/types/index.d.ts +8 -0
- package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
|
@@ -3,20 +3,21 @@ import { effect, flushSync, on, track } from 'ripple';
|
|
|
3
3
|
|
|
4
4
|
describe('on() event handler', () => {
|
|
5
5
|
it('should attach multiple handlers via onClick attribute (delegated)', () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
function Basic() {
|
|
7
|
+
return <>
|
|
8
|
+
let &[count1] = track(0);
|
|
9
|
+
let &[count2] = track(0);
|
|
10
|
+
<button
|
|
11
|
+
onClick={() => {
|
|
12
|
+
count1++;
|
|
13
|
+
count2++;
|
|
14
|
+
}}
|
|
15
|
+
>
|
|
16
|
+
{'Click me'}
|
|
17
|
+
</button>
|
|
18
|
+
<div class="count1">{count1}</div>
|
|
19
|
+
<div class="count2">{count2}</div>
|
|
20
|
+
</>;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
render(Basic);
|
|
@@ -35,17 +36,18 @@ describe('on() event handler', () => {
|
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
it('should attach and remove a single event handler', () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
function Basic() {
|
|
40
|
+
return <>
|
|
41
|
+
let &[count] = track(0);
|
|
42
|
+
const setupListener = (node: HTMLButtonElement) => {
|
|
43
|
+
const remove = on(node, 'click', () => {
|
|
44
|
+
count++;
|
|
45
|
+
});
|
|
46
|
+
return remove;
|
|
47
|
+
};
|
|
48
|
+
<button ref={setupListener}>{'Click me'}</button>
|
|
49
|
+
<div class="count">{count}</div>
|
|
50
|
+
</>;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
render(Basic);
|
|
@@ -66,25 +68,26 @@ describe('on() event handler', () => {
|
|
|
66
68
|
});
|
|
67
69
|
|
|
68
70
|
it('should handle multiple different event types on same element', () => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
function Basic() {
|
|
72
|
+
return <>
|
|
73
|
+
let &[clickCount] = track(0);
|
|
74
|
+
let &[mousedownCount] = track(0);
|
|
75
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
76
|
+
const remove1 = on(node, 'click', () => {
|
|
77
|
+
clickCount++;
|
|
78
|
+
});
|
|
79
|
+
const remove2 = on(node, 'mousedown', () => {
|
|
80
|
+
mousedownCount++;
|
|
81
|
+
});
|
|
82
|
+
return () => {
|
|
83
|
+
remove1();
|
|
84
|
+
remove2();
|
|
85
|
+
};
|
|
83
86
|
};
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
<button ref={setupListeners}>{'Test'}</button>
|
|
88
|
+
<div class="click-count">{clickCount}</div>
|
|
89
|
+
<div class="mousedown-count">{mousedownCount}</div>
|
|
90
|
+
</>;
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
render(Basic);
|
|
@@ -115,27 +118,28 @@ describe('on() event handler', () => {
|
|
|
115
118
|
});
|
|
116
119
|
|
|
117
120
|
it('should handle multiple handlers for same event type on same element', () => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
121
|
+
function Basic() {
|
|
122
|
+
return <>
|
|
123
|
+
let &[callOrder] = track<number[]>([]);
|
|
124
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
125
|
+
const remove1 = on(node, 'click', () => {
|
|
126
|
+
callOrder = [...callOrder, 1];
|
|
127
|
+
});
|
|
128
|
+
const remove2 = on(node, 'click', () => {
|
|
129
|
+
callOrder = [...callOrder, 2];
|
|
130
|
+
});
|
|
131
|
+
const remove3 = on(node, 'click', () => {
|
|
132
|
+
callOrder = [...callOrder, 3];
|
|
133
|
+
});
|
|
134
|
+
return () => {
|
|
135
|
+
remove1();
|
|
136
|
+
remove2();
|
|
137
|
+
remove3();
|
|
138
|
+
};
|
|
135
139
|
};
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
<button ref={setupListeners}>{'Click me'}</button>
|
|
141
|
+
<div class="order">{callOrder.join(',')}</div>
|
|
142
|
+
</>;
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
render(Basic);
|
|
@@ -157,43 +161,44 @@ describe('on() event handler', () => {
|
|
|
157
161
|
});
|
|
158
162
|
|
|
159
163
|
it('should remove specific handler without affecting others', () => {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
removeHandler2?.();
|
|
179
|
-
remove3();
|
|
180
|
-
};
|
|
181
|
-
};
|
|
182
|
-
<div>
|
|
183
|
-
<button class="test-btn" {ref setupListeners}>{'Click me'}</button>
|
|
184
|
-
<button
|
|
185
|
-
class="remove-btn"
|
|
186
|
-
onClick={() => {
|
|
164
|
+
function Basic() {
|
|
165
|
+
return <>
|
|
166
|
+
let &[handler1Called] = track(0);
|
|
167
|
+
let &[handler2Called] = track(0);
|
|
168
|
+
let &[handler3Called] = track(0);
|
|
169
|
+
let removeHandler2: OnEventListenerRemover | undefined;
|
|
170
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
171
|
+
const remove1 = on(node, 'click', () => {
|
|
172
|
+
handler1Called++;
|
|
173
|
+
});
|
|
174
|
+
removeHandler2 = on(node, 'click', () => {
|
|
175
|
+
handler2Called++;
|
|
176
|
+
});
|
|
177
|
+
const remove3 = on(node, 'click', () => {
|
|
178
|
+
handler3Called++;
|
|
179
|
+
});
|
|
180
|
+
return () => {
|
|
181
|
+
remove1();
|
|
187
182
|
removeHandler2?.();
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
183
|
+
remove3();
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
<div>
|
|
187
|
+
<button class="test-btn" ref={setupListeners}>{'Click me'}</button>
|
|
188
|
+
<button
|
|
189
|
+
class="remove-btn"
|
|
190
|
+
onClick={() => {
|
|
191
|
+
removeHandler2?.();
|
|
192
|
+
removeHandler2 = undefined;
|
|
193
|
+
}}
|
|
194
|
+
>
|
|
195
|
+
{'Remove handler 2'}
|
|
196
|
+
</button>
|
|
197
|
+
<div class="h1">{handler1Called}</div>
|
|
198
|
+
<div class="h2">{handler2Called}</div>
|
|
199
|
+
<div class="h3">{handler3Called}</div>
|
|
200
|
+
</div>
|
|
201
|
+
</>;
|
|
197
202
|
}
|
|
198
203
|
|
|
199
204
|
render(Basic);
|
|
@@ -234,30 +239,31 @@ describe('on() event handler', () => {
|
|
|
234
239
|
it(
|
|
235
240
|
'should handle change event with multiple handlers (like bindChecked and bindIndeterminate)',
|
|
236
241
|
() => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
242
|
+
function Basic() {
|
|
243
|
+
return <>
|
|
244
|
+
let &[checked] = track(false);
|
|
245
|
+
let &[indeterminate] = track(true);
|
|
246
|
+
const setupListeners = (node: HTMLInputElement) => {
|
|
247
|
+
node.indeterminate = indeterminate;
|
|
248
|
+
node.checked = checked;
|
|
249
|
+
|
|
250
|
+
const remove1 = on(node, 'change', () => {
|
|
251
|
+
checked = node.checked;
|
|
252
|
+
});
|
|
253
|
+
const remove2 = on(node, 'change', () => {
|
|
254
|
+
indeterminate = node.indeterminate;
|
|
255
|
+
});
|
|
256
|
+
return () => {
|
|
257
|
+
remove1();
|
|
258
|
+
remove2();
|
|
259
|
+
};
|
|
254
260
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
<div>
|
|
262
|
+
<input type="checkbox" ref={setupListeners} />
|
|
263
|
+
<div class="checked">{checked ? 'true' : 'false'}</div>
|
|
264
|
+
<div class="indeterminate">{indeterminate ? 'true' : 'false'}</div>
|
|
265
|
+
</div>
|
|
266
|
+
</>;
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
render(Basic);
|
|
@@ -282,18 +288,18 @@ describe('on() event handler', () => {
|
|
|
282
288
|
);
|
|
283
289
|
|
|
284
290
|
it('should support non-delegated events', () => {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
function Basic() {
|
|
292
|
+
return <>
|
|
293
|
+
let &[focusCount] = track(0);
|
|
294
|
+
const setupListener = (node: HTMLInputElement) => {
|
|
295
|
+
const remove = on(node, 'focus', () => {
|
|
296
|
+
focusCount++;
|
|
297
|
+
});
|
|
298
|
+
return remove;
|
|
299
|
+
};
|
|
300
|
+
<input ref={setupListener} />
|
|
301
|
+
<div class="focus-count">{focusCount}</div>
|
|
302
|
+
</>;
|
|
297
303
|
}
|
|
298
304
|
|
|
299
305
|
render(Basic);
|
|
@@ -314,43 +320,44 @@ describe('on() event handler', () => {
|
|
|
314
320
|
});
|
|
315
321
|
|
|
316
322
|
it('should handle removal of all handlers for same event type', () => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
remove1?.();
|
|
335
|
-
remove2?.();
|
|
336
|
-
remove3?.();
|
|
337
|
-
};
|
|
338
|
-
};
|
|
339
|
-
<div>
|
|
340
|
-
<button class="test-btn" {ref setupListeners}>{'Click me'}</button>
|
|
341
|
-
<button
|
|
342
|
-
class="remove-all"
|
|
343
|
-
onClick={() => {
|
|
323
|
+
function Basic() {
|
|
324
|
+
return <>
|
|
325
|
+
let &[count] = track(0);
|
|
326
|
+
let remove1: OnEventListenerRemover | undefined;
|
|
327
|
+
let remove2: OnEventListenerRemover | undefined;
|
|
328
|
+
let remove3: OnEventListenerRemover | undefined;
|
|
329
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
330
|
+
remove1 = on(node, 'click', () => {
|
|
331
|
+
count++;
|
|
332
|
+
});
|
|
333
|
+
remove2 = on(node, 'click', () => {
|
|
334
|
+
count += 10;
|
|
335
|
+
});
|
|
336
|
+
remove3 = on(node, 'click', () => {
|
|
337
|
+
count += 100;
|
|
338
|
+
});
|
|
339
|
+
return () => {
|
|
344
340
|
remove1?.();
|
|
345
341
|
remove2?.();
|
|
346
342
|
remove3?.();
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
>
|
|
350
|
-
{'
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
<div>
|
|
346
|
+
<button class="test-btn" ref={setupListeners}>{'Click me'}</button>
|
|
347
|
+
<button
|
|
348
|
+
class="remove-all"
|
|
349
|
+
onClick={() => {
|
|
350
|
+
remove1?.();
|
|
351
|
+
remove2?.();
|
|
352
|
+
remove3?.();
|
|
353
|
+
remove1 = remove2 = remove3 = undefined;
|
|
354
|
+
}}
|
|
355
|
+
>
|
|
356
|
+
{'Remove all'}
|
|
357
|
+
</button>
|
|
358
|
+
<div class="count">{count}</div>
|
|
359
|
+
</div>
|
|
360
|
+
</>;
|
|
354
361
|
}
|
|
355
362
|
|
|
356
363
|
render(Basic);
|
|
@@ -378,28 +385,27 @@ describe('on() event handler', () => {
|
|
|
378
385
|
});
|
|
379
386
|
|
|
380
387
|
it('should not add duplicate handlers when same handler is attached multiple times', () => {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
const setupListeners = (node: HTMLButtonElement) => {
|
|
389
|
-
// Attach the same handler multiple times
|
|
390
|
-
const remove1 = on(node, 'click', sharedHandler);
|
|
391
|
-
const remove2 = on(node, 'click', sharedHandler);
|
|
392
|
-
const remove3 = on(node, 'click', sharedHandler);
|
|
393
|
-
|
|
394
|
-
return () => {
|
|
395
|
-
remove1?.();
|
|
396
|
-
remove2?.();
|
|
397
|
-
remove3?.();
|
|
388
|
+
function Basic() {
|
|
389
|
+
return <>
|
|
390
|
+
let &[count] = track(0);
|
|
391
|
+
const sharedHandler = () => {
|
|
392
|
+
count++;
|
|
398
393
|
};
|
|
399
|
-
|
|
394
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
395
|
+
// Attach the same handler multiple times
|
|
396
|
+
const remove1 = on(node, 'click', sharedHandler);
|
|
397
|
+
const remove2 = on(node, 'click', sharedHandler);
|
|
398
|
+
const remove3 = on(node, 'click', sharedHandler);
|
|
400
399
|
|
|
401
|
-
|
|
402
|
-
|
|
400
|
+
return () => {
|
|
401
|
+
remove1?.();
|
|
402
|
+
remove2?.();
|
|
403
|
+
remove3?.();
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
<button ref={setupListeners}>{'Click me'}</button>
|
|
407
|
+
<div class="count">{count}</div>
|
|
408
|
+
</>;
|
|
403
409
|
}
|
|
404
410
|
|
|
405
411
|
render(Basic);
|
|
@@ -421,28 +427,27 @@ describe('on() event handler', () => {
|
|
|
421
427
|
});
|
|
422
428
|
|
|
423
429
|
it('should allow duplicate handlers when delegated is false (no deduplication)', () => {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
const setupListeners = (node: HTMLButtonElement) => {
|
|
432
|
-
// Attach the same handler multiple times with delegated: false
|
|
433
|
-
const remove1 = on(node, 'click', sharedHandler, { delegated: false });
|
|
434
|
-
const remove2 = on(node, 'click', sharedHandler, { delegated: false });
|
|
435
|
-
const remove3 = on(node, 'click', sharedHandler, { delegated: false });
|
|
436
|
-
|
|
437
|
-
return () => {
|
|
438
|
-
remove1?.();
|
|
439
|
-
remove2?.();
|
|
440
|
-
remove3?.();
|
|
430
|
+
function Basic() {
|
|
431
|
+
return <>
|
|
432
|
+
let &[count] = track(0);
|
|
433
|
+
const sharedHandler = () => {
|
|
434
|
+
count++;
|
|
441
435
|
};
|
|
442
|
-
|
|
436
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
437
|
+
// Attach the same handler multiple times with delegated: false
|
|
438
|
+
const remove1 = on(node, 'click', sharedHandler, { delegated: false });
|
|
439
|
+
const remove2 = on(node, 'click', sharedHandler, { delegated: false });
|
|
440
|
+
const remove3 = on(node, 'click', sharedHandler, { delegated: false });
|
|
443
441
|
|
|
444
|
-
|
|
445
|
-
|
|
442
|
+
return () => {
|
|
443
|
+
remove1?.();
|
|
444
|
+
remove2?.();
|
|
445
|
+
remove3?.();
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
<button ref={setupListeners}>{'Click me'}</button>
|
|
449
|
+
<div class="count">{count}</div>
|
|
450
|
+
</>;
|
|
446
451
|
}
|
|
447
452
|
|
|
448
453
|
render(Basic);
|
|
@@ -465,29 +470,26 @@ describe('on() event handler', () => {
|
|
|
465
470
|
});
|
|
466
471
|
|
|
467
472
|
it('should fire capture event on parent before bubbling event on child', () => {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
<button {ref setupChild} class="child">{'Click me'}</button>
|
|
489
|
-
</div>
|
|
490
|
-
<div class="order">{callOrder.join(',')}</div>
|
|
473
|
+
function Basic() {
|
|
474
|
+
return <>
|
|
475
|
+
let &[callOrder] = track<string[]>([]);
|
|
476
|
+
const parentCaptureHandler = () => {
|
|
477
|
+
callOrder = [...callOrder, 'parent-capture'];
|
|
478
|
+
};
|
|
479
|
+
const childBubbleHandler = () => {
|
|
480
|
+
callOrder = [...callOrder, 'child-bubble'];
|
|
481
|
+
};
|
|
482
|
+
const setupParent = (node: HTMLDivElement) => {
|
|
483
|
+
return on(node, 'clickCapture', parentCaptureHandler);
|
|
484
|
+
};
|
|
485
|
+
const setupChild = (node: HTMLButtonElement) => {
|
|
486
|
+
return on(node, 'click', childBubbleHandler);
|
|
487
|
+
};
|
|
488
|
+
<div ref={setupParent} class="parent">
|
|
489
|
+
<button ref={setupChild} class="child">{'Click me'}</button>
|
|
490
|
+
</div>
|
|
491
|
+
<div class="order">{callOrder.join(',')}</div>
|
|
492
|
+
</>;
|
|
491
493
|
}
|
|
492
494
|
|
|
493
495
|
render(Basic);
|
|
@@ -510,28 +512,28 @@ describe('on() event handler', () => {
|
|
|
510
512
|
});
|
|
511
513
|
|
|
512
514
|
it('should fire handler only once when once option is true', () => {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
515
|
+
function Basic() {
|
|
516
|
+
return <>
|
|
517
|
+
let &[count] = track(0);
|
|
518
|
+
let &[permanentCount] = track(0);
|
|
519
|
+
const setupListeners = (node: HTMLButtonElement) => {
|
|
520
|
+
const onceHandler = on(node, 'click', () => {
|
|
521
|
+
count++;
|
|
522
|
+
}, { once: true });
|
|
523
|
+
|
|
524
|
+
const permanentHandler = on(node, 'click', () => {
|
|
525
|
+
permanentCount++;
|
|
526
|
+
});
|
|
525
527
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
528
|
+
return () => {
|
|
529
|
+
onceHandler?.();
|
|
530
|
+
permanentHandler?.();
|
|
531
|
+
};
|
|
529
532
|
};
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
<div class="permanent-count">{permanentCount}</div>
|
|
533
|
+
<button ref={setupListeners}>{'Click me'}</button>
|
|
534
|
+
<div class="once-count">{count}</div>
|
|
535
|
+
<div class="permanent-count">{permanentCount}</div>
|
|
536
|
+
</>;
|
|
535
537
|
}
|
|
536
538
|
|
|
537
539
|
render(Basic);
|
|
@@ -564,20 +566,20 @@ describe('on() event handler', () => {
|
|
|
564
566
|
});
|
|
565
567
|
|
|
566
568
|
it('should handle click events on window', () => {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
569
|
+
function Basic() {
|
|
570
|
+
return <>
|
|
571
|
+
let &[windowClickCount] = track(0);
|
|
572
|
+
effect(() => {
|
|
573
|
+
const removeWindowListener = on(window, 'click', () => {
|
|
574
|
+
windowClickCount++;
|
|
575
|
+
});
|
|
576
|
+
return removeWindowListener;
|
|
573
577
|
});
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
<div class="window-count">{windowClickCount}</div>
|
|
580
|
-
</div>
|
|
578
|
+
<div>
|
|
579
|
+
<button class="test-btn">{'Click me'}</button>
|
|
580
|
+
<div class="window-count">{windowClickCount}</div>
|
|
581
|
+
</div>
|
|
582
|
+
</>;
|
|
581
583
|
}
|
|
582
584
|
|
|
583
585
|
render(Basic);
|
|
@@ -600,20 +602,20 @@ describe('on() event handler', () => {
|
|
|
600
602
|
});
|
|
601
603
|
|
|
602
604
|
it('should handle click events on document', () => {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
605
|
+
function Basic() {
|
|
606
|
+
return <>
|
|
607
|
+
let &[documentClickCount] = track(0);
|
|
608
|
+
effect(() => {
|
|
609
|
+
const removeDocumentListener = on(document, 'click', () => {
|
|
610
|
+
documentClickCount++;
|
|
611
|
+
});
|
|
612
|
+
return removeDocumentListener;
|
|
609
613
|
});
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
<div class="document-count">{documentClickCount}</div>
|
|
616
|
-
</div>
|
|
614
|
+
<div>
|
|
615
|
+
<button class="test-btn">{'Click me'}</button>
|
|
616
|
+
<div class="document-count">{documentClickCount}</div>
|
|
617
|
+
</div>
|
|
618
|
+
</>;
|
|
617
619
|
}
|
|
618
620
|
|
|
619
621
|
render(Basic);
|
|
@@ -636,20 +638,20 @@ describe('on() event handler', () => {
|
|
|
636
638
|
});
|
|
637
639
|
|
|
638
640
|
it('should handle click events on body', () => {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
641
|
+
function Basic() {
|
|
642
|
+
return <>
|
|
643
|
+
let &[bodyClickCount] = track(0);
|
|
644
|
+
effect(() => {
|
|
645
|
+
const removeBodyListener = on(document.body, 'click', () => {
|
|
646
|
+
bodyClickCount++;
|
|
647
|
+
});
|
|
648
|
+
return removeBodyListener;
|
|
645
649
|
});
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
<div class="body-count">{bodyClickCount}</div>
|
|
652
|
-
</div>
|
|
650
|
+
<div>
|
|
651
|
+
<button class="test-btn">{'Click me'}</button>
|
|
652
|
+
<div class="body-count">{bodyClickCount}</div>
|
|
653
|
+
</div>
|
|
654
|
+
</>;
|
|
653
655
|
}
|
|
654
656
|
|
|
655
657
|
render(Basic);
|