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.
@@ -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 { value, checked } from 'ripple/bindings';
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
- console.log('text changed', @text);
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 value(text)} />
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
- console.log('checked changed', @value);
78
+ logs.push('checked changed', @value);
50
79
  });
51
80
 
52
- <input type="checkbox" {ref checked(value)} />
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('input'));
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;
@@ -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;
@@ -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
- }