@xsynaptic/sonic-ui 0.8.0 → 0.10.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 (74) hide show
  1. package/README.md +0 -2
  2. package/dist/default/elements/dial.js +12 -3
  3. package/dist/default/elements/display-element.js +14 -2
  4. package/dist/default/elements/envelope.js +2 -2
  5. package/dist/default/elements/modulation.js +45 -0
  6. package/dist/default/elements/readout-claim.js +8 -3
  7. package/dist/default/elements/slider.js +16 -18
  8. package/dist/default/elements/spectrum.js +1 -0
  9. package/dist/default/elements/value-element.js +108 -330
  10. package/dist/default/elements/value-gestures.js +301 -0
  11. package/dist/default/elements/wave-element.js +5 -26
  12. package/dist/default/elements/waveform.js +6 -2
  13. package/dist/default/elements/wavestrip.js +5 -16
  14. package/dist/default/elements/xy.js +9 -20
  15. package/dist/default/lib/asked-value.js +21 -0
  16. package/dist/default/lib/canvas-surface.js +3 -0
  17. package/dist/default/lib/fill-watch.js +29 -0
  18. package/dist/default/lib/hover-preview.js +8 -3
  19. package/dist/default/lib/marker-rider.js +6 -3
  20. package/dist/default/lib/read-ms-property.js +10 -0
  21. package/dist/dev/elements/dial.js +12 -3
  22. package/dist/dev/elements/dial.js.map +1 -1
  23. package/dist/dev/elements/display-element.d.ts +4 -1
  24. package/dist/dev/elements/display-element.js +14 -2
  25. package/dist/dev/elements/display-element.js.map +1 -1
  26. package/dist/dev/elements/envelope.js +2 -2
  27. package/dist/dev/elements/envelope.js.map +1 -1
  28. package/dist/dev/elements/modulation.js +46 -0
  29. package/dist/dev/elements/modulation.js.map +1 -0
  30. package/dist/dev/elements/readout-claim.js +8 -3
  31. package/dist/dev/elements/readout-claim.js.map +1 -1
  32. package/dist/dev/elements/slider.d.ts +0 -1
  33. package/dist/dev/elements/slider.js +16 -18
  34. package/dist/dev/elements/slider.js.map +1 -1
  35. package/dist/dev/elements/spectrum.d.ts +1 -0
  36. package/dist/dev/elements/spectrum.js +1 -0
  37. package/dist/dev/elements/spectrum.js.map +1 -1
  38. package/dist/dev/elements/value-element.d.ts +11 -13
  39. package/dist/dev/elements/value-element.js +108 -330
  40. package/dist/dev/elements/value-element.js.map +1 -1
  41. package/dist/dev/elements/value-gestures.d.ts +10 -0
  42. package/dist/dev/elements/value-gestures.js +302 -0
  43. package/dist/dev/elements/value-gestures.js.map +1 -0
  44. package/dist/dev/elements/wave-element.js +5 -26
  45. package/dist/dev/elements/wave-element.js.map +1 -1
  46. package/dist/dev/elements/waveform.js +6 -2
  47. package/dist/dev/elements/waveform.js.map +1 -1
  48. package/dist/dev/elements/wavestrip.d.ts +0 -1
  49. package/dist/dev/elements/wavestrip.js +5 -16
  50. package/dist/dev/elements/wavestrip.js.map +1 -1
  51. package/dist/dev/elements/xy.js +9 -20
  52. package/dist/dev/elements/xy.js.map +1 -1
  53. package/dist/dev/lib/asked-value.js +22 -0
  54. package/dist/dev/lib/asked-value.js.map +1 -0
  55. package/dist/dev/lib/canvas-surface.d.ts +1 -0
  56. package/dist/dev/lib/canvas-surface.js +3 -0
  57. package/dist/dev/lib/canvas-surface.js.map +1 -1
  58. package/dist/dev/lib/fill-watch.js +30 -0
  59. package/dist/dev/lib/fill-watch.js.map +1 -0
  60. package/dist/dev/lib/hover-preview.js +8 -3
  61. package/dist/dev/lib/hover-preview.js.map +1 -1
  62. package/dist/dev/lib/marker-rider.js +6 -3
  63. package/dist/dev/lib/marker-rider.js.map +1 -1
  64. package/dist/dev/lib/read-ms-property.js +11 -0
  65. package/dist/dev/lib/read-ms-property.js.map +1 -0
  66. package/dist/styles/envelope.css +1 -1
  67. package/dist/styles/led.css +1 -1
  68. package/dist/styles/material.css +42 -8
  69. package/dist/styles/spectrum.css +5 -0
  70. package/dist/styles/switch.css +42 -33
  71. package/dist/styles/waveform.css +31 -2
  72. package/dist/styles/wavestrip.css +13 -7
  73. package/dist/styles/xy.css +4 -4
  74. package/package.json +1 -1
@@ -1,20 +1,15 @@
1
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
- import { requireChild } from "../lib/render.js";
5
- import { bindDrag } from "../lib/pointer-drag.js";
6
- import { ReadoutClaim } from "./readout-claim.js";
7
4
  import { Readout } from "./readout.js";
8
- import { ValueEntry } from "./value-entry.js";
9
- import { dragThresholdPx, startDrag, stepDrag } from "../lib/drag-step.js";
10
- import { focusByPointer } from "../lib/focus-by-pointer.js";
11
- import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
12
- import { parseNumberList } from "../lib/number-list.js";
13
5
  import { readPxProperty } from "../lib/read-px-property.js";
14
- import { resetKeys, valueMapping } from "../lib/value-mapping.js";
6
+ import { parseNumberList } from "../lib/number-list.js";
7
+ import { valueMapping } from "../lib/value-mapping.js";
8
+ import { ValueGestures } from "./value-gestures.js";
9
+ import { moveTo, resnap, setAsked } from "../lib/asked-value.js";
10
+ import { bindHoverPreview } from "../lib/hover-preview.js";
15
11
 
16
12
  //#region src/elements/value-element.ts
17
- const detentZonePx = 8;
18
13
  const fallbackTravelPx = 160;
19
14
  let instanceCount = 0;
20
15
  const proportionAttributes = /* @__PURE__ */ new Set([
@@ -68,7 +63,7 @@ var SonicValueElement = class extends SonicFormElement {
68
63
  element.#limit = bounds;
69
64
  },
70
65
  mapping: () => element.mapping(),
71
- value: () => element.#value,
66
+ value: () => element.#cell.value,
72
67
  watch: (listener) => {
73
68
  element.#watchers.add(listener);
74
69
  return () => {
@@ -96,11 +91,18 @@ var SonicValueElement = class extends SonicFormElement {
96
91
  this.reflect("dimmed", isDimmed);
97
92
  }
98
93
  get doublePress() {
99
- return this.getAttribute("double-press") === "reset" ? "reset" : "entry";
94
+ const gesture = this.getAttribute("double-press");
95
+ return gesture === "none" || gesture === "reset" ? gesture : "entry";
100
96
  }
101
97
  set doublePress(gesture) {
102
98
  this.reflect("double-press", gesture);
103
99
  }
100
+ get formatEntry() {
101
+ return this.#formatEntry;
102
+ }
103
+ set formatEntry(format) {
104
+ this.#formatEntry = format;
105
+ }
104
106
  get formatSpokenValue() {
105
107
  return this.#formatSpokenValue;
106
108
  }
@@ -115,6 +117,9 @@ var SonicValueElement = class extends SonicFormElement {
115
117
  this.#formatValue = format;
116
118
  this.render();
117
119
  }
120
+ get hoverValue() {
121
+ return this.#hover?.value();
122
+ }
118
123
  get keyStep() {
119
124
  return this.optionalNumberAttribute("key-step");
120
125
  }
@@ -158,7 +163,7 @@ var SonicValueElement = class extends SonicFormElement {
158
163
  this.#parseValue = parse;
159
164
  }
160
165
  get pointerType() {
161
- return this.#dragging()?.pointerType;
166
+ return this.#gestures?.pointerType();
162
167
  }
163
168
  get positions() {
164
169
  return parseNumberList(this.getAttribute("positions"));
@@ -191,7 +196,7 @@ var SonicValueElement = class extends SonicFormElement {
191
196
  this.reflect("taper", curve);
192
197
  }
193
198
  get value() {
194
- return this.#value;
199
+ return this.#cell.value;
195
200
  }
196
201
  set value(next) {
197
202
  if (next === void 0 || next === null) {
@@ -203,33 +208,28 @@ var SonicValueElement = class extends SonicFormElement {
203
208
  this.heldWrite(value);
204
209
  return;
205
210
  }
206
- this.#write(value);
207
- if (Number.isFinite(value)) this.#asked = value;
211
+ if (setAsked(this.#cell, this.mapping(), value)) this.render();
208
212
  }
209
213
  get valueText() {
210
- return this.#textFor(this.#value);
214
+ return this.#textFor(this.#cell.value);
211
215
  }
212
- #asked;
213
- #claim = new ReadoutClaim(() => {
214
- this.#renderHold();
215
- });
216
- #entry;
216
+ #cell = {
217
+ asked: void 0,
218
+ value: 0
219
+ };
220
+ #formatEntry;
217
221
  #formatSpokenValue;
218
222
  #formatValue;
223
+ #gestures;
219
224
  #heldAt;
225
+ #hover;
220
226
  #instance = String(instanceCount += 1);
221
- #isModulated = false;
222
- #isRevealed = false;
223
- #keyScrub;
224
227
  #land;
225
228
  #limit;
226
229
  #mapping;
227
- #modulationValue;
228
230
  #parseValue;
229
- #pointerDrag;
230
231
  #positions;
231
232
  #readout;
232
- #value = 0;
233
233
  #watchers = /* @__PURE__ */ new Set();
234
234
  attributeChangedCallback(name) {
235
235
  this.#mapping = void 0;
@@ -239,105 +239,100 @@ var SonicValueElement = class extends SonicFormElement {
239
239
  this.heldWrite(this.numberAttribute("value", this.min));
240
240
  return;
241
241
  }
242
- this.#asked = void 0;
242
+ this.#cell.asked = void 0;
243
243
  }
244
- if (name === "disabled" && this.isDisabled()) this.#endHolds();
245
- this.#value = this.mapping().snap(this.#asked ?? this.numberAttribute("value", this.min));
244
+ if (name === "disabled" && this.isDisabled()) this.#gestures?.end();
245
+ resnap(this.#cell, this.mapping(), this.numberAttribute("value", this.min));
246
246
  if (proportionAttributes.has(name) && this.isBound()) this.proportionsChanged();
247
247
  this.render();
248
248
  }
249
249
  connectedCallback() {
250
- this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "spokenStep", "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", "formatEntry", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
251
251
  super.connectedCallback();
252
252
  }
253
253
  bindGestures(control, signal, grab) {
254
- const entry = this.#bindEntry(control, signal);
255
- this.#pointerDrag = bindDrag(control, {
256
- cancel: (drag) => {
257
- if (drag.isKeptOnCancel !== true) this.input(drag.fromValue);
254
+ const bubble = control.querySelector("[popover]");
255
+ if (bubble) this.#readout = {
256
+ anchor: control,
257
+ bubble: new Readout(bubble)
258
+ };
259
+ this.#gestures = new ValueGestures({
260
+ default: () => this.default,
261
+ detent: () => this.detent,
262
+ dispatch: (type) => {
263
+ this.dispatchEvent(new Event(type, { bubbles: true }));
258
264
  },
259
- grab: (event) => {
260
- if (isMenuPress(event) || this.isDisabled() || entry.isOpen) return;
261
- this.toggleState("springing", false);
262
- if (event.pointerType === "touch") event.preventDefault();
263
- focusByPointer(control);
264
- if (isResetPress(event)) {
265
- this.#reset();
266
- return;
267
- }
268
- const fromValue = this.#value;
269
- const axis = grab(event);
270
- if (!axis) return;
271
- const drag = {
272
- ...axis,
273
- fromValue,
274
- isOutside: false,
275
- isRevealed: false,
276
- pointerType: event.pointerType,
277
- revealTimer: void 0,
278
- state: this.#startDrag(control, axis, event)
279
- };
280
- drag.revealTimer = setTimeout(() => {
281
- this.#reveal(drag);
282
- }, 250);
283
- return drag;
265
+ doublePress: () => this.doublePress,
266
+ entryId: `sonic-entry-${this.#instance}`,
267
+ entryText: () => this.#entryText(),
268
+ forwardNaming: (target, isNamed) => {
269
+ this.forwardNaming(target, isNamed);
284
270
  },
285
- lift: (drag, event) => {
286
- const tap = drag.state.isEngaged ? void 0 : this.tapTarget();
287
- if (tap !== void 0) {
288
- entry.forgetPress();
289
- this.#commit(tap);
290
- return;
291
- }
292
- if (!entry.press(event) || this.springTarget() !== void 0) return;
293
- if (this.doublePress === "reset") this.#reset();
294
- else entry.open();
271
+ holdChanged: () => {
272
+ this.#renderHold();
295
273
  },
296
- move: (drag, event) => {
297
- this.#dragTo(drag, event);
274
+ input: (next) => this.input(next),
275
+ isDisabled: () => this.isDisabled(),
276
+ keyStep: () => this.keyStep,
277
+ land: (target, direction) => this.#land?.(target, direction) ?? target,
278
+ limit: () => this.#limit,
279
+ mapping: () => this.mapping(),
280
+ parse: (text) => (this.#parseValue ?? Number.parseFloat)(text),
281
+ render: () => {
282
+ this.render();
298
283
  },
299
- release: (drag) => {
300
- this.#releaseDrag(drag);
284
+ scrubsKeyRepeat: () => this.scrubsKeyRepeat(),
285
+ springTarget: () => this.springTarget(),
286
+ tapTarget: () => this.tapTarget(),
287
+ toggleState: (state, isOn) => {
288
+ this.toggleState(state, isOn);
301
289
  },
302
- toggle: (isDragging) => {
303
- this.toggleState("dragging", isDragging);
304
- }
290
+ value: () => this.#cell.value
291
+ }, control);
292
+ this.#gestures.bind(signal, grab);
293
+ }
294
+ bindHover(control, signal, { canShow = () => true, place, valueAt }) {
295
+ this.#hover = bindHoverPreview(control, {
296
+ canShow,
297
+ changed: () => {
298
+ this.dispatchEvent(new Event("sonic-hover", { bubbles: true }));
299
+ },
300
+ dismiss: () => {
301
+ this.render();
302
+ },
303
+ isTaken: () => this.#isEditing() || this.isRevealed(),
304
+ show: () => {
305
+ if (!this.readout) return;
306
+ this.renderReadout();
307
+ place();
308
+ },
309
+ valueAt
305
310
  }, signal);
306
- control.addEventListener("pointercancel", () => {
307
- entry.forgetPress();
308
- }, { signal });
309
- this.#bindKeys(control, entry, signal);
310
- signal.addEventListener("abort", () => {
311
- this.#endKeyScrub();
312
- this.#concealKeyReveal();
313
- }, { once: true });
314
311
  }
315
312
  controlOrientation() {}
316
313
  controlRole() {
317
314
  return "slider";
318
315
  }
319
316
  heldFrom() {
320
- return this.#dragging()?.fromValue ?? this.#keyScrub?.fromValue;
317
+ return this.#gestures?.heldFrom();
321
318
  }
322
319
  heldWrite(next) {
323
320
  this.#heldAt = next;
324
321
  }
325
322
  holdChanged() {}
326
323
  input(next) {
327
- const previous = this.#value;
328
- this.#write(this.#limit ? clamp(next, ...this.#limit) : next);
329
- if (this.#value === previous) return false;
324
+ const previous = this.#cell.value;
325
+ const target = this.#limit ? clamp(next, ...this.#limit) : next;
326
+ if (moveTo(this.#cell, this.mapping(), target)) this.render();
327
+ if (this.#cell.value === previous) return false;
330
328
  this.dispatchEvent(new Event("input", {
331
329
  bubbles: true,
332
330
  composed: true
333
331
  }));
334
332
  return true;
335
333
  }
336
- isEditing() {
337
- return this.#entry?.isOpen === true;
338
- }
339
334
  isRevealed() {
340
- return this.#claim.isRevealed;
335
+ return this.#gestures?.isRevealed() === true;
341
336
  }
342
337
  isWrapping() {
343
338
  return false;
@@ -363,15 +358,11 @@ var SonicValueElement = class extends SonicFormElement {
363
358
  }
364
359
  playback() {
365
360
  const from = this.heldFrom();
366
- return from === void 0 ? this.#value : this.#heldAt ?? from;
361
+ return from === void 0 ? this.#cell.value : this.#heldAt ?? from;
367
362
  }
368
- previewValue() {}
369
363
  proportionsChanged() {}
370
- readModulationValue() {
371
- return this.#modulationValue;
372
- }
373
364
  readoutValue() {
374
- return this.#shown().value ?? this.#value;
365
+ return this.#shown().value ?? this.#cell.value;
375
366
  }
376
367
  render() {
377
368
  if (this.isBound()) this.#renderControl();
@@ -399,147 +390,20 @@ var SonicValueElement = class extends SonicFormElement {
399
390
  travelPx(control, property) {
400
391
  return Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));
401
392
  }
402
- writeModulationValue(control, prefix, next) {
403
- const value = next === void 0 || next === null ? void 0 : toNumber(next);
404
- if (value !== void 0 && !Number.isFinite(value)) return;
405
- this.#modulationValue = value;
406
- if (this.isBound()) this.#writeModulationProportion(control, prefix);
407
- }
408
- writeProportions(control, prefix, modulation) {
409
- const { style } = control;
410
- const mapping = this.mapping();
411
- const value = mapping.proportionOf(this.#value);
412
- const reach = mapping.proportionOf(this.#value + modulation);
413
- const { positionCount } = mapping;
414
- style.setProperty(`--_sonic-${prefix}-value`, String(value));
415
- style.setProperty(`--_sonic-${prefix}-origin`, String(mapping.proportionOf(this.originValue())));
416
- style.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(value, reach)));
417
- style.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(value, reach)));
418
- if (positionCount === void 0) style.removeProperty(`--_sonic-${prefix}-position-count`);
419
- else style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));
420
- this.#writeModulationProportion(control, prefix);
421
- }
422
- #bindEntry(control, signal) {
423
- const input = requireChild(control, "input", HTMLInputElement);
424
- const bubble = control.querySelector("[popover]");
425
- input.id = `sonic-entry-${this.#instance}`;
426
- if (bubble) this.#readout = {
427
- anchor: control,
428
- bubble: new Readout(bubble)
429
- };
430
- const entry = new ValueEntry(input, {
431
- commit: (text) => {
432
- this.#commit((this.#parseValue ?? Number.parseFloat)(text));
433
- },
434
- text: () => this.#parseValue ? this.valueText : String(this.#value),
435
- toggle: (isOpen) => {
436
- if (isOpen) this.forwardNaming(input, true);
437
- this.toggleState("editing", isOpen);
438
- this.render();
439
- }
440
- });
441
- this.#entry = entry;
442
- entry.bind(control, signal);
443
- return entry;
444
- }
445
- #bindKeys(control, entry, signal) {
446
- control.addEventListener("keydown", (event) => {
447
- if (this.isDisabled() || event.defaultPrevented || event.target !== control) return;
448
- this.toggleState("springing", false);
449
- if (event.key === "Enter") {
450
- if (this.springTarget() !== void 0) return;
451
- event.preventDefault();
452
- entry.open();
453
- return;
454
- }
455
- const next = this.#keyTarget(event.key);
456
- if (next === void 0) return;
457
- event.preventDefault();
458
- this.#keyTo(event, next);
459
- this.#claim.reveal("keys");
460
- this.#renderHold();
461
- }, { signal });
462
- control.addEventListener("keyup", (event) => {
463
- const isMeta = event.key === "Meta";
464
- if (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();
465
- if (isMeta && this.#dragging()) return;
466
- if (isMeta || this.mapping().keyTarget(event.key, this.#value) !== void 0) this.#springBack();
467
- }, { signal });
468
- control.addEventListener("blur", () => {
469
- this.#endKeyScrub();
470
- this.#concealKeyReveal();
471
- this.#springBack();
472
- }, { signal });
473
- }
474
- #commit(next, direction = 0) {
475
- const landed = Number.isFinite(next) ? this.#land?.(next, direction) ?? next : next;
476
- if (this.input(landed)) this.dispatchEvent(new Event("change", { bubbles: true }));
477
- }
478
- #concealKeyReveal() {
479
- if (this.#claim.conceal("keys")) this.#renderHold();
480
- }
481
- #dragging() {
482
- return this.#pointerDrag?.current();
483
- }
484
- #dragTo(drag, event) {
485
- const isOutside = drag.outside?.(event) === true;
486
- const wasEngaged = drag.state.isEngaged;
487
- const mapping = this.mapping();
488
- const { state, value } = stepDrag(mapping, drag.state, {
489
- isFine: event.shiftKey,
490
- isOutside,
491
- position: drag.position(event)
492
- });
493
- drag.state = this.#withinLimit(mapping, state);
494
- if (value === void 0) return;
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
- }
501
- this.input(isOutside ? drag.fromValue : value);
502
- if (isCrossing) this.#renderDragReveal(drag);
503
- }
504
- #endHolds() {
505
- this.#entry?.close(false);
506
- this.#pointerDrag?.end();
507
- this.#endKeyScrub();
393
+ #entryText() {
394
+ const value = this.#cell.value;
395
+ if (this.#formatEntry) return this.#formatEntry(value);
396
+ return this.#parseValue ? this.valueText : String(value);
508
397
  }
509
- #endKeyScrub() {
510
- const scrub = this.#keyScrub;
511
- if (!scrub) return;
512
- this.#keyScrub = void 0;
513
- this.#renderHold();
514
- if (this.#value !== scrub.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
398
+ #isEditing() {
399
+ return this.#gestures?.isEditing() === true;
515
400
  }
516
401
  #isHeld() {
517
- return this.#dragging() !== void 0 || this.#keyScrub !== void 0;
518
- }
519
- #keyTarget(key) {
520
- if (resetKeys.has(key)) return this.default;
521
- return this.mapping().keyTarget(key, this.#value, this.keyStep);
522
- }
523
- #keyTo(event, next) {
524
- if (event.repeat && this.scrubsKeyRepeat()) {
525
- this.#scrubKey(event.key, next);
526
- return;
527
- }
528
- this.#endKeyScrub();
529
- this.#commit(next, next > this.#value ? 1 : -1);
530
- }
531
- #releaseDrag(drag) {
532
- clearTimeout(drag.revealTimer);
533
- this.#claim.conceal("drag");
534
- this.toggleState("cancelling", false);
535
- this.#renderHold();
536
- this.#showRevealed(false);
537
- if (this.#value !== drag.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
538
- this.#springBack();
402
+ return this.#gestures?.isHeld() === true;
539
403
  }
540
404
  #renderAria(control, orientation) {
541
- this.writeFormValue(String(this.#value), String(this.#value));
542
- if (this.#entry?.isOpen) {
405
+ this.writeFormValue(String(this.#cell.value), String(this.#cell.value));
406
+ if (this.#isEditing()) {
543
407
  for (const name of roleAttributes) control.removeAttribute(name);
544
408
  this.forwardNaming(control, false);
545
409
  this.renderReadout();
@@ -551,14 +415,15 @@ var SonicValueElement = class extends SonicFormElement {
551
415
  writeAttribute(control, "aria-valuemax", String(high));
552
416
  writeAttribute(control, "aria-valuenow", String(this.#spokenNow()));
553
417
  if (orientation) writeAttribute(control, "aria-orientation", orientation);
554
- writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#value));
418
+ writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#cell.value));
555
419
  this.forwardNaming(control, true);
556
420
  this.#renderDisabled(control);
557
421
  this.renderReadout();
558
422
  }
559
423
  #renderControl() {
424
+ if (this.#isEditing() || this.isRevealed()) this.#hover?.clear();
560
425
  this.draw();
561
- this.toggleState("at-origin", !this.isWrapping() && this.#value === this.mapping().snap(this.originValue()));
426
+ this.toggleState("at-origin", !this.isWrapping() && this.#cell.value === this.mapping().snap(this.originValue()));
562
427
  this.#renderAria(this.focusTarget(), this.controlOrientation());
563
428
  }
564
429
  #renderDisabled(control) {
@@ -567,117 +432,30 @@ var SonicValueElement = class extends SonicFormElement {
567
432
  const stop = this.getAttribute("tabindex") === "-1" ? "-1" : "0";
568
433
  writeAttribute(control, "tabindex", isDisabled ? void 0 : stop);
569
434
  }
570
- #renderDragReveal(drag) {
571
- const isRevealed = drag.isRevealed && !drag.isOutside;
572
- if (isRevealed) this.#claim.reveal("drag");
573
- else this.#claim.conceal("drag");
574
- this.#renderHold();
575
- this.#showRevealed(isRevealed);
576
- }
577
435
  #renderHold() {
578
436
  if (this.heldFrom() === void 0) this.#heldAt = void 0;
579
437
  this.renderReadout();
580
438
  this.holdChanged();
581
439
  }
582
- #reset() {
583
- this.#commit(this.default ?? NaN);
584
- }
585
- #reveal(drag) {
586
- if (drag.isRevealed || this.#dragging() !== drag) return;
587
- drag.isRevealed = true;
588
- this.#renderDragReveal(drag);
589
- }
590
- #scrubKey(key, next) {
591
- if (this.#keyScrub?.key !== key) {
592
- this.#endKeyScrub();
593
- this.#keyScrub = {
594
- fromValue: this.#value,
595
- key
596
- };
597
- }
598
- this.input(next);
599
- }
600
440
  #shown() {
601
- if (this.isEditing()) return {
441
+ if (this.#isEditing()) return {
602
442
  isOpen: true,
603
443
  value: void 0
604
444
  };
605
- const isRevealed = this.#claim.isRevealed;
606
- const preview = isRevealed ? void 0 : this.previewValue();
445
+ const isRevealed = this.isRevealed();
446
+ const preview = isRevealed ? void 0 : this.#hover?.value();
607
447
  return {
608
448
  isOpen: (isRevealed || preview !== void 0) && this.readout,
609
- value: preview ?? this.#value
449
+ value: preview ?? this.#cell.value
610
450
  };
611
451
  }
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
452
  #spokenNow() {
619
453
  const step = this.spokenStep;
620
- return step !== void 0 && step > 0 ? trimFloat(Math.round(this.#value / step) * step) : this.#value;
621
- }
622
- #springBack() {
623
- const target = this.springTarget();
624
- if (target === void 0) return;
625
- if (this.mapping().snap(target) !== this.#value) this.toggleState("springing", true);
626
- this.#commit(target);
627
- }
628
- #startDrag(control, axis, event) {
629
- const mapping = this.mapping();
630
- const detent = this.detent;
631
- const start = {
632
- from: this.#value,
633
- position: axis.position(event),
634
- proportion: axis.fromProportion ?? mapping.proportionOf(this.#value),
635
- thresholdPx: dragThresholdPx(event.pointerType),
636
- travelPx: axis.travelPx
637
- };
638
- if (detent === void 0) return startDrag(mapping, start);
639
- const zonePx = readPxProperty(getComputedStyle(control), "--_sonic-detent-zone", detentZonePx);
640
- return startDrag(mapping, {
641
- ...start,
642
- detent: {
643
- value: detent,
644
- zone: zonePx / axis.travelPx
645
- }
646
- });
454
+ return step !== void 0 && step > 0 ? trimFloat(Math.round(this.#cell.value / step) * step) : this.#cell.value;
647
455
  }
648
456
  #textFor(value) {
649
457
  return this.#formatValue?.(value) ?? String(value);
650
458
  }
651
- #withinLimit(mapping, state) {
652
- const limit = this.#limit;
653
- if (!limit || mapping.isWrapping) return state;
654
- const [low, high] = limit;
655
- return {
656
- ...state,
657
- rawProportion: clamp(state.rawProportion, mapping.proportionOf(low), mapping.proportionOf(high))
658
- };
659
- }
660
- #write(next) {
661
- if (!Number.isFinite(next)) return;
662
- const clamped = this.mapping().snap(next);
663
- this.#asked = clamped;
664
- if (clamped === this.#value) return;
665
- this.#value = clamped;
666
- this.render();
667
- }
668
- #writeModulationProportion(control, prefix) {
669
- const modulationValue = this.isWrapping() ? void 0 : this.#modulationValue;
670
- const isModulated = modulationValue !== void 0;
671
- if (isModulated !== this.#isModulated) {
672
- this.#isModulated = isModulated;
673
- this.toggleState("modulated", isModulated);
674
- }
675
- if (modulationValue === void 0) {
676
- control.style.removeProperty(`--_sonic-${prefix}-modulation-value`);
677
- return;
678
- }
679
- control.style.setProperty(`--_sonic-${prefix}-modulation-value`, String(this.mapping().proportionOf(modulationValue)));
680
- }
681
459
  };
682
460
 
683
461
  //#endregion