ripple 0.2.113 → 0.2.114
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 +1 -6
- package/src/compiler/phases/1-parse/index.js +1 -0
- package/src/compiler/phases/3-transform/client/index.js +18 -13
- package/src/compiler/phases/3-transform/segments.js +1 -1
- package/src/runtime/index-client.js +185 -5
- package/src/runtime/internal/client/runtime.js +4 -4
- package/src/utils/builders.js +274 -262
- package/tests/client/input-value.test.ripple +66 -6
- package/types/index.d.ts +12 -0
- package/src/bindings/index.d.ts +0 -13
- package/src/bindings/index.js +0 -79
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
2
|
import { mount, flushSync, track, effect } from 'ripple';
|
|
3
|
-
import {
|
|
3
|
+
import { bindValue, bindChecked } from 'ripple';
|
|
4
4
|
|
|
5
5
|
describe('use value()', () => {
|
|
6
6
|
let container;
|
|
@@ -22,42 +22,102 @@ describe('use value()', () => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('should update value on input', () => {
|
|
25
|
+
const logs = [];
|
|
26
|
+
|
|
25
27
|
component App() {
|
|
26
28
|
const text = track('');
|
|
27
29
|
|
|
28
30
|
effect(() => {
|
|
29
|
-
|
|
31
|
+
logs.push('text changed', @text);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
<input type="text" {ref bindValue(text)} />
|
|
35
|
+
}
|
|
36
|
+
render(App);
|
|
37
|
+
flushSync();
|
|
38
|
+
|
|
39
|
+
const input = container.querySelector('input');
|
|
40
|
+
input.value = 'Hello';
|
|
41
|
+
input.dispatchEvent(new Event('input'));
|
|
42
|
+
flushSync();
|
|
43
|
+
expect(input.value).toBe('Hello');
|
|
44
|
+
expect(logs).toEqual(['text changed', '', 'text changed', 'Hello']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should update value on input with a predefined value', () => {
|
|
48
|
+
const logs = [];
|
|
49
|
+
|
|
50
|
+
component App() {
|
|
51
|
+
const text = track('foo');
|
|
52
|
+
|
|
53
|
+
effect(() => {
|
|
54
|
+
logs.push('text changed', @text);
|
|
30
55
|
});
|
|
31
56
|
|
|
32
|
-
<input type="text" {ref
|
|
57
|
+
<input type="text" {ref bindValue(text)} />
|
|
33
58
|
}
|
|
34
59
|
render(App);
|
|
35
60
|
flushSync();
|
|
36
61
|
|
|
62
|
+
expect(container.querySelector('input').value).toBe('foo');
|
|
37
63
|
const input = container.querySelector('input');
|
|
38
64
|
input.value = 'Hello';
|
|
39
65
|
input.dispatchEvent(new Event('input'));
|
|
40
66
|
flushSync();
|
|
41
67
|
expect(input.value).toBe('Hello');
|
|
68
|
+
expect(logs).toEqual(['text changed', 'foo', 'text changed', 'Hello']);
|
|
42
69
|
});
|
|
43
70
|
|
|
44
71
|
it('should update checked on input', () => {
|
|
72
|
+
const logs = [];
|
|
73
|
+
|
|
45
74
|
component App() {
|
|
46
75
|
const value = track(false);
|
|
47
76
|
|
|
48
77
|
effect(() => {
|
|
49
|
-
|
|
78
|
+
logs.push('checked changed', @value);
|
|
50
79
|
});
|
|
51
80
|
|
|
52
|
-
<input type="checkbox" {ref
|
|
81
|
+
<input type="checkbox" {ref bindChecked(value)} />
|
|
53
82
|
}
|
|
54
83
|
render(App);
|
|
55
84
|
flushSync();
|
|
56
85
|
|
|
57
86
|
const input = container.querySelector('input');
|
|
58
87
|
input.checked = true;
|
|
59
|
-
input.dispatchEvent(new Event('
|
|
88
|
+
input.dispatchEvent(new Event('change'));
|
|
60
89
|
flushSync();
|
|
90
|
+
|
|
61
91
|
expect(input.checked).toBe(true);
|
|
92
|
+
expect(logs).toEqual(['checked changed', false, 'checked changed', true]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should update select value on change', () => {
|
|
96
|
+
const logs = [];
|
|
97
|
+
|
|
98
|
+
component App() {
|
|
99
|
+
const select = track('2');
|
|
100
|
+
|
|
101
|
+
effect(() => {
|
|
102
|
+
logs.push('select changed', @select);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
<select {ref bindValue(select)}>
|
|
106
|
+
<option value="1">{"One"}</option>
|
|
107
|
+
<option value="2">{"Two"}</option>
|
|
108
|
+
<option value="3">{"Three"}</option>
|
|
109
|
+
</select>
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
render(App);
|
|
113
|
+
flushSync();
|
|
114
|
+
|
|
115
|
+
const select = container.querySelector('select');
|
|
116
|
+
select.value = '3';
|
|
117
|
+
select.dispatchEvent(new Event('change'));
|
|
118
|
+
flushSync();
|
|
119
|
+
|
|
120
|
+
expect(select.value).toBe('3');
|
|
121
|
+
expect(logs).toEqual(['select changed', '2', 'select changed', '3']);
|
|
62
122
|
});
|
|
63
123
|
});
|
package/types/index.d.ts
CHANGED
|
@@ -200,3 +200,15 @@ export declare const MediaQuery: {
|
|
|
200
200
|
};
|
|
201
201
|
|
|
202
202
|
export function Portal<V = HTMLElement>({ target, children: Component }: { target: V, children?: Component }): void;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {Tracked<V>} tracked
|
|
206
|
+
* @returns {(node: HTMLInputElement | HTMLSelectElement) => void}
|
|
207
|
+
*/
|
|
208
|
+
export declare function bindValue<V>(tracked: Tracked<V>): (node: HTMLInputElement | HTMLSelectElement) => void;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {Tracked<V>} tracked
|
|
212
|
+
* @returns {(node: HTMLInputElement) => void}
|
|
213
|
+
*/
|
|
214
|
+
export declare function bindChecked<V>(tracked: Tracked<V>): (node: HTMLInputElement) => void;
|
package/src/bindings/index.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Tracked } from "ripple";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {Tracked<V>} tracked
|
|
5
|
-
* @returns {(node: HTMLInputElement) => void}
|
|
6
|
-
*/
|
|
7
|
-
export declare function value<V>(tracked: Tracked<V>): (node: HTMLInputElement) => void;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {Tracked<V>} tracked
|
|
11
|
-
* @returns {(node: HTMLInputElement) => void}
|
|
12
|
-
*/
|
|
13
|
-
export declare function checked<V>(tracked: Tracked<V>): (node: HTMLInputElement) => void;
|
package/src/bindings/index.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/** @import {Block, Tracked} from '#client' */
|
|
2
|
-
|
|
3
|
-
import { active_block, get, set, tick } from '../runtime/internal/client';
|
|
4
|
-
import { on } from '../runtime/internal/client/events';
|
|
5
|
-
import { is_tracked_object } from '../runtime/internal/client/utils';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @param {string} value
|
|
9
|
-
*/
|
|
10
|
-
function to_number(value) {
|
|
11
|
-
return value === '' ? null : +value;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param {HTMLInputElement} input
|
|
16
|
-
*/
|
|
17
|
-
function is_numberlike_input(input) {
|
|
18
|
-
var type = input.type;
|
|
19
|
-
return type === 'number' || type === 'range';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param {unknown} maybe_tracked
|
|
24
|
-
* @returns {(node: HTMLInputElement) => void}
|
|
25
|
-
*/
|
|
26
|
-
export function value(maybe_tracked) {
|
|
27
|
-
if (!is_tracked_object(maybe_tracked)) {
|
|
28
|
-
throw new TypeError('value() argument is not a tracked object');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const block = /** @type {Block} */ (active_block);
|
|
32
|
-
const tracked = /** @type {Tracked} */ (maybe_tracked);
|
|
33
|
-
|
|
34
|
-
return (input) => {
|
|
35
|
-
const clear_event = on(input, 'input', async () => {
|
|
36
|
-
/** @type {any} */
|
|
37
|
-
var value = input.value;
|
|
38
|
-
value = is_numberlike_input(input) ? to_number(value) : value;
|
|
39
|
-
set(tracked, value, block);
|
|
40
|
-
|
|
41
|
-
await tick();
|
|
42
|
-
|
|
43
|
-
if (value !== (value = get(tracked))) {
|
|
44
|
-
var start = input.selectionStart;
|
|
45
|
-
var end = input.selectionEnd;
|
|
46
|
-
input.value = value ?? '';
|
|
47
|
-
|
|
48
|
-
// Restore selection
|
|
49
|
-
if (end !== null) {
|
|
50
|
-
input.selectionStart = start;
|
|
51
|
-
input.selectionEnd = Math.min(end, input.value.length);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return clear_event;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @param {unknown} maybe_tracked
|
|
62
|
-
* @returns {(node: HTMLInputElement) => void}
|
|
63
|
-
*/
|
|
64
|
-
export function checked(maybe_tracked) {
|
|
65
|
-
if (!is_tracked_object(maybe_tracked)) {
|
|
66
|
-
throw new TypeError('checked() argument is not a tracked object');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const block = /** @type {any} */ (active_block);
|
|
70
|
-
const tracked = /** @type {Tracked<any>} */ (maybe_tracked);
|
|
71
|
-
|
|
72
|
-
return (input) => {
|
|
73
|
-
const clear_event = on(input, 'change', () => {
|
|
74
|
-
set(tracked, input.checked, block);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return clear_event;
|
|
78
|
-
};
|
|
79
|
-
}
|