@xsynaptic/sonic-ui 0.25.1 → 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 +21 -0
- package/README.md +1 -1
- package/dist/default/elements/{display-element.js → analyser-element.js} +10 -12
- package/dist/default/elements/button.js +12 -6
- package/dist/default/elements/dial.js +9 -10
- package/dist/default/elements/envelope.js +26 -20
- package/dist/default/elements/field-gesture.js +49 -8
- package/dist/default/elements/meter.js +6 -5
- package/dist/default/elements/number.js +5 -11
- package/dist/default/elements/position-group.js +4 -4
- package/dist/default/elements/radio-group.js +7 -7
- package/dist/default/elements/region-layer.js +3 -1
- package/dist/default/elements/region.js +5 -1
- package/dist/default/elements/segmented.js +7 -4
- package/dist/default/elements/slider.js +12 -10
- package/dist/default/elements/sonic-element.js +10 -13
- package/dist/default/elements/spectrum.js +3 -3
- package/dist/default/elements/switch.js +11 -6
- package/dist/default/elements/toggle.js +16 -10
- package/dist/default/elements/value-element.js +26 -4
- package/dist/default/elements/wave-element.js +11 -9
- package/dist/default/elements/waveform.js +1 -4
- package/dist/default/elements/wavestrip.js +1 -1
- package/dist/default/elements/xy.js +34 -44
- package/dist/default/lib/canvas-surface.js +35 -2
- package/dist/default/lib/key-press.js +2 -2
- 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 -0
- package/dist/dev/elements/button.js +12 -11
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/dial.d.ts +4 -1
- package/dist/dev/elements/dial.js +9 -14
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/envelope.d.ts +5 -0
- package/dist/dev/elements/envelope.js +26 -24
- 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 -0
- package/dist/dev/elements/meter.js +6 -6
- package/dist/dev/elements/meter.js.map +1 -1
- package/dist/dev/elements/number.d.ts +2 -1
- package/dist/dev/elements/number.js +5 -12
- 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 -1
- package/dist/dev/elements/radio-group.js +7 -7
- package/dist/dev/elements/radio-group.js.map +1 -1
- package/dist/dev/elements/region-layer.js +3 -1
- package/dist/dev/elements/region-layer.js.map +1 -1
- package/dist/dev/elements/region.d.ts +1 -0
- package/dist/dev/elements/region.js +5 -1
- package/dist/dev/elements/region.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 -1
- package/dist/dev/elements/slider.js +12 -14
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/sonic-element.d.ts +6 -7
- package/dist/dev/elements/sonic-element.js +16 -91
- 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 +16 -15
- 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 +26 -4
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/wave-element.d.ts +2 -1
- package/dist/dev/elements/wave-element.js +11 -13
- 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 -0
- package/dist/dev/elements/xy.js +34 -48
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +3 -1
- package/dist/dev/lib/canvas-surface.js +35 -2
- 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/key-press.js +2 -2
- package/dist/dev/lib/key-press.js.map +1 -1
- package/dist/dev/lib/render.js +2 -2
- package/dist/dev/lib/render.js.map +1 -1
- package/dist/styles/button.css +11 -9
- package/dist/styles/dial.css +6 -6
- package/dist/styles/envelope.css +6 -0
- package/dist/styles/led.css +8 -8
- package/dist/styles/material/cap.css +13 -2
- package/dist/styles/material/pane.css +7 -1
- package/dist/styles/material/readout.css +10 -2
- package/dist/styles/material/reticle.css +2 -2
- package/dist/styles/meter.css +11 -11
- package/dist/styles/number.css +1 -1
- package/dist/styles/region.css +6 -0
- package/dist/styles/segmented.css +3 -3
- package/dist/styles/slider.css +12 -12
- package/dist/styles/switch.css +6 -0
- package/dist/styles/toggle.css +3 -3
- package/dist/styles/waveform.css +7 -1
- package/dist/styles/wavestrip.css +6 -0
- package/dist/styles/xy.css +15 -3
- package/package.json +1 -1
- package/dist/dev/elements/display-element.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @xsynaptic/sonic-ui
|
|
2
2
|
|
|
3
|
+
## 0.27.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- - Envelope: a handle drag reports its reveal as the other controls with a readout do, with `data-sonic-revealed` on `.sonic-envelope`, a bubbling `sonic-reveal` event and a read-only `revealed` property.
|
|
8
|
+
- The `FieldAxis` and `SplitMode` types are exported.
|
|
9
|
+
|
|
10
|
+
## 0.26.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- - Breaking: a state is an attribute on the control's drawn part, `data-sonic-<state>`, and no longer a custom state on the host. `sonic-slider:state(dragging) > .sonic-slider` becomes `.sonic-slider[data-sonic-dragging]`; a region's is on its `.sonic-region`. Every look that follows a state now draws at the browser floor, a meter's ladder included.
|
|
15
|
+
- Breaking: the mark on a button, an option or a toggle position held down by a key or a pointer is `data-sonic-active`, renamed from `data-sonic-pressed`, which on `.sonic-button` is now the `pressed` state.
|
|
16
|
+
- Wave controls and the spectrum: a canvas that parses no `color-mix()` is handed a colour it does take, so in an older Chrome the wave strip's unplayed bars no longer paint black and the waveform's edge shade no longer throws.
|
|
17
|
+
- Region: `tabindex="-1"` on `<sonic-region>` takes its part out of the tab order, as on a value control.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- - Value controls: the spoken formatter runs only when the spoken value or the formatter changes, and a wave strip with no `<sonic-region>` no longer calls it twice per write. A changed `lang` is heard at the next spoken value.
|
|
22
|
+
- Older browsers: a closed readout stays out of the layout without the popover API, snapped edges fall back to a hairline without `round()`, and three rules no longer drop where `:state()` is missing.
|
|
23
|
+
|
|
3
24
|
## 0.25.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ import '@xsynaptic/sonic-ui/define';
|
|
|
51
51
|
- `formatValue` and `parseValue` are properties holding functions. Once `parseValue` is set it has to read what `formatValue` writes, or typed entry opens on text it cannot take.
|
|
52
52
|
- To show a control without taking input, set `inert` on the host. It leaves the tab order and the accessibility tree and ignores presses, and it keeps its colours and keeps drawing; `disabled` dims it and is announced as disabled.
|
|
53
53
|
- A display takes its signal as data, and nothing in the library fetches, decodes or opens an `AudioContext`.
|
|
54
|
-
-
|
|
54
|
+
- A state a control sets itself is an attribute on its drawn part, `data-sonic-<state>`, selected as `.sonic-slider[data-sonic-dragging]`.
|
|
55
55
|
- The LED, the panel, the ring and the screen have no behaviour, so they are classes on your own elements (`sonic-led`, `sonic-panel`, `sonic-ring`, `sonic-screen`). A control draws no glass of its own: wrap one in a screen for the encased look.
|
|
56
56
|
|
|
57
57
|
## Skinning
|
|
@@ -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,21 +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.#surface.setFill(this.fill);
|
|
73
71
|
}
|
|
74
72
|
surface() {
|
|
75
73
|
return this.#surface;
|
|
@@ -87,4 +85,4 @@ var SonicDisplayElement = class extends SonicElement {
|
|
|
87
85
|
};
|
|
88
86
|
|
|
89
87
|
//#endregion
|
|
90
|
-
export {
|
|
88
|
+
export { SonicAnalyserElement };
|
|
@@ -88,7 +88,13 @@ var SonicButton = class extends SonicFormElement {
|
|
|
88
88
|
set value(value) {
|
|
89
89
|
this.reflect("value", value);
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
boxProbe = {
|
|
92
|
+
property: "padding-inline-start",
|
|
93
|
+
ratio: "--_sonic-button-padding-ratio",
|
|
94
|
+
selector: ".sonic-button-cap > :not(svg, .sonic-led)"
|
|
95
|
+
};
|
|
96
|
+
control = renderButton();
|
|
97
|
+
sheet = "button.css";
|
|
92
98
|
#holding;
|
|
93
99
|
#isDirty = false;
|
|
94
100
|
#pressed = false;
|
|
@@ -101,10 +107,10 @@ var SonicButton = class extends SonicFormElement {
|
|
|
101
107
|
this.attributeChangedCallback("pressed");
|
|
102
108
|
}
|
|
103
109
|
activate() {
|
|
104
|
-
this
|
|
110
|
+
this.control.click();
|
|
105
111
|
}
|
|
106
112
|
connect(signal) {
|
|
107
|
-
const button = this
|
|
113
|
+
const button = this.control;
|
|
108
114
|
const cap = requireChild(button, ".sonic-button-cap", HTMLSpanElement);
|
|
109
115
|
this.upgradeProperties("armed", "busy", "defaultPressed", "legend", "momentary", "softDisabled", "latching", "pressed", "value");
|
|
110
116
|
mirrorChildren(this, {
|
|
@@ -130,11 +136,11 @@ var SonicButton = class extends SonicFormElement {
|
|
|
130
136
|
bindKeyPress(button, signal);
|
|
131
137
|
}
|
|
132
138
|
focusTarget() {
|
|
133
|
-
return this
|
|
139
|
+
return this.control;
|
|
134
140
|
}
|
|
135
141
|
render() {
|
|
136
142
|
if (!this.isBound()) return;
|
|
137
|
-
const button = this
|
|
143
|
+
const button = this.control;
|
|
138
144
|
writeAttribute(button, "disabled", this.isDisabled() ? "" : void 0);
|
|
139
145
|
writeAttribute(button, "aria-disabled", this.#isSoftDisabled() ? "true" : void 0);
|
|
140
146
|
writeAttribute(button, "aria-busy", this.busy ? "true" : void 0);
|
|
@@ -187,7 +193,7 @@ var SonicButton = class extends SonicFormElement {
|
|
|
187
193
|
}
|
|
188
194
|
#showLegend() {
|
|
189
195
|
const legend = this.legend;
|
|
190
|
-
for (const part of this
|
|
196
|
+
for (const part of this.control.querySelectorAll(":scope > .sonic-button-cap > [data-sonic-when]")) {
|
|
191
197
|
const when = part.dataset.sonicWhen ?? "";
|
|
192
198
|
part.toggleAttribute("data-sonic-hidden", !pressWhens.has(when) && when !== legend);
|
|
193
199
|
}
|
|
@@ -51,8 +51,13 @@ var SonicDial = class extends SonicValueElement {
|
|
|
51
51
|
set modulationValue(value) {
|
|
52
52
|
this.#modulation.write(value, this.isBound() ? this.mapping() : void 0);
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
boxProbe = {
|
|
55
|
+
property: "margin-bottom",
|
|
56
|
+
selector: "[popover]"
|
|
57
|
+
};
|
|
58
|
+
control = renderDial();
|
|
59
|
+
sheet = "dial.css";
|
|
60
|
+
#modulation = createModulation(this.control, "dial", (isModulated) => {
|
|
56
61
|
this.toggleState("modulated", isModulated);
|
|
57
62
|
});
|
|
58
63
|
connectedCallback() {
|
|
@@ -60,16 +65,13 @@ var SonicDial = class extends SonicValueElement {
|
|
|
60
65
|
super.connectedCallback();
|
|
61
66
|
}
|
|
62
67
|
connect(signal) {
|
|
63
|
-
const dial = this
|
|
68
|
+
const dial = this.control;
|
|
64
69
|
bindScale(this, {
|
|
65
70
|
control: dial,
|
|
66
71
|
marks: requireChild(dial, ".sonic-dial-scale", HTMLDivElement)
|
|
67
72
|
}, signal);
|
|
68
73
|
this.render();
|
|
69
|
-
this.bindGestures(
|
|
70
|
-
position: (event) => -event.clientY,
|
|
71
|
-
travelPx: this.travelPx(dial, "--_sonic-dial-travel")
|
|
72
|
-
}));
|
|
74
|
+
this.bindGestures(signal, () => this.upwardAxis("--_sonic-dial-travel"));
|
|
73
75
|
}
|
|
74
76
|
draw() {
|
|
75
77
|
this.#modulation.draw({
|
|
@@ -79,9 +81,6 @@ var SonicDial = class extends SonicValueElement {
|
|
|
79
81
|
value: this.value
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
|
-
focusTarget() {
|
|
83
|
-
return this.#dial;
|
|
84
|
-
}
|
|
85
84
|
isWrapping() {
|
|
86
85
|
return this.endless;
|
|
87
86
|
}
|
|
@@ -2,7 +2,6 @@ import { writeAttribute } from "../lib/write-attribute.js";
|
|
|
2
2
|
import { SonicElement } from "./sonic-element.js";
|
|
3
3
|
import { requireChild, template } from "../lib/render.js";
|
|
4
4
|
import { Readout } from "./readout.js";
|
|
5
|
-
import { ReadoutClaim } from "./readout-claim.js";
|
|
6
5
|
import { SonicValueElement, linkValue } from "./value-element.js";
|
|
7
6
|
import { bindFieldGesture } from "./field-gesture.js";
|
|
8
7
|
import { adsrPath, adsrShape, adsrStages, timeStages } from "../lib/adsr-shape.js";
|
|
@@ -116,28 +115,33 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
116
115
|
set releaseCurve(id) {
|
|
117
116
|
this.reflect("release-curve", id);
|
|
118
117
|
}
|
|
118
|
+
get revealed() {
|
|
119
|
+
return this.hasState("revealed");
|
|
120
|
+
}
|
|
119
121
|
get sustain() {
|
|
120
122
|
return this.getAttribute("sustain") ?? "";
|
|
121
123
|
}
|
|
122
124
|
set sustain(id) {
|
|
123
125
|
this.reflect("sustain", id);
|
|
124
126
|
}
|
|
127
|
+
boxProbe = {
|
|
128
|
+
property: "margin-bottom",
|
|
129
|
+
selector: "[popover]"
|
|
130
|
+
};
|
|
131
|
+
control = renderEnvelope();
|
|
132
|
+
sheet = "envelope.css";
|
|
125
133
|
#bindings = /* @__PURE__ */ new Map();
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
#envelope = renderEnvelope();
|
|
130
|
-
#curveHandles = stageParts(this.#envelope, "sonic-envelope-curve", curveStages);
|
|
131
|
-
#fill = requireChild(this.#envelope, ".sonic-envelope-fill", SVGElement);
|
|
132
|
-
#floor = requireChild(this.#envelope, ".sonic-envelope-floor", SVGElement);
|
|
134
|
+
#curveHandles = stageParts(this.control, "sonic-envelope-curve", curveStages);
|
|
135
|
+
#fill = requireChild(this.control, ".sonic-envelope-fill", SVGElement);
|
|
136
|
+
#floor = requireChild(this.control, ".sonic-envelope-floor", SVGElement);
|
|
133
137
|
#gesture;
|
|
134
|
-
#graph = requireChild(this
|
|
135
|
-
#handles = stageParts(this
|
|
138
|
+
#graph = requireChild(this.control, ".sonic-envelope-graph", SVGElement);
|
|
139
|
+
#handles = stageParts(this.control, "sonic-envelope-handle", timeStages);
|
|
136
140
|
#held;
|
|
137
141
|
#isDriving = false;
|
|
138
|
-
#line = requireChild(this
|
|
139
|
-
#readout = new Readout(requireChild(this
|
|
140
|
-
#reticle = requireChild(this
|
|
142
|
+
#line = requireChild(this.control, ".sonic-envelope-line", SVGElement);
|
|
143
|
+
#readout = new Readout(requireChild(this.control, ".sonic-envelope-readout", HTMLDivElement));
|
|
144
|
+
#reticle = requireChild(this.control, ".sonic-envelope-reticle", HTMLDivElement);
|
|
141
145
|
#shape = adsrShape({});
|
|
142
146
|
#waiting = /* @__PURE__ */ new Set();
|
|
143
147
|
#warned = /* @__PURE__ */ new Set();
|
|
@@ -156,10 +160,9 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
156
160
|
super.connectedCallback();
|
|
157
161
|
}
|
|
158
162
|
connect(signal) {
|
|
159
|
-
|
|
160
|
-
this.keepControl(envelope, signal);
|
|
163
|
+
this.keepControl(signal);
|
|
161
164
|
this.#bind();
|
|
162
|
-
this.#bindPointer(
|
|
165
|
+
this.#bindPointer(this.control, signal);
|
|
163
166
|
signal.addEventListener("abort", () => {
|
|
164
167
|
this.#unbind();
|
|
165
168
|
}, { once: true });
|
|
@@ -184,7 +187,7 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
184
187
|
}
|
|
185
188
|
#bindPointer(envelope, signal) {
|
|
186
189
|
this.#gesture = bindFieldGesture(envelope, {
|
|
187
|
-
|
|
190
|
+
element: this,
|
|
188
191
|
grab: (event) => this.#grab(event),
|
|
189
192
|
input: ({ drives }, next) => {
|
|
190
193
|
this.#isDriving = true;
|
|
@@ -201,8 +204,11 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
201
204
|
binding.link.change();
|
|
202
205
|
}
|
|
203
206
|
},
|
|
204
|
-
|
|
205
|
-
this
|
|
207
|
+
renderReadout: () => {
|
|
208
|
+
this.#renderReadout();
|
|
209
|
+
},
|
|
210
|
+
toggle: (state, isOn) => {
|
|
211
|
+
this.toggleState(state, isOn);
|
|
206
212
|
}
|
|
207
213
|
}, signal);
|
|
208
214
|
}
|
|
@@ -316,7 +322,7 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
316
322
|
}
|
|
317
323
|
this.#readout.show({
|
|
318
324
|
anchor: drag.part,
|
|
319
|
-
isOpen: this.#
|
|
325
|
+
isOpen: this.#gesture?.isRevealed() === true && this.readout,
|
|
320
326
|
text: drag.drives.map(({ binding }) => binding.element.valueText).join(", ")
|
|
321
327
|
});
|
|
322
328
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { bindDrag } from "../lib/pointer-drag.js";
|
|
2
|
-
import { revealDelay } from "./readout-claim.js";
|
|
2
|
+
import { ReadoutClaim, revealDelay } from "./readout-claim.js";
|
|
3
|
+
import { createDoublePress } from "../lib/double-press.js";
|
|
3
4
|
import { dragThresholdPx } from "../lib/drag-step.js";
|
|
5
|
+
import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
|
|
4
6
|
import { pointerMove, pointerPosition, startFieldDrag, stepFieldDrag } from "../lib/field.js";
|
|
5
7
|
|
|
6
8
|
//#region src/elements/field-gesture.ts
|
|
@@ -23,16 +25,39 @@ function startAxis(hold) {
|
|
|
23
25
|
travelPx
|
|
24
26
|
};
|
|
25
27
|
}
|
|
28
|
+
function createReveal({ element, renderReadout, toggle }) {
|
|
29
|
+
let isRevealed = false;
|
|
30
|
+
const show = () => {
|
|
31
|
+
if (claim.isRevealed !== isRevealed) {
|
|
32
|
+
isRevealed = claim.isRevealed;
|
|
33
|
+
toggle("revealed", isRevealed);
|
|
34
|
+
element.dispatchEvent(new Event("sonic-reveal", { bubbles: true }));
|
|
35
|
+
}
|
|
36
|
+
renderReadout();
|
|
37
|
+
};
|
|
38
|
+
const claim = new ReadoutClaim(show);
|
|
39
|
+
return {
|
|
40
|
+
claim,
|
|
41
|
+
show
|
|
42
|
+
};
|
|
43
|
+
}
|
|
26
44
|
function bindFieldGesture(target, options, signal) {
|
|
27
|
-
const {
|
|
45
|
+
const { reset, resetsOnDoublePress } = options;
|
|
46
|
+
const { claim, show } = createReveal(options);
|
|
47
|
+
const doublePress = reset && resetsOnDoublePress ? createDoublePress() : void 0;
|
|
28
48
|
let pointerType;
|
|
49
|
+
const grab = (event) => {
|
|
50
|
+
if (isMenuPress(event)) return void 0;
|
|
51
|
+
if (!reset || !isResetPress(event)) return options.grab(event);
|
|
52
|
+
reset();
|
|
53
|
+
};
|
|
29
54
|
const drag = bindDrag(target, {
|
|
30
55
|
cancel: ({ from, hold }) => {
|
|
31
56
|
options.input(hold, from);
|
|
32
57
|
},
|
|
33
58
|
grab: (event) => {
|
|
34
59
|
pointerType = event.pointerType;
|
|
35
|
-
const hold =
|
|
60
|
+
const hold = grab(event);
|
|
36
61
|
if (!hold) {
|
|
37
62
|
pointerType = void 0;
|
|
38
63
|
return;
|
|
@@ -53,8 +78,8 @@ function bindFieldGesture(target, options, signal) {
|
|
|
53
78
|
})
|
|
54
79
|
};
|
|
55
80
|
},
|
|
56
|
-
lift: (
|
|
57
|
-
|
|
81
|
+
lift: (_held, event) => {
|
|
82
|
+
if (doublePress?.press(event) === true && resetsOnDoublePress?.() === true) reset?.();
|
|
58
83
|
},
|
|
59
84
|
move: (held, event) => {
|
|
60
85
|
const { axes } = held.hold;
|
|
@@ -63,7 +88,10 @@ function bindFieldGesture(target, options, signal) {
|
|
|
63
88
|
y: axes.y?.model.mapping()
|
|
64
89
|
}, held.state, flip(pointerMove(event), held.hold));
|
|
65
90
|
held.state = step.state;
|
|
66
|
-
if (step.state.isEngaged)
|
|
91
|
+
if (step.state.isEngaged) {
|
|
92
|
+
claim.reveal("drag");
|
|
93
|
+
show();
|
|
94
|
+
}
|
|
67
95
|
options.input(held.hold, step);
|
|
68
96
|
},
|
|
69
97
|
release: ({ from, hold }) => {
|
|
@@ -71,12 +99,25 @@ function bindFieldGesture(target, options, signal) {
|
|
|
71
99
|
options.release(hold, fieldAxes.filter((axis) => hold.axes[axis]?.model.value !== from[axis]));
|
|
72
100
|
pointerType = void 0;
|
|
73
101
|
},
|
|
74
|
-
toggle:
|
|
102
|
+
toggle: (isDragging) => {
|
|
103
|
+
options.toggle("dragging", isDragging);
|
|
104
|
+
}
|
|
75
105
|
}, signal);
|
|
106
|
+
target.addEventListener("pointercancel", () => {
|
|
107
|
+
doublePress?.forget();
|
|
108
|
+
}, { signal });
|
|
76
109
|
return {
|
|
110
|
+
concealKeys: () => {
|
|
111
|
+
if (claim.conceal("keys")) show();
|
|
112
|
+
},
|
|
77
113
|
current: () => drag.current()?.hold,
|
|
78
114
|
end: drag.end,
|
|
79
|
-
|
|
115
|
+
isRevealed: () => claim.isRevealed,
|
|
116
|
+
pointerType: () => pointerType,
|
|
117
|
+
revealKeys: () => {
|
|
118
|
+
claim.reveal("keys");
|
|
119
|
+
show();
|
|
120
|
+
}
|
|
80
121
|
};
|
|
81
122
|
}
|
|
82
123
|
|
|
@@ -109,6 +109,8 @@ var SonicMeter = class extends SonicElement {
|
|
|
109
109
|
set value(value) {
|
|
110
110
|
this.reflect("value", value);
|
|
111
111
|
}
|
|
112
|
+
control = renderMeter();
|
|
113
|
+
sheet = "meter.css";
|
|
112
114
|
#bar = -Infinity;
|
|
113
115
|
#carryMs = 0;
|
|
114
116
|
#clipAt = -Infinity;
|
|
@@ -116,7 +118,6 @@ var SonicMeter = class extends SonicElement {
|
|
|
116
118
|
#isValueShown = false;
|
|
117
119
|
#lastFrame;
|
|
118
120
|
#level = 0;
|
|
119
|
-
#meter = renderMeter();
|
|
120
121
|
#peak = -Infinity;
|
|
121
122
|
#peakHold = -Infinity;
|
|
122
123
|
#peakHoldAt = -Infinity;
|
|
@@ -138,7 +139,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
138
139
|
connect(signal) {
|
|
139
140
|
const now = performance.now();
|
|
140
141
|
this.upgradeProperties("ballistics", "max", "min", "orientation", "origin", "segments", "value", "level");
|
|
141
|
-
this.keepControl(
|
|
142
|
+
this.keepControl(signal);
|
|
142
143
|
this.#renderSegments();
|
|
143
144
|
this.#render(now);
|
|
144
145
|
this.#schedule(now);
|
|
@@ -172,7 +173,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
172
173
|
}
|
|
173
174
|
#render(now) {
|
|
174
175
|
if (!this.isBound()) return;
|
|
175
|
-
const meter = this
|
|
176
|
+
const meter = this.control;
|
|
176
177
|
const origin = this.origin === void 0 ? 0 : this.#proportionOf(this.origin);
|
|
177
178
|
meter.style.setProperty("--_sonic-meter-min", String(this.min));
|
|
178
179
|
meter.style.setProperty("--_sonic-meter-max", String(this.max));
|
|
@@ -193,7 +194,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
193
194
|
}
|
|
194
195
|
#renderSegments() {
|
|
195
196
|
if (!this.isBound()) return;
|
|
196
|
-
const meter = this
|
|
197
|
+
const meter = this.control;
|
|
197
198
|
const segments = this.#segments;
|
|
198
199
|
this.toggleState("ladder", segments !== void 0);
|
|
199
200
|
if (!segments) {
|
|
@@ -209,7 +210,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
209
210
|
meter.style.setProperty("--_sonic-meter-clip-segments", segmentsBelow(segments, "clip"));
|
|
210
211
|
}
|
|
211
212
|
#renderStill(bar) {
|
|
212
|
-
const { style } = this
|
|
213
|
+
const { style } = this.control;
|
|
213
214
|
style.setProperty("--_sonic-meter-bar", String(bar));
|
|
214
215
|
style.setProperty("--_sonic-meter-peak-hold", "0");
|
|
215
216
|
style.setProperty("--_sonic-meter-clipped", "0");
|
|
@@ -22,20 +22,17 @@ var SonicNumber = class extends SonicValueElement {
|
|
|
22
22
|
set press(gesture) {
|
|
23
23
|
this.reflect("press", gesture);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
control = renderNumber();
|
|
26
|
+
sheet = "number.css";
|
|
27
|
+
#digits = requireChild(this.control, ".sonic-number-value", HTMLSpanElement);
|
|
27
28
|
connectedCallback() {
|
|
28
29
|
this.upgradeProperties("press");
|
|
29
30
|
super.connectedCallback();
|
|
30
31
|
}
|
|
31
32
|
connect(signal) {
|
|
32
|
-
|
|
33
|
-
this.keepControl(number, signal);
|
|
33
|
+
this.keepControl(signal);
|
|
34
34
|
this.render();
|
|
35
|
-
this.bindGestures(
|
|
36
|
-
position: (event) => -event.clientY,
|
|
37
|
-
travelPx: this.travelPx(number, "--_sonic-number-travel")
|
|
38
|
-
}));
|
|
35
|
+
this.bindGestures(signal, () => this.upwardAxis("--_sonic-number-travel"));
|
|
39
36
|
}
|
|
40
37
|
controlRole() {
|
|
41
38
|
return "spinbutton";
|
|
@@ -43,9 +40,6 @@ var SonicNumber = class extends SonicValueElement {
|
|
|
43
40
|
draw() {
|
|
44
41
|
this.#digits.textContent = this.valueText;
|
|
45
42
|
}
|
|
46
|
-
focusTarget() {
|
|
47
|
-
return this.#number;
|
|
48
|
-
}
|
|
49
43
|
tapTarget() {
|
|
50
44
|
if (this.press !== "step") return void 0;
|
|
51
45
|
const mapping = this.mapping();
|
|
@@ -81,7 +81,7 @@ var SonicPositionGroupElement = class extends SonicRadioGroupElement {
|
|
|
81
81
|
connect(signal) {
|
|
82
82
|
this.upgradeProperties("defaultChecked", "checked", "orientation");
|
|
83
83
|
super.connect(signal);
|
|
84
|
-
this.#holding = bindHold(this.
|
|
84
|
+
this.#holding = bindHold(this.control, {
|
|
85
85
|
canHold: () => !this.isDisabled(),
|
|
86
86
|
leave: "focusout",
|
|
87
87
|
onHold: () => {
|
|
@@ -129,7 +129,7 @@ var SonicPositionGroupElement = class extends SonicRadioGroupElement {
|
|
|
129
129
|
}
|
|
130
130
|
render() {
|
|
131
131
|
if (!this.isBound()) return;
|
|
132
|
-
const group = this.
|
|
132
|
+
const group = this.control;
|
|
133
133
|
const count = this.options().length;
|
|
134
134
|
if (count === 0) {
|
|
135
135
|
this.#renderBare();
|
|
@@ -156,12 +156,12 @@ var SonicPositionGroupElement = class extends SonicRadioGroupElement {
|
|
|
156
156
|
springBack() {
|
|
157
157
|
const rest = restOf(this.positions(), this.checkedIndex());
|
|
158
158
|
if (rest === void 0) return;
|
|
159
|
-
const isFocused = this.
|
|
159
|
+
const isFocused = this.control.contains(this.ownerDocument.activeElement);
|
|
160
160
|
this.select(rest);
|
|
161
161
|
if (isFocused) this.options()[rest]?.focus();
|
|
162
162
|
}
|
|
163
163
|
#renderBare() {
|
|
164
|
-
const group = this.
|
|
164
|
+
const group = this.control;
|
|
165
165
|
const bare = this.bare;
|
|
166
166
|
const isChecked = this.checked;
|
|
167
167
|
writeAttribute(group, "role", void 0);
|
|
@@ -43,7 +43,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
45
|
connect(signal) {
|
|
46
|
-
const group = this.
|
|
46
|
+
const group = this.control;
|
|
47
47
|
this.upgradeProperties("value");
|
|
48
48
|
mirrorChildren(this, {
|
|
49
49
|
control: group,
|
|
@@ -91,10 +91,10 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
91
91
|
optionOf(target) {
|
|
92
92
|
if (!(target instanceof Element)) return void 0;
|
|
93
93
|
const option = target.closest("[role=\"radio\"]");
|
|
94
|
-
return option instanceof HTMLButtonElement && option.parentElement === this.
|
|
94
|
+
return option instanceof HTMLButtonElement && option.parentElement === this.control ? option : void 0;
|
|
95
95
|
}
|
|
96
96
|
options() {
|
|
97
|
-
return [...this.
|
|
97
|
+
return [...this.control.children].filter((child) => child instanceof HTMLButtonElement && child.getAttribute("role") === "radio");
|
|
98
98
|
}
|
|
99
99
|
placeCopies(copies) {
|
|
100
100
|
this.#copyOptions(copies);
|
|
@@ -109,7 +109,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
refocusAt(index) {
|
|
112
|
-
if (this.
|
|
112
|
+
if (this.control.matches(":focus-within")) this.options()[index]?.focus();
|
|
113
113
|
}
|
|
114
114
|
releaseTarget(index) {
|
|
115
115
|
return index;
|
|
@@ -126,7 +126,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
126
126
|
writeAttribute(option, "aria-checked", String(option === checked));
|
|
127
127
|
writeAttribute(option, "tabindex", option === focusable ? "0" : "-1");
|
|
128
128
|
}
|
|
129
|
-
this.forwardNaming(this.
|
|
129
|
+
this.forwardNaming(this.control, true);
|
|
130
130
|
this.writeFormValue(checked ? this.#value : null, this.#value);
|
|
131
131
|
}
|
|
132
132
|
restoreState(state) {
|
|
@@ -175,7 +175,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
175
175
|
}, signal);
|
|
176
176
|
}
|
|
177
177
|
#copyOptions(copies) {
|
|
178
|
-
const group = this.
|
|
178
|
+
const group = this.control;
|
|
179
179
|
const options = this.options();
|
|
180
180
|
const focused = this.optionOf(group.querySelector(":scope > :focus"));
|
|
181
181
|
const focusedValue = focused && optionValue(focused);
|
|
@@ -192,7 +192,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
192
192
|
if (focused) this.#refocus(focused, focusedValue);
|
|
193
193
|
}
|
|
194
194
|
#markPressed(pressed) {
|
|
195
|
-
for (const [index, option] of this.options().entries()) option.toggleAttribute("data-sonic-
|
|
195
|
+
for (const [index, option] of this.options().entries()) option.toggleAttribute("data-sonic-active", index === pressed);
|
|
196
196
|
}
|
|
197
197
|
#optionBoxes() {
|
|
198
198
|
const positions = this.positions();
|
|
@@ -51,6 +51,7 @@ var RegionLayer = class {
|
|
|
51
51
|
this.#release(true);
|
|
52
52
|
}
|
|
53
53
|
follow() {
|
|
54
|
+
if (this.#drawn.length === 0) return;
|
|
54
55
|
if (this.#stripKey() !== this.#key) this.render();
|
|
55
56
|
}
|
|
56
57
|
isHeld() {
|
|
@@ -158,6 +159,7 @@ var RegionLayer = class {
|
|
|
158
159
|
const span = link.span();
|
|
159
160
|
const [low, high] = regionTravel(span, mapping.bounds);
|
|
160
161
|
const canMove = this.#isEnabled(entry);
|
|
162
|
+
const stop = region.getAttribute("tabindex") === "-1" ? "-1" : "0";
|
|
161
163
|
writeProperty(part, "--_sonic-region-from", String(mapping.proportionOf(span.start)));
|
|
162
164
|
writeProperty(part, "--_sonic-region-to", String(mapping.proportionOf(span.end)));
|
|
163
165
|
if (!known || entry.kind !== region.kind) {
|
|
@@ -170,7 +172,7 @@ var RegionLayer = class {
|
|
|
170
172
|
writeAttribute(part, "aria-valuenow", String(span.start));
|
|
171
173
|
writeAttribute(part, "aria-valuetext", host.speak(span));
|
|
172
174
|
writeAttribute(part, "aria-disabled", canMove ? void 0 : "true");
|
|
173
|
-
writeAttribute(part, "tabindex", canMove ?
|
|
175
|
+
writeAttribute(part, "tabindex", canMove ? stop : void 0);
|
|
174
176
|
link.draw(part);
|
|
175
177
|
return entry;
|
|
176
178
|
}
|
|
@@ -18,7 +18,8 @@ var SonicRegion = class extends SonicFormElement {
|
|
|
18
18
|
"end",
|
|
19
19
|
"kind",
|
|
20
20
|
"name",
|
|
21
|
-
"start"
|
|
21
|
+
"start",
|
|
22
|
+
"tabindex"
|
|
22
23
|
];
|
|
23
24
|
static {
|
|
24
25
|
link = (element) => ({
|
|
@@ -108,6 +109,9 @@ var SonicRegion = class extends SonicFormElement {
|
|
|
108
109
|
};
|
|
109
110
|
this.render();
|
|
110
111
|
}
|
|
112
|
+
stateTarget() {
|
|
113
|
+
return this.#part;
|
|
114
|
+
}
|
|
111
115
|
#draw(part) {
|
|
112
116
|
this.#part = part;
|
|
113
117
|
this.forwardNaming(part, true);
|
|
@@ -9,10 +9,13 @@ const renderOption = template(`
|
|
|
9
9
|
</button>
|
|
10
10
|
`, HTMLButtonElement);
|
|
11
11
|
var SonicSegmented = class extends SonicRadioGroupElement {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
boxProbe = {
|
|
13
|
+
property: "padding-inline-start",
|
|
14
|
+
ratio: "--_sonic-segmented-padding-ratio",
|
|
15
|
+
selector: ".sonic-segmented-cap"
|
|
16
|
+
};
|
|
17
|
+
control = renderSegmented();
|
|
18
|
+
sheet = "segmented.css";
|
|
16
19
|
renderOption() {
|
|
17
20
|
return renderOption();
|
|
18
21
|
}
|
|
@@ -86,9 +86,14 @@ var SonicSlider = class extends SonicValueElement {
|
|
|
86
86
|
set spring(isSpring) {
|
|
87
87
|
this.reflect("spring", isSpring);
|
|
88
88
|
}
|
|
89
|
+
boxProbe = {
|
|
90
|
+
property: "margin-bottom",
|
|
91
|
+
selector: "[popover]"
|
|
92
|
+
};
|
|
93
|
+
control = renderSlider();
|
|
94
|
+
sheet = "slider.css";
|
|
89
95
|
#buffered = [];
|
|
90
|
-
#
|
|
91
|
-
#modulation = createModulation(this.#slider, "slider", (isModulated) => {
|
|
96
|
+
#modulation = createModulation(this.control, "slider", (isModulated) => {
|
|
92
97
|
this.toggleState("modulated", isModulated);
|
|
93
98
|
});
|
|
94
99
|
connectedCallback() {
|
|
@@ -96,7 +101,7 @@ var SonicSlider = class extends SonicValueElement {
|
|
|
96
101
|
super.connectedCallback();
|
|
97
102
|
}
|
|
98
103
|
connect(signal) {
|
|
99
|
-
const slider = this
|
|
104
|
+
const slider = this.control;
|
|
100
105
|
const cap = requireChild(slider, ".sonic-slider-cap", HTMLDivElement);
|
|
101
106
|
bindScale(this, {
|
|
102
107
|
control: slider,
|
|
@@ -118,7 +123,7 @@ var SonicSlider = class extends SonicValueElement {
|
|
|
118
123
|
}
|
|
119
124
|
});
|
|
120
125
|
this.render();
|
|
121
|
-
this.bindGestures(
|
|
126
|
+
this.bindGestures(signal, (event) => {
|
|
122
127
|
const axis = this.#axis(slider, cap);
|
|
123
128
|
if (event.target instanceof Node && cap.contains(event.target)) return axis;
|
|
124
129
|
if (this.groovePress === "none") return;
|
|
@@ -136,12 +141,9 @@ var SonicSlider = class extends SonicValueElement {
|
|
|
136
141
|
origin: this.originValue(),
|
|
137
142
|
value: this.value
|
|
138
143
|
});
|
|
139
|
-
this.#renderBuffered(this
|
|
140
|
-
this.#renderScrub(this
|
|
141
|
-
this.#placeReadout(this
|
|
142
|
-
}
|
|
143
|
-
focusTarget() {
|
|
144
|
-
return this.#slider;
|
|
144
|
+
this.#renderBuffered(this.control);
|
|
145
|
+
this.#renderScrub(this.control);
|
|
146
|
+
this.#placeReadout(this.control);
|
|
145
147
|
}
|
|
146
148
|
scrubChanged() {
|
|
147
149
|
if (this.scrub) this.render();
|