@xsynaptic/sonic-ui 0.26.0 → 0.28.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 +20 -0
- package/README.md +1 -0
- package/dist/default/define/ticker.js +7 -0
- package/dist/default/define.js +1 -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/ticker.js +313 -0
- 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 +3 -6
- package/dist/default/elements/xy.js +34 -47
- package/dist/default/index.js +2 -1
- package/dist/default/lib/cancel-zone.js +12 -0
- package/dist/default/lib/canvas-surface.js +13 -1
- package/dist/default/lib/distribute.js +2 -3
- package/dist/default/lib/mirror-children.js +1 -1
- package/dist/default/lib/pointer-drag.js +8 -2
- package/dist/default/lib/render.js +2 -2
- package/dist/default/lib/ticker-leg.js +54 -0
- package/dist/dev/define/ticker.d.ts +2 -0
- package/dist/dev/define/ticker.js +8 -0
- package/dist/dev/define/ticker.js.map +1 -0
- package/dist/dev/define.d.ts +3 -1
- package/dist/dev/define.js +1 -0
- 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 +6 -7
- package/dist/dev/elements/sonic-element.js +14 -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/ticker.d.ts +25 -0
- package/dist/dev/elements/ticker.js +314 -0
- package/dist/dev/elements/ticker.js.map +1 -0
- 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 +3 -6
- 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 +4 -1
- package/dist/dev/index.js +2 -1
- package/dist/dev/lib/cancel-zone.js +13 -0
- package/dist/dev/lib/cancel-zone.js.map +1 -0
- 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 +95 -0
- package/dist/dev/lib/check-styles.js.map +1 -0
- package/dist/dev/lib/distribute.js +2 -3
- package/dist/dev/lib/distribute.js.map +1 -1
- package/dist/dev/lib/mirror-children.js +9 -7
- package/dist/dev/lib/mirror-children.js.map +1 -1
- package/dist/dev/lib/pointer-drag.js +8 -2
- package/dist/dev/lib/pointer-drag.js.map +1 -1
- package/dist/dev/lib/render.js +2 -2
- package/dist/dev/lib/render.js.map +1 -1
- package/dist/dev/lib/ticker-leg.js +55 -0
- package/dist/dev/lib/ticker-leg.js.map +1 -0
- package/dist/styles/controls.css +1 -0
- package/dist/styles/dial.css +28 -5
- package/dist/styles/material/cap.css +16 -5
- package/dist/styles/material/core.css +1 -0
- package/dist/styles/slider.css +2 -1
- package/dist/styles/switch.css +3 -1
- package/dist/styles/ticker.css +115 -0
- package/dist/styles/toggle.css +7 -5
- package/package.json +2 -1
- package/dist/dev/elements/display-element.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @xsynaptic/sonic-ui
|
|
2
2
|
|
|
3
|
+
## 0.28.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- `--sonic-gloss` scales a cap's sheen apart from `--sonic-relief`: 0 is matte, 1 the default. A slider cap has no sheen until the token is set, so there `1` is not the same as unset.
|
|
8
|
+
- - `<sonic-ticker>`: one line of content that scrolls there and back when it does not fit its box, registered by `./define/ticker` with `ticker.css`, which needs no material sheet. It stands still with an ellipsis under reduced motion, and pauses under a mouse, while a link round it has keyboard focus, off screen, and while `paused` is set. A drag along the line moves the tape; with `cancellable` a drag that strays past `--sonic-cancel-zone`, shared with the wave strip, puts it back. `text` replaces the content. A link among the children is copied and still navigates.
|
|
9
|
+
- Ticker surface: tokens `--sonic-ticker-rate` (a length a second, `40px`), `--sonic-ticker-hold` (`2s`) and `--sonic-ticker-fade` (`0.75rem`); hook classes `.sonic-ticker` and `.sonic-ticker-tape`; states `data-sonic-overflowing`, `data-sonic-dragging`, `data-sonic-cancelling` and `data-sonic-paused`, and `data-sonic-clipped` naming each end with content past it.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Switch and toggle: the bat and the cap land with a small overshoot, and the switch's flip takes 120ms, up from 90ms.
|
|
14
|
+
- Split: a move the siblings cannot absorb on their own steps is turned back, so the total holds across mixed step grids.
|
|
15
|
+
|
|
16
|
+
## 0.27.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- - 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.
|
|
21
|
+
- The `FieldAxis` and `SplitMode` types are exported.
|
|
22
|
+
|
|
3
23
|
## 0.26.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -88,6 +88,7 @@ A skin is one rule that sets tokens on a class; copy `dist/skins/flat.css` to st
|
|
|
88
88
|
| `slider.css` | core, cap, glass, readout, value, groove, scale |
|
|
89
89
|
| `spectrum.css` | core |
|
|
90
90
|
| `switch.css` | core, cap |
|
|
91
|
+
| `ticker.css` | |
|
|
91
92
|
| `toggle.css` | core, cap, well, keycap |
|
|
92
93
|
| `waveform.css` | core, cap, glass, readout, value |
|
|
93
94
|
| `wavestrip.css` | core, cap, glass, readout, value |
|
package/dist/default/define.js
CHANGED
|
@@ -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);
|
|
@@ -149,9 +155,6 @@ var SonicButton = class extends SonicFormElement {
|
|
|
149
155
|
restoreState(state) {
|
|
150
156
|
if (this.latching) this.pressed = state === "true";
|
|
151
157
|
}
|
|
152
|
-
stateTarget() {
|
|
153
|
-
return this.#button;
|
|
154
|
-
}
|
|
155
158
|
#bindMomentary(button, signal) {
|
|
156
159
|
const holding = bindHold(button, {
|
|
157
160
|
canHold: () => !this.isDisabled() && !this.#isSoftDisabled(),
|
|
@@ -190,7 +193,7 @@ var SonicButton = class extends SonicFormElement {
|
|
|
190
193
|
}
|
|
191
194
|
#showLegend() {
|
|
192
195
|
const legend = this.legend;
|
|
193
|
-
for (const part of this
|
|
196
|
+
for (const part of this.control.querySelectorAll(":scope > .sonic-button-cap > [data-sonic-when]")) {
|
|
194
197
|
const when = part.dataset.sonicWhen ?? "";
|
|
195
198
|
part.toggleAttribute("data-sonic-hidden", !pressWhens.has(when) && when !== legend);
|
|
196
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,15 +81,9 @@ 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
|
}
|
|
88
|
-
stateTarget() {
|
|
89
|
-
return this.#dial;
|
|
90
|
-
}
|
|
91
87
|
};
|
|
92
88
|
|
|
93
89
|
//#endregion
|
|
@@ -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,17 +160,13 @@ 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 });
|
|
166
169
|
}
|
|
167
|
-
stateTarget() {
|
|
168
|
-
return this.#envelope;
|
|
169
|
-
}
|
|
170
170
|
#bind() {
|
|
171
171
|
this.#gesture?.end();
|
|
172
172
|
this.#unbind();
|
|
@@ -187,7 +187,7 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
187
187
|
}
|
|
188
188
|
#bindPointer(envelope, signal) {
|
|
189
189
|
this.#gesture = bindFieldGesture(envelope, {
|
|
190
|
-
|
|
190
|
+
element: this,
|
|
191
191
|
grab: (event) => this.#grab(event),
|
|
192
192
|
input: ({ drives }, next) => {
|
|
193
193
|
this.#isDriving = true;
|
|
@@ -204,8 +204,11 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
204
204
|
binding.link.change();
|
|
205
205
|
}
|
|
206
206
|
},
|
|
207
|
-
|
|
208
|
-
this
|
|
207
|
+
renderReadout: () => {
|
|
208
|
+
this.#renderReadout();
|
|
209
|
+
},
|
|
210
|
+
toggle: (state, isOn) => {
|
|
211
|
+
this.toggleState(state, isOn);
|
|
209
212
|
}
|
|
210
213
|
}, signal);
|
|
211
214
|
}
|
|
@@ -319,7 +322,7 @@ var SonicEnvelope = class extends SonicElement {
|
|
|
319
322
|
}
|
|
320
323
|
this.#readout.show({
|
|
321
324
|
anchor: drag.part,
|
|
322
|
-
isOpen: this.#
|
|
325
|
+
isOpen: this.#gesture?.isRevealed() === true && this.readout,
|
|
323
326
|
text: drag.drives.map(({ binding }) => binding.element.valueText).join(", ")
|
|
324
327
|
});
|
|
325
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);
|
|
@@ -148,9 +149,6 @@ var SonicMeter = class extends SonicElement {
|
|
|
148
149
|
this.#lastFrame = void 0;
|
|
149
150
|
}, { once: true });
|
|
150
151
|
}
|
|
151
|
-
stateTarget() {
|
|
152
|
-
return this.#meter;
|
|
153
|
-
}
|
|
154
152
|
#isSettled(now) {
|
|
155
153
|
if (this.#isValueShown) return true;
|
|
156
154
|
if (now - this.#clipAt < holdMs) return false;
|
|
@@ -175,7 +173,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
175
173
|
}
|
|
176
174
|
#render(now) {
|
|
177
175
|
if (!this.isBound()) return;
|
|
178
|
-
const meter = this
|
|
176
|
+
const meter = this.control;
|
|
179
177
|
const origin = this.origin === void 0 ? 0 : this.#proportionOf(this.origin);
|
|
180
178
|
meter.style.setProperty("--_sonic-meter-min", String(this.min));
|
|
181
179
|
meter.style.setProperty("--_sonic-meter-max", String(this.max));
|
|
@@ -196,7 +194,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
196
194
|
}
|
|
197
195
|
#renderSegments() {
|
|
198
196
|
if (!this.isBound()) return;
|
|
199
|
-
const meter = this
|
|
197
|
+
const meter = this.control;
|
|
200
198
|
const segments = this.#segments;
|
|
201
199
|
this.toggleState("ladder", segments !== void 0);
|
|
202
200
|
if (!segments) {
|
|
@@ -212,7 +210,7 @@ var SonicMeter = class extends SonicElement {
|
|
|
212
210
|
meter.style.setProperty("--_sonic-meter-clip-segments", segmentsBelow(segments, "clip"));
|
|
213
211
|
}
|
|
214
212
|
#renderStill(bar) {
|
|
215
|
-
const { style } = this
|
|
213
|
+
const { style } = this.control;
|
|
216
214
|
style.setProperty("--_sonic-meter-bar", String(bar));
|
|
217
215
|
style.setProperty("--_sonic-meter-peak-hold", "0");
|
|
218
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,12 +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
|
-
stateTarget() {
|
|
50
|
-
return this.#number;
|
|
51
|
-
}
|
|
52
43
|
tapTarget() {
|
|
53
44
|
if (this.press !== "step") return void 0;
|
|
54
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) {
|
|
@@ -139,9 +139,6 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
139
139
|
this.value = next;
|
|
140
140
|
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
141
141
|
}
|
|
142
|
-
stateTarget() {
|
|
143
|
-
return this.group;
|
|
144
|
-
}
|
|
145
142
|
stepFrom(from, step) {
|
|
146
143
|
return stepFrom(this.positions(), from, {
|
|
147
144
|
isWrapping: this.isWrapping(),
|
|
@@ -178,7 +175,7 @@ var SonicRadioGroupElement = class extends SonicFormElement {
|
|
|
178
175
|
}, signal);
|
|
179
176
|
}
|
|
180
177
|
#copyOptions(copies) {
|
|
181
|
-
const group = this.
|
|
178
|
+
const group = this.control;
|
|
182
179
|
const options = this.options();
|
|
183
180
|
const focused = this.optionOf(group.querySelector(":scope > :focus"));
|
|
184
181
|
const focusedValue = focused && optionValue(focused);
|
|
@@ -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
|
}
|