ripple 0.2.194 → 0.2.196

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.194",
6
+ "version": "0.2.196",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -92,6 +92,6 @@
92
92
  "vscode-languageserver-types": "^3.17.5"
93
93
  },
94
94
  "peerDependencies": {
95
- "ripple": "0.2.194"
95
+ "ripple": "0.2.196"
96
96
  }
97
97
  }
@@ -1,5 +1,12 @@
1
1
  /** @import { Tracked } from '#client' */
2
2
 
3
+ /**
4
+ @typedef {(v: unknown) => void} SetFunction
5
+ @typedef {() => any} BindGetter
6
+ @typedef {(v: unknown) => void} BindSetter
7
+ @typedef {{getter: BindGetter, setter: BindSetter}} BindGetSet
8
+ */
9
+
3
10
  import { effect, render } from './blocks.js';
4
11
  import { on } from './events.js';
5
12
  import { get, set, tick, untrack } from './runtime.js';
@@ -13,6 +20,44 @@ function not_tracked_type_error(name) {
13
20
  return new TypeError(`${name} argument is not a tracked object`);
14
21
  }
15
22
 
23
+ /**
24
+ * @param {string} name
25
+ * @returns {TypeError}
26
+ */
27
+ function not_set_function_type_error(name) {
28
+ return new TypeError(
29
+ `${name} second argument must be a set function when first argument is a get function`,
30
+ );
31
+ }
32
+
33
+ /**
34
+ * @param {string} name
35
+ * @param {unknown} maybe_tracked
36
+ * @param {SetFunction | undefined} set_func
37
+ * @returns {BindGetSet}
38
+ */
39
+ function get_bind_get_set(name, maybe_tracked, set_func) {
40
+ if (typeof maybe_tracked === 'function') {
41
+ if (typeof set_func !== 'function') {
42
+ throw not_set_function_type_error(name);
43
+ }
44
+
45
+ return {
46
+ getter: /** @type {BindGetter} */ (maybe_tracked),
47
+ setter: set_func,
48
+ };
49
+ } else {
50
+ if (!is_tracked_object(maybe_tracked)) {
51
+ throw not_tracked_type_error(name);
52
+ }
53
+
54
+ return {
55
+ getter: () => get(/** @type {Tracked} */ (maybe_tracked)),
56
+ setter: (value) => set(/** @type {Tracked} */ (maybe_tracked), value),
57
+ };
58
+ }
59
+ }
60
+
16
61
  /**
17
62
  * Resize observer singleton.
18
63
  * One listener per element only!
@@ -149,14 +194,11 @@ function select_option(select, value, mounting = false) {
149
194
 
150
195
  /**
151
196
  * @param {unknown} maybe_tracked
197
+ * @param {SetFunction | undefined} set_func
152
198
  * @returns {(node: HTMLInputElement | HTMLSelectElement) => void}
153
199
  */
154
- export function bindValue(maybe_tracked) {
155
- if (!is_tracked_object(maybe_tracked)) {
156
- throw not_tracked_type_error('bindValue()');
157
- }
158
-
159
- var tracked = /** @type {Tracked} */ (maybe_tracked);
200
+ export function bindValue(maybe_tracked, set_func = undefined) {
201
+ var { getter, setter } = get_bind_get_set('bindValue()', maybe_tracked, set_func);
160
202
 
161
203
  return (node) => {
162
204
  var clear_event;
@@ -182,11 +224,11 @@ export function bindValue(maybe_tracked) {
182
224
  value = selected_option && get_option_value(selected_option);
183
225
  }
184
226
 
185
- set(tracked, value);
227
+ setter(value);
186
228
  });
187
229
 
188
230
  effect(() => {
189
- var value = get(tracked);
231
+ var value = getter();
190
232
  select_option(select, value, mounting);
191
233
 
192
234
  // Mounting and value undefined -> take selection from dom
@@ -196,7 +238,7 @@ export function bindValue(maybe_tracked) {
196
238
  var selected_option = select.querySelector(':checked');
197
239
  if (selected_option !== null) {
198
240
  value = get_option_value(selected_option);
199
- set(tracked, value);
241
+ setter(value);
200
242
  }
201
243
  }
202
244
 
@@ -209,11 +251,11 @@ export function bindValue(maybe_tracked) {
209
251
  /** @type {any} */
210
252
  var value = input.value;
211
253
  value = is_numberlike_input(input) ? to_number(value) : value;
212
- set(tracked, value);
254
+ setter(value);
213
255
 
214
256
  await tick();
215
257
 
216
- if (value !== (value = get(tracked))) {
258
+ if (value !== getter()) {
217
259
  var start = input.selectionStart;
218
260
  var end = input.selectionEnd;
219
261
  input.value = value ?? '';
@@ -227,7 +269,7 @@ export function bindValue(maybe_tracked) {
227
269
  });
228
270
 
229
271
  render(() => {
230
- var value = get(tracked);
272
+ var value = getter();
231
273
 
232
274
  if (is_numberlike_input(input) && value === to_number(input.value)) {
233
275
  return;
@@ -249,22 +291,19 @@ export function bindValue(maybe_tracked) {
249
291
 
250
292
  /**
251
293
  * @param {unknown} maybe_tracked
294
+ * @param {SetFunction | undefined} set_func
252
295
  * @returns {(node: HTMLInputElement) => void}
253
296
  */
254
- export function bindChecked(maybe_tracked) {
255
- if (!is_tracked_object(maybe_tracked)) {
256
- throw not_tracked_type_error('bindChecked()');
257
- }
258
-
259
- var tracked = /** @type {Tracked} */ (maybe_tracked);
297
+ export function bindChecked(maybe_tracked, set_func = undefined) {
298
+ var { getter, setter } = get_bind_get_set('bindChecked()', maybe_tracked, set_func);
260
299
 
261
300
  return (input) => {
262
301
  var clear_event = on(input, 'change', () => {
263
- set(tracked, input.checked);
302
+ setter(input.checked);
264
303
  });
265
304
 
266
305
  effect(() => {
267
- var value = get(tracked);
306
+ var value = getter();
268
307
  input.checked = Boolean(value);
269
308
  });
270
309
 
@@ -274,22 +313,19 @@ export function bindChecked(maybe_tracked) {
274
313
 
275
314
  /**
276
315
  * @param {unknown} maybe_tracked
316
+ * @param {SetFunction | undefined} set_func
277
317
  * @returns {(node: HTMLInputElement) => void}
278
318
  */
279
- export function bindIndeterminate(maybe_tracked) {
280
- if (!is_tracked_object(maybe_tracked)) {
281
- throw not_tracked_type_error('bindIndeterminate()');
282
- }
283
-
284
- var tracked = /** @type {Tracked} */ (maybe_tracked);
319
+ export function bindIndeterminate(maybe_tracked, set_func = undefined) {
320
+ var { getter, setter } = get_bind_get_set('bindIndeterminate()', maybe_tracked, set_func);
285
321
 
286
322
  return (input) => {
287
323
  var clear_event = on(input, 'change', () => {
288
- set(tracked, input.indeterminate);
324
+ setter(input.indeterminate);
289
325
  });
290
326
 
291
327
  effect(() => {
292
- var value = get(tracked);
328
+ var value = getter();
293
329
  input.indeterminate = Boolean(value);
294
330
  });
295
331
 
@@ -299,14 +335,11 @@ export function bindIndeterminate(maybe_tracked) {
299
335
 
300
336
  /**
301
337
  * @param {unknown} maybe_tracked
338
+ * @param {SetFunction | undefined} set_func
302
339
  * @returns {(node: HTMLInputElement) => void}
303
340
  */
304
- export function bindGroup(maybe_tracked) {
305
- if (!is_tracked_object(maybe_tracked)) {
306
- throw not_tracked_type_error('bindGroup()');
307
- }
308
-
309
- var tracked = /** @type {Tracked} */ (maybe_tracked);
341
+ export function bindGroup(maybe_tracked, set_func = undefined) {
342
+ var { getter, setter } = get_bind_get_set('bindGroup()', maybe_tracked, set_func);
310
343
 
311
344
  return (input) => {
312
345
  var is_checkbox = input.getAttribute('type') === 'checkbox';
@@ -317,7 +350,7 @@ export function bindGroup(maybe_tracked) {
317
350
 
318
351
  if (is_checkbox) {
319
352
  /** @type {Array<any>} */
320
- var list = get(tracked) || [];
353
+ var list = getter() || [];
321
354
 
322
355
  if (input.checked) {
323
356
  if (!list.includes(value)) {
@@ -332,12 +365,11 @@ export function bindGroup(maybe_tracked) {
332
365
  result = input.value;
333
366
  }
334
367
 
335
- set(tracked, result);
368
+ setter(result);
336
369
  });
337
370
 
338
371
  effect(() => {
339
- var value = get(tracked);
340
-
372
+ var value = getter();
341
373
  if (is_checkbox) {
342
374
  value = value || [];
343
375
  input.checked = value.includes(input.value);
@@ -353,21 +385,20 @@ export function bindGroup(maybe_tracked) {
353
385
  /**
354
386
  * @param {unknown} maybe_tracked
355
387
  * @param {'clientWidth' | 'clientHeight' | 'offsetWidth' | 'offsetHeight'} type
388
+ * @param {SetFunction | undefined} set_func
356
389
  */
357
- function bind_element_size(maybe_tracked, type) {
358
- if (!is_tracked_object(maybe_tracked)) {
359
- throw not_tracked_type_error(`bind${type.charAt(0).toUpperCase() + type.slice(1)}()`);
360
- }
361
-
362
- var tracked = /** @type {Tracked<any>} */ (maybe_tracked);
390
+ function bind_element_size(maybe_tracked, type, set_func = undefined) {
391
+ var { setter } = get_bind_get_set(
392
+ `bind${type.charAt(0).toUpperCase() + type.slice(1)}()`,
393
+ maybe_tracked,
394
+ set_func,
395
+ );
363
396
 
364
397
  return (/** @type {HTMLElement} */ element) => {
365
- var unsubscribe = resize_observer_border_box.observe(element, () =>
366
- set(tracked, element[type]),
367
- );
398
+ var unsubscribe = resize_observer_border_box.observe(element, () => setter(element[type]));
368
399
 
369
400
  effect(() => {
370
- set(tracked, element[type]);
401
+ setter(element[type]);
371
402
  return unsubscribe;
372
403
  });
373
404
  };
@@ -375,46 +406,52 @@ function bind_element_size(maybe_tracked, type) {
375
406
 
376
407
  /**
377
408
  * @param {unknown} maybe_tracked
409
+ * @param {SetFunction | undefined} set_func
378
410
  * @returns {(node: HTMLElement) => void}
379
411
  */
380
- export function bindClientWidth(maybe_tracked) {
381
- return bind_element_size(maybe_tracked, 'clientWidth');
412
+ export function bindClientWidth(maybe_tracked, set_func = undefined) {
413
+ return bind_element_size(maybe_tracked, 'clientWidth', set_func);
382
414
  }
383
415
 
384
416
  /**
385
417
  * @param {unknown} maybe_tracked
418
+ * @param {SetFunction | undefined} set_func
386
419
  * @returns {(node: HTMLElement) => void}
387
420
  */
388
- export function bindClientHeight(maybe_tracked) {
389
- return bind_element_size(maybe_tracked, 'clientHeight');
421
+ export function bindClientHeight(maybe_tracked, set_func = undefined) {
422
+ return bind_element_size(maybe_tracked, 'clientHeight', set_func);
390
423
  }
391
424
 
392
425
  /**
393
426
  * @param {unknown} maybe_tracked
427
+ * @param {SetFunction | undefined} set_func
394
428
  * @returns {(node: HTMLElement) => void}
395
429
  */
396
- export function bindOffsetWidth(maybe_tracked) {
397
- return bind_element_size(maybe_tracked, 'offsetWidth');
430
+ export function bindOffsetWidth(maybe_tracked, set_func = undefined) {
431
+ return bind_element_size(maybe_tracked, 'offsetWidth', set_func);
398
432
  }
399
433
 
400
434
  /**
401
435
  * @param {unknown} maybe_tracked
436
+ * @param {SetFunction | undefined} set_func
402
437
  * @returns {(node: HTMLElement) => void}
403
438
  */
404
- export function bindOffsetHeight(maybe_tracked) {
405
- return bind_element_size(maybe_tracked, 'offsetHeight');
439
+ export function bindOffsetHeight(maybe_tracked, set_func = undefined) {
440
+ return bind_element_size(maybe_tracked, 'offsetHeight', set_func);
406
441
  }
407
442
 
408
443
  /**
409
444
  * @param {unknown} maybe_tracked
410
445
  * @param {'contentRect' | 'contentBoxSize' | 'borderBoxSize' | 'devicePixelContentBoxSize'} type
446
+ * @param {SetFunction | undefined} set_func
411
447
  */
412
- function bind_element_rect(maybe_tracked, type) {
413
- if (!is_tracked_object(maybe_tracked)) {
414
- throw not_tracked_type_error(`bind${type.charAt(0).toUpperCase() + type.slice(1)}()`);
415
- }
448
+ function bind_element_rect(maybe_tracked, type, set_func = undefined) {
449
+ var { setter } = get_bind_get_set(
450
+ `bind${type.charAt(0).toUpperCase() + type.slice(1)}()`,
451
+ maybe_tracked,
452
+ set_func,
453
+ );
416
454
 
417
- var tracked = /** @type {Tracked<any>} */ (maybe_tracked);
418
455
  var observer =
419
456
  type === 'contentRect' || type === 'contentBoxSize'
420
457
  ? resize_observer_content_box
@@ -425,7 +462,7 @@ function bind_element_rect(maybe_tracked, type) {
425
462
  return (/** @type {HTMLElement} */ element) => {
426
463
  var unsubscribe = observer.observe(
427
464
  element,
428
- /** @param {any} entry */ (entry) => set(tracked, entry[type]),
465
+ /** @param {any} entry */ (entry) => setter(entry[type]),
429
466
  );
430
467
 
431
468
  effect(() => unsubscribe);
@@ -434,61 +471,65 @@ function bind_element_rect(maybe_tracked, type) {
434
471
 
435
472
  /**
436
473
  * @param {unknown} maybe_tracked
474
+ * @param {SetFunction | undefined} set_func
437
475
  * @returns {(node: HTMLElement) => void}
438
476
  */
439
- export function bindContentRect(maybe_tracked) {
440
- return bind_element_rect(maybe_tracked, 'contentRect');
477
+ export function bindContentRect(maybe_tracked, set_func = undefined) {
478
+ return bind_element_rect(maybe_tracked, 'contentRect', set_func);
441
479
  }
442
480
 
443
481
  /**
444
482
  * @param {unknown} maybe_tracked
483
+ * @param {SetFunction | undefined} set_func
445
484
  * @returns {(node: HTMLElement) => void}
446
485
  */
447
- export function bindContentBoxSize(maybe_tracked) {
448
- return bind_element_rect(maybe_tracked, 'contentBoxSize');
486
+ export function bindContentBoxSize(maybe_tracked, set_func = undefined) {
487
+ return bind_element_rect(maybe_tracked, 'contentBoxSize', set_func);
449
488
  }
450
489
 
451
490
  /**
452
491
  * @param {unknown} maybe_tracked
492
+ * @param {SetFunction | undefined} set_func
453
493
  * @returns {(node: HTMLElement) => void}
454
494
  */
455
- export function bindBorderBoxSize(maybe_tracked) {
456
- return bind_element_rect(maybe_tracked, 'borderBoxSize');
495
+ export function bindBorderBoxSize(maybe_tracked, set_func = undefined) {
496
+ return bind_element_rect(maybe_tracked, 'borderBoxSize', set_func);
457
497
  }
458
498
 
459
499
  /**
460
500
  * @param {unknown} maybe_tracked
501
+ * @param {SetFunction | undefined} set_func
461
502
  * @returns {(node: HTMLElement) => void}
462
503
  */
463
- export function bindDevicePixelContentBoxSize(maybe_tracked) {
464
- return bind_element_rect(maybe_tracked, 'devicePixelContentBoxSize');
504
+ export function bindDevicePixelContentBoxSize(maybe_tracked, set_func = undefined) {
505
+ return bind_element_rect(maybe_tracked, 'devicePixelContentBoxSize', set_func);
465
506
  }
466
507
 
467
508
  /**
468
509
  * @param {unknown} maybe_tracked
469
510
  * @param {'innerHTML' | 'innerText' | 'textContent'} property
511
+ * @param {SetFunction | undefined} set_func
470
512
  * @returns {(node: HTMLElement) => void}
471
513
  */
472
- export function bind_content_editable(maybe_tracked, property) {
473
- if (!is_tracked_object(maybe_tracked)) {
474
- throw not_tracked_type_error(`bind${property.charAt(0).toUpperCase() + property.slice(1)}()`);
475
- }
476
-
477
- var tracked = /** @type {Tracked} */ (maybe_tracked);
514
+ export function bind_content_editable(maybe_tracked, property, set_func = undefined) {
515
+ var { getter, setter } = get_bind_get_set(
516
+ `bind${property.charAt(0).toUpperCase() + property.slice(1)}()`,
517
+ maybe_tracked,
518
+ set_func,
519
+ );
478
520
 
479
521
  return (element) => {
480
522
  var clear_event = on(element, 'input', () => {
481
- set(tracked, element[property]);
523
+ setter(element[property]);
482
524
  });
483
525
 
484
526
  render(() => {
485
- var value = get(tracked);
486
-
527
+ var value = getter();
487
528
  if (element[property] !== value) {
488
529
  if (value == null) {
489
530
  // @ts-ignore
490
531
  var non_null_value = element[property];
491
- set(tracked, non_null_value);
532
+ setter(non_null_value);
492
533
  } else {
493
534
  // @ts-ignore
494
535
  element[property] = value + '';
@@ -502,46 +543,46 @@ export function bind_content_editable(maybe_tracked, property) {
502
543
 
503
544
  /**
504
545
  * @param {unknown} maybe_tracked
546
+ * @param {SetFunction | undefined} set_func
505
547
  * @returns {(node: HTMLElement) => void}
506
548
  */
507
- export function bindInnerHTML(maybe_tracked) {
508
- return bind_content_editable(maybe_tracked, 'innerHTML');
549
+ export function bindInnerHTML(maybe_tracked, set_func = undefined) {
550
+ return bind_content_editable(maybe_tracked, 'innerHTML', set_func);
509
551
  }
510
552
 
511
553
  /**
512
554
  * @param {unknown} maybe_tracked
555
+ * @param {SetFunction | undefined} set_func
513
556
  * @returns {(node: HTMLElement) => void}
514
557
  */
515
- export function bindInnerText(maybe_tracked) {
516
- return bind_content_editable(maybe_tracked, 'innerText');
558
+ export function bindInnerText(maybe_tracked, set_func = undefined) {
559
+ return bind_content_editable(maybe_tracked, 'innerText', set_func);
517
560
  }
518
561
 
519
562
  /**
520
563
  * @param {unknown} maybe_tracked
564
+ * @param {SetFunction | undefined} set_func
521
565
  * @returns {(node: HTMLElement) => void}
522
566
  */
523
- export function bindTextContent(maybe_tracked) {
524
- return bind_content_editable(maybe_tracked, 'textContent');
567
+ export function bindTextContent(maybe_tracked, set_func = undefined) {
568
+ return bind_content_editable(maybe_tracked, 'textContent', set_func);
525
569
  }
526
570
 
527
571
  /**
528
572
  * @param {unknown} maybe_tracked
573
+ * @param {SetFunction | undefined} set_func
529
574
  * @returns {(node: HTMLInputElement) => void}
530
575
  */
531
- export function bindFiles(maybe_tracked) {
532
- if (!is_tracked_object(maybe_tracked)) {
533
- throw not_tracked_type_error('bindFiles()');
534
- }
535
-
536
- var tracked = /** @type {Tracked} */ (maybe_tracked);
576
+ export function bindFiles(maybe_tracked, set_func = undefined) {
577
+ var { getter, setter } = get_bind_get_set('bindFiles()', maybe_tracked, set_func);
537
578
 
538
579
  return (input) => {
539
580
  var clear_event = on(input, 'change', () => {
540
- set(tracked, input.files);
581
+ setter(input.files);
541
582
  });
542
583
 
543
584
  effect(() => {
544
- var value = get(tracked);
585
+ var value = getter();
545
586
 
546
587
  if (value !== input.files && value instanceof FileList) {
547
588
  input.files = value;
@@ -555,17 +596,14 @@ export function bindFiles(maybe_tracked) {
555
596
  /**
556
597
  * Syntactic sugar for binding a HTMLElement with {ref fn}
557
598
  * @param {unknown} maybe_tracked
599
+ * @param {SetFunction | undefined} set_func
558
600
  * @returns {(node: HTMLElement) => void}
559
601
  */
560
- export function bindNode(maybe_tracked) {
561
- if (!is_tracked_object(maybe_tracked)) {
562
- throw not_tracked_type_error('bindNode()');
563
- }
564
-
565
- var tracked = /** @type {Tracked} */ (maybe_tracked);
602
+ export function bindNode(maybe_tracked, set_func = undefined) {
603
+ var { setter } = get_bind_get_set('bindNode()', maybe_tracked, set_func);
566
604
 
567
605
  /** @param {HTMLElement} node */
568
606
  return (node) => {
569
- set(tracked, node);
607
+ setter(node);
570
608
  };
571
609
  }