@xsynaptic/sonic-ui 0.6.1 → 0.9.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.
- package/README.md +2 -0
- package/dist/default/define/spectrum.js +7 -0
- package/dist/default/define.js +1 -0
- package/dist/default/elements/button.js +30 -2
- package/dist/default/elements/dial.js +12 -3
- package/dist/default/elements/display-element.js +77 -0
- package/dist/default/elements/envelope.js +3 -3
- package/dist/default/elements/modulation.js +45 -0
- package/dist/default/elements/readout-claim.js +8 -3
- package/dist/default/elements/slider.js +68 -4
- package/dist/default/elements/spectrum.js +230 -0
- package/dist/default/elements/value-element.js +114 -317
- package/dist/default/elements/value-gestures.js +301 -0
- package/dist/default/elements/wave-element.js +59 -9
- package/dist/default/elements/waveform.js +61 -12
- package/dist/default/elements/wavestrip.js +25 -49
- package/dist/default/elements/xy.js +10 -21
- package/dist/default/index.js +2 -1
- package/dist/default/lib/asked-value.js +21 -0
- package/dist/default/lib/canvas-surface.js +10 -4
- package/dist/default/lib/frame-timeline.js +2 -2
- package/dist/default/lib/hover-preview.js +46 -0
- package/dist/default/lib/marker-rider.js +12 -6
- package/dist/default/lib/pointer-drag.js +7 -2
- package/dist/default/lib/read-ms-property.js +10 -0
- package/dist/default/lib/spectrum-columns.js +74 -0
- package/dist/default/lib/spectrum-levels.js +55 -0
- package/dist/default/lib/strip-scene.js +12 -1
- package/dist/default/lib/time-regions.js +5 -1
- package/dist/dev/define/spectrum.d.ts +2 -0
- package/dist/dev/define/spectrum.js +8 -0
- package/dist/dev/define/spectrum.js.map +1 -0
- package/dist/dev/define.d.ts +3 -1
- package/dist/dev/define.js +1 -0
- package/dist/dev/elements/button.d.ts +2 -0
- package/dist/dev/elements/button.js +30 -2
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/dial.js +12 -3
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/display-element.d.ts +29 -0
- package/dist/dev/elements/display-element.js +78 -0
- package/dist/dev/elements/display-element.js.map +1 -0
- package/dist/dev/elements/envelope.js +3 -3
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/modulation.js +46 -0
- package/dist/dev/elements/modulation.js.map +1 -0
- package/dist/dev/elements/readout-claim.js +8 -3
- package/dist/dev/elements/readout-claim.js.map +1 -1
- package/dist/dev/elements/slider.d.ts +5 -0
- package/dist/dev/elements/slider.js +68 -4
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/spectrum.d.ts +59 -0
- package/dist/dev/elements/spectrum.js +231 -0
- package/dist/dev/elements/spectrum.js.map +1 -0
- package/dist/dev/elements/value-element.d.ts +13 -14
- package/dist/dev/elements/value-element.js +114 -317
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/value-gestures.d.ts +10 -0
- package/dist/dev/elements/value-gestures.js +302 -0
- package/dist/dev/elements/value-gestures.js.map +1 -0
- package/dist/dev/elements/wave-element.d.ts +8 -2
- package/dist/dev/elements/wave-element.js +59 -9
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.d.ts +12 -4
- package/dist/dev/elements/waveform.js +61 -12
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +3 -1
- package/dist/dev/elements/wavestrip.js +25 -49
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.js +10 -21
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +4 -1
- package/dist/dev/index.js +2 -1
- package/dist/dev/lib/asked-value.js +22 -0
- package/dist/dev/lib/asked-value.js.map +1 -0
- package/dist/dev/lib/canvas-surface.d.ts +5 -3
- package/dist/dev/lib/canvas-surface.js +10 -4
- package/dist/dev/lib/canvas-surface.js.map +1 -1
- package/dist/dev/lib/frame-timeline.js +2 -2
- package/dist/dev/lib/frame-timeline.js.map +1 -1
- package/dist/dev/lib/hover-preview.js +47 -0
- package/dist/dev/lib/hover-preview.js.map +1 -0
- package/dist/dev/lib/marker-rider.js +12 -6
- package/dist/dev/lib/marker-rider.js.map +1 -1
- package/dist/dev/lib/pointer-drag.js +7 -2
- package/dist/dev/lib/pointer-drag.js.map +1 -1
- package/dist/dev/lib/read-ms-property.js +11 -0
- package/dist/dev/lib/read-ms-property.js.map +1 -0
- package/dist/dev/lib/spectrum-columns.js +75 -0
- package/dist/dev/lib/spectrum-columns.js.map +1 -0
- package/dist/dev/lib/spectrum-levels.js +56 -0
- package/dist/dev/lib/spectrum-levels.js.map +1 -0
- package/dist/dev/lib/strip-scene.js +12 -1
- package/dist/dev/lib/strip-scene.js.map +1 -1
- package/dist/dev/lib/time-regions.js +5 -1
- package/dist/dev/lib/time-regions.js.map +1 -1
- package/dist/styles/button.css +7 -1
- package/dist/styles/controls.css +1 -0
- package/dist/styles/material.css +36 -3
- package/dist/styles/meter.css +22 -18
- package/dist/styles/slider.css +42 -5
- package/dist/styles/spectrum.css +105 -0
- package/dist/styles/waveform.css +48 -16
- package/dist/styles/wavestrip.css +26 -5
- package/package.json +2 -1
|
@@ -1,20 +1,15 @@
|
|
|
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
|
-
import { requireChild } from "../lib/render.js";
|
|
5
|
-
import { ReadoutClaim } from "./readout-claim.js";
|
|
6
4
|
import { Readout } from "./readout.js";
|
|
7
|
-
import { ValueEntry } from "./value-entry.js";
|
|
8
|
-
import { dragThresholdPx, startDrag, stepDrag } from "../lib/drag-step.js";
|
|
9
|
-
import { focusByPointer } from "../lib/focus-by-pointer.js";
|
|
10
|
-
import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
|
|
11
|
-
import { parseNumberList } from "../lib/number-list.js";
|
|
12
|
-
import { bindDrag } from "../lib/pointer-drag.js";
|
|
13
5
|
import { readPxProperty } from "../lib/read-px-property.js";
|
|
14
|
-
import {
|
|
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([
|
|
@@ -49,6 +44,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
49
44
|
"notched",
|
|
50
45
|
"origin",
|
|
51
46
|
"readout",
|
|
47
|
+
"spoken-step",
|
|
52
48
|
"step",
|
|
53
49
|
"tabindex",
|
|
54
50
|
"taper",
|
|
@@ -67,7 +63,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
67
63
|
element.#limit = bounds;
|
|
68
64
|
},
|
|
69
65
|
mapping: () => element.mapping(),
|
|
70
|
-
value: () => element.#value,
|
|
66
|
+
value: () => element.#cell.value,
|
|
71
67
|
watch: (listener) => {
|
|
72
68
|
element.#watchers.add(listener);
|
|
73
69
|
return () => {
|
|
@@ -95,7 +91,8 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
95
91
|
this.reflect("dimmed", isDimmed);
|
|
96
92
|
}
|
|
97
93
|
get doublePress() {
|
|
98
|
-
|
|
94
|
+
const gesture = this.getAttribute("double-press");
|
|
95
|
+
return gesture === "none" || gesture === "reset" ? gesture : "entry";
|
|
99
96
|
}
|
|
100
97
|
set doublePress(gesture) {
|
|
101
98
|
this.reflect("double-press", gesture);
|
|
@@ -156,6 +153,9 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
156
153
|
set parseValue(parse) {
|
|
157
154
|
this.#parseValue = parse;
|
|
158
155
|
}
|
|
156
|
+
get pointerType() {
|
|
157
|
+
return this.#gestures?.pointerType();
|
|
158
|
+
}
|
|
159
159
|
get positions() {
|
|
160
160
|
return parseNumberList(this.getAttribute("positions"));
|
|
161
161
|
}
|
|
@@ -168,6 +168,12 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
168
168
|
set readout(isShown) {
|
|
169
169
|
this.reflect("readout", isShown);
|
|
170
170
|
}
|
|
171
|
+
get spokenStep() {
|
|
172
|
+
return this.optionalNumberAttribute("spoken-step");
|
|
173
|
+
}
|
|
174
|
+
set spokenStep(value) {
|
|
175
|
+
this.reflect("spoken-step", value);
|
|
176
|
+
}
|
|
171
177
|
get step() {
|
|
172
178
|
return this.numberAttribute("step", 1);
|
|
173
179
|
}
|
|
@@ -181,7 +187,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
181
187
|
this.reflect("taper", curve);
|
|
182
188
|
}
|
|
183
189
|
get value() {
|
|
184
|
-
return this.#value;
|
|
190
|
+
return this.#cell.value;
|
|
185
191
|
}
|
|
186
192
|
set value(next) {
|
|
187
193
|
if (next === void 0 || next === null) {
|
|
@@ -193,31 +199,27 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
193
199
|
this.heldWrite(value);
|
|
194
200
|
return;
|
|
195
201
|
}
|
|
196
|
-
this.#
|
|
197
|
-
if (Number.isFinite(value)) this.#asked = value;
|
|
202
|
+
if (setAsked(this.#cell, this.mapping(), value)) this.render();
|
|
198
203
|
}
|
|
199
204
|
get valueText() {
|
|
200
|
-
return this.#textFor(this.#value);
|
|
205
|
+
return this.#textFor(this.#cell.value);
|
|
201
206
|
}
|
|
202
|
-
#
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
#entry;
|
|
207
|
+
#cell = {
|
|
208
|
+
asked: void 0,
|
|
209
|
+
value: 0
|
|
210
|
+
};
|
|
207
211
|
#formatSpokenValue;
|
|
208
212
|
#formatValue;
|
|
213
|
+
#gestures;
|
|
214
|
+
#heldAt;
|
|
215
|
+
#hover;
|
|
209
216
|
#instance = String(instanceCount += 1);
|
|
210
|
-
#isModulated = false;
|
|
211
|
-
#keyScrub;
|
|
212
217
|
#land;
|
|
213
218
|
#limit;
|
|
214
219
|
#mapping;
|
|
215
|
-
#modulationValue;
|
|
216
220
|
#parseValue;
|
|
217
|
-
#pointerDrag;
|
|
218
221
|
#positions;
|
|
219
222
|
#readout;
|
|
220
|
-
#value = 0;
|
|
221
223
|
#watchers = /* @__PURE__ */ new Set();
|
|
222
224
|
attributeChangedCallback(name) {
|
|
223
225
|
this.#mapping = void 0;
|
|
@@ -227,102 +229,96 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
227
229
|
this.heldWrite(this.numberAttribute("value", this.min));
|
|
228
230
|
return;
|
|
229
231
|
}
|
|
230
|
-
this.#asked = void 0;
|
|
232
|
+
this.#cell.asked = void 0;
|
|
231
233
|
}
|
|
232
|
-
if (name === "disabled" && this.isDisabled()) this.#
|
|
233
|
-
this.#
|
|
234
|
+
if (name === "disabled" && this.isDisabled()) this.#gestures?.end();
|
|
235
|
+
resnap(this.#cell, this.mapping(), this.numberAttribute("value", this.min));
|
|
234
236
|
if (proportionAttributes.has(name) && this.isBound()) this.proportionsChanged();
|
|
235
237
|
this.render();
|
|
236
238
|
}
|
|
237
239
|
connectedCallback() {
|
|
238
|
-
this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
|
|
240
|
+
this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "spokenStep", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
|
|
239
241
|
super.connectedCallback();
|
|
240
242
|
}
|
|
241
243
|
bindGestures(control, signal, grab) {
|
|
242
|
-
const
|
|
243
|
-
this.#
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
const bubble = control.querySelector("[popover]");
|
|
245
|
+
if (bubble) this.#readout = {
|
|
246
|
+
anchor: control,
|
|
247
|
+
bubble: new Readout(bubble)
|
|
248
|
+
};
|
|
249
|
+
this.#gestures = new ValueGestures({
|
|
250
|
+
default: () => this.default,
|
|
251
|
+
detent: () => this.detent,
|
|
252
|
+
dispatch: (type) => {
|
|
253
|
+
this.dispatchEvent(new Event(type, { bubbles: true }));
|
|
246
254
|
},
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (isResetPress(event)) {
|
|
253
|
-
this.#reset();
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const fromValue = this.#value;
|
|
257
|
-
const axis = grab(event);
|
|
258
|
-
if (!axis) return;
|
|
259
|
-
const drag = {
|
|
260
|
-
...axis,
|
|
261
|
-
fromValue,
|
|
262
|
-
isOutside: false,
|
|
263
|
-
isRevealed: false,
|
|
264
|
-
revealTimer: void 0,
|
|
265
|
-
state: this.#startDrag(control, axis, event)
|
|
266
|
-
};
|
|
267
|
-
drag.revealTimer = setTimeout(() => {
|
|
268
|
-
this.#reveal(drag);
|
|
269
|
-
}, 250);
|
|
270
|
-
return drag;
|
|
255
|
+
doublePress: () => this.doublePress,
|
|
256
|
+
entryId: `sonic-entry-${this.#instance}`,
|
|
257
|
+
entryText: () => this.#parseValue ? this.valueText : String(this.#cell.value),
|
|
258
|
+
forwardNaming: (target, isNamed) => {
|
|
259
|
+
this.forwardNaming(target, isNamed);
|
|
271
260
|
},
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (tap !== void 0) {
|
|
275
|
-
entry.forgetPress();
|
|
276
|
-
this.#commit(tap);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
if (!entry.press(event) || this.springTarget() !== void 0) return;
|
|
280
|
-
if (this.doublePress === "reset") this.#reset();
|
|
281
|
-
else entry.open();
|
|
261
|
+
holdChanged: () => {
|
|
262
|
+
this.#renderHold();
|
|
282
263
|
},
|
|
283
|
-
|
|
284
|
-
|
|
264
|
+
input: (next) => this.input(next),
|
|
265
|
+
isDisabled: () => this.isDisabled(),
|
|
266
|
+
keyStep: () => this.keyStep,
|
|
267
|
+
land: (target, direction) => this.#land?.(target, direction) ?? target,
|
|
268
|
+
limit: () => this.#limit,
|
|
269
|
+
mapping: () => this.mapping(),
|
|
270
|
+
parse: (text) => (this.#parseValue ?? Number.parseFloat)(text),
|
|
271
|
+
render: () => {
|
|
272
|
+
this.render();
|
|
285
273
|
},
|
|
286
|
-
|
|
287
|
-
|
|
274
|
+
scrubsKeyRepeat: () => this.scrubsKeyRepeat(),
|
|
275
|
+
springTarget: () => this.springTarget(),
|
|
276
|
+
tapTarget: () => this.tapTarget(),
|
|
277
|
+
toggleState: (state, isOn) => {
|
|
278
|
+
this.toggleState(state, isOn);
|
|
288
279
|
},
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
280
|
+
value: () => this.#cell.value
|
|
281
|
+
}, control);
|
|
282
|
+
this.#gestures.bind(signal, grab);
|
|
283
|
+
}
|
|
284
|
+
bindHover(control, signal, { canShow, place, valueAt }) {
|
|
285
|
+
this.#hover = bindHoverPreview(control, {
|
|
286
|
+
canShow,
|
|
287
|
+
dismiss: () => {
|
|
288
|
+
this.render();
|
|
289
|
+
},
|
|
290
|
+
isTaken: () => this.#isEditing() || this.isRevealed(),
|
|
291
|
+
show: () => {
|
|
292
|
+
this.renderReadout();
|
|
293
|
+
place();
|
|
294
|
+
},
|
|
295
|
+
valueAt
|
|
292
296
|
}, signal);
|
|
293
|
-
control.addEventListener("pointercancel", () => {
|
|
294
|
-
entry.forgetPress();
|
|
295
|
-
}, { signal });
|
|
296
|
-
this.#bindKeys(control, entry, signal);
|
|
297
|
-
signal.addEventListener("abort", () => {
|
|
298
|
-
this.#endKeyScrub();
|
|
299
|
-
this.#concealKeyReveal();
|
|
300
|
-
}, { once: true });
|
|
301
297
|
}
|
|
302
298
|
controlOrientation() {}
|
|
303
299
|
controlRole() {
|
|
304
300
|
return "slider";
|
|
305
301
|
}
|
|
306
302
|
heldFrom() {
|
|
307
|
-
return this.#
|
|
303
|
+
return this.#gestures?.heldFrom();
|
|
304
|
+
}
|
|
305
|
+
heldWrite(next) {
|
|
306
|
+
this.#heldAt = next;
|
|
308
307
|
}
|
|
309
|
-
heldWrite(_next) {}
|
|
310
308
|
holdChanged() {}
|
|
311
309
|
input(next) {
|
|
312
|
-
const previous = this.#value;
|
|
313
|
-
this.#
|
|
314
|
-
if (this.#
|
|
310
|
+
const previous = this.#cell.value;
|
|
311
|
+
const target = this.#limit ? clamp(next, ...this.#limit) : next;
|
|
312
|
+
if (moveTo(this.#cell, this.mapping(), target)) this.render();
|
|
313
|
+
if (this.#cell.value === previous) return false;
|
|
315
314
|
this.dispatchEvent(new Event("input", {
|
|
316
315
|
bubbles: true,
|
|
317
316
|
composed: true
|
|
318
317
|
}));
|
|
319
318
|
return true;
|
|
320
319
|
}
|
|
321
|
-
isEditing() {
|
|
322
|
-
return this.#entry?.isOpen === true;
|
|
323
|
-
}
|
|
324
320
|
isRevealed() {
|
|
325
|
-
return this.#
|
|
321
|
+
return this.#gestures?.isRevealed() === true;
|
|
326
322
|
}
|
|
327
323
|
isWrapping() {
|
|
328
324
|
return false;
|
|
@@ -346,13 +342,13 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
346
342
|
originValue() {
|
|
347
343
|
return this.origin ?? this.mapping().bounds[0];
|
|
348
344
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return this.#modulationValue;
|
|
345
|
+
playback() {
|
|
346
|
+
const from = this.heldFrom();
|
|
347
|
+
return from === void 0 ? this.#cell.value : this.#heldAt ?? from;
|
|
353
348
|
}
|
|
349
|
+
proportionsChanged() {}
|
|
354
350
|
readoutValue() {
|
|
355
|
-
return this.#shown().value ?? this.#value;
|
|
351
|
+
return this.#shown().value ?? this.#cell.value;
|
|
356
352
|
}
|
|
357
353
|
render() {
|
|
358
354
|
if (this.isBound()) this.#renderControl();
|
|
@@ -362,10 +358,11 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
362
358
|
const readout = this.#readout;
|
|
363
359
|
if (!readout) return;
|
|
364
360
|
const { isOpen, value } = this.#shown();
|
|
361
|
+
const text = value === void 0 ? void 0 : this.#textFor(value);
|
|
365
362
|
readout.bubble.show({
|
|
366
363
|
anchor: readout.anchor,
|
|
367
|
-
isOpen,
|
|
368
|
-
text
|
|
364
|
+
isOpen: isOpen && text !== "",
|
|
365
|
+
text
|
|
369
366
|
});
|
|
370
367
|
}
|
|
371
368
|
restoreState(state) {
|
|
@@ -379,142 +376,15 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
379
376
|
travelPx(control, property) {
|
|
380
377
|
return Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));
|
|
381
378
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (value !== void 0 && !Number.isFinite(value)) return;
|
|
385
|
-
this.#modulationValue = value;
|
|
386
|
-
if (this.isBound()) this.#writeModulationProportion(control, prefix);
|
|
387
|
-
}
|
|
388
|
-
writeProportions(control, prefix, modulation) {
|
|
389
|
-
const { style } = control;
|
|
390
|
-
const mapping = this.mapping();
|
|
391
|
-
const value = mapping.proportionOf(this.#value);
|
|
392
|
-
const reach = mapping.proportionOf(this.#value + modulation);
|
|
393
|
-
const { positionCount } = mapping;
|
|
394
|
-
style.setProperty(`--_sonic-${prefix}-value`, String(value));
|
|
395
|
-
style.setProperty(`--_sonic-${prefix}-origin`, String(mapping.proportionOf(this.originValue())));
|
|
396
|
-
style.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(value, reach)));
|
|
397
|
-
style.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(value, reach)));
|
|
398
|
-
if (positionCount === void 0) style.removeProperty(`--_sonic-${prefix}-position-count`);
|
|
399
|
-
else style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));
|
|
400
|
-
this.#writeModulationProportion(control, prefix);
|
|
401
|
-
}
|
|
402
|
-
#bindEntry(control, signal) {
|
|
403
|
-
const input = requireChild(control, "input", HTMLInputElement);
|
|
404
|
-
const bubble = control.querySelector("[popover]");
|
|
405
|
-
input.id = `sonic-entry-${this.#instance}`;
|
|
406
|
-
if (bubble) this.#readout = {
|
|
407
|
-
anchor: control,
|
|
408
|
-
bubble: new Readout(bubble)
|
|
409
|
-
};
|
|
410
|
-
const entry = new ValueEntry(input, {
|
|
411
|
-
commit: (text) => {
|
|
412
|
-
this.#commit((this.#parseValue ?? Number.parseFloat)(text));
|
|
413
|
-
},
|
|
414
|
-
text: () => this.#parseValue ? this.valueText : String(this.#value),
|
|
415
|
-
toggle: (isOpen) => {
|
|
416
|
-
if (isOpen) this.forwardNaming(input, true);
|
|
417
|
-
this.toggleState("editing", isOpen);
|
|
418
|
-
this.render();
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
this.#entry = entry;
|
|
422
|
-
entry.bind(control, signal);
|
|
423
|
-
return entry;
|
|
424
|
-
}
|
|
425
|
-
#bindKeys(control, entry, signal) {
|
|
426
|
-
control.addEventListener("keydown", (event) => {
|
|
427
|
-
if (this.isDisabled() || event.defaultPrevented || event.target !== control) return;
|
|
428
|
-
this.toggleState("springing", false);
|
|
429
|
-
if (event.key === "Enter") {
|
|
430
|
-
if (this.springTarget() !== void 0) return;
|
|
431
|
-
event.preventDefault();
|
|
432
|
-
entry.open();
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
const next = this.#keyTarget(event.key);
|
|
436
|
-
if (next === void 0) return;
|
|
437
|
-
event.preventDefault();
|
|
438
|
-
this.#keyTo(event, next);
|
|
439
|
-
this.#claim.reveal("keys");
|
|
440
|
-
this.#renderHold();
|
|
441
|
-
}, { signal });
|
|
442
|
-
control.addEventListener("keyup", (event) => {
|
|
443
|
-
const isMeta = event.key === "Meta";
|
|
444
|
-
if (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();
|
|
445
|
-
if (isMeta && this.#dragging()) return;
|
|
446
|
-
if (isMeta || this.mapping().keyTarget(event.key, this.#value) !== void 0) this.#springBack();
|
|
447
|
-
}, { signal });
|
|
448
|
-
control.addEventListener("blur", () => {
|
|
449
|
-
this.#endKeyScrub();
|
|
450
|
-
this.#concealKeyReveal();
|
|
451
|
-
this.#springBack();
|
|
452
|
-
}, { signal });
|
|
453
|
-
}
|
|
454
|
-
#commit(next, direction = 0) {
|
|
455
|
-
const landed = Number.isFinite(next) ? this.#land?.(next, direction) ?? next : next;
|
|
456
|
-
if (this.input(landed)) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
457
|
-
}
|
|
458
|
-
#concealKeyReveal() {
|
|
459
|
-
if (this.#claim.conceal("keys")) this.#renderHold();
|
|
460
|
-
}
|
|
461
|
-
#dragging() {
|
|
462
|
-
return this.#pointerDrag?.current();
|
|
463
|
-
}
|
|
464
|
-
#dragTo(drag, event) {
|
|
465
|
-
const isOutside = drag.outside?.(event) === true;
|
|
466
|
-
const wasEngaged = drag.state.isEngaged;
|
|
467
|
-
const mapping = this.mapping();
|
|
468
|
-
const { state, value } = stepDrag(mapping, drag.state, {
|
|
469
|
-
isFine: event.shiftKey,
|
|
470
|
-
isOutside,
|
|
471
|
-
position: drag.position(event)
|
|
472
|
-
});
|
|
473
|
-
drag.state = this.#withinLimit(mapping, state);
|
|
474
|
-
if (value === void 0) return;
|
|
475
|
-
if (!wasEngaged) this.#reveal(drag);
|
|
476
|
-
this.input(isOutside ? drag.fromValue : value);
|
|
477
|
-
if (isOutside === drag.isOutside) return;
|
|
478
|
-
drag.isOutside = isOutside;
|
|
479
|
-
this.#renderDragReveal(drag);
|
|
480
|
-
}
|
|
481
|
-
#endHolds() {
|
|
482
|
-
this.#entry?.close(false);
|
|
483
|
-
this.#pointerDrag?.end();
|
|
484
|
-
this.#endKeyScrub();
|
|
485
|
-
}
|
|
486
|
-
#endKeyScrub() {
|
|
487
|
-
const scrub = this.#keyScrub;
|
|
488
|
-
if (!scrub) return;
|
|
489
|
-
this.#keyScrub = void 0;
|
|
490
|
-
this.#renderHold();
|
|
491
|
-
if (this.#value !== scrub.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
379
|
+
#isEditing() {
|
|
380
|
+
return this.#gestures?.isEditing() === true;
|
|
492
381
|
}
|
|
493
382
|
#isHeld() {
|
|
494
|
-
return this.#
|
|
495
|
-
}
|
|
496
|
-
#keyTarget(key) {
|
|
497
|
-
if (resetKeys.has(key)) return this.default;
|
|
498
|
-
return this.mapping().keyTarget(key, this.#value, this.keyStep);
|
|
499
|
-
}
|
|
500
|
-
#keyTo(event, next) {
|
|
501
|
-
if (event.repeat && this.scrubsKeyRepeat()) {
|
|
502
|
-
this.#scrubKey(event.key, next);
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
this.#endKeyScrub();
|
|
506
|
-
this.#commit(next, next > this.#value ? 1 : -1);
|
|
507
|
-
}
|
|
508
|
-
#releaseDrag(drag) {
|
|
509
|
-
clearTimeout(drag.revealTimer);
|
|
510
|
-
this.#claim.conceal("drag");
|
|
511
|
-
this.#renderHold();
|
|
512
|
-
if (this.#value !== drag.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
513
|
-
this.#springBack();
|
|
383
|
+
return this.#gestures?.isHeld() === true;
|
|
514
384
|
}
|
|
515
385
|
#renderAria(control, orientation) {
|
|
516
|
-
this.writeFormValue(String(this.#value), String(this.#value));
|
|
517
|
-
if (this.#
|
|
386
|
+
this.writeFormValue(String(this.#cell.value), String(this.#cell.value));
|
|
387
|
+
if (this.#isEditing()) {
|
|
518
388
|
for (const name of roleAttributes) control.removeAttribute(name);
|
|
519
389
|
this.forwardNaming(control, false);
|
|
520
390
|
this.renderReadout();
|
|
@@ -524,16 +394,17 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
524
394
|
writeAttribute(control, "role", this.controlRole());
|
|
525
395
|
writeAttribute(control, "aria-valuemin", String(low));
|
|
526
396
|
writeAttribute(control, "aria-valuemax", String(high));
|
|
527
|
-
writeAttribute(control, "aria-valuenow", String(this.#
|
|
397
|
+
writeAttribute(control, "aria-valuenow", String(this.#spokenNow()));
|
|
528
398
|
if (orientation) writeAttribute(control, "aria-orientation", orientation);
|
|
529
|
-
writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#value));
|
|
399
|
+
writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#cell.value));
|
|
530
400
|
this.forwardNaming(control, true);
|
|
531
401
|
this.#renderDisabled(control);
|
|
532
402
|
this.renderReadout();
|
|
533
403
|
}
|
|
534
404
|
#renderControl() {
|
|
405
|
+
if (this.#isEditing() || this.isRevealed()) this.#hover?.clear();
|
|
535
406
|
this.draw();
|
|
536
|
-
this.toggleState("at-origin", !this.isWrapping() && this.#value === this.mapping().snap(this.originValue()));
|
|
407
|
+
this.toggleState("at-origin", !this.isWrapping() && this.#cell.value === this.mapping().snap(this.originValue()));
|
|
537
408
|
this.#renderAria(this.focusTarget(), this.controlOrientation());
|
|
538
409
|
}
|
|
539
410
|
#renderDisabled(control) {
|
|
@@ -542,104 +413,30 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
542
413
|
const stop = this.getAttribute("tabindex") === "-1" ? "-1" : "0";
|
|
543
414
|
writeAttribute(control, "tabindex", isDisabled ? void 0 : stop);
|
|
544
415
|
}
|
|
545
|
-
#renderDragReveal(drag) {
|
|
546
|
-
if (drag.isRevealed && !drag.isOutside) this.#claim.reveal("drag");
|
|
547
|
-
else this.#claim.conceal("drag");
|
|
548
|
-
this.#renderHold();
|
|
549
|
-
}
|
|
550
416
|
#renderHold() {
|
|
417
|
+
if (this.heldFrom() === void 0) this.#heldAt = void 0;
|
|
551
418
|
this.renderReadout();
|
|
552
419
|
this.holdChanged();
|
|
553
420
|
}
|
|
554
|
-
#reset() {
|
|
555
|
-
this.#commit(this.default ?? NaN);
|
|
556
|
-
}
|
|
557
|
-
#reveal(drag) {
|
|
558
|
-
if (drag.isRevealed || this.#dragging() !== drag) return;
|
|
559
|
-
drag.isRevealed = true;
|
|
560
|
-
this.#renderDragReveal(drag);
|
|
561
|
-
}
|
|
562
|
-
#scrubKey(key, next) {
|
|
563
|
-
if (this.#keyScrub?.key !== key) {
|
|
564
|
-
this.#endKeyScrub();
|
|
565
|
-
this.#keyScrub = {
|
|
566
|
-
fromValue: this.#value,
|
|
567
|
-
key
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
|
-
this.input(next);
|
|
571
|
-
}
|
|
572
421
|
#shown() {
|
|
573
|
-
if (this
|
|
422
|
+
if (this.#isEditing()) return {
|
|
574
423
|
isOpen: true,
|
|
575
424
|
value: void 0
|
|
576
425
|
};
|
|
577
|
-
const isRevealed = this
|
|
578
|
-
const preview = isRevealed ? void 0 : this
|
|
426
|
+
const isRevealed = this.isRevealed();
|
|
427
|
+
const preview = isRevealed ? void 0 : this.#hover?.value();
|
|
579
428
|
return {
|
|
580
429
|
isOpen: (isRevealed || preview !== void 0) && this.readout,
|
|
581
|
-
value: preview ?? this.#value
|
|
430
|
+
value: preview ?? this.#cell.value
|
|
582
431
|
};
|
|
583
432
|
}
|
|
584
|
-
#
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
if (this.mapping().snap(target) !== this.#value) this.toggleState("springing", true);
|
|
588
|
-
this.#commit(target);
|
|
589
|
-
}
|
|
590
|
-
#startDrag(control, axis, event) {
|
|
591
|
-
const mapping = this.mapping();
|
|
592
|
-
const detent = this.detent;
|
|
593
|
-
const start = {
|
|
594
|
-
from: this.#value,
|
|
595
|
-
position: axis.position(event),
|
|
596
|
-
proportion: axis.fromProportion ?? mapping.proportionOf(this.#value),
|
|
597
|
-
thresholdPx: dragThresholdPx(event.pointerType),
|
|
598
|
-
travelPx: axis.travelPx
|
|
599
|
-
};
|
|
600
|
-
if (detent === void 0) return startDrag(mapping, start);
|
|
601
|
-
const zonePx = readPxProperty(getComputedStyle(control), "--_sonic-detent-zone", detentZonePx);
|
|
602
|
-
return startDrag(mapping, {
|
|
603
|
-
...start,
|
|
604
|
-
detent: {
|
|
605
|
-
value: detent,
|
|
606
|
-
zone: zonePx / axis.travelPx
|
|
607
|
-
}
|
|
608
|
-
});
|
|
433
|
+
#spokenNow() {
|
|
434
|
+
const step = this.spokenStep;
|
|
435
|
+
return step !== void 0 && step > 0 ? trimFloat(Math.round(this.#cell.value / step) * step) : this.#cell.value;
|
|
609
436
|
}
|
|
610
437
|
#textFor(value) {
|
|
611
438
|
return this.#formatValue?.(value) ?? String(value);
|
|
612
439
|
}
|
|
613
|
-
#withinLimit(mapping, state) {
|
|
614
|
-
const limit = this.#limit;
|
|
615
|
-
if (!limit || mapping.isWrapping) return state;
|
|
616
|
-
const [low, high] = limit;
|
|
617
|
-
return {
|
|
618
|
-
...state,
|
|
619
|
-
rawProportion: clamp(state.rawProportion, mapping.proportionOf(low), mapping.proportionOf(high))
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
#write(next) {
|
|
623
|
-
if (!Number.isFinite(next)) return;
|
|
624
|
-
const clamped = this.mapping().snap(next);
|
|
625
|
-
this.#asked = clamped;
|
|
626
|
-
if (clamped === this.#value) return;
|
|
627
|
-
this.#value = clamped;
|
|
628
|
-
this.render();
|
|
629
|
-
}
|
|
630
|
-
#writeModulationProportion(control, prefix) {
|
|
631
|
-
const modulationValue = this.isWrapping() ? void 0 : this.#modulationValue;
|
|
632
|
-
const isModulated = modulationValue !== void 0;
|
|
633
|
-
if (isModulated !== this.#isModulated) {
|
|
634
|
-
this.#isModulated = isModulated;
|
|
635
|
-
this.toggleState("modulated", isModulated);
|
|
636
|
-
}
|
|
637
|
-
if (modulationValue === void 0) {
|
|
638
|
-
control.style.removeProperty(`--_sonic-${prefix}-modulation-value`);
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
control.style.setProperty(`--_sonic-${prefix}-modulation-value`, String(this.mapping().proportionOf(modulationValue)));
|
|
642
|
-
}
|
|
643
440
|
};
|
|
644
441
|
|
|
645
442
|
//#endregion
|