@xsynaptic/sonic-ui 0.5.0 → 0.6.1
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 +3 -1
- package/dist/default/dat.js +5 -4
- package/dist/default/define/button.js +1 -1
- package/dist/default/define.js +2 -2
- package/dist/default/elements/button.js +6 -5
- package/dist/default/elements/dial.js +5 -1
- package/dist/default/elements/envelope.js +46 -18
- package/dist/default/elements/meter.js +12 -8
- package/dist/default/elements/number.js +1 -1
- package/dist/default/elements/radio-group.js +46 -47
- package/dist/default/elements/readout-claim.js +0 -29
- package/dist/default/elements/readout.js +1 -1
- package/dist/default/elements/scale.js +43 -0
- package/dist/default/elements/slider.js +16 -3
- package/dist/default/elements/sonic-element.js +17 -55
- package/dist/default/elements/switch.js +33 -39
- package/dist/default/elements/value-element.js +142 -187
- package/dist/default/elements/wave-element.js +5 -2
- package/dist/default/elements/waveform.js +35 -12
- package/dist/default/elements/wavestrip.js +59 -18
- package/dist/default/elements/xy.js +34 -19
- package/dist/default/index.js +2 -2
- package/dist/default/lib/adsr-shape.js +5 -0
- package/dist/default/lib/ballistics.js +2 -2
- package/dist/default/lib/canvas-surface.js +13 -2
- package/dist/default/lib/distribute.js +1 -1
- package/dist/default/lib/drag-step.js +4 -4
- package/dist/default/lib/frame-timeline.js +2 -1
- package/dist/default/lib/marker-band.js +54 -10
- package/dist/default/lib/marker-rider.js +10 -4
- package/dist/default/lib/math.js +6 -1
- package/dist/default/lib/mirror-children.js +64 -0
- package/dist/default/lib/owned-control.js +10 -0
- package/dist/default/lib/pointer-drag.js +8 -5
- package/dist/default/lib/resample-peaks.js +11 -1
- package/dist/default/lib/time-regions.js +4 -1
- package/dist/default/lib/write-attribute.js +1 -0
- package/dist/dev/dat.d.ts +2 -2
- package/dist/dev/dat.js +5 -4
- package/dist/dev/dat.js.map +1 -1
- package/dist/dev/define/button.js +1 -1
- package/dist/dev/define.d.ts +4 -4
- package/dist/dev/define.js +2 -2
- package/dist/dev/elements/button.js +6 -5
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/dial.d.ts +1 -1
- package/dist/dev/elements/dial.js +5 -1
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/envelope.js +46 -18
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/meter.d.ts +1 -1
- package/dist/dev/elements/meter.js +12 -8
- package/dist/dev/elements/meter.js.map +1 -1
- package/dist/dev/elements/number.js +1 -1
- package/dist/dev/elements/number.js.map +1 -1
- package/dist/dev/elements/radio-group.js +46 -47
- package/dist/dev/elements/radio-group.js.map +1 -1
- package/dist/dev/elements/readout-claim.js +0 -29
- package/dist/dev/elements/readout-claim.js.map +1 -1
- package/dist/dev/elements/readout.js +1 -1
- package/dist/dev/elements/readout.js.map +1 -1
- package/dist/dev/elements/scale.js +44 -0
- package/dist/dev/elements/scale.js.map +1 -0
- package/dist/dev/elements/slider.d.ts +4 -1
- package/dist/dev/elements/slider.js +16 -3
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/sonic-element.d.ts +2 -8
- package/dist/dev/elements/sonic-element.js +18 -55
- package/dist/dev/elements/sonic-element.js.map +1 -1
- package/dist/dev/elements/switch.js +33 -39
- package/dist/dev/elements/switch.js.map +1 -1
- package/dist/dev/elements/value-element.d.ts +6 -8
- package/dist/dev/elements/value-element.js +142 -187
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/wave-element.d.ts +1 -0
- package/dist/dev/elements/wave-element.js +5 -2
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.d.ts +1 -1
- package/dist/dev/elements/waveform.js +35 -12
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +4 -0
- package/dist/dev/elements/wavestrip.js +59 -18
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.d.ts +3 -3
- package/dist/dev/elements/xy.js +34 -19
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +2 -2
- package/dist/dev/index.js +2 -2
- package/dist/dev/lib/adsr-shape.js +5 -0
- package/dist/dev/lib/adsr-shape.js.map +1 -1
- package/dist/dev/lib/ballistics.js +2 -2
- package/dist/dev/lib/ballistics.js.map +1 -1
- package/dist/dev/lib/canvas-surface.d.ts +1 -0
- package/dist/dev/lib/canvas-surface.js +13 -2
- package/dist/dev/lib/canvas-surface.js.map +1 -1
- package/dist/dev/lib/distribute.js +1 -1
- package/dist/dev/lib/distribute.js.map +1 -1
- package/dist/dev/lib/drag-step.js +4 -4
- package/dist/dev/lib/drag-step.js.map +1 -1
- package/dist/dev/lib/frame-timeline.js +2 -1
- package/dist/dev/lib/frame-timeline.js.map +1 -1
- package/dist/dev/lib/marker-band.js +54 -10
- package/dist/dev/lib/marker-band.js.map +1 -1
- package/dist/dev/lib/marker-rider.js +10 -4
- package/dist/dev/lib/marker-rider.js.map +1 -1
- package/dist/dev/lib/math.js +6 -1
- package/dist/dev/lib/math.js.map +1 -1
- package/dist/dev/lib/mirror-children.js +80 -0
- package/dist/dev/lib/mirror-children.js.map +1 -0
- package/dist/dev/lib/owned-control.js +23 -0
- package/dist/dev/lib/owned-control.js.map +1 -0
- package/dist/dev/lib/pointer-drag.js +8 -5
- package/dist/dev/lib/pointer-drag.js.map +1 -1
- package/dist/dev/lib/resample-peaks.js +11 -1
- package/dist/dev/lib/resample-peaks.js.map +1 -1
- package/dist/dev/lib/time-regions.js +4 -1
- package/dist/dev/lib/time-regions.js.map +1 -1
- package/dist/dev/lib/write-attribute.js +1 -0
- package/dist/dev/lib/write-attribute.js.map +1 -1
- package/dist/skins/amber.css +8 -0
- package/dist/skins/flat.css +26 -0
- package/dist/skins/ivory.css +1 -0
- package/dist/skins/lime.css +2 -0
- package/dist/skins/slate.css +2 -0
- package/dist/styles/button.css +59 -10
- package/dist/styles/dial.css +24 -16
- package/dist/styles/envelope.css +58 -13
- package/dist/styles/led.css +20 -4
- package/dist/styles/material.css +143 -55
- package/dist/styles/meter.css +8 -4
- package/dist/styles/panel.css +7 -4
- package/dist/styles/segmented.css +27 -5
- package/dist/styles/slider.css +2 -1
- package/dist/styles/switch.css +65 -23
- package/dist/styles/waveform.css +28 -5
- package/dist/styles/wavestrip.css +23 -6
- package/dist/styles/xy.css +48 -27
- package/package.json +2 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { TimeRegions } from "../lib/time-regions.js";
|
|
2
|
-
import { ValueMapping } from "../lib/value-mapping.js";
|
|
3
1
|
import { SonicFormElement } from "./form-element.js";
|
|
2
|
+
import { ValueMapping } from "../lib/value-mapping.js";
|
|
4
3
|
//#region src/elements/value-element.d.ts
|
|
5
4
|
export interface ValueAxis {
|
|
6
5
|
fromProportion?: number;
|
|
@@ -12,8 +11,6 @@ export interface ValueAxis {
|
|
|
12
11
|
export declare abstract class SonicValueElement extends SonicFormElement {
|
|
13
12
|
#private;
|
|
14
13
|
static readonly observedAttributes: string[];
|
|
15
|
-
get buffered(): Array<[number, number]>;
|
|
16
|
-
set buffered(regions: TimeRegions | undefined);
|
|
17
14
|
get default(): number | undefined;
|
|
18
15
|
set default(value: number | undefined);
|
|
19
16
|
get detent(): number | undefined;
|
|
@@ -49,12 +46,11 @@ export declare abstract class SonicValueElement extends SonicFormElement {
|
|
|
49
46
|
get taper(): 'linear' | 'log';
|
|
50
47
|
set taper(curve: 'linear' | 'log' | undefined);
|
|
51
48
|
get value(): number;
|
|
52
|
-
set value(next: number);
|
|
49
|
+
set value(next: null | number | undefined);
|
|
53
50
|
get valueText(): string;
|
|
54
51
|
attributeChangedCallback(name: string): void;
|
|
55
52
|
connectedCallback(): void;
|
|
56
53
|
protected bindGestures(control: HTMLElement, signal: AbortSignal, grab: (event: PointerEvent) => undefined | ValueAxis): void;
|
|
57
|
-
protected bindScale(control: HTMLElement, marks: HTMLElement, signal: AbortSignal): void;
|
|
58
54
|
protected controlOrientation(): 'horizontal' | 'vertical' | undefined;
|
|
59
55
|
protected controlRole(): 'slider' | 'spinbutton';
|
|
60
56
|
protected abstract draw(): void;
|
|
@@ -62,22 +58,24 @@ export declare abstract class SonicValueElement extends SonicFormElement {
|
|
|
62
58
|
protected heldFrom(): number | undefined;
|
|
63
59
|
protected heldWrite(_next: number): void;
|
|
64
60
|
protected holdChanged(): void;
|
|
65
|
-
protected hoverReadout(value: number | undefined): void;
|
|
66
61
|
protected input(next: number): boolean;
|
|
62
|
+
protected isEditing(): boolean;
|
|
67
63
|
protected isRevealed(): boolean;
|
|
68
64
|
protected isWrapping(): boolean;
|
|
69
65
|
protected mapping(): ValueMapping;
|
|
70
66
|
protected originValue(): number;
|
|
67
|
+
protected previewValue(): number | undefined;
|
|
71
68
|
protected proportionsChanged(): void;
|
|
72
69
|
protected readModulationValue(): number | undefined;
|
|
73
70
|
protected readoutValue(): number;
|
|
74
71
|
protected render(): void;
|
|
72
|
+
protected renderReadout(): void;
|
|
75
73
|
protected restoreState(state: string): void;
|
|
76
74
|
protected scrubsKeyRepeat(): boolean;
|
|
77
75
|
protected springTarget(): number | undefined;
|
|
78
76
|
protected tapTarget(): number | undefined;
|
|
79
77
|
protected travelPx(control: HTMLElement, property: `--_sonic-${string}`): number;
|
|
80
|
-
protected writeModulationValue(control: HTMLElement, prefix: 'dial' | 'slider', next: number | undefined): void;
|
|
78
|
+
protected writeModulationValue(control: HTMLElement, prefix: 'dial' | 'slider', next: null | number | undefined): void;
|
|
81
79
|
protected writeProportions(control: HTMLElement, prefix: 'dial' | 'slider', modulation: number): void;
|
|
82
80
|
}
|
|
83
81
|
//#endregion
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { clamp } from "../lib/math.js";
|
|
2
|
-
import { placeChildren, requireChild } from "../lib/render.js";
|
|
1
|
+
import { clamp, toNumber } from "../lib/math.js";
|
|
3
2
|
import { writeAttribute } from "../lib/write-attribute.js";
|
|
4
3
|
import { SonicFormElement } from "./form-element.js";
|
|
4
|
+
import { requireChild } from "../lib/render.js";
|
|
5
5
|
import { ReadoutClaim } from "./readout-claim.js";
|
|
6
6
|
import { Readout } from "./readout.js";
|
|
7
7
|
import { ValueEntry } from "./value-entry.js";
|
|
8
|
-
import { copyNode } from "../lib/copy-node.js";
|
|
9
8
|
import { dragThresholdPx, startDrag, stepDrag } from "../lib/drag-step.js";
|
|
10
9
|
import { focusByPointer } from "../lib/focus-by-pointer.js";
|
|
11
10
|
import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
|
|
12
11
|
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
|
-
import { readRegions } from "../lib/time-regions.js";
|
|
15
14
|
import { resetKeys, valueMapping } from "../lib/value-mapping.js";
|
|
16
15
|
|
|
17
16
|
//#region src/elements/value-element.ts
|
|
@@ -36,18 +35,6 @@ const roleAttributes = [
|
|
|
36
35
|
"role",
|
|
37
36
|
"tabindex"
|
|
38
37
|
];
|
|
39
|
-
function scaleValue(mark) {
|
|
40
|
-
const text = mark.dataset.sonicValue?.trim();
|
|
41
|
-
return text ? Number(text) : NaN;
|
|
42
|
-
}
|
|
43
|
-
function scaleMark(original) {
|
|
44
|
-
const mark = copyNode(original);
|
|
45
|
-
if (!(mark instanceof HTMLElement || mark instanceof SVGElement)) return void 0;
|
|
46
|
-
if (!Number.isFinite(scaleValue(mark))) return void 0;
|
|
47
|
-
const isTick = mark.childElementCount === 0 && mark.textContent.trim() === "";
|
|
48
|
-
mark.classList.add(isTick ? "sonic-scale-tick" : "sonic-scale-label");
|
|
49
|
-
return mark;
|
|
50
|
-
}
|
|
51
38
|
let link;
|
|
52
39
|
function linkValue(element) {
|
|
53
40
|
return link(element);
|
|
@@ -63,6 +50,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
63
50
|
"origin",
|
|
64
51
|
"readout",
|
|
65
52
|
"step",
|
|
53
|
+
"tabindex",
|
|
66
54
|
"taper",
|
|
67
55
|
"value",
|
|
68
56
|
"positions"
|
|
@@ -88,13 +76,6 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
88
76
|
}
|
|
89
77
|
});
|
|
90
78
|
}
|
|
91
|
-
get buffered() {
|
|
92
|
-
return this.#buffered.map(([start, end]) => [start, end]);
|
|
93
|
-
}
|
|
94
|
-
set buffered(regions) {
|
|
95
|
-
this.#buffered = regions ? readRegions(regions).toSorted((first, second) => first[0] - second[0]) : [];
|
|
96
|
-
this.render();
|
|
97
|
-
}
|
|
98
79
|
get default() {
|
|
99
80
|
return this.optionalNumberAttribute("default");
|
|
100
81
|
}
|
|
@@ -203,151 +184,130 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
203
184
|
return this.#value;
|
|
204
185
|
}
|
|
205
186
|
set value(next) {
|
|
187
|
+
if (next === void 0 || next === null) {
|
|
188
|
+
this.formResetCallback();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const value = toNumber(next);
|
|
206
192
|
if (this.#isHeld()) {
|
|
207
|
-
this.heldWrite(
|
|
193
|
+
this.heldWrite(value);
|
|
208
194
|
return;
|
|
209
195
|
}
|
|
210
|
-
this.#write(
|
|
196
|
+
this.#write(value);
|
|
197
|
+
if (Number.isFinite(value)) this.#asked = value;
|
|
211
198
|
}
|
|
212
199
|
get valueText() {
|
|
213
200
|
return this.#textFor(this.#value);
|
|
214
201
|
}
|
|
215
|
-
#
|
|
202
|
+
#asked;
|
|
216
203
|
#claim = new ReadoutClaim(() => {
|
|
217
204
|
this.#renderHold();
|
|
218
205
|
});
|
|
219
|
-
#drag;
|
|
220
206
|
#entry;
|
|
221
|
-
#escapeWatch;
|
|
222
207
|
#formatSpokenValue;
|
|
223
208
|
#formatValue;
|
|
224
209
|
#instance = String(instanceCount += 1);
|
|
225
|
-
#isDirty = false;
|
|
226
210
|
#isModulated = false;
|
|
227
211
|
#keyScrub;
|
|
228
212
|
#land;
|
|
229
213
|
#limit;
|
|
214
|
+
#mapping;
|
|
230
215
|
#modulationValue;
|
|
231
216
|
#parseValue;
|
|
217
|
+
#pointerDrag;
|
|
232
218
|
#positions;
|
|
233
219
|
#readout;
|
|
234
|
-
#scaleMarks;
|
|
235
220
|
#value = 0;
|
|
236
221
|
#watchers = /* @__PURE__ */ new Set();
|
|
237
222
|
attributeChangedCallback(name) {
|
|
223
|
+
this.#mapping = void 0;
|
|
238
224
|
this.#positions = parseNumberList(this.getAttribute("positions"));
|
|
239
225
|
if (name === "value") {
|
|
240
226
|
if (this.#isHeld()) {
|
|
241
227
|
this.heldWrite(this.numberAttribute("value", this.min));
|
|
242
228
|
return;
|
|
243
229
|
}
|
|
244
|
-
this.#
|
|
230
|
+
this.#asked = void 0;
|
|
245
231
|
}
|
|
246
|
-
if (name === "disabled" && this.isDisabled())
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
this.#endKeyScrub();
|
|
250
|
-
}
|
|
251
|
-
this.#value = this.mapping().snap(this.#isDirty ? this.#value : this.numberAttribute("value", this.min));
|
|
252
|
-
if (proportionAttributes.has(name)) this.proportionsChanged();
|
|
232
|
+
if (name === "disabled" && this.isDisabled()) this.#endHolds();
|
|
233
|
+
this.#value = this.mapping().snap(this.#asked ?? this.numberAttribute("value", this.min));
|
|
234
|
+
if (proportionAttributes.has(name) && this.isBound()) this.proportionsChanged();
|
|
253
235
|
this.render();
|
|
254
236
|
}
|
|
255
237
|
connectedCallback() {
|
|
256
|
-
this.upgradeProperties("
|
|
238
|
+
this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
|
|
257
239
|
super.connectedCallback();
|
|
258
240
|
}
|
|
259
241
|
bindGestures(control, signal, grab) {
|
|
260
242
|
const entry = this.#bindEntry(control, signal);
|
|
261
|
-
control
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
243
|
+
this.#pointerDrag = bindDrag(control, {
|
|
244
|
+
cancel: (drag) => {
|
|
245
|
+
if (drag.isKeptOnCancel !== true) this.input(drag.fromValue);
|
|
246
|
+
},
|
|
247
|
+
grab: (event) => {
|
|
248
|
+
if (isMenuPress(event) || this.isDisabled() || entry.isOpen) return;
|
|
249
|
+
this.toggleState("springing", false);
|
|
250
|
+
if (event.pointerType === "touch") event.preventDefault();
|
|
251
|
+
focusByPointer(control);
|
|
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;
|
|
271
|
+
},
|
|
272
|
+
lift: (drag, event) => {
|
|
273
|
+
const tap = drag.state.isEngaged ? void 0 : this.tapTarget();
|
|
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();
|
|
282
|
+
},
|
|
283
|
+
move: (drag, event) => {
|
|
284
|
+
this.#dragTo(drag, event);
|
|
285
|
+
},
|
|
286
|
+
release: (drag) => {
|
|
287
|
+
this.#releaseDrag(drag);
|
|
288
|
+
},
|
|
289
|
+
toggle: (isDragging) => {
|
|
290
|
+
this.toggleState("dragging", isDragging);
|
|
270
291
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (!axis) return;
|
|
274
|
-
const drag = {
|
|
275
|
-
...axis,
|
|
276
|
-
fromValue,
|
|
277
|
-
isOutside: false,
|
|
278
|
-
isRevealed: false,
|
|
279
|
-
pointerId: event.pointerId,
|
|
280
|
-
revealTimer: void 0,
|
|
281
|
-
state: this.#startDrag(control, axis, event)
|
|
282
|
-
};
|
|
283
|
-
drag.revealTimer = setTimeout(() => {
|
|
284
|
-
this.#reveal(drag);
|
|
285
|
-
}, 250);
|
|
286
|
-
this.#drag = drag;
|
|
287
|
-
control.setPointerCapture(event.pointerId);
|
|
288
|
-
this.toggleState("dragging", true);
|
|
289
|
-
}, { signal });
|
|
290
|
-
control.addEventListener("pointermove", (event) => {
|
|
291
|
-
const drag = this.#drag;
|
|
292
|
-
if (event.pointerId === drag?.pointerId) this.#dragTo(drag, event);
|
|
293
|
-
}, { signal });
|
|
294
|
-
const endDrag = (event) => {
|
|
295
|
-
if (event.pointerId === this.#drag?.pointerId) this.#endDrag();
|
|
296
|
-
};
|
|
297
|
-
control.addEventListener("pointercancel", (event) => {
|
|
298
|
-
const drag = this.#drag;
|
|
299
|
-
if (event.pointerId === drag?.pointerId && drag.isKeptOnCancel !== true) this.input(drag.fromValue);
|
|
300
|
-
endDrag(event);
|
|
292
|
+
}, signal);
|
|
293
|
+
control.addEventListener("pointercancel", () => {
|
|
301
294
|
entry.forgetPress();
|
|
302
295
|
}, { signal });
|
|
303
|
-
control.addEventListener("lostpointercapture", endDrag, { signal });
|
|
304
|
-
control.addEventListener("pointerup", (event) => {
|
|
305
|
-
const drag = this.#drag;
|
|
306
|
-
if (event.pointerId !== drag?.pointerId) return;
|
|
307
|
-
this.#endDrag();
|
|
308
|
-
const tap = drag.state.isEngaged ? void 0 : this.tapTarget();
|
|
309
|
-
if (tap !== void 0) {
|
|
310
|
-
entry.forgetPress();
|
|
311
|
-
this.#commit(tap);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
if (!entry.press(event) || this.springTarget() !== void 0) return;
|
|
315
|
-
if (this.doublePress === "reset") this.#reset();
|
|
316
|
-
else entry.open();
|
|
317
|
-
}, { signal });
|
|
318
296
|
this.#bindKeys(control, entry, signal);
|
|
319
297
|
signal.addEventListener("abort", () => {
|
|
320
|
-
this.#endDrag();
|
|
321
298
|
this.#endKeyScrub();
|
|
322
299
|
this.#concealKeyReveal();
|
|
323
300
|
}, { once: true });
|
|
324
301
|
}
|
|
325
|
-
bindScale(control, marks, signal) {
|
|
326
|
-
this.#scaleMarks = marks;
|
|
327
|
-
this.mirrorChildren({
|
|
328
|
-
control,
|
|
329
|
-
copy: scaleMark,
|
|
330
|
-
isCopied: (child) => child instanceof Element && child.matches("[data-sonic-value]"),
|
|
331
|
-
place: (copies) => {
|
|
332
|
-
placeChildren(marks, copies);
|
|
333
|
-
this.#renderScale();
|
|
334
|
-
}
|
|
335
|
-
}, signal);
|
|
336
|
-
}
|
|
337
302
|
controlOrientation() {}
|
|
338
303
|
controlRole() {
|
|
339
304
|
return "slider";
|
|
340
305
|
}
|
|
341
306
|
heldFrom() {
|
|
342
|
-
return this.#
|
|
307
|
+
return this.#dragging()?.fromValue ?? this.#keyScrub?.fromValue;
|
|
343
308
|
}
|
|
344
309
|
heldWrite(_next) {}
|
|
345
310
|
holdChanged() {}
|
|
346
|
-
hoverReadout(value) {
|
|
347
|
-
this.#claim.hover(value);
|
|
348
|
-
this.#renderReadout();
|
|
349
|
-
this.#watchEscape(value !== void 0);
|
|
350
|
-
}
|
|
351
311
|
input(next) {
|
|
352
312
|
const previous = this.#value;
|
|
353
313
|
this.#write(this.#limit ? clamp(next, ...this.#limit) : next);
|
|
@@ -358,6 +318,9 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
358
318
|
}));
|
|
359
319
|
return true;
|
|
360
320
|
}
|
|
321
|
+
isEditing() {
|
|
322
|
+
return this.#entry?.isOpen === true;
|
|
323
|
+
}
|
|
361
324
|
isRevealed() {
|
|
362
325
|
return this.#claim.isRevealed;
|
|
363
326
|
}
|
|
@@ -365,8 +328,9 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
365
328
|
return false;
|
|
366
329
|
}
|
|
367
330
|
mapping() {
|
|
331
|
+
if (this.#mapping) return this.#mapping;
|
|
368
332
|
const { detent, midpoint } = this;
|
|
369
|
-
|
|
333
|
+
this.#mapping = valueMapping({
|
|
370
334
|
...detent === void 0 ? {} : { detent },
|
|
371
335
|
...this.#positions ? { positions: this.#positions } : {},
|
|
372
336
|
max: this.max,
|
|
@@ -377,24 +341,33 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
377
341
|
step: this.step,
|
|
378
342
|
taper: this.taper
|
|
379
343
|
});
|
|
344
|
+
return this.#mapping;
|
|
380
345
|
}
|
|
381
346
|
originValue() {
|
|
382
347
|
return this.origin ?? this.mapping().bounds[0];
|
|
383
348
|
}
|
|
349
|
+
previewValue() {}
|
|
384
350
|
proportionsChanged() {}
|
|
385
351
|
readModulationValue() {
|
|
386
352
|
return this.#modulationValue;
|
|
387
353
|
}
|
|
388
354
|
readoutValue() {
|
|
389
|
-
return this.#
|
|
355
|
+
return this.#shown().value ?? this.#value;
|
|
390
356
|
}
|
|
391
357
|
render() {
|
|
392
|
-
this.
|
|
393
|
-
this.#renderScale();
|
|
394
|
-
this.toggleState("at-origin", !this.isWrapping() && this.#value === this.mapping().snap(this.originValue()));
|
|
395
|
-
this.#renderAria(this.focusTarget(), this.controlOrientation());
|
|
358
|
+
if (this.isBound()) this.#renderControl();
|
|
396
359
|
for (const listener of this.#watchers) listener();
|
|
397
360
|
}
|
|
361
|
+
renderReadout() {
|
|
362
|
+
const readout = this.#readout;
|
|
363
|
+
if (!readout) return;
|
|
364
|
+
const { isOpen, value } = this.#shown();
|
|
365
|
+
readout.bubble.show({
|
|
366
|
+
anchor: readout.anchor,
|
|
367
|
+
isOpen,
|
|
368
|
+
text: value === void 0 ? void 0 : this.#textFor(value)
|
|
369
|
+
});
|
|
370
|
+
}
|
|
398
371
|
restoreState(state) {
|
|
399
372
|
this.value = Number(state);
|
|
400
373
|
}
|
|
@@ -407,9 +380,10 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
407
380
|
return Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));
|
|
408
381
|
}
|
|
409
382
|
writeModulationValue(control, prefix, next) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
this.#
|
|
383
|
+
const value = next === void 0 || next === null ? void 0 : toNumber(next);
|
|
384
|
+
if (value !== void 0 && !Number.isFinite(value)) return;
|
|
385
|
+
this.#modulationValue = value;
|
|
386
|
+
if (this.isBound()) this.#writeModulationProportion(control, prefix);
|
|
413
387
|
}
|
|
414
388
|
writeProportions(control, prefix, modulation) {
|
|
415
389
|
const { style } = control;
|
|
@@ -439,7 +413,6 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
439
413
|
},
|
|
440
414
|
text: () => this.#parseValue ? this.valueText : String(this.#value),
|
|
441
415
|
toggle: (isOpen) => {
|
|
442
|
-
this.#claim.edit(isOpen);
|
|
443
416
|
if (isOpen) this.forwardNaming(input, true);
|
|
444
417
|
this.toggleState("editing", isOpen);
|
|
445
418
|
this.render();
|
|
@@ -469,7 +442,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
469
442
|
control.addEventListener("keyup", (event) => {
|
|
470
443
|
const isMeta = event.key === "Meta";
|
|
471
444
|
if (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();
|
|
472
|
-
if (isMeta && this.#
|
|
445
|
+
if (isMeta && this.#dragging()) return;
|
|
473
446
|
if (isMeta || this.mapping().keyTarget(event.key, this.#value) !== void 0) this.#springBack();
|
|
474
447
|
}, { signal });
|
|
475
448
|
control.addEventListener("blur", () => {
|
|
@@ -478,10 +451,6 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
478
451
|
this.#springBack();
|
|
479
452
|
}, { signal });
|
|
480
453
|
}
|
|
481
|
-
#canPress(event, entry) {
|
|
482
|
-
if (event.button !== 0 || isMenuPress(event) || this.isDisabled() || entry.isOpen) return false;
|
|
483
|
-
return !this.#drag || this.#drag.pointerId === event.pointerId;
|
|
484
|
-
}
|
|
485
454
|
#commit(next, direction = 0) {
|
|
486
455
|
const landed = Number.isFinite(next) ? this.#land?.(next, direction) ?? next : next;
|
|
487
456
|
if (this.input(landed)) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
@@ -489,6 +458,9 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
489
458
|
#concealKeyReveal() {
|
|
490
459
|
if (this.#claim.conceal("keys")) this.#renderHold();
|
|
491
460
|
}
|
|
461
|
+
#dragging() {
|
|
462
|
+
return this.#pointerDrag?.current();
|
|
463
|
+
}
|
|
492
464
|
#dragTo(drag, event) {
|
|
493
465
|
const isOutside = drag.outside?.(event) === true;
|
|
494
466
|
const wasEngaged = drag.state.isEngaged;
|
|
@@ -506,16 +478,10 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
506
478
|
drag.isOutside = isOutside;
|
|
507
479
|
this.#renderDragReveal(drag);
|
|
508
480
|
}
|
|
509
|
-
#
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
this.#drag = void 0;
|
|
514
|
-
this.toggleState("dragging", false);
|
|
515
|
-
this.#claim.conceal("drag");
|
|
516
|
-
this.#renderHold();
|
|
517
|
-
if (this.#value !== drag.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
518
|
-
this.#springBack();
|
|
481
|
+
#endHolds() {
|
|
482
|
+
this.#entry?.close(false);
|
|
483
|
+
this.#pointerDrag?.end();
|
|
484
|
+
this.#endKeyScrub();
|
|
519
485
|
}
|
|
520
486
|
#endKeyScrub() {
|
|
521
487
|
const scrub = this.#keyScrub;
|
|
@@ -525,7 +491,7 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
525
491
|
if (this.#value !== scrub.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
526
492
|
}
|
|
527
493
|
#isHeld() {
|
|
528
|
-
return this.#
|
|
494
|
+
return this.#dragging() !== void 0 || this.#keyScrub !== void 0;
|
|
529
495
|
}
|
|
530
496
|
#keyTarget(key) {
|
|
531
497
|
if (resetKeys.has(key)) return this.default;
|
|
@@ -539,33 +505,42 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
539
505
|
this.#endKeyScrub();
|
|
540
506
|
this.#commit(next, next > this.#value ? 1 : -1);
|
|
541
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();
|
|
514
|
+
}
|
|
542
515
|
#renderAria(control, orientation) {
|
|
543
516
|
this.writeFormValue(String(this.#value), String(this.#value));
|
|
544
517
|
if (this.#entry?.isOpen) {
|
|
545
518
|
for (const name of roleAttributes) control.removeAttribute(name);
|
|
546
519
|
this.forwardNaming(control, false);
|
|
547
|
-
this
|
|
520
|
+
this.renderReadout();
|
|
548
521
|
return;
|
|
549
522
|
}
|
|
550
523
|
const [low, high] = this.mapping().bounds;
|
|
551
|
-
control
|
|
552
|
-
control
|
|
553
|
-
control
|
|
554
|
-
control
|
|
555
|
-
if (orientation) control
|
|
524
|
+
writeAttribute(control, "role", this.controlRole());
|
|
525
|
+
writeAttribute(control, "aria-valuemin", String(low));
|
|
526
|
+
writeAttribute(control, "aria-valuemax", String(high));
|
|
527
|
+
writeAttribute(control, "aria-valuenow", String(this.#value));
|
|
528
|
+
if (orientation) writeAttribute(control, "aria-orientation", orientation);
|
|
556
529
|
writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#value));
|
|
557
530
|
this.forwardNaming(control, true);
|
|
558
531
|
this.#renderDisabled(control);
|
|
559
|
-
this
|
|
532
|
+
this.renderReadout();
|
|
533
|
+
}
|
|
534
|
+
#renderControl() {
|
|
535
|
+
this.draw();
|
|
536
|
+
this.toggleState("at-origin", !this.isWrapping() && this.#value === this.mapping().snap(this.originValue()));
|
|
537
|
+
this.#renderAria(this.focusTarget(), this.controlOrientation());
|
|
560
538
|
}
|
|
561
539
|
#renderDisabled(control) {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
control.removeAttribute("aria-disabled");
|
|
568
|
-
control.setAttribute("tabindex", "0");
|
|
540
|
+
const isDisabled = this.isDisabled();
|
|
541
|
+
writeAttribute(control, "aria-disabled", isDisabled ? "true" : void 0);
|
|
542
|
+
const stop = this.getAttribute("tabindex") === "-1" ? "-1" : "0";
|
|
543
|
+
writeAttribute(control, "tabindex", isDisabled ? void 0 : stop);
|
|
569
544
|
}
|
|
570
545
|
#renderDragReveal(drag) {
|
|
571
546
|
if (drag.isRevealed && !drag.isOutside) this.#claim.reveal("drag");
|
|
@@ -573,33 +548,14 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
573
548
|
this.#renderHold();
|
|
574
549
|
}
|
|
575
550
|
#renderHold() {
|
|
576
|
-
this
|
|
551
|
+
this.renderReadout();
|
|
577
552
|
this.holdChanged();
|
|
578
553
|
}
|
|
579
|
-
#renderReadout() {
|
|
580
|
-
const readout = this.#readout;
|
|
581
|
-
if (!readout) return;
|
|
582
|
-
const { isOpen, value } = this.#claim.shown(this.#value, this.readout);
|
|
583
|
-
readout.bubble.show({
|
|
584
|
-
anchor: readout.anchor,
|
|
585
|
-
isOpen,
|
|
586
|
-
text: value === void 0 ? void 0 : this.#textFor(value)
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
#renderScale() {
|
|
590
|
-
const marks = this.#scaleMarks?.children ?? [];
|
|
591
|
-
const mapping = this.mapping();
|
|
592
|
-
for (const mark of marks) {
|
|
593
|
-
if (!(mark instanceof HTMLElement || mark instanceof SVGElement)) continue;
|
|
594
|
-
const at = String(mapping.proportionOf(scaleValue(mark)));
|
|
595
|
-
if (mark.style.getPropertyValue("--_sonic-scale-at") !== at) mark.style.setProperty("--_sonic-scale-at", at);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
554
|
#reset() {
|
|
599
555
|
this.#commit(this.default ?? NaN);
|
|
600
556
|
}
|
|
601
557
|
#reveal(drag) {
|
|
602
|
-
if (drag.isRevealed || this.#
|
|
558
|
+
if (drag.isRevealed || this.#dragging() !== drag) return;
|
|
603
559
|
drag.isRevealed = true;
|
|
604
560
|
this.#renderDragReveal(drag);
|
|
605
561
|
}
|
|
@@ -613,6 +569,18 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
613
569
|
}
|
|
614
570
|
this.input(next);
|
|
615
571
|
}
|
|
572
|
+
#shown() {
|
|
573
|
+
if (this.isEditing()) return {
|
|
574
|
+
isOpen: true,
|
|
575
|
+
value: void 0
|
|
576
|
+
};
|
|
577
|
+
const isRevealed = this.#claim.isRevealed;
|
|
578
|
+
const preview = isRevealed ? void 0 : this.previewValue();
|
|
579
|
+
return {
|
|
580
|
+
isOpen: (isRevealed || preview !== void 0) && this.readout,
|
|
581
|
+
value: preview ?? this.#value
|
|
582
|
+
};
|
|
583
|
+
}
|
|
616
584
|
#springBack() {
|
|
617
585
|
const target = this.springTarget();
|
|
618
586
|
if (target === void 0) return;
|
|
@@ -642,19 +610,6 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
642
610
|
#textFor(value) {
|
|
643
611
|
return this.#formatValue?.(value) ?? String(value);
|
|
644
612
|
}
|
|
645
|
-
#watchEscape(isHovered) {
|
|
646
|
-
if (!isHovered) {
|
|
647
|
-
this.#escapeWatch?.abort();
|
|
648
|
-
this.#escapeWatch = void 0;
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
651
|
-
if (this.#escapeWatch) return;
|
|
652
|
-
const watch = new AbortController();
|
|
653
|
-
this.#escapeWatch = watch;
|
|
654
|
-
this.ownerDocument.addEventListener("keydown", (event) => {
|
|
655
|
-
if (event.key === "Escape" && this.#claim.dismiss()) this.#renderHold();
|
|
656
|
-
}, { signal: watch.signal });
|
|
657
|
-
}
|
|
658
613
|
#withinLimit(mapping, state) {
|
|
659
614
|
const limit = this.#limit;
|
|
660
615
|
if (!limit || mapping.isWrapping) return state;
|
|
@@ -666,8 +621,8 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
666
621
|
}
|
|
667
622
|
#write(next) {
|
|
668
623
|
if (!Number.isFinite(next)) return;
|
|
669
|
-
this.#isDirty = true;
|
|
670
624
|
const clamped = this.mapping().snap(next);
|
|
625
|
+
this.#asked = clamped;
|
|
671
626
|
if (clamped === this.#value) return;
|
|
672
627
|
this.#value = clamped;
|
|
673
628
|
this.render();
|