@xsynaptic/sonic-ui 0.26.0 → 0.27.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/CHANGELOG.md +7 -0
- package/dist/default/elements/{display-element.js → analyser-element.js} +10 -12
- package/dist/default/elements/button.js +12 -9
- package/dist/default/elements/dial.js +9 -13
- package/dist/default/elements/envelope.js +26 -23
- package/dist/default/elements/field-gesture.js +49 -8
- package/dist/default/elements/meter.js +6 -8
- package/dist/default/elements/number.js +5 -14
- package/dist/default/elements/position-group.js +4 -4
- package/dist/default/elements/radio-group.js +6 -9
- package/dist/default/elements/segmented.js +7 -4
- package/dist/default/elements/slider.js +12 -13
- package/dist/default/elements/sonic-element.js +7 -5
- package/dist/default/elements/spectrum.js +3 -3
- package/dist/default/elements/switch.js +11 -6
- package/dist/default/elements/toggle.js +14 -8
- package/dist/default/elements/value-element.js +11 -3
- package/dist/default/elements/wave-element.js +11 -12
- package/dist/default/elements/waveform.js +1 -4
- package/dist/default/elements/wavestrip.js +1 -1
- package/dist/default/elements/xy.js +34 -47
- package/dist/default/lib/canvas-surface.js +13 -1
- package/dist/default/lib/render.js +2 -2
- package/dist/dev/elements/{display-element.d.ts → analyser-element.d.ts} +3 -3
- package/dist/dev/elements/{display-element.js → analyser-element.js} +11 -14
- package/dist/dev/elements/analyser-element.js.map +1 -0
- package/dist/dev/elements/button.d.ts +4 -1
- package/dist/dev/elements/button.js +12 -14
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/dial.d.ts +4 -2
- package/dist/dev/elements/dial.js +9 -17
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/envelope.d.ts +5 -1
- package/dist/dev/elements/envelope.js +26 -27
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/field-gesture.js +49 -8
- package/dist/dev/elements/field-gesture.js.map +1 -1
- package/dist/dev/elements/meter.d.ts +2 -1
- package/dist/dev/elements/meter.js +6 -9
- package/dist/dev/elements/meter.js.map +1 -1
- package/dist/dev/elements/number.d.ts +2 -2
- package/dist/dev/elements/number.js +5 -15
- package/dist/dev/elements/number.js.map +1 -1
- package/dist/dev/elements/position-group.js +4 -4
- package/dist/dev/elements/position-group.js.map +1 -1
- package/dist/dev/elements/radio-group.d.ts +1 -2
- package/dist/dev/elements/radio-group.js +6 -9
- package/dist/dev/elements/radio-group.js.map +1 -1
- package/dist/dev/elements/segmented.d.ts +4 -2
- package/dist/dev/elements/segmented.js +7 -9
- package/dist/dev/elements/segmented.js.map +1 -1
- package/dist/dev/elements/slider.d.ts +4 -2
- package/dist/dev/elements/slider.js +12 -17
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/sonic-element.d.ts +5 -7
- package/dist/dev/elements/sonic-element.js +13 -83
- package/dist/dev/elements/sonic-element.js.map +1 -1
- package/dist/dev/elements/spectrum.d.ts +2 -2
- package/dist/dev/elements/spectrum.js +3 -3
- package/dist/dev/elements/spectrum.js.map +1 -1
- package/dist/dev/elements/switch.d.ts +4 -1
- package/dist/dev/elements/switch.js +11 -10
- package/dist/dev/elements/switch.js.map +1 -1
- package/dist/dev/elements/toggle.d.ts +4 -1
- package/dist/dev/elements/toggle.js +14 -13
- package/dist/dev/elements/toggle.js.map +1 -1
- package/dist/dev/elements/value-element.d.ts +4 -3
- package/dist/dev/elements/value-element.js +11 -3
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/wave-element.d.ts +2 -2
- package/dist/dev/elements/wave-element.js +11 -16
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.d.ts +0 -1
- package/dist/dev/elements/waveform.js +1 -4
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.js +1 -1
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.d.ts +4 -1
- package/dist/dev/elements/xy.js +34 -51
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +3 -1
- package/dist/dev/lib/canvas-surface.js +13 -1
- package/dist/dev/lib/canvas-surface.js.map +1 -1
- package/dist/dev/lib/check-styles.d.ts +8 -0
- package/dist/dev/lib/check-styles.js +87 -0
- package/dist/dev/lib/check-styles.js.map +1 -0
- package/dist/dev/lib/render.js +2 -2
- package/dist/dev/lib/render.js.map +1 -1
- package/package.json +1 -1
- package/dist/dev/elements/display-element.js.map +0 -1
|
@@ -48,6 +48,7 @@ var SonicElement = class SonicElement extends HTMLElement {
|
|
|
48
48
|
this.#connection = void 0;
|
|
49
49
|
throw error;
|
|
50
50
|
}
|
|
51
|
+
const { boxProbe: box, control, sheet } = this;
|
|
51
52
|
}
|
|
52
53
|
connectedMoveCallback() {}
|
|
53
54
|
disconnectedCallback() {
|
|
@@ -67,7 +68,6 @@ var SonicElement = class SonicElement extends HTMLElement {
|
|
|
67
68
|
}
|
|
68
69
|
if (!this.isDisabled() && !this.#focused()) target.focus(options);
|
|
69
70
|
}
|
|
70
|
-
checkStyles(control, sheet, box) {}
|
|
71
71
|
focusTarget() {}
|
|
72
72
|
forwardNaming(target, isNamed) {
|
|
73
73
|
const labels = isNamed ? this.namingLabels() : [];
|
|
@@ -87,7 +87,9 @@ var SonicElement = class SonicElement extends HTMLElement {
|
|
|
87
87
|
isDisabled() {
|
|
88
88
|
return this.disabled || this.matches(":disabled");
|
|
89
89
|
}
|
|
90
|
-
keepControl(
|
|
90
|
+
keepControl(signal) {
|
|
91
|
+
const control = this.control;
|
|
92
|
+
if (!control) return;
|
|
91
93
|
const keep = () => {
|
|
92
94
|
appendOnce(this, control);
|
|
93
95
|
};
|
|
@@ -116,7 +118,9 @@ var SonicElement = class SonicElement extends HTMLElement {
|
|
|
116
118
|
}
|
|
117
119
|
this.setAttribute(name, value === true ? "" : value.toString());
|
|
118
120
|
}
|
|
119
|
-
stateTarget() {
|
|
121
|
+
stateTarget() {
|
|
122
|
+
return this.control;
|
|
123
|
+
}
|
|
120
124
|
toggleState(state, isOn) {
|
|
121
125
|
if (isOn) this.#states.add(state);
|
|
122
126
|
else this.#states.delete(state);
|
|
@@ -133,8 +137,6 @@ var SonicElement = class SonicElement extends HTMLElement {
|
|
|
133
137
|
usesChild(_child) {
|
|
134
138
|
return false;
|
|
135
139
|
}
|
|
136
|
-
#checkBox(control, checked, box) {}
|
|
137
|
-
#checkHost(checked) {}
|
|
138
140
|
#focused() {
|
|
139
141
|
const root = this.getRootNode();
|
|
140
142
|
const active = root instanceof ShadowRoot ? root.activeElement : this.ownerDocument.activeElement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { requireChild, template } from "../lib/render.js";
|
|
2
|
-
import {
|
|
2
|
+
import { SonicAnalyserElement } from "./analyser-element.js";
|
|
3
3
|
import { columnEdges, columnLevels, gridColumns, gridRows, levelRows, loudestBin, zoneRows } from "../lib/spectrum-columns.js";
|
|
4
4
|
import { areSettled, createLevels, receiveLevels, stepLevels } from "../lib/spectrum-levels.js";
|
|
5
5
|
|
|
@@ -71,9 +71,9 @@ function paintHolds(context, { look, rowOf }, { bars, holds }) {
|
|
|
71
71
|
context.fillStyle = look.colours.lit;
|
|
72
72
|
context.fill();
|
|
73
73
|
}
|
|
74
|
-
var SonicSpectrum = class extends
|
|
74
|
+
var SonicSpectrum = class extends SonicAnalyserElement {
|
|
75
75
|
static observedAttributes = [
|
|
76
|
-
...
|
|
76
|
+
...SonicAnalyserElement.observedAttributes,
|
|
77
77
|
"frequency-max",
|
|
78
78
|
"frequency-min",
|
|
79
79
|
"grid",
|
|
@@ -20,20 +20,25 @@ const renderBare = template(`<button class="sonic-switch-position" role="switch"
|
|
|
20
20
|
const pressCenterZone = .08;
|
|
21
21
|
var SonicSwitch = class extends SonicPositionGroupElement {
|
|
22
22
|
bare = renderBare();
|
|
23
|
+
boxProbe = {
|
|
24
|
+
property: "padding-top",
|
|
25
|
+
selector: ".sonic-switch-label"
|
|
26
|
+
};
|
|
27
|
+
control = renderSwitch();
|
|
23
28
|
defaultOrientation = "vertical";
|
|
24
|
-
|
|
25
|
-
#bat = requireChild(this.
|
|
29
|
+
sheet = "switch.css";
|
|
30
|
+
#bat = requireChild(this.control, ".sonic-switch-bat", HTMLSpanElement);
|
|
26
31
|
#isClickSwallowed = false;
|
|
27
32
|
claimPress(index, event) {
|
|
28
33
|
if (this.#isOnBat(event)) return true;
|
|
29
34
|
const target = this.pressTarget(index);
|
|
30
35
|
if (this.isOptionDisabled(target) || !this.isMomentary(target)) return false;
|
|
31
|
-
capturePointer(this.
|
|
36
|
+
capturePointer(this.control, event.pointerId);
|
|
32
37
|
this.hold(target, event.pointerId);
|
|
33
38
|
return true;
|
|
34
39
|
}
|
|
35
40
|
connect(signal) {
|
|
36
|
-
const group = this.
|
|
41
|
+
const group = this.control;
|
|
37
42
|
super.connect(signal);
|
|
38
43
|
this.bare.addEventListener("click", (event) => {
|
|
39
44
|
const isSwallowed = this.#isClickSwallowed && event instanceof PointerEvent && event.pointerType !== "";
|
|
@@ -70,7 +75,7 @@ var SonicSwitch = class extends SonicPositionGroupElement {
|
|
|
70
75
|
lift: (press, event) => {
|
|
71
76
|
this.#isClickSwallowed = true;
|
|
72
77
|
if (press.hasMoved || this.isDisabled()) return;
|
|
73
|
-
if (!isUnder(this.
|
|
78
|
+
if (!isUnder(this.control, event.clientX, event.clientY)) return;
|
|
74
79
|
this.#pressBat(event);
|
|
75
80
|
},
|
|
76
81
|
move: (press, event) => {
|
|
@@ -101,7 +106,7 @@ var SonicSwitch = class extends SonicPositionGroupElement {
|
|
|
101
106
|
#renderThrow(index) {
|
|
102
107
|
const count = this.positions().length;
|
|
103
108
|
const at = index < 0 || count < 2 ? 0 : 2 * index / (count - 1) - 1;
|
|
104
|
-
this.
|
|
109
|
+
this.control.style.setProperty("--_sonic-switch-at", String(at));
|
|
105
110
|
}
|
|
106
111
|
#sideStep(from, event) {
|
|
107
112
|
const box = this.#bat.getBoundingClientRect();
|
|
@@ -22,12 +22,18 @@ const renderBare = template(`<button class="sonic-toggle-position" role="switch"
|
|
|
22
22
|
const pressTolerance = 2;
|
|
23
23
|
var SonicToggle = class extends SonicPositionGroupElement {
|
|
24
24
|
bare = renderBare();
|
|
25
|
+
boxProbe = {
|
|
26
|
+
property: "margin-top",
|
|
27
|
+
ratio: "--_sonic-toggle-gap-ratio",
|
|
28
|
+
selector: ".sonic-toggle-cap"
|
|
29
|
+
};
|
|
30
|
+
control = renderToggle();
|
|
25
31
|
defaultOrientation = "horizontal";
|
|
26
|
-
|
|
27
|
-
#cap = requireChild(this.
|
|
32
|
+
sheet = "toggle.css";
|
|
33
|
+
#cap = requireChild(this.control, ".sonic-toggle-cap", HTMLSpanElement);
|
|
28
34
|
#draggedTo;
|
|
29
35
|
#hasWarnedOfLegends = false;
|
|
30
|
-
#well = requireChild(this.
|
|
36
|
+
#well = requireChild(this.control, ".sonic-toggle-well", HTMLSpanElement);
|
|
31
37
|
claimPress() {
|
|
32
38
|
return true;
|
|
33
39
|
}
|
|
@@ -49,7 +55,7 @@ var SonicToggle = class extends SonicPositionGroupElement {
|
|
|
49
55
|
}
|
|
50
56
|
render() {
|
|
51
57
|
if (!this.isBound()) return;
|
|
52
|
-
this.
|
|
58
|
+
this.control.style.setProperty("--_sonic-toggle-count", String(this.positions().length));
|
|
53
59
|
this.#placeCap(this.#draggedTo ?? this.#restingAt());
|
|
54
60
|
super.render();
|
|
55
61
|
for (const [index, option] of this.options().entries()) option.style.setProperty("--_sonic-toggle-index", String(index));
|
|
@@ -58,11 +64,11 @@ var SonicToggle = class extends SonicPositionGroupElement {
|
|
|
58
64
|
return renderPosition();
|
|
59
65
|
}
|
|
60
66
|
#bindCap(signal) {
|
|
61
|
-
bindDrag(this.
|
|
67
|
+
bindDrag(this.control, {
|
|
62
68
|
grab: (event) => this.#grab(event),
|
|
63
69
|
lift: (drag, event) => {
|
|
64
70
|
if (!drag.isPress || drag.isHolding || this.isDisabled()) return;
|
|
65
|
-
if (!isUnder(this.
|
|
71
|
+
if (!isUnder(this.control, event.clientX, event.clientY)) return;
|
|
66
72
|
this.#press(drag.position);
|
|
67
73
|
},
|
|
68
74
|
move: (drag, event) => {
|
|
@@ -85,7 +91,7 @@ var SonicToggle = class extends SonicPositionGroupElement {
|
|
|
85
91
|
}
|
|
86
92
|
#checkLegends() {}
|
|
87
93
|
#fixedLegend() {
|
|
88
|
-
return [...this.children].find((child) => child !== this.
|
|
94
|
+
return [...this.children].find((child) => child !== this.control && !super.isMirrored(child));
|
|
89
95
|
}
|
|
90
96
|
#grab(event) {
|
|
91
97
|
const position = this.pressedIndex(event.target);
|
|
@@ -113,7 +119,7 @@ var SonicToggle = class extends SonicPositionGroupElement {
|
|
|
113
119
|
return true;
|
|
114
120
|
}
|
|
115
121
|
#placeCap(at) {
|
|
116
|
-
this.
|
|
122
|
+
this.control.style.setProperty("--_sonic-toggle-at", String(at));
|
|
117
123
|
}
|
|
118
124
|
#press(position) {
|
|
119
125
|
const target = this.pressTarget(position);
|
|
@@ -251,7 +251,8 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
251
251
|
abandonHold() {
|
|
252
252
|
this.#gestures?.abandon();
|
|
253
253
|
}
|
|
254
|
-
bindGestures(
|
|
254
|
+
bindGestures(signal, grab) {
|
|
255
|
+
const control = this.control;
|
|
255
256
|
const bubble = control.querySelector("[popover]");
|
|
256
257
|
if (bubble) this.#readout = {
|
|
257
258
|
anchor: control,
|
|
@@ -316,6 +317,9 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
316
317
|
controlRole() {
|
|
317
318
|
return "slider";
|
|
318
319
|
}
|
|
320
|
+
focusTarget() {
|
|
321
|
+
return this.control;
|
|
322
|
+
}
|
|
319
323
|
input(next) {
|
|
320
324
|
const previous = this.#model.value;
|
|
321
325
|
if (this.#model.input(next)) this.render();
|
|
@@ -374,8 +378,12 @@ var SonicValueElement = class extends SonicFormElement {
|
|
|
374
378
|
}
|
|
375
379
|
springTarget() {}
|
|
376
380
|
tapTarget() {}
|
|
377
|
-
|
|
378
|
-
|
|
381
|
+
upwardAxis(travelProperty) {
|
|
382
|
+
const styles = getComputedStyle(this.control);
|
|
383
|
+
return {
|
|
384
|
+
position: (event) => -event.clientY,
|
|
385
|
+
travelPx: Math.max(1, readPxProperty(styles, travelProperty, fallbackTravelPx))
|
|
386
|
+
};
|
|
379
387
|
}
|
|
380
388
|
#entryText() {
|
|
381
389
|
const value = this.#model.value;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SonicValueElement } from "./value-element.js";
|
|
2
|
-
import {
|
|
2
|
+
import { bindControlSurface } from "../lib/canvas-surface.js";
|
|
3
3
|
import { formatClock, parseClock } from "../lib/clock.js";
|
|
4
4
|
import { spokenDuration } from "../lib/spoken-duration.js";
|
|
5
5
|
|
|
@@ -32,6 +32,10 @@ var SonicWaveElement = class extends SonicValueElement {
|
|
|
32
32
|
this.renderMarkers();
|
|
33
33
|
this.render();
|
|
34
34
|
}
|
|
35
|
+
boxProbe = {
|
|
36
|
+
property: "margin-bottom",
|
|
37
|
+
selector: "[popover]"
|
|
38
|
+
};
|
|
35
39
|
notation = {
|
|
36
40
|
format: formatClock,
|
|
37
41
|
parse: parseClock,
|
|
@@ -65,15 +69,13 @@ var SonicWaveElement = class extends SonicValueElement {
|
|
|
65
69
|
}
|
|
66
70
|
connect(signal) {
|
|
67
71
|
const control = this.control;
|
|
68
|
-
this.keepControl(
|
|
72
|
+
this.keepControl(signal);
|
|
69
73
|
this.renderEmpty();
|
|
70
|
-
this.#surface =
|
|
74
|
+
this.#surface = bindControlSurface({
|
|
71
75
|
canvas: this.canvas,
|
|
72
76
|
colours: this.colours,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
sizeProperty: this.sizeProperty
|
|
76
|
-
},
|
|
77
|
+
control,
|
|
78
|
+
fill: this.fill,
|
|
77
79
|
lengths: this.lengths,
|
|
78
80
|
numbers: this.numbers,
|
|
79
81
|
paint: (context, frame) => {
|
|
@@ -82,10 +84,10 @@ var SonicWaveElement = class extends SonicValueElement {
|
|
|
82
84
|
resize: () => {
|
|
83
85
|
this.renderMarkers();
|
|
84
86
|
},
|
|
85
|
-
signal
|
|
87
|
+
signal,
|
|
88
|
+
sizeProperty: this.sizeProperty
|
|
86
89
|
});
|
|
87
90
|
this.render();
|
|
88
|
-
this.#surface.setFill(this.fill);
|
|
89
91
|
}
|
|
90
92
|
markerList() {
|
|
91
93
|
return this.#markers;
|
|
@@ -113,9 +115,6 @@ var SonicWaveElement = class extends SonicValueElement {
|
|
|
113
115
|
this.#current = current;
|
|
114
116
|
this.dispatchEvent(new Event("sonic-marker", { bubbles: true }));
|
|
115
117
|
}
|
|
116
|
-
stateTarget() {
|
|
117
|
-
return this.control;
|
|
118
|
-
}
|
|
119
118
|
surface() {
|
|
120
119
|
return this.#surface;
|
|
121
120
|
}
|
|
@@ -231,7 +231,7 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
231
231
|
}
|
|
232
232
|
};
|
|
233
233
|
this.#zoomGesture = bindZoom(this.control, zoomTarget, signal);
|
|
234
|
-
this.bindGestures(
|
|
234
|
+
this.bindGestures(signal, () => this.#grab());
|
|
235
235
|
bindZoomKeys(this.control, zoomTarget, signal);
|
|
236
236
|
if (!("fonts" in document)) return;
|
|
237
237
|
document.fonts.addEventListener("loadingdone", () => {
|
|
@@ -243,9 +243,6 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
243
243
|
surface?.requestFrame();
|
|
244
244
|
if (surface?.isVisible === false || !this.#drawn) this.showCurrentMarker(this.#sourceSeconds());
|
|
245
245
|
}
|
|
246
|
-
focusTarget() {
|
|
247
|
-
return this.control;
|
|
248
|
-
}
|
|
249
246
|
isEmpty() {
|
|
250
247
|
return !this.#peaks || this.#peaks.samples.length === 0;
|
|
251
248
|
}
|
|
@@ -157,7 +157,7 @@ var SonicWavestrip = class extends SonicWaveElement {
|
|
|
157
157
|
},
|
|
158
158
|
valueAt: (event) => this.#markerStartAt(event, this.#axis()) ?? this.mapping().snap(this.valueFromPoint(event.clientX, event.clientY))
|
|
159
159
|
});
|
|
160
|
-
this.bindGestures(
|
|
160
|
+
this.bindGestures(signal, (event) => this.#grab(event));
|
|
161
161
|
}
|
|
162
162
|
draw() {
|
|
163
163
|
const surface = this.surface();
|
|
@@ -3,10 +3,7 @@ import { writeAttribute } from "../lib/write-attribute.js";
|
|
|
3
3
|
import { SonicFormElement } from "./form-element.js";
|
|
4
4
|
import { requireChild, template } from "../lib/render.js";
|
|
5
5
|
import { Readout } from "./readout.js";
|
|
6
|
-
import { ReadoutClaim } from "./readout-claim.js";
|
|
7
|
-
import { createDoublePress } from "../lib/double-press.js";
|
|
8
6
|
import { focusByPointer } from "../lib/focus-by-pointer.js";
|
|
9
|
-
import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
|
|
10
7
|
import { resetKeys } from "../lib/value-mapping.js";
|
|
11
8
|
import { createValueModel } from "../lib/value-model.js";
|
|
12
9
|
import { pointerPosition } from "../lib/field.js";
|
|
@@ -203,26 +200,26 @@ var SonicXy = class extends SonicFormElement {
|
|
|
203
200
|
set yTaper(curve) {
|
|
204
201
|
this.reflect("y-taper", curve);
|
|
205
202
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
203
|
+
boxProbe = {
|
|
204
|
+
property: "margin-bottom",
|
|
205
|
+
selector: "[popover]"
|
|
206
|
+
};
|
|
207
|
+
control = renderXy();
|
|
208
|
+
sheet = "xy.css";
|
|
209
209
|
#currentAxis = "x";
|
|
210
|
-
#
|
|
211
|
-
#xy = renderXy();
|
|
212
|
-
#field = requireChild(this.#xy, ".sonic-xy-field", HTMLDivElement);
|
|
210
|
+
#field = requireChild(this.control, ".sonic-xy-field", HTMLDivElement);
|
|
213
211
|
#formatValue;
|
|
214
212
|
#gesture;
|
|
215
|
-
#isRevealed = false;
|
|
216
213
|
#models = {
|
|
217
214
|
x: createValueModel(() => this.#spec("x")),
|
|
218
215
|
y: createValueModel(() => this.#spec("y"))
|
|
219
216
|
};
|
|
220
217
|
#parts = {
|
|
221
|
-
x: requireChild(this
|
|
222
|
-
y: requireChild(this
|
|
218
|
+
x: requireChild(this.control, "[data-sonic-axis=\"x\"]", HTMLDivElement),
|
|
219
|
+
y: requireChild(this.control, "[data-sonic-axis=\"y\"]", HTMLDivElement)
|
|
223
220
|
};
|
|
224
|
-
#puck = requireChild(this
|
|
225
|
-
#readout = new Readout(requireChild(this
|
|
221
|
+
#puck = requireChild(this.control, ".sonic-xy-puck", HTMLDivElement);
|
|
222
|
+
#readout = new Readout(requireChild(this.control, ".sonic-xy-readout", HTMLDivElement));
|
|
226
223
|
attributeChangedCallback(name) {
|
|
227
224
|
if ((name === "x" || name === "y") && this.#gesture?.current()) return;
|
|
228
225
|
if (name === "disabled" && this.isDisabled()) this.#gesture?.end();
|
|
@@ -237,8 +234,8 @@ var SonicXy = class extends SonicFormElement {
|
|
|
237
234
|
this.#respec(...axes);
|
|
238
235
|
}
|
|
239
236
|
connect(signal) {
|
|
240
|
-
const xy = this
|
|
241
|
-
this.keepControl(
|
|
237
|
+
const xy = this.control;
|
|
238
|
+
this.keepControl(signal);
|
|
242
239
|
this.render();
|
|
243
240
|
this.#bindPointer(xy, signal);
|
|
244
241
|
this.#bindKeys(xy, signal);
|
|
@@ -248,7 +245,7 @@ var SonicXy = class extends SonicFormElement {
|
|
|
248
245
|
}
|
|
249
246
|
render() {
|
|
250
247
|
if (!this.isBound()) return;
|
|
251
|
-
const { style } = this
|
|
248
|
+
const { style } = this.control;
|
|
252
249
|
for (const axis of axes) {
|
|
253
250
|
const model = this.#models[axis];
|
|
254
251
|
const mapping = model.mapping();
|
|
@@ -265,9 +262,6 @@ var SonicXy = class extends SonicFormElement {
|
|
|
265
262
|
this.x = x;
|
|
266
263
|
this.y = y;
|
|
267
264
|
}
|
|
268
|
-
stateTarget() {
|
|
269
|
-
return this.#xy;
|
|
270
|
-
}
|
|
271
265
|
#axisText(axis) {
|
|
272
266
|
const { value } = this.#models[axis];
|
|
273
267
|
return `${this.getAttribute(`${axis}-label`) ?? axis.toUpperCase()} ${this.#formatValue?.(value, axis) ?? String(value)}`;
|
|
@@ -278,49 +272,47 @@ var SonicXy = class extends SonicFormElement {
|
|
|
278
272
|
const move = keyMoves.get(event.key);
|
|
279
273
|
if (!move && !(resetKeys.has(event.key) && this.#hasDefault())) return;
|
|
280
274
|
event.preventDefault();
|
|
281
|
-
this.#
|
|
282
|
-
this.#renderReadout();
|
|
275
|
+
this.#gesture?.revealKeys();
|
|
283
276
|
if (move) this.#keyTo(...move);
|
|
284
277
|
else this.#reset();
|
|
285
278
|
}, { signal });
|
|
286
279
|
xy.addEventListener("focusout", (event) => {
|
|
287
280
|
if (event.relatedTarget instanceof Node && xy.contains(event.relatedTarget)) return;
|
|
288
|
-
|
|
281
|
+
this.#gesture?.concealKeys();
|
|
289
282
|
}, { signal });
|
|
290
283
|
signal.addEventListener("abort", () => {
|
|
291
|
-
|
|
284
|
+
this.#gesture?.concealKeys();
|
|
292
285
|
}, { once: true });
|
|
293
286
|
}
|
|
294
287
|
#bindPointer(xy, signal) {
|
|
295
288
|
xy.addEventListener("mousedown", (event) => {
|
|
296
289
|
event.preventDefault();
|
|
297
290
|
}, { signal });
|
|
298
|
-
xy.addEventListener("pointercancel", () => {
|
|
299
|
-
this.#doublePress.forget();
|
|
300
|
-
}, { signal });
|
|
301
291
|
this.#gesture = bindFieldGesture(xy, {
|
|
302
|
-
|
|
292
|
+
element: this,
|
|
303
293
|
grab: (event) => {
|
|
304
|
-
if (this.isDisabled()
|
|
294
|
+
if (this.isDisabled()) return;
|
|
305
295
|
focusByPointer(this.focusTarget());
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return this.#grab(event);
|
|
309
|
-
}
|
|
310
|
-
this.#reset();
|
|
296
|
+
this.toggleState("dragging", true);
|
|
297
|
+
return this.#grab(event);
|
|
311
298
|
},
|
|
312
299
|
input: (_hold, next) => {
|
|
313
|
-
|
|
314
|
-
},
|
|
315
|
-
lift: (_hold, event) => {
|
|
316
|
-
if (!this.#doublePress.press(event) || this.doublePress !== "reset") return;
|
|
317
|
-
this.#reset();
|
|
300
|
+
this.#input(next);
|
|
318
301
|
},
|
|
319
302
|
release: (_hold, moved) => {
|
|
320
303
|
if (moved.length > 0) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
321
304
|
},
|
|
322
|
-
|
|
323
|
-
this
|
|
305
|
+
renderReadout: () => {
|
|
306
|
+
this.#renderReadout();
|
|
307
|
+
},
|
|
308
|
+
reset: () => {
|
|
309
|
+
if (this.isDisabled()) return;
|
|
310
|
+
focusByPointer(this.focusTarget());
|
|
311
|
+
this.#reset();
|
|
312
|
+
},
|
|
313
|
+
resetsOnDoublePress: () => this.doublePress === "reset",
|
|
314
|
+
toggle: (state, isOn) => {
|
|
315
|
+
this.toggleState(state, isOn);
|
|
324
316
|
}
|
|
325
317
|
}, signal);
|
|
326
318
|
}
|
|
@@ -411,16 +403,11 @@ var SonicXy = class extends SonicFormElement {
|
|
|
411
403
|
this.writeFormFields([["x", x], ["y", y]], `${String(x)},${String(y)}`);
|
|
412
404
|
}
|
|
413
405
|
#renderReadout() {
|
|
414
|
-
const { isRevealed } = this.#claim;
|
|
415
406
|
this.#readout.show({
|
|
416
407
|
anchor: this.#puck,
|
|
417
|
-
isOpen: isRevealed && this.readout,
|
|
408
|
+
isOpen: this.#gesture?.isRevealed() === true && this.readout,
|
|
418
409
|
text: this.#valueText("x")
|
|
419
410
|
});
|
|
420
|
-
if (isRevealed === this.#isRevealed) return;
|
|
421
|
-
this.#isRevealed = isRevealed;
|
|
422
|
-
this.toggleState("revealed", isRevealed);
|
|
423
|
-
this.dispatchEvent(new Event("sonic-reveal", { bubbles: true }));
|
|
424
411
|
}
|
|
425
412
|
#reset() {
|
|
426
413
|
this.#commit({
|
|
@@ -254,6 +254,18 @@ var CanvasSurface = class {
|
|
|
254
254
|
function bindSurface(options) {
|
|
255
255
|
return new CanvasSurface(options);
|
|
256
256
|
}
|
|
257
|
+
function bindControlSurface(options) {
|
|
258
|
+
const { control, fill, sizeProperty, ...surfaceOptions } = options;
|
|
259
|
+
const surface = bindSurface({
|
|
260
|
+
...surfaceOptions,
|
|
261
|
+
fill: {
|
|
262
|
+
control,
|
|
263
|
+
sizeProperty
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
surface.setFill(fill);
|
|
267
|
+
return surface;
|
|
268
|
+
}
|
|
257
269
|
|
|
258
270
|
//#endregion
|
|
259
|
-
export { bindSurface };
|
|
271
|
+
export { bindControlSurface, bindSurface };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/lib/render.ts
|
|
2
2
|
function requireChild(root, selector, child) {
|
|
3
3
|
const found = root.querySelector(selector);
|
|
4
|
-
if (!(found instanceof child)) throw new
|
|
4
|
+
if (!(found instanceof child)) throw new TypeError(`A template is missing its ${selector}`);
|
|
5
5
|
return found;
|
|
6
6
|
}
|
|
7
7
|
function template(html, root) {
|
|
@@ -9,7 +9,7 @@ function template(html, root) {
|
|
|
9
9
|
parsed.innerHTML = html;
|
|
10
10
|
return () => {
|
|
11
11
|
const clone = document.importNode(parsed.content, true).firstElementChild;
|
|
12
|
-
if (!(clone instanceof root)) throw new
|
|
12
|
+
if (!(clone instanceof root)) throw new TypeError(`A template's root is not a ${root.name}`);
|
|
13
13
|
return clone;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SonicElement } from "./sonic-element.js";
|
|
2
2
|
import { Decibels } from "../lib/units.js";
|
|
3
3
|
import { Surface, SurfaceFrame } from "../lib/canvas-surface.js";
|
|
4
|
-
//#region src/elements/
|
|
5
|
-
export declare abstract class
|
|
4
|
+
//#region src/elements/analyser-element.d.ts
|
|
5
|
+
export declare abstract class SonicAnalyserElement<Colour extends string, Numeric extends string = never> extends SonicElement {
|
|
6
6
|
#private;
|
|
7
7
|
static readonly observedAttributes: string[];
|
|
8
8
|
get analyser(): AnalyserNode | undefined;
|
|
@@ -31,4 +31,4 @@ export declare abstract class SonicDisplayElement<Colour extends string, Numeric
|
|
|
31
31
|
protected surface(): Surface | undefined;
|
|
32
32
|
}
|
|
33
33
|
//#endregion
|
|
34
|
-
//# sourceMappingURL=
|
|
34
|
+
//# sourceMappingURL=analyser-element.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SonicElement } from "./sonic-element.js";
|
|
2
|
-
import {
|
|
2
|
+
import { bindControlSurface } from "../lib/canvas-surface.js";
|
|
3
3
|
|
|
4
|
-
//#region src/elements/
|
|
5
|
-
var
|
|
4
|
+
//#region src/elements/analyser-element.ts
|
|
5
|
+
var SonicAnalyserElement = class extends SonicElement {
|
|
6
6
|
static observedAttributes = [
|
|
7
7
|
...SonicElement.observedAttributes,
|
|
8
8
|
"fill",
|
|
@@ -55,22 +55,19 @@ var SonicDisplayElement = class extends SonicElement {
|
|
|
55
55
|
}
|
|
56
56
|
connect(signal) {
|
|
57
57
|
const control = this.control;
|
|
58
|
-
this.keepControl(
|
|
59
|
-
this.#surface =
|
|
58
|
+
this.keepControl(signal);
|
|
59
|
+
this.#surface = bindControlSurface({
|
|
60
60
|
canvas: this.canvas,
|
|
61
61
|
colours: this.colours,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
sizeProperty: this.sizeProperty
|
|
65
|
-
},
|
|
62
|
+
control,
|
|
63
|
+
fill: this.fill,
|
|
66
64
|
numbers: this.numbers,
|
|
67
65
|
paint: (context, frame) => {
|
|
68
66
|
this.#paint(context, frame);
|
|
69
67
|
},
|
|
70
|
-
signal
|
|
68
|
+
signal,
|
|
69
|
+
sizeProperty: this.sizeProperty
|
|
71
70
|
});
|
|
72
|
-
this.checkStyles(control, this.sheet);
|
|
73
|
-
this.#surface.setFill(this.fill);
|
|
74
71
|
}
|
|
75
72
|
surface() {
|
|
76
73
|
return this.#surface;
|
|
@@ -88,5 +85,5 @@ var SonicDisplayElement = class extends SonicElement {
|
|
|
88
85
|
};
|
|
89
86
|
|
|
90
87
|
//#endregion
|
|
91
|
-
export {
|
|
92
|
-
//# sourceMappingURL=
|
|
88
|
+
export { SonicAnalyserElement };
|
|
89
|
+
//# sourceMappingURL=analyser-element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyser-element.js","names":[],"sources":["../../../src/elements/analyser-element.ts"],"sourcesContent":["import type { Surface, SurfaceFrame } from '#lib/canvas-surface.ts';\nimport type { Decibels } from '#lib/units.ts';\n\nimport { SonicElement } from '#elements/sonic-element.ts';\nimport { bindControlSurface } from '#lib/canvas-surface.ts';\n\nexport abstract class SonicAnalyserElement<\n\tColour extends string,\n\tNumeric extends string = never,\n> extends SonicElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicElement.observedAttributes,\n\t\t'fill',\n\t\t'max',\n\t\t'min',\n\t];\n\n\tget analyser(): AnalyserNode | undefined {\n\t\treturn this.#analyser;\n\t}\n\n\tset analyser(node: AnalyserNode | null | undefined) {\n\t\tthis.#analyser = node ?? undefined;\n\t\tthis.#surface?.requestFrame();\n\t}\n\n\t// fallow-ignore-next-line code-duplication -- one accessor pair per reflected attribute\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\t// fallow-ignore-next-line code-duplication -- one accessor pair per reflected attribute\n\tget max(): Decibels {\n\t\treturn this.numberAttribute('max', 0);\n\t}\n\n\tset max(decibels: number | undefined) {\n\t\tthis.reflect('max', decibels);\n\t}\n\n\tget min(): Decibels {\n\t\treturn this.numberAttribute('min', -90);\n\t}\n\n\tset min(decibels: number | undefined) {\n\t\tthis.reflect('min', decibels);\n\t}\n\n\tprotected abstract readonly canvas: HTMLCanvasElement;\n\n\tprotected abstract readonly colours: Record<Colour, `--_sonic-${string}`>;\n\n\tprotected abstract override readonly control: HTMLElement;\n\n\tprotected abstract readonly numbers: Record<Numeric, `--_sonic-${string}`>;\n\n\tprotected abstract override readonly sheet: string;\n\n\tprotected abstract readonly sizeProperty: `--_sonic-${string}`;\n\n\t#analyser: AnalyserNode | undefined;\n\n\t#buffer = new Float32Array(0);\n\n\t#surface: Surface | undefined;\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (name === 'fill') this.#surface?.setFill(this.fill);\n\t\tthis.#surface?.invalidate();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties('analyser', 'fill', 'max', 'min');\n\t\tsuper.connectedCallback();\n\t}\n\n\t/** One level per bin, as `AnalyserNode.getFloatFrequencyData` fills it */\n\tpush(decibels: Float32Array): void {\n\t\tthis.receive(decibels);\n\t\tthis.#surface?.requestFrame();\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(signal);\n\t\tthis.#surface = bindControlSurface({\n\t\t\tcanvas: this.canvas,\n\t\t\tcolours: this.colours,\n\t\t\tcontrol,\n\t\t\tfill: this.fill,\n\t\t\tnumbers: this.numbers,\n\t\t\tpaint: (context, frame) => {\n\t\t\t\tthis.#paint(context, frame);\n\t\t\t},\n\t\t\tsignal,\n\t\t\tsizeProperty: this.sizeProperty,\n\t\t});\n\t}\n\n\tprotected abstract paint(\n\t\tcontext: CanvasRenderingContext2D,\n\t\tframe: SurfaceFrame<Colour, never, Numeric>,\n\t): void;\n\n\tprotected abstract pull(analyser: AnalyserNode, buffer: Float32Array<ArrayBuffer>): void;\n\n\tprotected abstract receive(frame: Float32Array): void;\n\n\tprotected surface(): Surface | undefined {\n\t\treturn this.#surface;\n\t}\n\n\t// The node never signals that sound came back, so every paint pulls\n\t#paint(context: CanvasRenderingContext2D, frame: SurfaceFrame<Colour, never, Numeric>): void {\n\t\tconst analyser = this.isDisabled() ? undefined : this.#analyser;\n\n\t\tif (analyser) {\n\t\t\tif (this.#buffer.length !== analyser.frequencyBinCount) {\n\t\t\t\tthis.#buffer = new Float32Array(analyser.frequencyBinCount);\n\t\t\t}\n\t\t\tthis.pull(analyser, this.#buffer);\n\t\t\tthis.receive(this.#buffer);\n\t\t}\n\t\tthis.paint(context, frame);\n\t\tif (analyser) this.#surface?.requestFrame();\n\t}\n}\n"],"mappings":";;;;AAMA,IAAsB,uBAAtB,cAGU,aAAa;CACtB,OAAyB,qBAAqB;EAC7C,GAAG,aAAa;EAChB;EACA;EACA;CACD;CAEA,IAAI,WAAqC;EACxC,OAAO,KAAK;CACb;CAEA,IAAI,SAAS,MAAuC;EACnD,KAAK,YAAY,QAAQ;EACzB,KAAK,UAAU,aAAa;CAC7B;CAGA,IAAI,OAAgB;EACnB,OAAO,KAAK,aAAa,MAAM;CAChC;CAEA,IAAI,KAAK,WAAoB;EAC5B,KAAK,QAAQ,QAAQ,SAAS;CAC/B;CAGA,IAAI,MAAgB;EACnB,OAAO,KAAK,gBAAgB,OAAO,CAAC;CACrC;CAEA,IAAI,IAAI,UAA8B;EACrC,KAAK,QAAQ,OAAO,QAAQ;CAC7B;CAEA,IAAI,MAAgB;EACnB,OAAO,KAAK,gBAAgB,OAAO,GAAG;CACvC;CAEA,IAAI,IAAI,UAA8B;EACrC,KAAK,QAAQ,OAAO,QAAQ;CAC7B;CAcA;CAEA,0BAAU,IAAI,aAAa,CAAC;CAE5B;CAEA,yBAAyB,MAAoB;EAC5C,IAAI,SAAS,QAAQ,KAAK,UAAU,QAAQ,KAAK,IAAI;EACrD,KAAK,UAAU,WAAW;CAC3B;CAEA,AAAS,oBAA0B;EAClC,KAAK,kBAAkB,YAAY,QAAQ,OAAO,KAAK;EACvD,MAAM,kBAAkB;CACzB;;CAGA,KAAK,UAA8B;EAClC,KAAK,QAAQ,QAAQ;EACrB,KAAK,UAAU,aAAa;CAC7B;CAEA,UAAgB;EACf,KAAK,UAAU,QAAQ;CACxB;CAEA,AAAU,QAAQ,QAA2B;EAC5C,MAAM,UAAU,KAAK;EAErB,KAAK,YAAY,MAAM;EACvB,KAAK,WAAW,mBAAmB;GAClC,QAAQ,KAAK;GACb,SAAS,KAAK;GACd;GACA,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,SAAS,UAAU;IAC1B,KAAK,OAAO,SAAS,KAAK;GAC3B;GACA;GACA,cAAc,KAAK;EACpB,CAAC;CACF;CAWA,AAAU,UAA+B;EACxC,OAAO,KAAK;CACb;CAGA,OAAO,SAAmC,OAAmD;EAC5F,MAAM,WAAW,KAAK,WAAW,IAAI,SAAY,KAAK;EAEtD,IAAI,UAAU;GACb,IAAI,KAAK,QAAQ,WAAW,SAAS,mBACpC,KAAK,UAAU,IAAI,aAAa,SAAS,iBAAiB;GAE3D,KAAK,KAAK,UAAU,KAAK,OAAO;GAChC,KAAK,QAAQ,KAAK,OAAO;EAC1B;EACA,KAAK,MAAM,SAAS,KAAK;EACzB,IAAI,UAAU,KAAK,UAAU,aAAa;CAC3C;AACD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BoxProbe } from "../lib/check-styles.js";
|
|
1
2
|
import { SonicFormElement } from "./form-element.js";
|
|
2
3
|
//#region src/elements/button.d.ts
|
|
3
4
|
declare global {
|
|
@@ -28,6 +29,9 @@ export declare class SonicButton extends SonicFormElement {
|
|
|
28
29
|
/** Submitted with the form while a latching button is pressed */
|
|
29
30
|
get value(): string;
|
|
30
31
|
set value(value: string | undefined);
|
|
32
|
+
protected readonly boxProbe: BoxProbe;
|
|
33
|
+
protected readonly control: HTMLButtonElement;
|
|
34
|
+
protected readonly sheet = "button.css";
|
|
31
35
|
attributeChangedCallback(name: string): void;
|
|
32
36
|
formResetCallback(): void;
|
|
33
37
|
protected activate(): void;
|
|
@@ -35,7 +39,6 @@ export declare class SonicButton extends SonicFormElement {
|
|
|
35
39
|
protected focusTarget(): HTMLElement;
|
|
36
40
|
protected render(): void;
|
|
37
41
|
protected restoreState(state: string): void;
|
|
38
|
-
protected stateTarget(): HTMLElement;
|
|
39
42
|
}
|
|
40
43
|
//#endregion
|
|
41
44
|
//# sourceMappingURL=button.d.ts.map
|