@xsynaptic/sonic-ui 0.6.1 → 0.8.0

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.
Files changed (84) hide show
  1. package/README.md +4 -0
  2. package/dist/default/define/spectrum.js +7 -0
  3. package/dist/default/define.js +1 -0
  4. package/dist/default/elements/button.js +30 -2
  5. package/dist/default/elements/display-element.js +77 -0
  6. package/dist/default/elements/envelope.js +1 -1
  7. package/dist/default/elements/slider.js +67 -1
  8. package/dist/default/elements/spectrum.js +230 -0
  9. package/dist/default/elements/value-element.js +49 -11
  10. package/dist/default/elements/wave-element.js +59 -9
  11. package/dist/default/elements/waveform.js +56 -10
  12. package/dist/default/elements/wavestrip.js +31 -45
  13. package/dist/default/elements/xy.js +1 -1
  14. package/dist/default/index.js +2 -1
  15. package/dist/default/lib/canvas-surface.js +7 -4
  16. package/dist/default/lib/frame-timeline.js +2 -2
  17. package/dist/default/lib/hover-preview.js +46 -0
  18. package/dist/default/lib/marker-rider.js +7 -4
  19. package/dist/default/lib/pointer-drag.js +7 -2
  20. package/dist/default/lib/spectrum-columns.js +74 -0
  21. package/dist/default/lib/spectrum-levels.js +55 -0
  22. package/dist/default/lib/strip-scene.js +12 -1
  23. package/dist/default/lib/time-regions.js +5 -1
  24. package/dist/dev/define/spectrum.d.ts +2 -0
  25. package/dist/dev/define/spectrum.js +8 -0
  26. package/dist/dev/define/spectrum.js.map +1 -0
  27. package/dist/dev/define.d.ts +3 -1
  28. package/dist/dev/define.js +1 -0
  29. package/dist/dev/elements/button.d.ts +2 -0
  30. package/dist/dev/elements/button.js +30 -2
  31. package/dist/dev/elements/button.js.map +1 -1
  32. package/dist/dev/elements/display-element.d.ts +29 -0
  33. package/dist/dev/elements/display-element.js +78 -0
  34. package/dist/dev/elements/display-element.js.map +1 -0
  35. package/dist/dev/elements/envelope.js +1 -1
  36. package/dist/dev/elements/slider.d.ts +6 -0
  37. package/dist/dev/elements/slider.js +67 -1
  38. package/dist/dev/elements/slider.js.map +1 -1
  39. package/dist/dev/elements/spectrum.d.ts +59 -0
  40. package/dist/dev/elements/spectrum.js +231 -0
  41. package/dist/dev/elements/spectrum.js.map +1 -0
  42. package/dist/dev/elements/value-element.d.ts +5 -1
  43. package/dist/dev/elements/value-element.js +49 -11
  44. package/dist/dev/elements/value-element.js.map +1 -1
  45. package/dist/dev/elements/wave-element.d.ts +8 -2
  46. package/dist/dev/elements/wave-element.js +59 -9
  47. package/dist/dev/elements/wave-element.js.map +1 -1
  48. package/dist/dev/elements/waveform.d.ts +12 -4
  49. package/dist/dev/elements/waveform.js +56 -10
  50. package/dist/dev/elements/waveform.js.map +1 -1
  51. package/dist/dev/elements/wavestrip.d.ts +3 -0
  52. package/dist/dev/elements/wavestrip.js +31 -45
  53. package/dist/dev/elements/wavestrip.js.map +1 -1
  54. package/dist/dev/elements/xy.js +1 -1
  55. package/dist/dev/index.d.ts +4 -1
  56. package/dist/dev/index.js +2 -1
  57. package/dist/dev/lib/canvas-surface.d.ts +4 -3
  58. package/dist/dev/lib/canvas-surface.js +7 -4
  59. package/dist/dev/lib/canvas-surface.js.map +1 -1
  60. package/dist/dev/lib/frame-timeline.js +2 -2
  61. package/dist/dev/lib/frame-timeline.js.map +1 -1
  62. package/dist/dev/lib/hover-preview.js +47 -0
  63. package/dist/dev/lib/hover-preview.js.map +1 -0
  64. package/dist/dev/lib/marker-rider.js +7 -4
  65. package/dist/dev/lib/marker-rider.js.map +1 -1
  66. package/dist/dev/lib/pointer-drag.js +7 -2
  67. package/dist/dev/lib/pointer-drag.js.map +1 -1
  68. package/dist/dev/lib/spectrum-columns.js +75 -0
  69. package/dist/dev/lib/spectrum-columns.js.map +1 -0
  70. package/dist/dev/lib/spectrum-levels.js +56 -0
  71. package/dist/dev/lib/spectrum-levels.js.map +1 -0
  72. package/dist/dev/lib/strip-scene.js +12 -1
  73. package/dist/dev/lib/strip-scene.js.map +1 -1
  74. package/dist/dev/lib/time-regions.js +5 -1
  75. package/dist/dev/lib/time-regions.js.map +1 -1
  76. package/dist/styles/button.css +7 -1
  77. package/dist/styles/controls.css +1 -0
  78. package/dist/styles/material.css +18 -3
  79. package/dist/styles/meter.css +22 -18
  80. package/dist/styles/slider.css +42 -5
  81. package/dist/styles/spectrum.css +105 -0
  82. package/dist/styles/waveform.css +38 -16
  83. package/dist/styles/wavestrip.css +22 -4
  84. package/package.json +2 -1
@@ -1,7 +1,8 @@
1
- import { clamp, toNumber } from "../lib/math.js";
1
+ import { clamp, toNumber, trimFloat } from "../lib/math.js";
2
2
  import { writeAttribute } from "../lib/write-attribute.js";
3
3
  import { SonicFormElement } from "./form-element.js";
4
4
  import { requireChild } from "../lib/render.js";
5
+ import { bindDrag } from "../lib/pointer-drag.js";
5
6
  import { ReadoutClaim } from "./readout-claim.js";
6
7
  import { Readout } from "./readout.js";
7
8
  import { ValueEntry } from "./value-entry.js";
@@ -9,7 +10,6 @@ import { dragThresholdPx, startDrag, stepDrag } from "../lib/drag-step.js";
9
10
  import { focusByPointer } from "../lib/focus-by-pointer.js";
10
11
  import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
11
12
  import { parseNumberList } from "../lib/number-list.js";
12
- import { bindDrag } from "../lib/pointer-drag.js";
13
13
  import { readPxProperty } from "../lib/read-px-property.js";
14
14
  import { resetKeys, valueMapping } from "../lib/value-mapping.js";
15
15
 
@@ -49,6 +49,7 @@ var SonicValueElement = class extends SonicFormElement {
49
49
  "notched",
50
50
  "origin",
51
51
  "readout",
52
+ "spoken-step",
52
53
  "step",
53
54
  "tabindex",
54
55
  "taper",
@@ -156,6 +157,9 @@ var SonicValueElement = class extends SonicFormElement {
156
157
  set parseValue(parse) {
157
158
  this.#parseValue = parse;
158
159
  }
160
+ get pointerType() {
161
+ return this.#dragging()?.pointerType;
162
+ }
159
163
  get positions() {
160
164
  return parseNumberList(this.getAttribute("positions"));
161
165
  }
@@ -168,6 +172,12 @@ var SonicValueElement = class extends SonicFormElement {
168
172
  set readout(isShown) {
169
173
  this.reflect("readout", isShown);
170
174
  }
175
+ get spokenStep() {
176
+ return this.optionalNumberAttribute("spoken-step");
177
+ }
178
+ set spokenStep(value) {
179
+ this.reflect("spoken-step", value);
180
+ }
171
181
  get step() {
172
182
  return this.numberAttribute("step", 1);
173
183
  }
@@ -206,8 +216,10 @@ var SonicValueElement = class extends SonicFormElement {
206
216
  #entry;
207
217
  #formatSpokenValue;
208
218
  #formatValue;
219
+ #heldAt;
209
220
  #instance = String(instanceCount += 1);
210
221
  #isModulated = false;
222
+ #isRevealed = false;
211
223
  #keyScrub;
212
224
  #land;
213
225
  #limit;
@@ -235,7 +247,7 @@ var SonicValueElement = class extends SonicFormElement {
235
247
  this.render();
236
248
  }
237
249
  connectedCallback() {
238
- this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
250
+ this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "spokenStep", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
239
251
  super.connectedCallback();
240
252
  }
241
253
  bindGestures(control, signal, grab) {
@@ -261,6 +273,7 @@ var SonicValueElement = class extends SonicFormElement {
261
273
  fromValue,
262
274
  isOutside: false,
263
275
  isRevealed: false,
276
+ pointerType: event.pointerType,
264
277
  revealTimer: void 0,
265
278
  state: this.#startDrag(control, axis, event)
266
279
  };
@@ -306,7 +319,9 @@ var SonicValueElement = class extends SonicFormElement {
306
319
  heldFrom() {
307
320
  return this.#dragging()?.fromValue ?? this.#keyScrub?.fromValue;
308
321
  }
309
- heldWrite(_next) {}
322
+ heldWrite(next) {
323
+ this.#heldAt = next;
324
+ }
310
325
  holdChanged() {}
311
326
  input(next) {
312
327
  const previous = this.#value;
@@ -346,6 +361,10 @@ var SonicValueElement = class extends SonicFormElement {
346
361
  originValue() {
347
362
  return this.origin ?? this.mapping().bounds[0];
348
363
  }
364
+ playback() {
365
+ const from = this.heldFrom();
366
+ return from === void 0 ? this.#value : this.#heldAt ?? from;
367
+ }
349
368
  previewValue() {}
350
369
  proportionsChanged() {}
351
370
  readModulationValue() {
@@ -362,10 +381,11 @@ var SonicValueElement = class extends SonicFormElement {
362
381
  const readout = this.#readout;
363
382
  if (!readout) return;
364
383
  const { isOpen, value } = this.#shown();
384
+ const text = value === void 0 ? void 0 : this.#textFor(value);
365
385
  readout.bubble.show({
366
386
  anchor: readout.anchor,
367
- isOpen,
368
- text: value === void 0 ? void 0 : this.#textFor(value)
387
+ isOpen: isOpen && text !== "",
388
+ text
369
389
  });
370
390
  }
371
391
  restoreState(state) {
@@ -473,10 +493,13 @@ var SonicValueElement = class extends SonicFormElement {
473
493
  drag.state = this.#withinLimit(mapping, state);
474
494
  if (value === void 0) return;
475
495
  if (!wasEngaged) this.#reveal(drag);
496
+ const isCrossing = isOutside !== drag.isOutside;
497
+ if (isCrossing) {
498
+ drag.isOutside = isOutside;
499
+ this.toggleState("cancelling", isOutside);
500
+ }
476
501
  this.input(isOutside ? drag.fromValue : value);
477
- if (isOutside === drag.isOutside) return;
478
- drag.isOutside = isOutside;
479
- this.#renderDragReveal(drag);
502
+ if (isCrossing) this.#renderDragReveal(drag);
480
503
  }
481
504
  #endHolds() {
482
505
  this.#entry?.close(false);
@@ -508,7 +531,9 @@ var SonicValueElement = class extends SonicFormElement {
508
531
  #releaseDrag(drag) {
509
532
  clearTimeout(drag.revealTimer);
510
533
  this.#claim.conceal("drag");
534
+ this.toggleState("cancelling", false);
511
535
  this.#renderHold();
536
+ this.#showRevealed(false);
512
537
  if (this.#value !== drag.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
513
538
  this.#springBack();
514
539
  }
@@ -524,7 +549,7 @@ var SonicValueElement = class extends SonicFormElement {
524
549
  writeAttribute(control, "role", this.controlRole());
525
550
  writeAttribute(control, "aria-valuemin", String(low));
526
551
  writeAttribute(control, "aria-valuemax", String(high));
527
- writeAttribute(control, "aria-valuenow", String(this.#value));
552
+ writeAttribute(control, "aria-valuenow", String(this.#spokenNow()));
528
553
  if (orientation) writeAttribute(control, "aria-orientation", orientation);
529
554
  writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#value));
530
555
  this.forwardNaming(control, true);
@@ -543,11 +568,14 @@ var SonicValueElement = class extends SonicFormElement {
543
568
  writeAttribute(control, "tabindex", isDisabled ? void 0 : stop);
544
569
  }
545
570
  #renderDragReveal(drag) {
546
- if (drag.isRevealed && !drag.isOutside) this.#claim.reveal("drag");
571
+ const isRevealed = drag.isRevealed && !drag.isOutside;
572
+ if (isRevealed) this.#claim.reveal("drag");
547
573
  else this.#claim.conceal("drag");
548
574
  this.#renderHold();
575
+ this.#showRevealed(isRevealed);
549
576
  }
550
577
  #renderHold() {
578
+ if (this.heldFrom() === void 0) this.#heldAt = void 0;
551
579
  this.renderReadout();
552
580
  this.holdChanged();
553
581
  }
@@ -581,6 +609,16 @@ var SonicValueElement = class extends SonicFormElement {
581
609
  value: preview ?? this.#value
582
610
  };
583
611
  }
612
+ #showRevealed(isRevealed) {
613
+ if (isRevealed === this.#isRevealed) return;
614
+ this.#isRevealed = isRevealed;
615
+ this.toggleState("revealed", isRevealed);
616
+ this.dispatchEvent(new Event("sonic-reveal", { bubbles: true }));
617
+ }
618
+ #spokenNow() {
619
+ const step = this.spokenStep;
620
+ return step !== void 0 && step > 0 ? trimFloat(Math.round(this.#value / step) * step) : this.#value;
621
+ }
584
622
  #springBack() {
585
623
  const target = this.springTarget();
586
624
  if (target === void 0) return;
@@ -1 +1 @@
1
- {"version":3,"file":"value-element.js","names":[],"sources":["../../../src/elements/value-element.ts"],"sourcesContent":["import type { DragState } from '#lib/drag-step.ts';\nimport type { PointerDrag } from '#lib/pointer-drag.ts';\nimport type { ValueMapping } from '#lib/value-mapping.ts';\n\nimport { SonicFormElement } from '#elements/form-element.ts';\nimport { ReadoutClaim, revealMs } from '#elements/readout-claim.ts';\nimport { Readout } from '#elements/readout.ts';\nimport { ValueEntry } from '#elements/value-entry.ts';\nimport { dragThresholdPx, startDrag, stepDrag } from '#lib/drag-step.ts';\nimport { focusByPointer } from '#lib/focus-by-pointer.ts';\nimport { clamp, toNumber } from '#lib/math.ts';\nimport { isMenuPress, isResetPress } from '#lib/modifier-press.ts';\nimport { parseNumberList } from '#lib/number-list.ts';\nimport { bindDrag } from '#lib/pointer-drag.ts';\nimport { readPxProperty } from '#lib/read-px-property.ts';\nimport { requireChild } from '#lib/render.ts';\nimport { resetKeys, valueMapping } from '#lib/value-mapping.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\nexport interface ValueAxis {\n\tfromProportion?: number;\n\tisKeptOnCancel?: boolean;\n\toutside?: (event: PointerEvent) => boolean;\n\tposition: (event: PointerEvent) => number;\n\ttravelPx: number;\n}\n\ninterface ValueDrag extends ValueAxis {\n\tfromValue: number;\n\tisOutside: boolean;\n\tisRevealed: boolean;\n\trevealTimer: ReturnType<typeof setTimeout> | undefined;\n\tstate: DragState;\n}\n\ninterface KeyScrub {\n\tfromValue: number;\n\tkey: string;\n}\n\nconst detentZonePx = 8;\nconst fallbackTravelPx = 160;\n\nlet instanceCount = 0;\n\nconst proportionAttributes = new Set(['max', 'midpoint', 'min', 'notched', 'positions', 'taper']);\n\nconst roleAttributes = [\n\t'aria-disabled',\n\t'aria-orientation',\n\t'aria-valuemax',\n\t'aria-valuemin',\n\t'aria-valuenow',\n\t'aria-valuetext',\n\t'role',\n\t'tabindex',\n];\n\ntype ValueLanding = (target: number, direction: -1 | 0 | 1) => number;\n\nexport interface ValueLink {\n\tinput: (next: number, isMover?: boolean) => boolean;\n\tisDisabled: () => boolean;\n\tisHeld: () => boolean;\n\tland: (resolve: undefined | ValueLanding) => void;\n\tlimit: (bounds: [number, number] | undefined) => void;\n\tmapping: () => ValueMapping;\n\tvalue: () => number;\n\twatch: (listener: () => void) => () => void;\n}\n\n// Filled from inside the class, so it reaches protected members and nothing lands on the element's public type\nlet link: (element: SonicValueElement) => ValueLink;\n\nexport function linkValue(element: SonicValueElement): ValueLink {\n\treturn link(element);\n}\n\nexport abstract class SonicValueElement extends SonicFormElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicFormElement.observedAttributes,\n\t\t'detent',\n\t\t'max',\n\t\t'midpoint',\n\t\t'min',\n\t\t'notched',\n\t\t'origin',\n\t\t'readout',\n\t\t'step',\n\t\t'tabindex',\n\t\t'taper',\n\t\t'value',\n\t\t'positions',\n\t];\n\n\tstatic {\n\t\tlink = (element) => ({\n\t\t\tinput: (next, isMover = false) => (isMover || !element.#isHeld()) && element.input(next),\n\t\t\tisDisabled: () => element.isDisabled(),\n\t\t\tisHeld: () => element.#isHeld(),\n\t\t\tland: (resolve) => {\n\t\t\t\telement.#land = resolve;\n\t\t\t},\n\t\t\tlimit: (bounds) => {\n\t\t\t\telement.#limit = bounds;\n\t\t\t},\n\t\t\tmapping: () => element.mapping(),\n\t\t\tvalue: () => element.#value,\n\t\t\twatch: (listener) => {\n\t\t\t\telement.#watchers.add(listener);\n\n\t\t\t\treturn () => {\n\t\t\t\t\telement.#watchers.delete(listener);\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tget default(): number | undefined {\n\t\treturn this.optionalNumberAttribute('default');\n\t}\n\n\tset default(value: number | undefined) {\n\t\tthis.reflect('default', value);\n\t}\n\n\tget detent(): number | undefined {\n\t\treturn this.optionalNumberAttribute('detent');\n\t}\n\n\tset detent(value: number | undefined) {\n\t\tthis.reflect('detent', value);\n\t}\n\n\tget dimmed(): boolean {\n\t\treturn this.hasAttribute('dimmed');\n\t}\n\n\tset dimmed(isDimmed: boolean) {\n\t\tthis.reflect('dimmed', isDimmed);\n\t}\n\n\tget doublePress(): 'entry' | 'reset' {\n\t\treturn this.getAttribute('double-press') === 'reset' ? 'reset' : 'entry';\n\t}\n\n\tset doublePress(gesture: 'entry' | 'reset' | undefined) {\n\t\tthis.reflect('double-press', gesture);\n\t}\n\n\tget formatSpokenValue(): ((value: number) => string) | undefined {\n\t\treturn this.#formatSpokenValue;\n\t}\n\n\tset formatSpokenValue(format: ((value: number) => string) | undefined) {\n\t\tthis.#formatSpokenValue = format;\n\t\tthis.render();\n\t}\n\n\tget formatValue(): ((value: number) => string) | undefined {\n\t\treturn this.#formatValue;\n\t}\n\n\tset formatValue(format: ((value: number) => string) | undefined) {\n\t\tthis.#formatValue = format;\n\t\tthis.render();\n\t}\n\n\tget keyStep(): number | undefined {\n\t\treturn this.optionalNumberAttribute('key-step');\n\t}\n\n\tset keyStep(value: number | undefined) {\n\t\tthis.reflect('key-step', value);\n\t}\n\n\tget max(): number {\n\t\treturn this.numberAttribute('max', 100);\n\t}\n\n\tset max(value: number | undefined) {\n\t\tthis.reflect('max', value);\n\t}\n\n\tget midpoint(): number | undefined {\n\t\treturn this.optionalNumberAttribute('midpoint');\n\t}\n\n\tset midpoint(value: number | undefined) {\n\t\tthis.reflect('midpoint', value);\n\t}\n\n\tget min(): number {\n\t\treturn this.numberAttribute('min', 0);\n\t}\n\n\tset min(value: number | undefined) {\n\t\tthis.reflect('min', value);\n\t}\n\n\tget notched(): boolean {\n\t\treturn this.hasAttribute('notched');\n\t}\n\n\tset notched(isNotched: boolean) {\n\t\tthis.reflect('notched', isNotched);\n\t}\n\n\tget origin(): number | undefined {\n\t\treturn this.optionalNumberAttribute('origin');\n\t}\n\n\tset origin(value: number | undefined) {\n\t\tthis.reflect('origin', value);\n\t}\n\n\tget parseValue(): ((text: string) => number) | undefined {\n\t\treturn this.#parseValue;\n\t}\n\n\tset parseValue(parse: ((text: string) => number) | undefined) {\n\t\tthis.#parseValue = parse;\n\t}\n\n\tget positions(): Array<number> | undefined {\n\t\treturn parseNumberList(this.getAttribute('positions'));\n\t}\n\n\tset positions(positions: Array<number> | undefined) {\n\t\tthis.reflect('positions', positions?.join(' '));\n\t}\n\n\tget readout(): boolean {\n\t\treturn this.hasAttribute('readout');\n\t}\n\n\tset readout(isShown: boolean) {\n\t\tthis.reflect('readout', isShown);\n\t}\n\n\tget step(): number {\n\t\treturn this.numberAttribute('step', 1);\n\t}\n\n\tset step(value: number | undefined) {\n\t\tthis.reflect('step', value);\n\t}\n\n\tget taper(): 'linear' | 'log' {\n\t\treturn this.getAttribute('taper') === 'log' ? 'log' : 'linear';\n\t}\n\n\tset taper(curve: 'linear' | 'log' | undefined) {\n\t\tthis.reflect('taper', curve);\n\t}\n\n\tget value(): number {\n\t\treturn this.#value;\n\t}\n\n\tset value(next: null | number | undefined) {\n\t\t// A framework removes a prop by setting the property to `undefined`\n\t\tif (next === undefined || next === null) {\n\t\t\tthis.formResetCallback();\n\t\t\treturn;\n\t\t}\n\n\t\tconst value = toNumber(next);\n\n\t\tif (this.#isHeld()) {\n\t\t\tthis.heldWrite(value);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#write(value);\n\t\tif (Number.isFinite(value)) this.#asked = value;\n\t}\n\n\tget valueText(): string {\n\t\treturn this.#textFor(this.#value);\n\t}\n\n\t#asked: number | undefined;\n\n\treadonly #claim = new ReadoutClaim(() => {\n\t\tthis.#renderHold();\n\t});\n\n\t#entry: undefined | ValueEntry;\n\n\t#formatSpokenValue: ((value: number) => string) | undefined;\n\n\t#formatValue: ((value: number) => string) | undefined;\n\n\treadonly #instance = String((instanceCount += 1));\n\n\t#isModulated = false;\n\n\t#keyScrub: KeyScrub | undefined;\n\n\t#land: undefined | ValueLanding;\n\n\t#limit: [number, number] | undefined;\n\n\t// Every attribute it reads is observed; a subclass adding an input to `isWrapping()` has to observe it\n\t#mapping: undefined | ValueMapping;\n\n\t#modulationValue: number | undefined;\n\n\t#parseValue: ((text: string) => number) | undefined;\n\n\t#pointerDrag: PointerDrag<ValueDrag> | undefined;\n\n\t#positions: Array<number> | undefined;\n\n\t#readout: undefined | { anchor: HTMLElement; bubble: Readout };\n\n\t#value = 0;\n\n\treadonly #watchers = new Set<() => void>();\n\n\tattributeChangedCallback(name: string): void {\n\t\tthis.#mapping = undefined;\n\t\tthis.#positions = parseNumberList(this.getAttribute('positions'));\n\t\tif (name === 'value') {\n\t\t\tif (this.#isHeld()) {\n\t\t\t\tthis.heldWrite(this.numberAttribute('value', this.min));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.#asked = undefined;\n\t\t}\n\t\tif (name === 'disabled' && this.isDisabled()) this.#endHolds();\n\n\t\tthis.#value = this.mapping().snap(this.#asked ?? this.numberAttribute('value', this.min));\n\t\tif (proportionAttributes.has(name) && this.isBound()) this.proportionsChanged();\n\t\tthis.render();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(\n\t\t\t'default',\n\t\t\t'dimmed',\n\t\t\t'doublePress',\n\t\t\t'max',\n\t\t\t'midpoint',\n\t\t\t'min',\n\t\t\t'notched',\n\t\t\t'origin',\n\t\t\t'readout',\n\t\t\t'step',\n\t\t\t'taper',\n\t\t\t'positions',\n\t\t\t'detent',\n\t\t\t'formatValue',\n\t\t\t'formatSpokenValue',\n\t\t\t'keyStep',\n\t\t\t'parseValue',\n\t\t\t'value',\n\t\t);\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected bindGestures(\n\t\tcontrol: HTMLElement,\n\t\tsignal: AbortSignal,\n\t\tgrab: (event: PointerEvent) => undefined | ValueAxis,\n\t): void {\n\t\tconst entry = this.#bindEntry(control, signal);\n\n\t\tthis.#pointerDrag = bindDrag<ValueDrag>(\n\t\t\tcontrol,\n\t\t\t{\n\t\t\t\tcancel: (drag) => {\n\t\t\t\t\tif (drag.isKeptOnCancel !== true) this.input(drag.fromValue);\n\t\t\t\t},\n\t\t\t\tgrab: (event) => {\n\t\t\t\t\tif (isMenuPress(event) || this.isDisabled() || entry.isOpen) return;\n\n\t\t\t\t\tthis.toggleState('springing', false);\n\t\t\t\t\t// A click listener above makes WebKit send a tap's compatibility mousedown, which blurs the entry a double tap just opened\n\t\t\t\t\tif (event.pointerType === 'touch') event.preventDefault();\n\t\t\t\t\tfocusByPointer(control);\n\t\t\t\t\tif (isResetPress(event)) {\n\t\t\t\t\t\tthis.#reset();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromValue = this.#value;\n\t\t\t\t\tconst axis = grab(event);\n\t\t\t\t\tif (!axis) return;\n\n\t\t\t\t\tconst drag: ValueDrag = {\n\t\t\t\t\t\t...axis,\n\t\t\t\t\t\tfromValue,\n\t\t\t\t\t\tisOutside: false,\n\t\t\t\t\t\tisRevealed: false,\n\t\t\t\t\t\trevealTimer: undefined,\n\t\t\t\t\t\tstate: this.#startDrag(control, axis, event),\n\t\t\t\t\t};\n\n\t\t\t\t\tdrag.revealTimer = setTimeout(() => {\n\t\t\t\t\t\tthis.#reveal(drag);\n\t\t\t\t\t}, revealMs);\n\n\t\t\t\t\treturn drag;\n\t\t\t\t},\n\t\t\t\tlift: (drag, event) => {\n\t\t\t\t\tconst tap = drag.state.isEngaged ? undefined : this.tapTarget();\n\n\t\t\t\t\tif (tap !== undefined) {\n\t\t\t\t\t\tentry.forgetPress();\n\t\t\t\t\t\tthis.#commit(tap);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!entry.press(event) || this.springTarget() !== undefined) return;\n\n\t\t\t\t\tif (this.doublePress === 'reset') this.#reset();\n\t\t\t\t\telse entry.open();\n\t\t\t\t},\n\t\t\t\tmove: (drag, event) => {\n\t\t\t\t\tthis.#dragTo(drag, event);\n\t\t\t\t},\n\t\t\t\trelease: (drag) => {\n\t\t\t\t\tthis.#releaseDrag(drag);\n\t\t\t\t},\n\t\t\t\ttoggle: (isDragging) => {\n\t\t\t\t\tthis.toggleState('dragging', isDragging);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'pointercancel',\n\t\t\t() => {\n\t\t\t\tentry.forgetPress();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#bindKeys(control, entry, signal);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#endKeyScrub();\n\t\t\t\tthis.#concealKeyReveal();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\tprotected controlOrientation(): 'horizontal' | 'vertical' | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected controlRole(): 'slider' | 'spinbutton' {\n\t\treturn 'slider';\n\t}\n\n\tprotected abstract draw(): void;\n\n\tprotected abstract override focusTarget(): HTMLElement;\n\n\tprotected heldFrom(): number | undefined {\n\t\treturn this.#dragging()?.fromValue ?? this.#keyScrub?.fromValue;\n\t}\n\n\tprotected heldWrite(_next: number): void {\n\t\t// Dropped unless a subclass draws where playback carries on\n\t}\n\n\tprotected holdChanged(): void {\n\t\t// Only a subclass draws a hold\n\t}\n\n\tprotected input(next: number): boolean {\n\t\tconst previous = this.#value;\n\n\t\tthis.#write(this.#limit ? clamp(next, ...this.#limit) : next);\n\t\tif (this.#value === previous) return false;\n\n\t\tthis.dispatchEvent(new Event('input', { bubbles: true, composed: true }));\n\n\t\treturn true;\n\t}\n\n\tprotected isEditing(): boolean {\n\t\treturn this.#entry?.isOpen === true;\n\t}\n\n\tprotected isRevealed(): boolean {\n\t\treturn this.#claim.isRevealed;\n\t}\n\n\tprotected isWrapping(): boolean {\n\t\treturn false;\n\t}\n\n\tprotected mapping(): ValueMapping {\n\t\tif (this.#mapping) return this.#mapping;\n\n\t\tconst { detent, midpoint } = this;\n\n\t\tthis.#mapping = valueMapping({\n\t\t\t...(detent === undefined ? {} : { detent }),\n\t\t\t...(this.#positions ? { positions: this.#positions } : {}),\n\t\t\tmax: this.max,\n\t\t\t...(midpoint === undefined ? {} : { midpoint }),\n\t\t\tisNotched: this.notched,\n\t\t\tisWrapping: this.isWrapping(),\n\t\t\tmin: this.min,\n\t\t\tstep: this.step,\n\t\t\ttaper: this.taper,\n\t\t});\n\n\t\treturn this.#mapping;\n\t}\n\n\tprotected originValue(): number {\n\t\treturn this.origin ?? this.mapping().bounds[0];\n\t}\n\n\tprotected previewValue(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected proportionsChanged(): void {\n\t\t// Runs when every proportion moves, never per input\n\t}\n\n\tprotected readModulationValue(): number | undefined {\n\t\treturn this.#modulationValue;\n\t}\n\n\tprotected readoutValue(): number {\n\t\treturn this.#shown().value ?? this.#value;\n\t}\n\n\tprotected render(): void {\n\t\tif (this.isBound()) this.#renderControl();\n\t\tfor (const listener of this.#watchers) listener();\n\t}\n\n\tprotected renderReadout(): void {\n\t\tconst readout = this.#readout;\n\t\tif (!readout) return;\n\n\t\tconst { isOpen, value } = this.#shown();\n\n\t\treadout.bubble.show({\n\t\t\tanchor: readout.anchor,\n\t\t\tisOpen,\n\t\t\ttext: value === undefined ? undefined : this.#textFor(value),\n\t\t});\n\t}\n\n\tprotected restoreState(state: string): void {\n\t\tthis.value = Number(state);\n\t}\n\n\tprotected scrubsKeyRepeat(): boolean {\n\t\treturn false;\n\t}\n\n\tprotected springTarget(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected tapTarget(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected travelPx(control: HTMLElement, property: `--_sonic-${string}`): number {\n\t\treturn Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));\n\t}\n\n\tprotected writeModulationValue(\n\t\tcontrol: HTMLElement,\n\t\tprefix: 'dial' | 'slider',\n\t\tnext: null | number | undefined,\n\t): void {\n\t\tconst value = next === undefined || next === null ? undefined : toNumber(next);\n\t\tif (value !== undefined && !Number.isFinite(value)) return;\n\n\t\tthis.#modulationValue = value;\n\t\tif (this.isBound()) this.#writeModulationProportion(control, prefix);\n\t}\n\n\tprotected writeProportions(\n\t\tcontrol: HTMLElement,\n\t\tprefix: 'dial' | 'slider',\n\t\tmodulation: number,\n\t): void {\n\t\tconst { style } = control;\n\t\tconst mapping = this.mapping();\n\t\tconst value = mapping.proportionOf(this.#value);\n\t\tconst reach = mapping.proportionOf(this.#value + modulation);\n\t\tconst { positionCount } = mapping;\n\n\t\tstyle.setProperty(`--_sonic-${prefix}-value`, String(value));\n\t\tstyle.setProperty(\n\t\t\t`--_sonic-${prefix}-origin`,\n\t\t\tString(mapping.proportionOf(this.originValue())),\n\t\t);\n\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(value, reach)));\n\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(value, reach)));\n\t\tif (positionCount === undefined) style.removeProperty(`--_sonic-${prefix}-position-count`);\n\t\telse style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));\n\t\tthis.#writeModulationProportion(control, prefix);\n\t}\n\n\t#bindEntry(control: HTMLElement, signal: AbortSignal): ValueEntry {\n\t\tconst input = requireChild(control, 'input', HTMLInputElement);\n\t\tconst bubble = control.querySelector<HTMLElement>('[popover]');\n\n\t\t// Chrome's issues panel flags a form field with no id or name; a `name` would submit it\n\t\tinput.id = `sonic-entry-${this.#instance}`;\n\t\tif (bubble) this.#readout = { anchor: control, bubble: new Readout(bubble) };\n\n\t\tconst entry = new ValueEntry(input, {\n\t\t\tcommit: (text) => {\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-number-coercion -- `Number('')` is 0; an emptied field should leave the value alone\n\t\t\t\tthis.#commit((this.#parseValue ?? Number.parseFloat)(text));\n\t\t\t},\n\t\t\t// `Number.parseFloat` reads \"5 kHz\" as 5\n\t\t\ttext: () => (this.#parseValue ? this.valueText : String(this.#value)),\n\t\t\ttoggle: (isOpen) => {\n\t\t\t\tif (isOpen) this.forwardNaming(input, true);\n\t\t\t\tthis.toggleState('editing', isOpen);\n\t\t\t\tthis.render();\n\t\t\t},\n\t\t});\n\n\t\tthis.#entry = entry;\n\t\tentry.bind(control, signal);\n\n\t\treturn entry;\n\t}\n\n\t#bindKeys(control: HTMLElement, entry: ValueEntry, signal: AbortSignal): void {\n\t\tcontrol.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (this.isDisabled() || event.defaultPrevented || event.target !== control) return;\n\n\t\t\t\tthis.toggleState('springing', false);\n\t\t\t\tif (event.key === 'Enter') {\n\t\t\t\t\tif (this.springTarget() !== undefined) return;\n\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tentry.open();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst next = this.#keyTarget(event.key);\n\t\t\t\tif (next === undefined) return;\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.#keyTo(event, next);\n\t\t\t\tthis.#claim.reveal('keys');\n\t\t\t\tthis.#renderHold();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'keyup',\n\t\t\t(event) => {\n\t\t\t\t// macOS sends no `keyup` for a key let go while Cmd is down\n\t\t\t\tconst isMeta = event.key === 'Meta';\n\n\t\t\t\tif (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();\n\t\t\t\tif (isMeta && this.#dragging()) return;\n\t\t\t\tif (isMeta || this.mapping().keyTarget(event.key, this.#value) !== undefined) {\n\t\t\t\t\tthis.#springBack();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'blur',\n\t\t\t() => {\n\t\t\t\tthis.#endKeyScrub();\n\t\t\t\tthis.#concealKeyReveal();\n\t\t\t\tthis.#springBack();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\n\t#commit(next: number, direction: -1 | 0 | 1 = 0): void {\n\t\tconst landed = Number.isFinite(next) ? (this.#land?.(next, direction) ?? next) : next;\n\n\t\tif (this.input(landed)) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#concealKeyReveal(): void {\n\t\tif (this.#claim.conceal('keys')) this.#renderHold();\n\t}\n\n\t#dragging(): undefined | ValueDrag {\n\t\treturn this.#pointerDrag?.current();\n\t}\n\n\t#dragTo(drag: ValueDrag, event: PointerEvent): void {\n\t\tconst isOutside = drag.outside?.(event) === true;\n\t\tconst wasEngaged = drag.state.isEngaged;\n\t\tconst mapping = this.mapping();\n\t\tconst { state, value } = stepDrag(mapping, drag.state, {\n\t\t\tisFine: event.shiftKey,\n\t\t\tisOutside,\n\t\t\tposition: drag.position(event),\n\t\t});\n\n\t\tdrag.state = this.#withinLimit(mapping, state);\n\t\tif (value === undefined) return;\n\n\t\tif (!wasEngaged) this.#reveal(drag);\n\t\tthis.input(isOutside ? drag.fromValue : value);\n\t\tif (isOutside === drag.isOutside) return;\n\n\t\tdrag.isOutside = isOutside;\n\t\tthis.#renderDragReveal(drag);\n\t}\n\n\t#endHolds(): void {\n\t\tthis.#entry?.close(false);\n\t\tthis.#pointerDrag?.end();\n\t\tthis.#endKeyScrub();\n\t}\n\n\t#endKeyScrub(): void {\n\t\tconst scrub = this.#keyScrub;\n\t\tif (!scrub) return;\n\n\t\tthis.#keyScrub = undefined;\n\t\tthis.#renderHold();\n\t\tif (this.#value !== scrub.fromValue) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#isHeld(): boolean {\n\t\treturn this.#dragging() !== undefined || this.#keyScrub !== undefined;\n\t}\n\n\t#keyTarget(key: string): number | undefined {\n\t\tif (resetKeys.has(key)) return this.default;\n\n\t\treturn this.mapping().keyTarget(key, this.#value, this.keyStep);\n\t}\n\n\t#keyTo(event: KeyboardEvent, next: number): void {\n\t\tif (event.repeat && this.scrubsKeyRepeat()) {\n\t\t\tthis.#scrubKey(event.key, next);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#endKeyScrub();\n\t\tthis.#commit(next, next > this.#value ? 1 : -1);\n\t}\n\n\t#releaseDrag(drag: ValueDrag): void {\n\t\tclearTimeout(drag.revealTimer);\n\t\tthis.#claim.conceal('drag');\n\t\tthis.#renderHold();\n\t\tif (this.#value !== drag.fromValue) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t\tthis.#springBack();\n\t}\n\n\t#renderAria(control: HTMLElement, orientation?: 'horizontal' | 'vertical'): void {\n\t\tthis.writeFormValue(String(this.#value), String(this.#value));\n\t\tif (this.#entry?.isOpen) {\n\t\t\tfor (const name of roleAttributes) control.removeAttribute(name);\n\t\t\tthis.forwardNaming(control, false);\n\t\t\tthis.renderReadout();\n\t\t\treturn;\n\t\t}\n\n\t\tconst [low, high] = this.mapping().bounds;\n\n\t\twriteAttribute(control, 'role', this.controlRole());\n\t\twriteAttribute(control, 'aria-valuemin', String(low));\n\t\twriteAttribute(control, 'aria-valuemax', String(high));\n\t\twriteAttribute(control, 'aria-valuenow', String(this.#value));\n\t\tif (orientation) writeAttribute(control, 'aria-orientation', orientation);\n\t\twriteAttribute(\n\t\t\tcontrol,\n\t\t\t'aria-valuetext',\n\t\t\t(this.#formatSpokenValue ?? this.#formatValue)?.(this.#value),\n\t\t);\n\t\tthis.forwardNaming(control, true);\n\t\tthis.#renderDisabled(control);\n\t\tthis.renderReadout();\n\t}\n\n\t#renderControl(): void {\n\t\tthis.draw();\n\t\tthis.toggleState(\n\t\t\t'at-origin',\n\t\t\t!this.isWrapping() && this.#value === this.mapping().snap(this.originValue()),\n\t\t);\n\t\tthis.#renderAria(this.focusTarget(), this.controlOrientation());\n\t}\n\n\t#renderDisabled(control: HTMLElement): void {\n\t\tconst isDisabled = this.isDisabled();\n\n\t\twriteAttribute(control, 'aria-disabled', isDisabled ? 'true' : undefined);\n\t\t// The host is `display: contents`, so its tab stop is the control's\n\t\tconst stop = this.getAttribute('tabindex') === '-1' ? '-1' : '0';\n\n\t\twriteAttribute(control, 'tabindex', isDisabled ? undefined : stop);\n\t}\n\n\t#renderDragReveal(drag: ValueDrag): void {\n\t\tif (drag.isRevealed && !drag.isOutside) this.#claim.reveal('drag');\n\t\telse this.#claim.conceal('drag');\n\t\tthis.#renderHold();\n\t}\n\n\t#renderHold(): void {\n\t\tthis.renderReadout();\n\t\tthis.holdChanged();\n\t}\n\n\t#reset(): void {\n\t\tthis.#commit(this.default ?? NaN);\n\t}\n\n\t#reveal(drag: ValueDrag): void {\n\t\tif (drag.isRevealed || this.#dragging() !== drag) return;\n\n\t\tdrag.isRevealed = true;\n\t\tthis.#renderDragReveal(drag);\n\t}\n\n\t#scrubKey(key: string, next: number): void {\n\t\tif (this.#keyScrub?.key !== key) {\n\t\t\tthis.#endKeyScrub();\n\t\t\tthis.#keyScrub = { fromValue: this.#value, key };\n\t\t}\n\t\tthis.input(next);\n\t}\n\n\t#shown(): { isOpen: boolean; value: number | undefined } {\n\t\tif (this.isEditing()) return { isOpen: true, value: undefined };\n\n\t\tconst isRevealed = this.#claim.isRevealed;\n\t\tconst preview = isRevealed ? undefined : this.previewValue();\n\n\t\treturn {\n\t\t\tisOpen: (isRevealed || preview !== undefined) && this.readout,\n\t\t\tvalue: preview ?? this.#value,\n\t\t};\n\t}\n\n\t#springBack(): void {\n\t\tconst target = this.springTarget();\n\t\tif (target === undefined) return;\n\n\t\t// Set before the commit so a `change` listener reading styles sees the glide\n\t\tif (this.mapping().snap(target) !== this.#value) this.toggleState('springing', true);\n\t\tthis.#commit(target);\n\t}\n\n\t#startDrag(control: HTMLElement, axis: ValueAxis, event: PointerEvent): DragState {\n\t\tconst mapping = this.mapping();\n\t\tconst detent = this.detent;\n\t\tconst start = {\n\t\t\tfrom: this.#value,\n\t\t\tposition: axis.position(event),\n\t\t\tproportion: axis.fromProportion ?? mapping.proportionOf(this.#value),\n\t\t\tthresholdPx: dragThresholdPx(event.pointerType),\n\t\t\ttravelPx: axis.travelPx,\n\t\t};\n\t\tif (detent === undefined) return startDrag(mapping, start);\n\n\t\tconst zonePx = readPxProperty(getComputedStyle(control), '--_sonic-detent-zone', detentZonePx);\n\n\t\treturn startDrag(mapping, {\n\t\t\t...start,\n\t\t\tdetent: { value: detent, zone: zonePx / axis.travelPx },\n\t\t});\n\t}\n\n\t#textFor(value: number): string {\n\t\treturn this.#formatValue?.(value) ?? String(value);\n\t}\n\n\t#withinLimit(mapping: ValueMapping, state: DragState): DragState {\n\t\tconst limit = this.#limit;\n\t\tif (!limit || mapping.isWrapping) return state;\n\n\t\tconst [low, high] = limit;\n\n\t\treturn {\n\t\t\t...state,\n\t\t\trawProportion: clamp(\n\t\t\t\tstate.rawProportion,\n\t\t\t\tmapping.proportionOf(low),\n\t\t\t\tmapping.proportionOf(high),\n\t\t\t),\n\t\t};\n\t}\n\n\t#write(next: number): void {\n\t\tif (!Number.isFinite(next)) return;\n\n\t\tconst clamped = this.mapping().snap(next);\n\n\t\tthis.#asked = clamped;\n\t\tif (clamped === this.#value) return;\n\n\t\tthis.#value = clamped;\n\t\tthis.render();\n\t}\n\n\t#writeModulationProportion(control: HTMLElement, prefix: 'dial' | 'slider'): void {\n\t\tconst modulationValue = this.isWrapping() ? undefined : this.#modulationValue;\n\t\tconst isModulated = modulationValue !== undefined;\n\n\t\tif (isModulated !== this.#isModulated) {\n\t\t\tthis.#isModulated = isModulated;\n\t\t\tthis.toggleState('modulated', isModulated);\n\t\t}\n\t\tif (modulationValue === undefined) {\n\t\t\tcontrol.style.removeProperty(`--_sonic-${prefix}-modulation-value`);\n\t\t\treturn;\n\t\t}\n\n\t\tcontrol.style.setProperty(\n\t\t\t`--_sonic-${prefix}-modulation-value`,\n\t\t\tString(this.mapping().proportionOf(modulationValue)),\n\t\t);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"value-element.js","names":[],"sources":["../../../src/elements/value-element.ts"],"sourcesContent":["import type { DragState } from '#lib/drag-step.ts';\nimport type { PointerDrag } from '#lib/pointer-drag.ts';\nimport type { ValueMapping } from '#lib/value-mapping.ts';\n\nimport { SonicFormElement } from '#elements/form-element.ts';\nimport { ReadoutClaim, revealMs } from '#elements/readout-claim.ts';\nimport { Readout } from '#elements/readout.ts';\nimport { ValueEntry } from '#elements/value-entry.ts';\nimport { dragThresholdPx, startDrag, stepDrag } from '#lib/drag-step.ts';\nimport { focusByPointer } from '#lib/focus-by-pointer.ts';\nimport { clamp, toNumber, trimFloat } from '#lib/math.ts';\nimport { isMenuPress, isResetPress } from '#lib/modifier-press.ts';\nimport { parseNumberList } from '#lib/number-list.ts';\nimport { bindDrag } from '#lib/pointer-drag.ts';\nimport { readPxProperty } from '#lib/read-px-property.ts';\nimport { requireChild } from '#lib/render.ts';\nimport { resetKeys, valueMapping } from '#lib/value-mapping.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\nexport interface ValueAxis {\n\tfromProportion?: number;\n\tisKeptOnCancel?: boolean;\n\toutside?: (event: PointerEvent) => boolean;\n\tposition: (event: PointerEvent) => number;\n\ttravelPx: number;\n}\n\ninterface ValueDrag extends ValueAxis {\n\tfromValue: number;\n\tisOutside: boolean;\n\tisRevealed: boolean;\n\tpointerType: string;\n\trevealTimer: ReturnType<typeof setTimeout> | undefined;\n\tstate: DragState;\n}\n\ninterface KeyScrub {\n\tfromValue: number;\n\tkey: string;\n}\n\nconst detentZonePx = 8;\nconst fallbackTravelPx = 160;\n\nlet instanceCount = 0;\n\nconst proportionAttributes = new Set(['max', 'midpoint', 'min', 'notched', 'positions', 'taper']);\n\nconst roleAttributes = [\n\t'aria-disabled',\n\t'aria-orientation',\n\t'aria-valuemax',\n\t'aria-valuemin',\n\t'aria-valuenow',\n\t'aria-valuetext',\n\t'role',\n\t'tabindex',\n];\n\ntype ValueLanding = (target: number, direction: -1 | 0 | 1) => number;\n\nexport interface ValueLink {\n\tinput: (next: number, isMover?: boolean) => boolean;\n\tisDisabled: () => boolean;\n\tisHeld: () => boolean;\n\tland: (resolve: undefined | ValueLanding) => void;\n\tlimit: (bounds: [number, number] | undefined) => void;\n\tmapping: () => ValueMapping;\n\tvalue: () => number;\n\twatch: (listener: () => void) => () => void;\n}\n\n// Filled from inside the class, so it reaches protected members and nothing lands on the element's public type\nlet link: (element: SonicValueElement) => ValueLink;\n\nexport function linkValue(element: SonicValueElement): ValueLink {\n\treturn link(element);\n}\n\nexport abstract class SonicValueElement extends SonicFormElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicFormElement.observedAttributes,\n\t\t'detent',\n\t\t'max',\n\t\t'midpoint',\n\t\t'min',\n\t\t'notched',\n\t\t'origin',\n\t\t'readout',\n\t\t'spoken-step',\n\t\t'step',\n\t\t'tabindex',\n\t\t'taper',\n\t\t'value',\n\t\t'positions',\n\t];\n\n\tstatic {\n\t\tlink = (element) => ({\n\t\t\tinput: (next, isMover = false) => (isMover || !element.#isHeld()) && element.input(next),\n\t\t\tisDisabled: () => element.isDisabled(),\n\t\t\tisHeld: () => element.#isHeld(),\n\t\t\tland: (resolve) => {\n\t\t\t\telement.#land = resolve;\n\t\t\t},\n\t\t\tlimit: (bounds) => {\n\t\t\t\telement.#limit = bounds;\n\t\t\t},\n\t\t\tmapping: () => element.mapping(),\n\t\t\tvalue: () => element.#value,\n\t\t\twatch: (listener) => {\n\t\t\t\telement.#watchers.add(listener);\n\n\t\t\t\treturn () => {\n\t\t\t\t\telement.#watchers.delete(listener);\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tget default(): number | undefined {\n\t\treturn this.optionalNumberAttribute('default');\n\t}\n\n\tset default(value: number | undefined) {\n\t\tthis.reflect('default', value);\n\t}\n\n\tget detent(): number | undefined {\n\t\treturn this.optionalNumberAttribute('detent');\n\t}\n\n\tset detent(value: number | undefined) {\n\t\tthis.reflect('detent', value);\n\t}\n\n\tget dimmed(): boolean {\n\t\treturn this.hasAttribute('dimmed');\n\t}\n\n\tset dimmed(isDimmed: boolean) {\n\t\tthis.reflect('dimmed', isDimmed);\n\t}\n\n\tget doublePress(): 'entry' | 'reset' {\n\t\treturn this.getAttribute('double-press') === 'reset' ? 'reset' : 'entry';\n\t}\n\n\tset doublePress(gesture: 'entry' | 'reset' | undefined) {\n\t\tthis.reflect('double-press', gesture);\n\t}\n\n\tget formatSpokenValue(): ((value: number) => string) | undefined {\n\t\treturn this.#formatSpokenValue;\n\t}\n\n\tset formatSpokenValue(format: ((value: number) => string) | undefined) {\n\t\tthis.#formatSpokenValue = format;\n\t\tthis.render();\n\t}\n\n\tget formatValue(): ((value: number) => string) | undefined {\n\t\treturn this.#formatValue;\n\t}\n\n\tset formatValue(format: ((value: number) => string) | undefined) {\n\t\tthis.#formatValue = format;\n\t\tthis.render();\n\t}\n\n\tget keyStep(): number | undefined {\n\t\treturn this.optionalNumberAttribute('key-step');\n\t}\n\n\tset keyStep(value: number | undefined) {\n\t\tthis.reflect('key-step', value);\n\t}\n\n\tget max(): number {\n\t\treturn this.numberAttribute('max', 100);\n\t}\n\n\tset max(value: number | undefined) {\n\t\tthis.reflect('max', value);\n\t}\n\n\tget midpoint(): number | undefined {\n\t\treturn this.optionalNumberAttribute('midpoint');\n\t}\n\n\tset midpoint(value: number | undefined) {\n\t\tthis.reflect('midpoint', value);\n\t}\n\n\tget min(): number {\n\t\treturn this.numberAttribute('min', 0);\n\t}\n\n\tset min(value: number | undefined) {\n\t\tthis.reflect('min', value);\n\t}\n\n\tget notched(): boolean {\n\t\treturn this.hasAttribute('notched');\n\t}\n\n\tset notched(isNotched: boolean) {\n\t\tthis.reflect('notched', isNotched);\n\t}\n\n\tget origin(): number | undefined {\n\t\treturn this.optionalNumberAttribute('origin');\n\t}\n\n\tset origin(value: number | undefined) {\n\t\tthis.reflect('origin', value);\n\t}\n\n\tget parseValue(): ((text: string) => number) | undefined {\n\t\treturn this.#parseValue;\n\t}\n\n\tset parseValue(parse: ((text: string) => number) | undefined) {\n\t\tthis.#parseValue = parse;\n\t}\n\n\tget pointerType(): string | undefined {\n\t\treturn this.#dragging()?.pointerType;\n\t}\n\n\tget positions(): Array<number> | undefined {\n\t\treturn parseNumberList(this.getAttribute('positions'));\n\t}\n\n\tset positions(positions: Array<number> | undefined) {\n\t\tthis.reflect('positions', positions?.join(' '));\n\t}\n\n\tget readout(): boolean {\n\t\treturn this.hasAttribute('readout');\n\t}\n\n\tset readout(isShown: boolean) {\n\t\tthis.reflect('readout', isShown);\n\t}\n\n\tget spokenStep(): number | undefined {\n\t\treturn this.optionalNumberAttribute('spoken-step');\n\t}\n\n\tset spokenStep(value: number | undefined) {\n\t\tthis.reflect('spoken-step', value);\n\t}\n\n\tget step(): number {\n\t\treturn this.numberAttribute('step', 1);\n\t}\n\n\tset step(value: number | undefined) {\n\t\tthis.reflect('step', value);\n\t}\n\n\tget taper(): 'linear' | 'log' {\n\t\treturn this.getAttribute('taper') === 'log' ? 'log' : 'linear';\n\t}\n\n\tset taper(curve: 'linear' | 'log' | undefined) {\n\t\tthis.reflect('taper', curve);\n\t}\n\n\tget value(): number {\n\t\treturn this.#value;\n\t}\n\n\tset value(next: null | number | undefined) {\n\t\t// A framework removes a prop by setting the property to `undefined`\n\t\tif (next === undefined || next === null) {\n\t\t\tthis.formResetCallback();\n\t\t\treturn;\n\t\t}\n\n\t\tconst value = toNumber(next);\n\n\t\tif (this.#isHeld()) {\n\t\t\tthis.heldWrite(value);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#write(value);\n\t\tif (Number.isFinite(value)) this.#asked = value;\n\t}\n\n\tget valueText(): string {\n\t\treturn this.#textFor(this.#value);\n\t}\n\n\t#asked: number | undefined;\n\n\treadonly #claim = new ReadoutClaim(() => {\n\t\tthis.#renderHold();\n\t});\n\n\t#entry: undefined | ValueEntry;\n\n\t#formatSpokenValue: ((value: number) => string) | undefined;\n\n\t#formatValue: ((value: number) => string) | undefined;\n\n\t#heldAt: number | undefined;\n\n\treadonly #instance = String((instanceCount += 1));\n\n\t#isModulated = false;\n\n\t#isRevealed = false;\n\n\t#keyScrub: KeyScrub | undefined;\n\n\t#land: undefined | ValueLanding;\n\n\t#limit: [number, number] | undefined;\n\n\t// Every attribute it reads is observed; a subclass adding an input to `isWrapping()` has to observe it\n\t#mapping: undefined | ValueMapping;\n\n\t#modulationValue: number | undefined;\n\n\t#parseValue: ((text: string) => number) | undefined;\n\n\t#pointerDrag: PointerDrag<ValueDrag> | undefined;\n\n\t#positions: Array<number> | undefined;\n\n\t#readout: undefined | { anchor: HTMLElement; bubble: Readout };\n\n\t#value = 0;\n\n\treadonly #watchers = new Set<() => void>();\n\n\tattributeChangedCallback(name: string): void {\n\t\tthis.#mapping = undefined;\n\t\tthis.#positions = parseNumberList(this.getAttribute('positions'));\n\t\tif (name === 'value') {\n\t\t\tif (this.#isHeld()) {\n\t\t\t\tthis.heldWrite(this.numberAttribute('value', this.min));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.#asked = undefined;\n\t\t}\n\t\tif (name === 'disabled' && this.isDisabled()) this.#endHolds();\n\n\t\tthis.#value = this.mapping().snap(this.#asked ?? this.numberAttribute('value', this.min));\n\t\tif (proportionAttributes.has(name) && this.isBound()) this.proportionsChanged();\n\t\tthis.render();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(\n\t\t\t'default',\n\t\t\t'dimmed',\n\t\t\t'doublePress',\n\t\t\t'max',\n\t\t\t'midpoint',\n\t\t\t'min',\n\t\t\t'notched',\n\t\t\t'origin',\n\t\t\t'readout',\n\t\t\t'spokenStep',\n\t\t\t'step',\n\t\t\t'taper',\n\t\t\t'positions',\n\t\t\t'detent',\n\t\t\t'formatValue',\n\t\t\t'formatSpokenValue',\n\t\t\t'keyStep',\n\t\t\t'parseValue',\n\t\t\t'value',\n\t\t);\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected bindGestures(\n\t\tcontrol: HTMLElement,\n\t\tsignal: AbortSignal,\n\t\tgrab: (event: PointerEvent) => undefined | ValueAxis,\n\t): void {\n\t\tconst entry = this.#bindEntry(control, signal);\n\n\t\tthis.#pointerDrag = bindDrag<ValueDrag>(\n\t\t\tcontrol,\n\t\t\t{\n\t\t\t\tcancel: (drag) => {\n\t\t\t\t\tif (drag.isKeptOnCancel !== true) this.input(drag.fromValue);\n\t\t\t\t},\n\t\t\t\tgrab: (event) => {\n\t\t\t\t\tif (isMenuPress(event) || this.isDisabled() || entry.isOpen) return;\n\n\t\t\t\t\tthis.toggleState('springing', false);\n\t\t\t\t\t// A click listener above makes WebKit send a tap's compatibility mousedown, which blurs the entry a double tap just opened\n\t\t\t\t\tif (event.pointerType === 'touch') event.preventDefault();\n\t\t\t\t\tfocusByPointer(control);\n\t\t\t\t\tif (isResetPress(event)) {\n\t\t\t\t\t\tthis.#reset();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromValue = this.#value;\n\t\t\t\t\tconst axis = grab(event);\n\t\t\t\t\tif (!axis) return;\n\n\t\t\t\t\tconst drag: ValueDrag = {\n\t\t\t\t\t\t...axis,\n\t\t\t\t\t\tfromValue,\n\t\t\t\t\t\tisOutside: false,\n\t\t\t\t\t\tisRevealed: false,\n\t\t\t\t\t\tpointerType: event.pointerType,\n\t\t\t\t\t\trevealTimer: undefined,\n\t\t\t\t\t\tstate: this.#startDrag(control, axis, event),\n\t\t\t\t\t};\n\n\t\t\t\t\tdrag.revealTimer = setTimeout(() => {\n\t\t\t\t\t\tthis.#reveal(drag);\n\t\t\t\t\t}, revealMs);\n\n\t\t\t\t\treturn drag;\n\t\t\t\t},\n\t\t\t\tlift: (drag, event) => {\n\t\t\t\t\tconst tap = drag.state.isEngaged ? undefined : this.tapTarget();\n\n\t\t\t\t\tif (tap !== undefined) {\n\t\t\t\t\t\tentry.forgetPress();\n\t\t\t\t\t\tthis.#commit(tap);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!entry.press(event) || this.springTarget() !== undefined) return;\n\n\t\t\t\t\tif (this.doublePress === 'reset') this.#reset();\n\t\t\t\t\telse entry.open();\n\t\t\t\t},\n\t\t\t\tmove: (drag, event) => {\n\t\t\t\t\tthis.#dragTo(drag, event);\n\t\t\t\t},\n\t\t\t\trelease: (drag) => {\n\t\t\t\t\tthis.#releaseDrag(drag);\n\t\t\t\t},\n\t\t\t\ttoggle: (isDragging) => {\n\t\t\t\t\tthis.toggleState('dragging', isDragging);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'pointercancel',\n\t\t\t() => {\n\t\t\t\tentry.forgetPress();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#bindKeys(control, entry, signal);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#endKeyScrub();\n\t\t\t\tthis.#concealKeyReveal();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\tprotected controlOrientation(): 'horizontal' | 'vertical' | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected controlRole(): 'slider' | 'spinbutton' {\n\t\treturn 'slider';\n\t}\n\n\tprotected abstract draw(): void;\n\n\tprotected abstract override focusTarget(): HTMLElement;\n\n\tprotected heldFrom(): number | undefined {\n\t\treturn this.#dragging()?.fromValue ?? this.#keyScrub?.fromValue;\n\t}\n\n\tprotected heldWrite(next: number): void {\n\t\tthis.#heldAt = next;\n\t}\n\n\tprotected holdChanged(): void {\n\t\t// Only a subclass draws a hold\n\t}\n\n\tprotected input(next: number): boolean {\n\t\tconst previous = this.#value;\n\n\t\tthis.#write(this.#limit ? clamp(next, ...this.#limit) : next);\n\t\tif (this.#value === previous) return false;\n\n\t\tthis.dispatchEvent(new Event('input', { bubbles: true, composed: true }));\n\n\t\treturn true;\n\t}\n\n\tprotected isEditing(): boolean {\n\t\treturn this.#entry?.isOpen === true;\n\t}\n\n\tprotected isRevealed(): boolean {\n\t\treturn this.#claim.isRevealed;\n\t}\n\n\tprotected isWrapping(): boolean {\n\t\treturn false;\n\t}\n\n\tprotected mapping(): ValueMapping {\n\t\tif (this.#mapping) return this.#mapping;\n\n\t\tconst { detent, midpoint } = this;\n\n\t\tthis.#mapping = valueMapping({\n\t\t\t...(detent === undefined ? {} : { detent }),\n\t\t\t...(this.#positions ? { positions: this.#positions } : {}),\n\t\t\tmax: this.max,\n\t\t\t...(midpoint === undefined ? {} : { midpoint }),\n\t\t\tisNotched: this.notched,\n\t\t\tisWrapping: this.isWrapping(),\n\t\t\tmin: this.min,\n\t\t\tstep: this.step,\n\t\t\ttaper: this.taper,\n\t\t});\n\n\t\treturn this.#mapping;\n\t}\n\n\tprotected originValue(): number {\n\t\treturn this.origin ?? this.mapping().bounds[0];\n\t}\n\n\tprotected playback(): number {\n\t\tconst from = this.heldFrom();\n\n\t\treturn from === undefined ? this.#value : (this.#heldAt ?? from);\n\t}\n\n\tprotected previewValue(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected proportionsChanged(): void {\n\t\t// Runs when every proportion moves, never per input\n\t}\n\n\tprotected readModulationValue(): number | undefined {\n\t\treturn this.#modulationValue;\n\t}\n\n\tprotected readoutValue(): number {\n\t\treturn this.#shown().value ?? this.#value;\n\t}\n\n\tprotected render(): void {\n\t\tif (this.isBound()) this.#renderControl();\n\t\tfor (const listener of this.#watchers) listener();\n\t}\n\n\tprotected renderReadout(): void {\n\t\tconst readout = this.#readout;\n\t\tif (!readout) return;\n\n\t\tconst { isOpen, value } = this.#shown();\n\t\tconst text = value === undefined ? undefined : this.#textFor(value);\n\n\t\treadout.bubble.show({ anchor: readout.anchor, isOpen: isOpen && text !== '', text });\n\t}\n\n\tprotected restoreState(state: string): void {\n\t\tthis.value = Number(state);\n\t}\n\n\tprotected scrubsKeyRepeat(): boolean {\n\t\treturn false;\n\t}\n\n\tprotected springTarget(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected tapTarget(): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tprotected travelPx(control: HTMLElement, property: `--_sonic-${string}`): number {\n\t\treturn Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));\n\t}\n\n\tprotected writeModulationValue(\n\t\tcontrol: HTMLElement,\n\t\tprefix: 'dial' | 'slider',\n\t\tnext: null | number | undefined,\n\t): void {\n\t\tconst value = next === undefined || next === null ? undefined : toNumber(next);\n\t\tif (value !== undefined && !Number.isFinite(value)) return;\n\n\t\tthis.#modulationValue = value;\n\t\tif (this.isBound()) this.#writeModulationProportion(control, prefix);\n\t}\n\n\tprotected writeProportions(\n\t\tcontrol: HTMLElement,\n\t\tprefix: 'dial' | 'slider',\n\t\tmodulation: number,\n\t): void {\n\t\tconst { style } = control;\n\t\tconst mapping = this.mapping();\n\t\tconst value = mapping.proportionOf(this.#value);\n\t\tconst reach = mapping.proportionOf(this.#value + modulation);\n\t\tconst { positionCount } = mapping;\n\n\t\tstyle.setProperty(`--_sonic-${prefix}-value`, String(value));\n\t\tstyle.setProperty(\n\t\t\t`--_sonic-${prefix}-origin`,\n\t\t\tString(mapping.proportionOf(this.originValue())),\n\t\t);\n\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(value, reach)));\n\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(value, reach)));\n\t\tif (positionCount === undefined) style.removeProperty(`--_sonic-${prefix}-position-count`);\n\t\telse style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));\n\t\tthis.#writeModulationProportion(control, prefix);\n\t}\n\n\t#bindEntry(control: HTMLElement, signal: AbortSignal): ValueEntry {\n\t\tconst input = requireChild(control, 'input', HTMLInputElement);\n\t\tconst bubble = control.querySelector<HTMLElement>('[popover]');\n\n\t\t// Chrome's issues panel flags a form field with no id or name; a `name` would submit it\n\t\tinput.id = `sonic-entry-${this.#instance}`;\n\t\tif (bubble) this.#readout = { anchor: control, bubble: new Readout(bubble) };\n\n\t\tconst entry = new ValueEntry(input, {\n\t\t\tcommit: (text) => {\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-number-coercion -- `Number('')` is 0; an emptied field should leave the value alone\n\t\t\t\tthis.#commit((this.#parseValue ?? Number.parseFloat)(text));\n\t\t\t},\n\t\t\t// `Number.parseFloat` reads \"5 kHz\" as 5\n\t\t\ttext: () => (this.#parseValue ? this.valueText : String(this.#value)),\n\t\t\ttoggle: (isOpen) => {\n\t\t\t\tif (isOpen) this.forwardNaming(input, true);\n\t\t\t\tthis.toggleState('editing', isOpen);\n\t\t\t\tthis.render();\n\t\t\t},\n\t\t});\n\n\t\tthis.#entry = entry;\n\t\tentry.bind(control, signal);\n\n\t\treturn entry;\n\t}\n\n\t#bindKeys(control: HTMLElement, entry: ValueEntry, signal: AbortSignal): void {\n\t\tcontrol.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (this.isDisabled() || event.defaultPrevented || event.target !== control) return;\n\n\t\t\t\tthis.toggleState('springing', false);\n\t\t\t\tif (event.key === 'Enter') {\n\t\t\t\t\tif (this.springTarget() !== undefined) return;\n\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tentry.open();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst next = this.#keyTarget(event.key);\n\t\t\t\tif (next === undefined) return;\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.#keyTo(event, next);\n\t\t\t\tthis.#claim.reveal('keys');\n\t\t\t\tthis.#renderHold();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'keyup',\n\t\t\t(event) => {\n\t\t\t\t// macOS sends no `keyup` for a key let go while Cmd is down\n\t\t\t\tconst isMeta = event.key === 'Meta';\n\n\t\t\t\tif (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();\n\t\t\t\tif (isMeta && this.#dragging()) return;\n\t\t\t\tif (isMeta || this.mapping().keyTarget(event.key, this.#value) !== undefined) {\n\t\t\t\t\tthis.#springBack();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'blur',\n\t\t\t() => {\n\t\t\t\tthis.#endKeyScrub();\n\t\t\t\tthis.#concealKeyReveal();\n\t\t\t\tthis.#springBack();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\n\t#commit(next: number, direction: -1 | 0 | 1 = 0): void {\n\t\tconst landed = Number.isFinite(next) ? (this.#land?.(next, direction) ?? next) : next;\n\n\t\tif (this.input(landed)) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#concealKeyReveal(): void {\n\t\tif (this.#claim.conceal('keys')) this.#renderHold();\n\t}\n\n\t#dragging(): undefined | ValueDrag {\n\t\treturn this.#pointerDrag?.current();\n\t}\n\n\t#dragTo(drag: ValueDrag, event: PointerEvent): void {\n\t\tconst isOutside = drag.outside?.(event) === true;\n\t\tconst wasEngaged = drag.state.isEngaged;\n\t\tconst mapping = this.mapping();\n\t\tconst { state, value } = stepDrag(mapping, drag.state, {\n\t\t\tisFine: event.shiftKey,\n\t\t\tisOutside,\n\t\t\tposition: drag.position(event),\n\t\t});\n\n\t\tdrag.state = this.#withinLimit(mapping, state);\n\t\tif (value === undefined) return;\n\n\t\tif (!wasEngaged) this.#reveal(drag);\n\n\t\tconst isCrossing = isOutside !== drag.isOutside;\n\n\t\tif (isCrossing) {\n\t\t\tdrag.isOutside = isOutside;\n\t\t\tthis.toggleState('cancelling', isOutside);\n\t\t}\n\t\tthis.input(isOutside ? drag.fromValue : value);\n\t\tif (isCrossing) this.#renderDragReveal(drag);\n\t}\n\n\t#endHolds(): void {\n\t\tthis.#entry?.close(false);\n\t\tthis.#pointerDrag?.end();\n\t\tthis.#endKeyScrub();\n\t}\n\n\t#endKeyScrub(): void {\n\t\tconst scrub = this.#keyScrub;\n\t\tif (!scrub) return;\n\n\t\tthis.#keyScrub = undefined;\n\t\tthis.#renderHold();\n\t\tif (this.#value !== scrub.fromValue) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#isHeld(): boolean {\n\t\treturn this.#dragging() !== undefined || this.#keyScrub !== undefined;\n\t}\n\n\t#keyTarget(key: string): number | undefined {\n\t\tif (resetKeys.has(key)) return this.default;\n\n\t\treturn this.mapping().keyTarget(key, this.#value, this.keyStep);\n\t}\n\n\t#keyTo(event: KeyboardEvent, next: number): void {\n\t\tif (event.repeat && this.scrubsKeyRepeat()) {\n\t\t\tthis.#scrubKey(event.key, next);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#endKeyScrub();\n\t\tthis.#commit(next, next > this.#value ? 1 : -1);\n\t}\n\n\t#releaseDrag(drag: ValueDrag): void {\n\t\tclearTimeout(drag.revealTimer);\n\t\tthis.#claim.conceal('drag');\n\t\tthis.toggleState('cancelling', false);\n\t\tthis.#renderHold();\n\t\tthis.#showRevealed(false);\n\t\tif (this.#value !== drag.fromValue) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t\tthis.#springBack();\n\t}\n\n\t#renderAria(control: HTMLElement, orientation?: 'horizontal' | 'vertical'): void {\n\t\tthis.writeFormValue(String(this.#value), String(this.#value));\n\t\tif (this.#entry?.isOpen) {\n\t\t\tfor (const name of roleAttributes) control.removeAttribute(name);\n\t\t\tthis.forwardNaming(control, false);\n\t\t\tthis.renderReadout();\n\t\t\treturn;\n\t\t}\n\n\t\tconst [low, high] = this.mapping().bounds;\n\n\t\twriteAttribute(control, 'role', this.controlRole());\n\t\twriteAttribute(control, 'aria-valuemin', String(low));\n\t\twriteAttribute(control, 'aria-valuemax', String(high));\n\t\twriteAttribute(control, 'aria-valuenow', String(this.#spokenNow()));\n\t\tif (orientation) writeAttribute(control, 'aria-orientation', orientation);\n\t\twriteAttribute(\n\t\t\tcontrol,\n\t\t\t'aria-valuetext',\n\t\t\t(this.#formatSpokenValue ?? this.#formatValue)?.(this.#value),\n\t\t);\n\t\tthis.forwardNaming(control, true);\n\t\tthis.#renderDisabled(control);\n\t\tthis.renderReadout();\n\t}\n\n\t#renderControl(): void {\n\t\tthis.draw();\n\t\tthis.toggleState(\n\t\t\t'at-origin',\n\t\t\t!this.isWrapping() && this.#value === this.mapping().snap(this.originValue()),\n\t\t);\n\t\tthis.#renderAria(this.focusTarget(), this.controlOrientation());\n\t}\n\n\t#renderDisabled(control: HTMLElement): void {\n\t\tconst isDisabled = this.isDisabled();\n\n\t\twriteAttribute(control, 'aria-disabled', isDisabled ? 'true' : undefined);\n\t\t// The host is `display: contents`, so its tab stop is the control's\n\t\tconst stop = this.getAttribute('tabindex') === '-1' ? '-1' : '0';\n\n\t\twriteAttribute(control, 'tabindex', isDisabled ? undefined : stop);\n\t}\n\n\t#renderDragReveal(drag: ValueDrag): void {\n\t\tconst isRevealed = drag.isRevealed && !drag.isOutside;\n\n\t\tif (isRevealed) this.#claim.reveal('drag');\n\t\telse this.#claim.conceal('drag');\n\t\tthis.#renderHold();\n\t\tthis.#showRevealed(isRevealed);\n\t}\n\n\t#renderHold(): void {\n\t\tif (this.heldFrom() === undefined) this.#heldAt = undefined;\n\t\tthis.renderReadout();\n\t\tthis.holdChanged();\n\t}\n\n\t#reset(): void {\n\t\tthis.#commit(this.default ?? NaN);\n\t}\n\n\t#reveal(drag: ValueDrag): void {\n\t\tif (drag.isRevealed || this.#dragging() !== drag) return;\n\n\t\tdrag.isRevealed = true;\n\t\tthis.#renderDragReveal(drag);\n\t}\n\n\t#scrubKey(key: string, next: number): void {\n\t\tif (this.#keyScrub?.key !== key) {\n\t\t\tthis.#endKeyScrub();\n\t\t\tthis.#keyScrub = { fromValue: this.#value, key };\n\t\t}\n\t\tthis.input(next);\n\t}\n\n\t#shown(): { isOpen: boolean; value: number | undefined } {\n\t\tif (this.isEditing()) return { isOpen: true, value: undefined };\n\n\t\tconst isRevealed = this.#claim.isRevealed;\n\t\tconst preview = isRevealed ? undefined : this.previewValue();\n\n\t\treturn {\n\t\t\tisOpen: (isRevealed || preview !== undefined) && this.readout,\n\t\t\tvalue: preview ?? this.#value,\n\t\t};\n\t}\n\n\t#showRevealed(isRevealed: boolean): void {\n\t\tif (isRevealed === this.#isRevealed) return;\n\n\t\tthis.#isRevealed = isRevealed;\n\t\tthis.toggleState('revealed', isRevealed);\n\t\tthis.dispatchEvent(new Event('sonic-reveal', { bubbles: true }));\n\t}\n\n\t#spokenNow(): number {\n\t\tconst step = this.spokenStep;\n\n\t\treturn step !== undefined && step > 0\n\t\t\t? trimFloat(Math.round(this.#value / step) * step)\n\t\t\t: this.#value;\n\t}\n\n\t#springBack(): void {\n\t\tconst target = this.springTarget();\n\t\tif (target === undefined) return;\n\n\t\t// Set before the commit so a `change` listener reading styles sees the glide\n\t\tif (this.mapping().snap(target) !== this.#value) this.toggleState('springing', true);\n\t\tthis.#commit(target);\n\t}\n\n\t#startDrag(control: HTMLElement, axis: ValueAxis, event: PointerEvent): DragState {\n\t\tconst mapping = this.mapping();\n\t\tconst detent = this.detent;\n\t\tconst start = {\n\t\t\tfrom: this.#value,\n\t\t\tposition: axis.position(event),\n\t\t\tproportion: axis.fromProportion ?? mapping.proportionOf(this.#value),\n\t\t\tthresholdPx: dragThresholdPx(event.pointerType),\n\t\t\ttravelPx: axis.travelPx,\n\t\t};\n\t\tif (detent === undefined) return startDrag(mapping, start);\n\n\t\tconst zonePx = readPxProperty(getComputedStyle(control), '--_sonic-detent-zone', detentZonePx);\n\n\t\treturn startDrag(mapping, {\n\t\t\t...start,\n\t\t\tdetent: { value: detent, zone: zonePx / axis.travelPx },\n\t\t});\n\t}\n\n\t#textFor(value: number): string {\n\t\treturn this.#formatValue?.(value) ?? String(value);\n\t}\n\n\t#withinLimit(mapping: ValueMapping, state: DragState): DragState {\n\t\tconst limit = this.#limit;\n\t\tif (!limit || mapping.isWrapping) return state;\n\n\t\tconst [low, high] = limit;\n\n\t\treturn {\n\t\t\t...state,\n\t\t\trawProportion: clamp(\n\t\t\t\tstate.rawProportion,\n\t\t\t\tmapping.proportionOf(low),\n\t\t\t\tmapping.proportionOf(high),\n\t\t\t),\n\t\t};\n\t}\n\n\t#write(next: number): void {\n\t\tif (!Number.isFinite(next)) return;\n\n\t\tconst clamped = this.mapping().snap(next);\n\n\t\tthis.#asked = clamped;\n\t\tif (clamped === this.#value) return;\n\n\t\tthis.#value = clamped;\n\t\tthis.render();\n\t}\n\n\t#writeModulationProportion(control: HTMLElement, prefix: 'dial' | 'slider'): void {\n\t\tconst modulationValue = this.isWrapping() ? undefined : this.#modulationValue;\n\t\tconst isModulated = modulationValue !== undefined;\n\n\t\tif (isModulated !== this.#isModulated) {\n\t\t\tthis.#isModulated = isModulated;\n\t\t\tthis.toggleState('modulated', isModulated);\n\t\t}\n\t\tif (modulationValue === undefined) {\n\t\t\tcontrol.style.removeProperty(`--_sonic-${prefix}-modulation-value`);\n\t\t\treturn;\n\t\t}\n\n\t\tcontrol.style.setProperty(\n\t\t\t`--_sonic-${prefix}-modulation-value`,\n\t\t\tString(this.mapping().proportionOf(modulationValue)),\n\t\t);\n\t}\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { SonicValueElement } from "./value-element.js";
2
2
  import { Surface, SurfaceFrame } from "../lib/canvas-surface.js";
3
3
  //#region src/elements/wave-element.d.ts
4
- interface WaveMarker {
4
+ export interface WaveMarker {
5
5
  dimmed?: boolean;
6
6
  end?: number;
7
7
  kind?: string;
@@ -10,6 +10,10 @@ interface WaveMarker {
10
10
  }
11
11
  export declare abstract class SonicWaveElement<Colour extends string, Length extends string = never> extends SonicValueElement {
12
12
  #private;
13
+ static readonly observedAttributes: string[];
14
+ get currentMarker(): undefined | WaveMarker;
15
+ get fill(): boolean;
16
+ set fill(isFilling: boolean);
13
17
  get markers(): Array<WaveMarker>;
14
18
  set markers(list: Iterable<WaveMarker> | undefined);
15
19
  protected abstract readonly canvas: HTMLCanvasElement;
@@ -17,6 +21,8 @@ export declare abstract class SonicWaveElement<Colour extends string, Length ext
17
21
  protected abstract readonly control: HTMLElement;
18
22
  protected abstract readonly lengths: Record<Length, `--_sonic-${string}`>;
19
23
  protected abstract readonly sheet: string;
24
+ protected abstract readonly sizeProperty: `--_sonic-${string}`;
25
+ attributeChangedCallback(name: string): void;
20
26
  connectedCallback(): void;
21
27
  repaint(): void;
22
28
  protected connect(signal: AbortSignal): void;
@@ -27,10 +33,10 @@ export declare abstract class SonicWaveElement<Colour extends string, Length ext
27
33
  protected markerList(): ReadonlyArray<WaveMarker>;
28
34
  protected markerProportions(): Array<[number, number]>;
29
35
  protected abstract paint(context: CanvasRenderingContext2D, frame: SurfaceFrame<Colour, Length>): void;
30
- protected playback(): number;
31
36
  protected proportionsChanged(): void;
32
37
  protected renderEmpty(): void;
33
38
  protected abstract renderMarkers(): void;
39
+ protected showCurrentMarker(seconds: number): void;
34
40
  protected surface(): Surface | undefined;
35
41
  }
36
42
  //#endregion
@@ -2,19 +2,44 @@ import { SonicValueElement } from "./value-element.js";
2
2
  import { bindSurface } from "../lib/canvas-surface.js";
3
3
 
4
4
  //#region src/elements/wave-element.ts
5
+ function markerKey(marker) {
6
+ return marker ? [
7
+ marker.start,
8
+ marker.end,
9
+ marker.kind,
10
+ marker.label
11
+ ].join("|") : "";
12
+ }
5
13
  var SonicWaveElement = class extends SonicValueElement {
14
+ static observedAttributes = [...SonicValueElement.observedAttributes, "fill"];
15
+ get currentMarker() {
16
+ return this.#current ? { ...this.#current } : void 0;
17
+ }
18
+ get fill() {
19
+ return this.hasAttribute("fill");
20
+ }
21
+ set fill(isFilling) {
22
+ this.reflect("fill", isFilling);
23
+ }
6
24
  get markers() {
7
25
  return this.#markers.map((marker) => ({ ...marker }));
8
26
  }
9
27
  set markers(list) {
10
28
  this.#markers = [...list ?? []].filter((marker) => Number.isFinite(marker.start)).map((marker) => ({ ...marker })).toSorted((first, second) => first.start - second.start);
11
- if (this.isBound()) this.renderMarkers();
29
+ if (!this.isBound()) return;
30
+ this.renderMarkers();
31
+ this.render();
12
32
  }
13
- #heldAt;
33
+ #current;
34
+ #fillWatch;
14
35
  #markers = [];
15
36
  #surface;
37
+ attributeChangedCallback(name) {
38
+ super.attributeChangedCallback(name);
39
+ if (name === "fill") this.#watchFill();
40
+ }
16
41
  connectedCallback() {
17
- this.upgradeProperties("markers");
42
+ this.upgradeProperties("fill", "markers");
18
43
  super.connectedCallback();
19
44
  }
20
45
  repaint() {
@@ -38,16 +63,20 @@ var SonicWaveElement = class extends SonicValueElement {
38
63
  });
39
64
  this.render();
40
65
  this.checkStyles(control, this.sheet);
66
+ this.#watchFill();
67
+ signal.addEventListener("abort", () => {
68
+ this.#fillWatch?.disconnect();
69
+ this.#fillWatch = void 0;
70
+ }, { once: true });
41
71
  }
42
72
  focusTarget() {
43
73
  return this.control;
44
74
  }
45
75
  heldWrite(next) {
46
- this.#heldAt = next;
76
+ super.heldWrite(next);
47
77
  this.render();
48
78
  }
49
79
  holdChanged() {
50
- if (this.heldFrom() === void 0) this.#heldAt = void 0;
51
80
  this.render();
52
81
  }
53
82
  markerList() {
@@ -61,19 +90,40 @@ var SonicWaveElement = class extends SonicValueElement {
61
90
  return [Math.min(at, to), Math.max(at, to)];
62
91
  });
63
92
  }
64
- playback() {
65
- const from = this.heldFrom();
66
- return from === void 0 ? this.value : this.#heldAt ?? from;
67
- }
68
93
  proportionsChanged() {
69
94
  this.renderMarkers();
70
95
  }
71
96
  renderEmpty() {
72
97
  this.toggleState("empty", this.isEmpty());
73
98
  }
99
+ showCurrentMarker(seconds) {
100
+ const current = this.#markers.findLast((marker) => marker.start <= seconds);
101
+ if (markerKey(current) === markerKey(this.#current)) return;
102
+ this.#current = current;
103
+ this.dispatchEvent(new Event("sonic-marker", { bubbles: true }));
104
+ }
74
105
  surface() {
75
106
  return this.#surface;
76
107
  }
108
+ #watchFill() {
109
+ const control = this.control;
110
+ const isFilling = this.fill && this.isBound();
111
+ if (isFilling === (this.#fillWatch !== void 0)) return;
112
+ this.#fillWatch?.disconnect();
113
+ this.#fillWatch = void 0;
114
+ if (!isFilling) {
115
+ control.style.removeProperty(this.sizeProperty);
116
+ return;
117
+ }
118
+ this.#fillWatch = new ResizeObserver((entries) => {
119
+ const box = entries.at(-1)?.borderBoxSize[0];
120
+ if (!box) return;
121
+ requestAnimationFrame(() => {
122
+ if (this.#fillWatch) control.style.setProperty(this.sizeProperty, `${String(box.blockSize)}px`);
123
+ });
124
+ });
125
+ this.#fillWatch.observe(control);
126
+ }
77
127
  };
78
128
 
79
129
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"wave-element.js","names":[],"sources":["../../../src/elements/wave-element.ts"],"sourcesContent":["import type { Surface, SurfaceFrame } from '#lib/canvas-surface.ts';\n\nimport { SonicValueElement } from '#elements/value-element.ts';\nimport { bindSurface } from '#lib/canvas-surface.ts';\n\ninterface WaveMarker {\n\tdimmed?: boolean;\n\tend?: number;\n\tkind?: string;\n\tlabel?: string;\n\tstart: number;\n}\n\nexport abstract class SonicWaveElement<\n\tColour extends string,\n\tLength extends string = never,\n> extends SonicValueElement {\n\tget markers(): Array<WaveMarker> {\n\t\treturn this.#markers.map((marker) => ({ ...marker }));\n\t}\n\n\tset markers(list: Iterable<WaveMarker> | undefined) {\n\t\tthis.#markers = [...(list ?? [])]\n\t\t\t.filter((marker) => Number.isFinite(marker.start))\n\t\t\t.map((marker) => ({ ...marker }))\n\t\t\t.toSorted((first, second) => first.start - second.start);\n\t\tif (this.isBound()) this.renderMarkers();\n\t}\n\n\tprotected abstract readonly canvas: HTMLCanvasElement;\n\n\tprotected abstract readonly colours: Record<Colour, `--_sonic-${string}`>;\n\n\tprotected abstract readonly control: HTMLElement;\n\n\tprotected abstract readonly lengths: Record<Length, `--_sonic-${string}`>;\n\n\tprotected abstract readonly sheet: string;\n\n\t#heldAt: number | undefined;\n\n\t#markers: Array<WaveMarker> = [];\n\n\t#surface: Surface | undefined;\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties('markers');\n\t\tsuper.connectedCallback();\n\t}\n\n\trepaint(): void {\n\t\tthis.#surface?.rebuild();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst control = this.control;\n\n\t\tthis.keepControl(control, signal);\n\t\tthis.renderEmpty();\n\t\tthis.#surface = bindSurface({\n\t\t\tcanvas: this.canvas,\n\t\t\tcolours: this.colours,\n\t\t\tlengths: this.lengths,\n\t\t\tpaint: (context, frame) => {\n\t\t\t\tthis.paint(context, frame);\n\t\t\t},\n\t\t\tresize: () => {\n\t\t\t\tthis.renderMarkers();\n\t\t\t},\n\t\t\tsignal,\n\t\t});\n\t\tthis.render();\n\t\tthis.checkStyles(control, this.sheet);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.control;\n\t}\n\n\tprotected override heldWrite(next: number): void {\n\t\tthis.#heldAt = next;\n\t\tthis.render();\n\t}\n\n\tprotected override holdChanged(): void {\n\t\tif (this.heldFrom() === undefined) this.#heldAt = undefined;\n\t\tthis.render();\n\t}\n\n\tprotected abstract isEmpty(): boolean;\n\n\tprotected markerList(): ReadonlyArray<WaveMarker> {\n\t\treturn this.#markers;\n\t}\n\n\tprotected markerProportions(): Array<[number, number]> {\n\t\tconst mapping = this.mapping();\n\n\t\treturn this.#markers.map(({ end, start }) => {\n\t\t\tconst at = mapping.proportionOf(start);\n\t\t\tconst to = end === undefined ? at : mapping.proportionOf(end);\n\n\t\t\treturn [Math.min(at, to), Math.max(at, to)];\n\t\t});\n\t}\n\n\tprotected abstract paint(\n\t\tcontext: CanvasRenderingContext2D,\n\t\tframe: SurfaceFrame<Colour, Length>,\n\t): void;\n\n\tprotected playback(): number {\n\t\tconst from = this.heldFrom();\n\n\t\treturn from === undefined ? this.value : (this.#heldAt ?? from);\n\t}\n\n\tprotected override proportionsChanged(): void {\n\t\tthis.renderMarkers();\n\t}\n\n\tprotected renderEmpty(): void {\n\t\tthis.toggleState('empty', this.isEmpty());\n\t}\n\n\tprotected abstract renderMarkers(): void;\n\n\tprotected surface(): Surface | undefined {\n\t\treturn this.#surface;\n\t}\n}\n"],"mappings":";;;;AAaA,IAAsB,mBAAtB,cAGU,kBAAkB;CAC3B,IAAI,UAA6B;EAChC,OAAO,KAAK,SAAS,KAAK,YAAY,EAAE,GAAG,OAAO,EAAE;CACrD;CAEA,IAAI,QAAQ,MAAwC;EACnD,KAAK,WAAW,CAAC,GAAI,QAAQ,CAAC,CAAE,CAAC,CAC/B,QAAQ,WAAW,OAAO,SAAS,OAAO,KAAK,CAAC,CAAC,CACjD,KAAK,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC,CAChC,UAAU,OAAO,WAAW,MAAM,QAAQ,OAAO,KAAK;EACxD,IAAI,KAAK,QAAQ,GAAG,KAAK,cAAc;CACxC;CAYA;CAEA,WAA8B,CAAC;CAE/B;CAEA,AAAS,oBAA0B;EAClC,KAAK,kBAAkB,SAAS;EAChC,MAAM,kBAAkB;CACzB;CAEA,UAAgB;EACf,KAAK,UAAU,QAAQ;CACxB;CAEA,AAAU,QAAQ,QAA2B;EAC5C,MAAM,UAAU,KAAK;EAErB,KAAK,YAAY,SAAS,MAAM;EAChC,KAAK,YAAY;EACjB,KAAK,WAAW,YAAY;GAC3B,QAAQ,KAAK;GACb,SAAS,KAAK;GACd,SAAS,KAAK;GACd,QAAQ,SAAS,UAAU;IAC1B,KAAK,MAAM,SAAS,KAAK;GAC1B;GACA,cAAc;IACb,KAAK,cAAc;GACpB;GACA;EACD,CAAC;EACD,KAAK,OAAO;EACZ,KAAK,YAAY,SAAS,KAAK,KAAK;CACrC;CAEA,AAAmB,cAA2B;EAC7C,OAAO,KAAK;CACb;CAEA,AAAmB,UAAU,MAAoB;EAChD,KAAK,UAAU;EACf,KAAK,OAAO;CACb;CAEA,AAAmB,cAAoB;EACtC,IAAI,KAAK,SAAS,MAAM,QAAW,KAAK,UAAU;EAClD,KAAK,OAAO;CACb;CAIA,AAAU,aAAwC;EACjD,OAAO,KAAK;CACb;CAEA,AAAU,oBAA6C;EACtD,MAAM,UAAU,KAAK,QAAQ;EAE7B,OAAO,KAAK,SAAS,KAAK,EAAE,KAAK,YAAY;GAC5C,MAAM,KAAK,QAAQ,aAAa,KAAK;GACrC,MAAM,KAAK,QAAQ,SAAY,KAAK,QAAQ,aAAa,GAAG;GAE5D,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC;EAC3C,CAAC;CACF;CAOA,AAAU,WAAmB;EAC5B,MAAM,OAAO,KAAK,SAAS;EAE3B,OAAO,SAAS,SAAY,KAAK,QAAS,KAAK,WAAW;CAC3D;CAEA,AAAmB,qBAA2B;EAC7C,KAAK,cAAc;CACpB;CAEA,AAAU,cAAoB;EAC7B,KAAK,YAAY,SAAS,KAAK,QAAQ,CAAC;CACzC;CAIA,AAAU,UAA+B;EACxC,OAAO,KAAK;CACb;AACD"}
1
+ {"version":3,"file":"wave-element.js","names":[],"sources":["../../../src/elements/wave-element.ts"],"sourcesContent":["import type { Surface, SurfaceFrame } from '#lib/canvas-surface.ts';\n\nimport { SonicValueElement } from '#elements/value-element.ts';\nimport { bindSurface } from '#lib/canvas-surface.ts';\n\nexport interface WaveMarker {\n\tdimmed?: boolean;\n\tend?: number;\n\tkind?: string;\n\tlabel?: string;\n\tstart: number;\n}\n\nfunction markerKey(marker: undefined | WaveMarker): string {\n\treturn marker ? [marker.start, marker.end, marker.kind, marker.label].join('|') : '';\n}\n\nexport abstract class SonicWaveElement<\n\tColour extends string,\n\tLength extends string = never,\n> extends SonicValueElement {\n\tstatic override readonly observedAttributes = [...SonicValueElement.observedAttributes, 'fill'];\n\n\tget currentMarker(): undefined | WaveMarker {\n\t\treturn this.#current ? { ...this.#current } : undefined;\n\t}\n\n\tget fill(): boolean {\n\t\treturn this.hasAttribute('fill');\n\t}\n\n\tset fill(isFilling: boolean) {\n\t\tthis.reflect('fill', isFilling);\n\t}\n\n\tget markers(): Array<WaveMarker> {\n\t\treturn this.#markers.map((marker) => ({ ...marker }));\n\t}\n\n\tset markers(list: Iterable<WaveMarker> | undefined) {\n\t\tthis.#markers = [...(list ?? [])]\n\t\t\t.filter((marker) => Number.isFinite(marker.start))\n\t\t\t.map((marker) => ({ ...marker }))\n\t\t\t.toSorted((first, second) => first.start - second.start);\n\t\tif (!this.isBound()) return;\n\n\t\tthis.renderMarkers();\n\t\tthis.render();\n\t}\n\n\tprotected abstract readonly canvas: HTMLCanvasElement;\n\n\tprotected abstract readonly colours: Record<Colour, `--_sonic-${string}`>;\n\n\tprotected abstract readonly control: HTMLElement;\n\n\tprotected abstract readonly lengths: Record<Length, `--_sonic-${string}`>;\n\n\tprotected abstract readonly sheet: string;\n\n\tprotected abstract readonly sizeProperty: `--_sonic-${string}`;\n\n\t#current: undefined | WaveMarker;\n\n\t#fillWatch: ResizeObserver | undefined;\n\n\t#markers: Array<WaveMarker> = [];\n\n\t#surface: Surface | undefined;\n\n\toverride attributeChangedCallback(name: string): void {\n\t\tsuper.attributeChangedCallback(name);\n\t\tif (name === 'fill') this.#watchFill();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties('fill', 'markers');\n\t\tsuper.connectedCallback();\n\t}\n\n\trepaint(): void {\n\t\tthis.#surface?.rebuild();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst control = this.control;\n\n\t\tthis.keepControl(control, signal);\n\t\tthis.renderEmpty();\n\t\tthis.#surface = bindSurface({\n\t\t\tcanvas: this.canvas,\n\t\t\tcolours: this.colours,\n\t\t\tlengths: this.lengths,\n\t\t\tpaint: (context, frame) => {\n\t\t\t\tthis.paint(context, frame);\n\t\t\t},\n\t\t\tresize: () => {\n\t\t\t\tthis.renderMarkers();\n\t\t\t},\n\t\t\tsignal,\n\t\t});\n\t\tthis.render();\n\t\tthis.checkStyles(control, this.sheet);\n\t\tthis.#watchFill();\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#fillWatch?.disconnect();\n\t\t\t\tthis.#fillWatch = undefined;\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.control;\n\t}\n\n\tprotected override heldWrite(next: number): void {\n\t\tsuper.heldWrite(next);\n\t\tthis.render();\n\t}\n\n\tprotected override holdChanged(): void {\n\t\tthis.render();\n\t}\n\n\tprotected abstract isEmpty(): boolean;\n\n\tprotected markerList(): ReadonlyArray<WaveMarker> {\n\t\treturn this.#markers;\n\t}\n\n\tprotected markerProportions(): Array<[number, number]> {\n\t\tconst mapping = this.mapping();\n\n\t\treturn this.#markers.map(({ end, start }) => {\n\t\t\tconst at = mapping.proportionOf(start);\n\t\t\tconst to = end === undefined ? at : mapping.proportionOf(end);\n\n\t\t\treturn [Math.min(at, to), Math.max(at, to)];\n\t\t});\n\t}\n\n\tprotected abstract paint(\n\t\tcontext: CanvasRenderingContext2D,\n\t\tframe: SurfaceFrame<Colour, Length>,\n\t): void;\n\n\tprotected override proportionsChanged(): void {\n\t\tthis.renderMarkers();\n\t}\n\n\tprotected renderEmpty(): void {\n\t\tthis.toggleState('empty', this.isEmpty());\n\t}\n\n\tprotected abstract renderMarkers(): void;\n\n\tprotected showCurrentMarker(seconds: number): void {\n\t\tconst current = this.#markers.findLast((marker) => marker.start <= seconds);\n\t\tif (markerKey(current) === markerKey(this.#current)) return;\n\n\t\tthis.#current = current;\n\t\tthis.dispatchEvent(new Event('sonic-marker', { bubbles: true }));\n\t}\n\n\tprotected surface(): Surface | undefined {\n\t\treturn this.#surface;\n\t}\n\n\t#watchFill(): void {\n\t\tconst control = this.control;\n\t\tconst isFilling = this.fill && this.isBound();\n\t\tif (isFilling === (this.#fillWatch !== undefined)) return;\n\n\t\tthis.#fillWatch?.disconnect();\n\t\tthis.#fillWatch = undefined;\n\t\tif (!isFilling) {\n\t\t\tcontrol.style.removeProperty(this.sizeProperty);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#fillWatch = new ResizeObserver((entries) => {\n\t\t\tconst box = entries.at(-1)?.borderBoxSize[0];\n\t\t\tif (!box) return;\n\n\t\t\t// Written a frame on, or the canvas resizes inside this delivery and WebKit reports a loop\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (this.#fillWatch) {\n\t\t\t\t\tcontrol.style.setProperty(this.sizeProperty, `${String(box.blockSize)}px`);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tthis.#fillWatch.observe(control);\n\t}\n}\n"],"mappings":"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"}
@@ -9,10 +9,12 @@ declare global {
9
9
  }
10
10
  }
11
11
  type Colour = keyof typeof colours;
12
+ type PeaksRequest = (fromSeconds: number, toSeconds: number) => unknown;
12
13
  declare const colours: {
14
+ readonly ends: "--_sonic-waveform-ends";
13
15
  readonly grid: "--_sonic-waveform-grid";
14
- readonly hatch: "--_sonic-waveform-hatch";
15
16
  readonly marker: "--_sonic-waveform-marker";
17
+ readonly placeholder: "--_sonic-waveform-placeholder";
16
18
  readonly wave: "--_sonic-waveform-wave";
17
19
  readonly waveEdge: "--_sonic-waveform-wave-edge";
18
20
  };
@@ -23,27 +25,33 @@ export declare class SonicWaveform extends SonicWaveElement<Colour> {
23
25
  set peaks(peaks: undefined | WaveformPeaks);
24
26
  get pending(): Array<[number, number]>;
25
27
  set pending(regions: TimeRegions | undefined);
28
+ get pendingDelay(): number;
29
+ set pendingDelay(value: number | undefined);
26
30
  get playbackRate(): number;
27
31
  set playbackRate(value: number | undefined);
28
32
  get playing(): boolean;
29
33
  set playing(isPlaying: boolean);
30
34
  get readTime(): (() => number | undefined) | undefined;
31
35
  set readTime(read: (() => number | undefined) | undefined);
32
- get requestPeaks(): ((fromSeconds: number, toSeconds: number) => void) | undefined;
33
- set requestPeaks(request: ((fromSeconds: number, toSeconds: number) => void) | undefined);
36
+ get reducedMotion(): 'page' | 'scroll';
37
+ set reducedMotion(motion: 'page' | 'scroll' | undefined);
38
+ get requestPeaks(): PeaksRequest | undefined;
39
+ set requestPeaks(request: PeaksRequest | undefined);
34
40
  get zoom(): number;
35
41
  set zoom(value: number | undefined);
36
42
  protected readonly control: HTMLDivElement;
37
43
  protected readonly canvas: HTMLCanvasElement;
38
44
  protected readonly colours: {
45
+ readonly ends: "--_sonic-waveform-ends";
39
46
  readonly grid: "--_sonic-waveform-grid";
40
- readonly hatch: "--_sonic-waveform-hatch";
41
47
  readonly marker: "--_sonic-waveform-marker";
48
+ readonly placeholder: "--_sonic-waveform-placeholder";
42
49
  readonly wave: "--_sonic-waveform-wave";
43
50
  readonly waveEdge: "--_sonic-waveform-wave-edge";
44
51
  };
45
52
  protected readonly lengths: {};
46
53
  protected readonly sheet = "waveform.css";
54
+ protected readonly sizeProperty = "--_sonic-waveform-size";
47
55
  connectedCallback(): void;
48
56
  protected connect(signal: AbortSignal): void;
49
57
  protected draw(): void;