ripple 0.2.168 → 0.2.169
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 +2 -2
- package/src/compiler/phases/2-analyze/index.js +4 -5
- package/src/compiler/phases/3-transform/client/index.js +20 -36
- package/src/compiler/utils.js +13 -6
- package/src/jsx-runtime.d.ts +5 -3
- package/src/runtime/internal/client/events.js +134 -25
- package/src/runtime/internal/client/index.js +1 -1
- package/src/runtime/internal/client/render.js +36 -26
- package/src/runtime/media-query.js +14 -8
- package/src/utils/events.js +120 -43
- package/tests/client/basic/basic.attributes.test.ripple +442 -0
- package/tests/client/basic/basic.events.test.ripple +2 -2
- package/tests/client/composite/composite.reactivity.test.ripple +6 -5
- package/tests/client/input-value.test.ripple +4 -4
- package/tests/client/media-query.test.ripple +1 -1
- package/tests/utils/events.test.js +57 -46
- package/types/index.d.ts +15 -5
|
@@ -18,7 +18,7 @@ describe('use value()', () => {
|
|
|
18
18
|
|
|
19
19
|
const input = container.querySelector('input') as HTMLInputElement;
|
|
20
20
|
input.value = 'Hello';
|
|
21
|
-
input.dispatchEvent(new Event('input'));
|
|
21
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
22
22
|
flushSync();
|
|
23
23
|
expect(input.value).toBe('Hello');
|
|
24
24
|
expect(logs).toEqual(['text changed', '', 'text changed', 'Hello']);
|
|
@@ -42,7 +42,7 @@ describe('use value()', () => {
|
|
|
42
42
|
const input = container.querySelector('input') as HTMLInputElement;
|
|
43
43
|
expect(input.value).toBe('foo');
|
|
44
44
|
input.value = 'Hello';
|
|
45
|
-
input.dispatchEvent(new Event('input'));
|
|
45
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
46
46
|
flushSync();
|
|
47
47
|
expect(input.value).toBe('Hello');
|
|
48
48
|
expect(logs).toEqual(['text changed', 'foo', 'text changed', 'Hello']);
|
|
@@ -65,7 +65,7 @@ describe('use value()', () => {
|
|
|
65
65
|
|
|
66
66
|
const input = container.querySelector('input') as HTMLInputElement;
|
|
67
67
|
input.checked = true;
|
|
68
|
-
input.dispatchEvent(new Event('change'));
|
|
68
|
+
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
69
69
|
flushSync();
|
|
70
70
|
|
|
71
71
|
expect(input.checked).toBe(true);
|
|
@@ -94,7 +94,7 @@ describe('use value()', () => {
|
|
|
94
94
|
|
|
95
95
|
const select = container.querySelector('select') as HTMLSelectElement;
|
|
96
96
|
select.value = '3';
|
|
97
|
-
select.dispatchEvent(new Event('change'));
|
|
97
|
+
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
98
98
|
flushSync();
|
|
99
99
|
|
|
100
100
|
expect(select.value).toBe('3');
|
|
@@ -1,37 +1,39 @@
|
|
|
1
|
+
/** @import { AddEventObject } from '#public'*/
|
|
2
|
+
|
|
1
3
|
import { describe, it, expect } from 'vitest';
|
|
2
4
|
import {
|
|
3
|
-
|
|
5
|
+
is_non_delegated,
|
|
4
6
|
is_event_attribute,
|
|
5
|
-
is_capture_event,
|
|
6
7
|
get_attribute_event_name,
|
|
7
|
-
is_passive_event
|
|
8
|
+
is_passive_event,
|
|
9
|
+
is_capture_event,
|
|
8
10
|
} from '../../src/utils/events.js';
|
|
9
11
|
|
|
10
12
|
describe('events utility', () => {
|
|
11
|
-
describe('
|
|
12
|
-
it('should
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
15
|
-
expect(
|
|
16
|
-
expect(
|
|
17
|
-
expect(
|
|
18
|
-
expect(
|
|
19
|
-
expect(
|
|
20
|
-
expect(
|
|
21
|
-
expect(
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should
|
|
25
|
-
expect(
|
|
26
|
-
expect(
|
|
27
|
-
expect(
|
|
28
|
-
expect(
|
|
29
|
-
expect(
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should
|
|
33
|
-
expect(
|
|
34
|
-
expect(
|
|
13
|
+
describe('is event delegated', () => {
|
|
14
|
+
it('should confirm delegated events', () => {
|
|
15
|
+
expect(is_non_delegated('click')).toBe(false);
|
|
16
|
+
expect(is_non_delegated('input')).toBe(false);
|
|
17
|
+
expect(is_non_delegated('change')).toBe(false);
|
|
18
|
+
expect(is_non_delegated('mousedown')).toBe(false);
|
|
19
|
+
expect(is_non_delegated('keydown')).toBe(false);
|
|
20
|
+
expect(is_non_delegated('pointerdown')).toBe(false);
|
|
21
|
+
expect(is_non_delegated('touchstart')).toBe(false);
|
|
22
|
+
expect(is_non_delegated('focusin')).toBe(false);
|
|
23
|
+
expect(is_non_delegated('focusout')).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should confirm non-delegated events', () => {
|
|
27
|
+
expect(is_non_delegated('focus')).toBe(true);
|
|
28
|
+
expect(is_non_delegated('blur')).toBe(true);
|
|
29
|
+
expect(is_non_delegated('scroll')).toBe(true);
|
|
30
|
+
expect(is_non_delegated('load')).toBe(true);
|
|
31
|
+
expect(is_non_delegated('resize')).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should confirm that events with any capital letters are delegated', () => {
|
|
35
|
+
expect(is_non_delegated('Click')).toBe(false);
|
|
36
|
+
expect(is_non_delegated('CLICK')).toBe(false);
|
|
35
37
|
});
|
|
36
38
|
});
|
|
37
39
|
|
|
@@ -74,6 +76,32 @@ describe('events utility', () => {
|
|
|
74
76
|
});
|
|
75
77
|
});
|
|
76
78
|
|
|
79
|
+
describe('get_attribute_event_name', () => {
|
|
80
|
+
it('should convert event attribute names to lowercase and strip "on" prefix', () => {
|
|
81
|
+
const fn = () => {};
|
|
82
|
+
expect(get_attribute_event_name('onClick', fn)).toBe('click');
|
|
83
|
+
expect(get_attribute_event_name('onInput', fn)).toBe('input');
|
|
84
|
+
expect(get_attribute_event_name('onMouseDown', fn)).toBe('mousedown');
|
|
85
|
+
expect(get_attribute_event_name('onKeyPress', fn)).toBe('keypress');
|
|
86
|
+
expect(get_attribute_event_name('onChange', fn)).toBe('change');
|
|
87
|
+
expect(get_attribute_event_name('onFocus', fn)).toBe('focus');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should keep event attribute names letter case and strip "on" prefix', () => {
|
|
91
|
+
/** @type AddEventObject */
|
|
92
|
+
const customHandler = { handleEvent: () => {} };
|
|
93
|
+
expect(get_attribute_event_name('onClick', { ...customHandler, customName: 'Click' })).toBe(
|
|
94
|
+
'Click',
|
|
95
|
+
);
|
|
96
|
+
expect(get_attribute_event_name('onInput', { ...customHandler, customName: 'Input' })).toBe(
|
|
97
|
+
'Input',
|
|
98
|
+
);
|
|
99
|
+
expect(
|
|
100
|
+
get_attribute_event_name('onMouseDown', { ...customHandler, customName: 'MouseDown' }),
|
|
101
|
+
).toBe('MouseDown');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
77
105
|
describe('is_capture_event', () => {
|
|
78
106
|
it('should return true for capture events', () => {
|
|
79
107
|
expect(is_capture_event('clickCapture')).toBe(true);
|
|
@@ -104,25 +132,6 @@ describe('events utility', () => {
|
|
|
104
132
|
expect(is_capture_event('keypressCapture')).toBe(true);
|
|
105
133
|
expect(is_capture_event('clickcapture')).toBe(false);
|
|
106
134
|
expect(is_capture_event('keypresscapture')).toBe(false);
|
|
107
|
-
})
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('get_attribute_event_name', () => {
|
|
111
|
-
it('should convert event attribute names to lowercase and strip "on" prefix', () => {
|
|
112
|
-
expect(get_attribute_event_name('onClick')).toBe('click');
|
|
113
|
-
expect(get_attribute_event_name('onInput')).toBe('input');
|
|
114
|
-
expect(get_attribute_event_name('onMouseDown')).toBe('mousedown');
|
|
115
|
-
expect(get_attribute_event_name('onKeyPress')).toBe('keypress');
|
|
116
|
-
expect(get_attribute_event_name('onChange')).toBe('change');
|
|
117
|
-
expect(get_attribute_event_name('onFocus')).toBe('focus');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should handle capture events and strip both "on" and "Capture"', () => {
|
|
121
|
-
expect(get_attribute_event_name('onClickCapture')).toBe('click');
|
|
122
|
-
expect(get_attribute_event_name('onMouseDownCapture')).toBe('mousedown');
|
|
123
|
-
expect(get_attribute_event_name('onMouseDownCapture')).toBe('mousedown');
|
|
124
|
-
expect(get_attribute_event_name('onGotPointerCapture')).toBe('gotpointercapture');
|
|
125
|
-
expect(get_attribute_event_name('onLostPointerCapture')).toBe('lostpointercapture');
|
|
126
135
|
});
|
|
127
136
|
});
|
|
128
137
|
|
|
@@ -130,6 +139,8 @@ describe('events utility', () => {
|
|
|
130
139
|
it('should return true for passive events', () => {
|
|
131
140
|
expect(is_passive_event('touchstart')).toBe(true);
|
|
132
141
|
expect(is_passive_event('touchmove')).toBe(true);
|
|
142
|
+
expect(is_passive_event('wheel')).toBe(true);
|
|
143
|
+
expect(is_passive_event('mousewheel')).toBe(true);
|
|
133
144
|
});
|
|
134
145
|
|
|
135
146
|
it('should return false for non-passive events', () => {
|
package/types/index.d.ts
CHANGED
|
@@ -137,39 +137,49 @@ export declare function trackSplit<V extends Props, const K extends readonly (ke
|
|
|
137
137
|
splitKeys: K,
|
|
138
138
|
): SplitResult<V, K>;
|
|
139
139
|
|
|
140
|
+
export interface AddEventOptions extends ExtendedEventOptions {
|
|
141
|
+
customName?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface AddEventObject extends AddEventOptions, EventListenerObject {}
|
|
145
|
+
|
|
146
|
+
export interface ExtendedEventOptions extends AddEventListenerOptions, EventListenerOptions {
|
|
147
|
+
delegated?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
140
150
|
export function on<Type extends keyof WindowEventMap>(
|
|
141
151
|
window: Window,
|
|
142
152
|
type: Type,
|
|
143
153
|
handler: (this: Window, event: WindowEventMap[Type]) => any,
|
|
144
|
-
options?:
|
|
154
|
+
options?: ExtendedEventOptions | undefined,
|
|
145
155
|
): () => void;
|
|
146
156
|
|
|
147
157
|
export function on<Type extends keyof DocumentEventMap>(
|
|
148
158
|
document: Document,
|
|
149
159
|
type: Type,
|
|
150
160
|
handler: (this: Document, event: DocumentEventMap[Type]) => any,
|
|
151
|
-
options?:
|
|
161
|
+
options?: ExtendedEventOptions | undefined,
|
|
152
162
|
): () => void;
|
|
153
163
|
|
|
154
164
|
export function on<Element extends HTMLElement, Type extends keyof HTMLElementEventMap>(
|
|
155
165
|
element: Element,
|
|
156
166
|
type: Type,
|
|
157
167
|
handler: (this: Element, event: HTMLElementEventMap[Type]) => any,
|
|
158
|
-
options?:
|
|
168
|
+
options?: ExtendedEventOptions | undefined,
|
|
159
169
|
): () => void;
|
|
160
170
|
|
|
161
171
|
export function on<Element extends MediaQueryList, Type extends keyof MediaQueryListEventMap>(
|
|
162
172
|
element: Element,
|
|
163
173
|
type: Type,
|
|
164
174
|
handler: (this: Element, event: MediaQueryListEventMap[Type]) => any,
|
|
165
|
-
options?:
|
|
175
|
+
options?: ExtendedEventOptions | undefined,
|
|
166
176
|
): () => void;
|
|
167
177
|
|
|
168
178
|
export function on(
|
|
169
179
|
element: EventTarget,
|
|
170
180
|
type: string,
|
|
171
181
|
handler: EventListener,
|
|
172
|
-
options?:
|
|
182
|
+
options?: ExtendedEventOptions | undefined,
|
|
173
183
|
): () => void;
|
|
174
184
|
|
|
175
185
|
export type TrackedObjectShallow<T> = {
|