@xsynaptic/sonic-ui 0.10.4 → 0.12.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 +17 -0
- package/README.md +5 -16
- package/dist/default/define/toggle.js +7 -0
- package/dist/default/define.js +1 -0
- package/dist/default/elements/button.js +2 -0
- package/dist/default/elements/position-group.js +163 -0
- package/dist/default/elements/radio-group.js +34 -12
- package/dist/default/elements/switch.js +33 -167
- package/dist/default/elements/toggle.js +189 -0
- package/dist/default/elements/waveform.js +30 -10
- package/dist/default/elements/wavestrip.js +4 -0
- package/dist/default/index.js +2 -1
- package/dist/default/lib/key-press.js +27 -0
- package/dist/default/lib/toggle-travel.js +19 -0
- package/dist/dev/define/toggle.d.ts +2 -0
- package/dist/dev/define/toggle.js +8 -0
- package/dist/dev/define/toggle.js.map +1 -0
- package/dist/dev/define.d.ts +3 -1
- package/dist/dev/define.js +1 -0
- package/dist/dev/elements/button.js +2 -0
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/position-group.d.ts +38 -0
- package/dist/dev/elements/position-group.js +164 -0
- package/dist/dev/elements/position-group.js.map +1 -0
- package/dist/dev/elements/radio-group.d.ts +4 -0
- package/dist/dev/elements/radio-group.js +34 -12
- package/dist/dev/elements/radio-group.js.map +1 -1
- package/dist/dev/elements/switch.d.ts +4 -19
- package/dist/dev/elements/switch.js +33 -167
- package/dist/dev/elements/switch.js.map +1 -1
- package/dist/dev/elements/toggle.d.ts +21 -0
- package/dist/dev/elements/toggle.js +197 -0
- package/dist/dev/elements/toggle.js.map +1 -0
- package/dist/dev/elements/waveform.d.ts +1 -1
- package/dist/dev/elements/waveform.js +30 -10
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +1 -0
- package/dist/dev/elements/wavestrip.js +4 -0
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/index.d.ts +3 -2
- package/dist/dev/index.js +2 -1
- package/dist/dev/lib/key-press.js +28 -0
- package/dist/dev/lib/key-press.js.map +1 -0
- package/dist/dev/lib/toggle-travel.js +20 -0
- package/dist/dev/lib/toggle-travel.js.map +1 -0
- package/dist/styles/button.css +2 -2
- package/dist/styles/controls.css +1 -0
- package/dist/styles/led.css +16 -13
- package/dist/styles/material.css +36 -9
- package/dist/styles/meter.css +7 -6
- package/dist/styles/segmented.css +8 -4
- package/dist/styles/spectrum.css +2 -2
- package/dist/styles/switch.css +6 -2
- package/dist/styles/toggle.css +481 -0
- package/package.json +2 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { placeChildren, requireChild, template } from "../lib/render.js";
|
|
2
|
+
import { bindDrag } from "../lib/pointer-drag.js";
|
|
3
|
+
import { dragThresholdPx } from "../lib/drag-step.js";
|
|
4
|
+
import { isUnder, optionValue } from "./radio-group.js";
|
|
5
|
+
import { SonicPositionGroupElement } from "./position-group.js";
|
|
6
|
+
import { positionAt, travelFrom } from "../lib/toggle-travel.js";
|
|
7
|
+
|
|
8
|
+
//#region src/elements/toggle.ts
|
|
9
|
+
const renderToggle = template(`
|
|
10
|
+
<div class="sonic-toggle">
|
|
11
|
+
<span aria-hidden="true" class="sonic-toggle-well"></span>
|
|
12
|
+
<span aria-hidden="true" class="sonic-toggle-cap"></span>
|
|
13
|
+
</div>
|
|
14
|
+
`, HTMLDivElement);
|
|
15
|
+
const renderPosition = template(`
|
|
16
|
+
<button class="sonic-toggle-position" role="radio" type="button">
|
|
17
|
+
<span class="sonic-toggle-legend"></span>
|
|
18
|
+
</button>
|
|
19
|
+
`, HTMLButtonElement);
|
|
20
|
+
const renderBare = template(`<button class="sonic-toggle-position" role="switch" type="button"></button>`, HTMLButtonElement);
|
|
21
|
+
var SonicToggle = class extends SonicPositionGroupElement {
|
|
22
|
+
bare = renderBare();
|
|
23
|
+
defaultOrientation = "horizontal";
|
|
24
|
+
group = renderToggle();
|
|
25
|
+
#cap = requireChild(this.group, ".sonic-toggle-cap", HTMLSpanElement);
|
|
26
|
+
#draggedTo;
|
|
27
|
+
#hasWarnedOfLegends = false;
|
|
28
|
+
#well = requireChild(this.group, ".sonic-toggle-well", HTMLSpanElement);
|
|
29
|
+
claimPress() {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
connect(signal) {
|
|
33
|
+
super.connect(signal);
|
|
34
|
+
this.checkStyles(this.group, "toggle.css");
|
|
35
|
+
this.bare.addEventListener("click", (event) => {
|
|
36
|
+
if (event instanceof PointerEvent && event.pointerType !== "") return;
|
|
37
|
+
this.setChecked(!this.checked);
|
|
38
|
+
}, { signal });
|
|
39
|
+
this.#bindCap(signal);
|
|
40
|
+
}
|
|
41
|
+
isMirrored(child) {
|
|
42
|
+
return super.isMirrored(child) || child === this.#fixedLegend();
|
|
43
|
+
}
|
|
44
|
+
placeCopies(copies) {
|
|
45
|
+
const positions = copies.filter((copy) => super.isMirrored(copy));
|
|
46
|
+
placeChildren(this.#cap, copies.filter((copy) => !positions.includes(copy)));
|
|
47
|
+
super.placeCopies(positions);
|
|
48
|
+
}
|
|
49
|
+
render() {
|
|
50
|
+
if (!this.isBound()) return;
|
|
51
|
+
this.group.style.setProperty("--_sonic-toggle-count", String(this.#stopCount()));
|
|
52
|
+
this.#placeCap(this.#draggedTo ?? this.#restingAt());
|
|
53
|
+
super.render();
|
|
54
|
+
for (const [index, option] of this.options().entries()) option.style.setProperty("--_sonic-toggle-index", String(index));
|
|
55
|
+
}
|
|
56
|
+
renderOption() {
|
|
57
|
+
return renderPosition();
|
|
58
|
+
}
|
|
59
|
+
#bindCap(signal) {
|
|
60
|
+
bindDrag(this.group, {
|
|
61
|
+
grab: (event) => this.#grab(event),
|
|
62
|
+
lift: (drag, event) => {
|
|
63
|
+
if (drag.hasMoved || drag.isHolding || this.isDisabled()) return;
|
|
64
|
+
if (!isUnder(this.group, event.clientX, event.clientY)) return;
|
|
65
|
+
this.#press(drag.position);
|
|
66
|
+
},
|
|
67
|
+
move: (drag, event) => {
|
|
68
|
+
if (drag.isHolding || this.isDisabled()) return;
|
|
69
|
+
const pointer = this.along(event);
|
|
70
|
+
if (!drag.hasMoved && Math.abs(pointer - drag.start) < drag.thresholdPx) return;
|
|
71
|
+
drag.hasMoved = true;
|
|
72
|
+
this.toggleState("dragging", true);
|
|
73
|
+
this.#slideTo(positionAt(drag.travel, pointer), event.pointerId);
|
|
74
|
+
},
|
|
75
|
+
release: (drag) => {
|
|
76
|
+
delete (drag.position ?? this.bare).dataset.sonicPressed;
|
|
77
|
+
this.#draggedTo = void 0;
|
|
78
|
+
this.toggleState("dragging", false);
|
|
79
|
+
this.render();
|
|
80
|
+
}
|
|
81
|
+
}, signal);
|
|
82
|
+
}
|
|
83
|
+
#checkLegends() {}
|
|
84
|
+
#enabledEnds() {
|
|
85
|
+
if (this.isBare()) return [0, 1];
|
|
86
|
+
const options = this.options();
|
|
87
|
+
const isEnabled = (option) => !this.isOptionDisabled(option);
|
|
88
|
+
return [options.findIndex(isEnabled), options.findLastIndex(isEnabled)];
|
|
89
|
+
}
|
|
90
|
+
#fixedLegend() {
|
|
91
|
+
return [...this.children].find((child) => child !== this.group && !super.isMirrored(child));
|
|
92
|
+
}
|
|
93
|
+
#grab(event) {
|
|
94
|
+
const position = this.optionOf(event.target);
|
|
95
|
+
if (this.isDisabled() || !position && event.target !== this.bare) return void 0;
|
|
96
|
+
const isOnCap = isUnder(this.#cap, event.clientX, event.clientY);
|
|
97
|
+
const travel = this.#travel(event, isOnCap);
|
|
98
|
+
if (!travel || this.#isBlocked(position, isOnCap)) return void 0;
|
|
99
|
+
(position ?? this.bare).toggleAttribute("data-sonic-pressed", true);
|
|
100
|
+
return {
|
|
101
|
+
hasMoved: false,
|
|
102
|
+
isHolding: this.#holdFrom(position, event.pointerId),
|
|
103
|
+
position,
|
|
104
|
+
start: this.along(event),
|
|
105
|
+
thresholdPx: dragThresholdPx(event.pointerType),
|
|
106
|
+
travel
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
#holdFrom(position, pointerId) {
|
|
110
|
+
const target = position && this.pressTarget(position);
|
|
111
|
+
if (!target || !this.isMomentary(target) || this.isOptionDisabled(target)) return false;
|
|
112
|
+
this.hold(target, pointerId);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
#isBlocked(position, isOnCap) {
|
|
116
|
+
return !isOnCap && position !== void 0 && this.isOptionDisabled(position);
|
|
117
|
+
}
|
|
118
|
+
#onAt() {
|
|
119
|
+
return this.orientation === "vertical" ? 0 : 1;
|
|
120
|
+
}
|
|
121
|
+
#placeCap(at) {
|
|
122
|
+
this.group.style.setProperty("--_sonic-toggle-at", String(at));
|
|
123
|
+
}
|
|
124
|
+
#press(position) {
|
|
125
|
+
if (!position) {
|
|
126
|
+
this.setChecked(!this.checked);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const target = this.pressTarget(position);
|
|
130
|
+
if (this.isOptionDisabled(target)) return;
|
|
131
|
+
this.select(target);
|
|
132
|
+
this.#refocus(target);
|
|
133
|
+
}
|
|
134
|
+
#refocus(position) {
|
|
135
|
+
if (this.group.matches(":focus-within")) position.focus();
|
|
136
|
+
}
|
|
137
|
+
#restingAt() {
|
|
138
|
+
if (this.isBare()) return this.checked ? this.#onAt() : 1 - this.#onAt();
|
|
139
|
+
return Math.max(0, this.checkedIndex(this.options()));
|
|
140
|
+
}
|
|
141
|
+
#slideTo(at, pointerId) {
|
|
142
|
+
const crossed = this.options()[Math.round(at)];
|
|
143
|
+
this.#draggedTo = at;
|
|
144
|
+
this.#placeCap(at);
|
|
145
|
+
if (this.isBare()) {
|
|
146
|
+
this.setChecked(Math.round(at) === this.#onAt());
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (!crossed || optionValue(crossed) === this.value) return;
|
|
150
|
+
this.releaseHold();
|
|
151
|
+
if (this.isOptionDisabled(crossed) || optionValue(crossed) === this.value) return;
|
|
152
|
+
if (this.isMomentary(crossed)) this.hold(crossed, pointerId);
|
|
153
|
+
else this.select(crossed);
|
|
154
|
+
this.#refocus(crossed);
|
|
155
|
+
}
|
|
156
|
+
#stopCount() {
|
|
157
|
+
return this.options().length || 2;
|
|
158
|
+
}
|
|
159
|
+
#travel(event, isOnCap) {
|
|
160
|
+
const [first, last] = this.#enabledEnds();
|
|
161
|
+
if (first < 0) return void 0;
|
|
162
|
+
const box = this.#well.getBoundingClientRect();
|
|
163
|
+
const [start, length, thickness] = this.orientation === "vertical" ? [
|
|
164
|
+
box.top,
|
|
165
|
+
box.height,
|
|
166
|
+
box.width
|
|
167
|
+
] : [
|
|
168
|
+
box.left,
|
|
169
|
+
box.width,
|
|
170
|
+
box.height
|
|
171
|
+
];
|
|
172
|
+
return travelFrom({
|
|
173
|
+
at: this.#restingAt(),
|
|
174
|
+
count: this.#stopCount(),
|
|
175
|
+
first,
|
|
176
|
+
isOnCap,
|
|
177
|
+
last,
|
|
178
|
+
pointer: this.along(event),
|
|
179
|
+
well: {
|
|
180
|
+
length,
|
|
181
|
+
start,
|
|
182
|
+
thickness
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
//#endregion
|
|
189
|
+
export { SonicToggle };
|
|
@@ -125,20 +125,22 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
125
125
|
set peaks(peaks) {
|
|
126
126
|
this.#peaks = peaks;
|
|
127
127
|
this.renderEmpty();
|
|
128
|
-
this
|
|
128
|
+
this.#repaint();
|
|
129
129
|
}
|
|
130
130
|
get pending() {
|
|
131
131
|
return this.#pending.map(([start, end]) => [start, end]);
|
|
132
132
|
}
|
|
133
133
|
set pending(regions) {
|
|
134
|
+
const pending = regions ? readRegions(regions) : [];
|
|
135
|
+
if (String(pending) === String(this.#pending)) return;
|
|
134
136
|
const listedMs = this.#pendingListedMs;
|
|
135
137
|
const nowMs = performance.now();
|
|
136
|
-
this.#pending =
|
|
138
|
+
this.#pending = pending;
|
|
137
139
|
this.#pendingListedMs = new Map(this.#pending.map((region) => {
|
|
138
140
|
const key = region.join(":");
|
|
139
141
|
return [key, listedMs.get(key) ?? nowMs];
|
|
140
142
|
}));
|
|
141
|
-
this
|
|
143
|
+
this.#repaint();
|
|
142
144
|
}
|
|
143
145
|
get pendingDelay() {
|
|
144
146
|
return Math.max(0, this.numberAttribute("pending-delay", 0));
|
|
@@ -177,6 +179,7 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
177
179
|
}
|
|
178
180
|
set requestPeaks(request) {
|
|
179
181
|
this.#requestPeaks = request;
|
|
182
|
+
this.#askedKey = void 0;
|
|
180
183
|
this.surface()?.invalidate();
|
|
181
184
|
}
|
|
182
185
|
get zoom() {
|
|
@@ -192,11 +195,13 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
192
195
|
lengths = {};
|
|
193
196
|
sheet = "waveform.css";
|
|
194
197
|
sizeProperty = "--_sonic-waveform-size";
|
|
195
|
-
#asked = /* @__PURE__ */ new
|
|
198
|
+
#asked = /* @__PURE__ */ new WeakSet();
|
|
199
|
+
#askedKey;
|
|
196
200
|
#clock = createTrackingClock();
|
|
197
201
|
#drawn;
|
|
198
202
|
#ghost = requireChild(this.control, ".sonic-waveform-ghost", HTMLDivElement);
|
|
199
203
|
#grabbed;
|
|
204
|
+
#isAsking = false;
|
|
200
205
|
#kindColours = /* @__PURE__ */ new Map();
|
|
201
206
|
#paintedKey = "";
|
|
202
207
|
#peaks;
|
|
@@ -287,10 +292,22 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
287
292
|
this.surface()?.rebuild();
|
|
288
293
|
}
|
|
289
294
|
#ask(wanted) {
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
this.#
|
|
295
|
+
const key = wanted.join(":");
|
|
296
|
+
if (key === this.#askedKey) return;
|
|
297
|
+
let asked;
|
|
298
|
+
this.#askedKey = key;
|
|
299
|
+
this.#isAsking = true;
|
|
300
|
+
try {
|
|
301
|
+
asked = this.#requestPeaks?.(...wanted);
|
|
302
|
+
} finally {
|
|
303
|
+
this.#isAsking = false;
|
|
304
|
+
}
|
|
305
|
+
const promises = asked instanceof Promise ? [asked] : asked ?? [];
|
|
306
|
+
for (const promise of promises) {
|
|
307
|
+
if (this.#asked.has(promise)) continue;
|
|
308
|
+
this.#asked.add(promise);
|
|
309
|
+
this.#repaintAfter(promise);
|
|
310
|
+
}
|
|
294
311
|
}
|
|
295
312
|
#duePending() {
|
|
296
313
|
const due = dueRegions(this.#pending, this.#pendingListedMs, [performance.now(), this.pendingDelay]);
|
|
@@ -363,10 +380,13 @@ var SonicWaveform = class extends SonicWaveElement {
|
|
|
363
380
|
for (const probe of probes) probe.remove();
|
|
364
381
|
return new Map(kinds.map((kind, index) => [kind, read[index] ?? ""]));
|
|
365
382
|
}
|
|
383
|
+
#repaint() {
|
|
384
|
+
if (!this.#isAsking) this.#askedKey = void 0;
|
|
385
|
+
this.surface()?.invalidate();
|
|
386
|
+
}
|
|
366
387
|
async #repaintAfter(asked) {
|
|
367
388
|
await Promise.allSettled([asked]);
|
|
368
|
-
this.#
|
|
369
|
-
this.surface()?.invalidate();
|
|
389
|
+
this.#repaint();
|
|
370
390
|
}
|
|
371
391
|
#sourceSeconds() {
|
|
372
392
|
return this.#readTime?.() ?? this.playback();
|
|
@@ -80,6 +80,10 @@ var SonicWavestrip = class extends SonicWaveElement {
|
|
|
80
80
|
#markerBand = createMarkerBand(requireChild(this.control, ".sonic-wavestrip-markers", HTMLDivElement));
|
|
81
81
|
#paintedKey = "";
|
|
82
82
|
#peaks;
|
|
83
|
+
clientXOf(value) {
|
|
84
|
+
const { startPx, travelPx } = this.#axis();
|
|
85
|
+
return startPx + this.mapping().proportionOf(value) * travelPx;
|
|
86
|
+
}
|
|
83
87
|
connectedCallback() {
|
|
84
88
|
this.upgradeProperties("buffered", "cancellable", "peaks");
|
|
85
89
|
super.connectedCallback();
|
package/dist/default/index.js
CHANGED
|
@@ -9,10 +9,11 @@ import { SonicSlider } from "./elements/slider.js";
|
|
|
9
9
|
import { SonicSpectrum } from "./elements/spectrum.js";
|
|
10
10
|
import { SonicSplit } from "./elements/split.js";
|
|
11
11
|
import { SonicSwitch } from "./elements/switch.js";
|
|
12
|
+
import { SonicToggle } from "./elements/toggle.js";
|
|
12
13
|
import { SonicWaveform } from "./elements/waveform.js";
|
|
13
14
|
import { SonicWavestrip } from "./elements/wavestrip.js";
|
|
14
15
|
import { SonicXy } from "./elements/xy.js";
|
|
15
16
|
import { crossfadeGains } from "./lib/crossfade.js";
|
|
16
17
|
import { formatPercent, parsePercent } from "./lib/percent.js";
|
|
17
18
|
|
|
18
|
-
export { SonicButton, SonicDial, SonicEnvelope, SonicMeter, SonicNumber, SonicSegmented, SonicSlider, SonicSpectrum, SonicSplit, SonicSwitch, SonicWaveform, SonicWavestrip, SonicXy, crossfadeGains, envelopeCurve, formatPercent, parsePercent };
|
|
19
|
+
export { SonicButton, SonicDial, SonicEnvelope, SonicMeter, SonicNumber, SonicSegmented, SonicSlider, SonicSpectrum, SonicSplit, SonicSwitch, SonicToggle, SonicWaveform, SonicWavestrip, SonicXy, crossfadeGains, envelopeCurve, formatPercent, parsePercent };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/lib/key-press.ts
|
|
2
|
+
function bindKeyPress(root, signal) {
|
|
3
|
+
let pressed;
|
|
4
|
+
const release = () => {
|
|
5
|
+
if (!pressed) return;
|
|
6
|
+
delete pressed.dataset.sonicPressed;
|
|
7
|
+
pressed = void 0;
|
|
8
|
+
};
|
|
9
|
+
root.addEventListener("keydown", (event) => {
|
|
10
|
+
if (event.key !== " " || event.repeat || event.defaultPrevented) return;
|
|
11
|
+
const part = event.target;
|
|
12
|
+
if (!(part instanceof HTMLButtonElement) || part.disabled) return;
|
|
13
|
+
release();
|
|
14
|
+
pressed = part;
|
|
15
|
+
part.dataset.sonicPressed = "";
|
|
16
|
+
}, { signal });
|
|
17
|
+
root.addEventListener("keyup", (event) => {
|
|
18
|
+
if (event.key === " " || event.key === "Meta") release();
|
|
19
|
+
}, { signal });
|
|
20
|
+
root.addEventListener("focusout", (event) => {
|
|
21
|
+
if (event.target === pressed) release();
|
|
22
|
+
}, { signal });
|
|
23
|
+
signal.addEventListener("abort", release, { once: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { bindKeyPress };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { clamp } from "./math.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/toggle-travel.ts
|
|
4
|
+
function travelFrom({ at, count, first, isOnCap, last, pointer, well }) {
|
|
5
|
+
const step = count < 2 ? 0 : (well.length - well.thickness) / (count - 1);
|
|
6
|
+
return {
|
|
7
|
+
first,
|
|
8
|
+
last,
|
|
9
|
+
origin: isOnCap ? pointer - at * step : well.start + well.thickness / 2,
|
|
10
|
+
step
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function positionAt({ first, last, origin, step }, pointer) {
|
|
14
|
+
if (step <= 0) return first;
|
|
15
|
+
return clamp((pointer - origin) / step, first, last);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { positionAt, travelFrom };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toggle.js","names":[],"sources":["../../../src/define/toggle.ts"],"sourcesContent":["import { defineOnce } from '#elements/define-once.ts';\nimport { SonicToggle } from '#elements/toggle.ts';\n\ndefineOnce('sonic-toggle', SonicToggle);\n\nexport type { SonicToggle } from '#elements/toggle.ts';\n"],"mappings":";;;;AAGA,WAAW,gBAAgB,WAAW"}
|
package/dist/dev/define.d.ts
CHANGED
|
@@ -18,10 +18,12 @@ import { SonicSplit } from "./elements/split.js";
|
|
|
18
18
|
import "./define/split.js";
|
|
19
19
|
import { SonicSwitch } from "./elements/switch.js";
|
|
20
20
|
import "./define/switch.js";
|
|
21
|
+
import { SonicToggle } from "./elements/toggle.js";
|
|
22
|
+
import "./define/toggle.js";
|
|
21
23
|
import { SonicWaveform } from "./elements/waveform.js";
|
|
22
24
|
import "./define/waveform.js";
|
|
23
25
|
import { SonicWavestrip } from "./elements/wavestrip.js";
|
|
24
26
|
import "./define/wavestrip.js";
|
|
25
27
|
import { SonicXy } from "./elements/xy.js";
|
|
26
28
|
import "./define/xy.js";
|
|
27
|
-
export type { SonicButton, SonicDial, SonicEnvelope, SonicMeter, SonicNumber, SonicSegmented, SonicSlider, SonicSpectrum, SonicSplit, SonicSwitch, SonicWaveform, SonicWavestrip, SonicXy };
|
|
29
|
+
export type { SonicButton, SonicDial, SonicEnvelope, SonicMeter, SonicNumber, SonicSegmented, SonicSlider, SonicSpectrum, SonicSplit, SonicSwitch, SonicToggle, SonicWaveform, SonicWavestrip, SonicXy };
|
package/dist/dev/define.js
CHANGED
|
@@ -2,6 +2,7 @@ import { writeAttribute } from "../lib/write-attribute.js";
|
|
|
2
2
|
import { SonicFormElement } from "./form-element.js";
|
|
3
3
|
import { copyNode } from "../lib/copy-node.js";
|
|
4
4
|
import { bindHold } from "../lib/hold.js";
|
|
5
|
+
import { bindKeyPress } from "../lib/key-press.js";
|
|
5
6
|
import { placeChildren, requireChild, template } from "../lib/render.js";
|
|
6
7
|
import { mirrorChildren } from "../lib/mirror-children.js";
|
|
7
8
|
import { capturePointer } from "../lib/pointer-drag.js";
|
|
@@ -125,6 +126,7 @@ var SonicButton = class extends SonicFormElement {
|
|
|
125
126
|
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
126
127
|
}, { signal });
|
|
127
128
|
this.#bindMomentary(button, signal);
|
|
129
|
+
bindKeyPress(button, signal);
|
|
128
130
|
}
|
|
129
131
|
focusTarget() {
|
|
130
132
|
return this.#button;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":[],"sources":["../../../src/elements/button.ts"],"sourcesContent":["import type { Hold } from '#lib/hold.ts';\n\nimport { SonicFormElement } from '#elements/form-element.ts';\nimport { copyNode } from '#lib/copy-node.ts';\nimport { bindHold } from '#lib/hold.ts';\nimport { mirrorChildren } from '#lib/mirror-children.ts';\nimport { capturePointer } from '#lib/pointer-drag.ts';\nimport { placeChildren, requireChild, template } from '#lib/render.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-button': SonicButton;\n\t}\n}\n\nconst renderButton = template(\n\t/* HTML */ `\n\t\t<button class=\"sonic-button\" type=\"button\"><span class=\"sonic-button-cap\"></span></button>\n\t`,\n\tHTMLButtonElement,\n);\n\nconst holdKeys = new Set([' ', 'Enter']);\n\nconst popupAttributes = {\n\tcontrols: 'aria-controls',\n\texpanded: 'aria-expanded',\n\tpopup: 'aria-haspopup',\n} as const;\n\nconst pressWhens = new Set(['pressed', 'released']);\n\nexport class SonicButton extends SonicFormElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicFormElement.observedAttributes,\n\t\t...Object.keys(popupAttributes),\n\t\t'busy',\n\t\t'legend',\n\t\t'momentary',\n\t\t'pressed',\n\t\t'soft-disabled',\n\t\t'latching',\n\t\t'value',\n\t];\n\n\tget armed(): boolean {\n\t\treturn this.hasAttribute('armed');\n\t}\n\n\tset armed(isArmed: boolean) {\n\t\tthis.reflect('armed', isArmed);\n\t}\n\n\tget busy(): boolean {\n\t\treturn this.hasAttribute('busy');\n\t}\n\n\tset busy(isBusy: boolean) {\n\t\tthis.reflect('busy', isBusy);\n\t}\n\n\tget defaultPressed(): boolean {\n\t\treturn this.hasAttribute('pressed');\n\t}\n\n\tset defaultPressed(isPressed: boolean) {\n\t\tthis.reflect('pressed', isPressed);\n\t}\n\n\tget latching(): boolean {\n\t\treturn this.hasAttribute('latching');\n\t}\n\n\tset latching(isLatching: boolean) {\n\t\tthis.reflect('latching', isLatching);\n\t}\n\n\tget legend(): string | undefined {\n\t\treturn this.getAttribute('legend') ?? undefined;\n\t}\n\n\tset legend(name: string | undefined) {\n\t\tthis.reflect('legend', name);\n\t}\n\n\tget momentary(): boolean {\n\t\treturn this.hasAttribute('momentary');\n\t}\n\n\tset momentary(isMomentary: boolean) {\n\t\tthis.reflect('momentary', isMomentary);\n\t}\n\n\tget pressed(): boolean {\n\t\treturn this.#isDirty ? this.#pressed : this.defaultPressed;\n\t}\n\n\tset pressed(isPressed: boolean | undefined) {\n\t\tthis.#isDirty = true;\n\t\tthis.#pressed = isPressed === true;\n\t\tthis.render();\n\t}\n\n\tget softDisabled(): boolean {\n\t\treturn this.hasAttribute('soft-disabled');\n\t}\n\n\tset softDisabled(isSoftDisabled: boolean) {\n\t\tthis.reflect('soft-disabled', isSoftDisabled);\n\t}\n\n\tget value(): string {\n\t\treturn this.getAttribute('value') ?? 'on';\n\t}\n\n\tset value(value: string | undefined) {\n\t\tthis.reflect('value', value);\n\t}\n\n\treadonly #button = renderButton();\n\n\t#holding: Hold | undefined;\n\n\t#isDirty = false;\n\n\t#pressed = false;\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (name === 'pressed') this.#isDirty = false;\n\t\tif (this.isDisabled() || this.#isSoftDisabled()) this.#holding?.release();\n\t\tthis.render();\n\t}\n\n\toverride formResetCallback(): void {\n\t\tthis.attributeChangedCallback('pressed');\n\t}\n\n\tprotected override activate(): void {\n\t\tthis.#button.click();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst button = this.#button;\n\t\tconst cap = requireChild(button, '.sonic-button-cap', HTMLSpanElement);\n\n\t\tthis.upgradeProperties(\n\t\t\t'armed',\n\t\t\t'busy',\n\t\t\t'defaultPressed',\n\t\t\t'legend',\n\t\t\t'momentary',\n\t\t\t'softDisabled',\n\t\t\t'latching',\n\t\t\t'pressed',\n\t\t\t'value',\n\t\t);\n\t\tmirrorChildren(\n\t\t\tthis,\n\t\t\t{\n\t\t\t\tcontrol: button,\n\t\t\t\tcopy: copyNode,\n\t\t\t\tplace: (copies) => {\n\t\t\t\t\tplaceChildren(cap, copies);\n\t\t\t\t\tthis.#showLegend();\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tthis.render();\n\t\tthis.checkStyles(button, 'button.css');\n\n\t\tbutton.addEventListener(\n\t\t\t'click',\n\t\t\t(event) => {\n\t\t\t\t// A native disabled button fires no click at all\n\t\t\t\tif (this.#isSoftDisabled()) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.latching) return;\n\n\t\t\t\tthis.pressed = !this.pressed;\n\t\t\t\tthis.dispatchEvent(new Event('change', { bubbles: true }));\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#bindMomentary(button, signal);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.#button;\n\t}\n\n\tprotected render(): void {\n\t\tif (!this.isBound()) return;\n\n\t\tconst button = this.#button;\n\n\t\twriteAttribute(button, 'disabled', this.isDisabled() ? '' : undefined);\n\t\twriteAttribute(button, 'aria-disabled', this.#isSoftDisabled() ? 'true' : undefined);\n\t\twriteAttribute(button, 'aria-busy', this.busy ? 'true' : undefined);\n\t\twriteAttribute(button, 'aria-pressed', this.latching ? String(this.pressed) : undefined);\n\t\tthis.toggleState('pressed', this.pressed);\n\t\tthis.forwardNaming(button, true);\n\t\tthis.#forwardPopup(button);\n\t\tthis.#showLegend();\n\n\t\t// eslint-disable-next-line unicorn/no-null -- `null` submits nothing\n\t\tconst submitted = this.latching && this.pressed ? this.value : null;\n\n\t\tthis.writeFormValue(submitted, String(this.pressed));\n\t}\n\n\tprotected restoreState(state: string): void {\n\t\tif (this.latching) this.pressed = state === 'true';\n\t}\n\n\t#bindMomentary(button: HTMLButtonElement, signal: AbortSignal): void {\n\t\tconst holding = bindHold(\n\t\t\tbutton,\n\t\t\t{\n\t\t\t\tcanHold: () => !this.isDisabled() && !this.#isSoftDisabled(),\n\t\t\t\tleave: 'blur',\n\t\t\t\tonHold: () => {\n\t\t\t\t\tthis.#press(true);\n\t\t\t\t},\n\t\t\t\tonRelease: () => {\n\t\t\t\t\tthis.#press(false);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\n\t\tthis.#holding = holding;\n\t\tbutton.addEventListener(\n\t\t\t'pointerdown',\n\t\t\t(event) => {\n\t\t\t\tif (event.button !== 0 || !this.#isMomentary()) return;\n\n\t\t\t\tcapturePointer(button, event.pointerId);\n\t\t\t\tholding.hold(event.pointerId);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tbutton.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (event.repeat || !holdKeys.has(event.key) || !this.#isMomentary()) return;\n\n\t\t\t\tholding.hold(event.key);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\n\t#forwardPopup(button: HTMLButtonElement): void {\n\t\tfor (const [name, aria] of Object.entries(popupAttributes)) {\n\t\t\twriteAttribute(button, aria, this.getAttribute(name) ?? undefined);\n\t\t}\n\t}\n\n\t#isMomentary(): boolean {\n\t\treturn this.momentary && !this.latching;\n\t}\n\n\t#isSoftDisabled(): boolean {\n\t\treturn this.softDisabled && !this.isDisabled();\n\t}\n\n\t#press(isPressed: boolean): void {\n\t\tthis.pressed = isPressed;\n\t\tthis.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#showLegend(): void {\n\t\tconst legend = this.legend;\n\n\t\tfor (const part of this.#button.querySelectorAll<HTMLElement | SVGElement>(\n\t\t\t':scope > .sonic-button-cap > [data-sonic-when]',\n\t\t)) {\n\t\t\tconst when = part.dataset.sonicWhen ?? '';\n\n\t\t\tpart.toggleAttribute('data-sonic-hidden', !pressWhens.has(when) && when !== legend);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"button.js","names":[],"sources":["../../../src/elements/button.ts"],"sourcesContent":["import type { Hold } from '#lib/hold.ts';\n\nimport { SonicFormElement } from '#elements/form-element.ts';\nimport { copyNode } from '#lib/copy-node.ts';\nimport { bindHold } from '#lib/hold.ts';\nimport { bindKeyPress } from '#lib/key-press.ts';\nimport { mirrorChildren } from '#lib/mirror-children.ts';\nimport { capturePointer } from '#lib/pointer-drag.ts';\nimport { placeChildren, requireChild, template } from '#lib/render.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-button': SonicButton;\n\t}\n}\n\nconst renderButton = template(\n\t/* HTML */ `\n\t\t<button class=\"sonic-button\" type=\"button\"><span class=\"sonic-button-cap\"></span></button>\n\t`,\n\tHTMLButtonElement,\n);\n\nconst holdKeys = new Set([' ', 'Enter']);\n\nconst popupAttributes = {\n\tcontrols: 'aria-controls',\n\texpanded: 'aria-expanded',\n\tpopup: 'aria-haspopup',\n} as const;\n\nconst pressWhens = new Set(['pressed', 'released']);\n\nexport class SonicButton extends SonicFormElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicFormElement.observedAttributes,\n\t\t...Object.keys(popupAttributes),\n\t\t'busy',\n\t\t'legend',\n\t\t'momentary',\n\t\t'pressed',\n\t\t'soft-disabled',\n\t\t'latching',\n\t\t'value',\n\t];\n\n\tget armed(): boolean {\n\t\treturn this.hasAttribute('armed');\n\t}\n\n\tset armed(isArmed: boolean) {\n\t\tthis.reflect('armed', isArmed);\n\t}\n\n\tget busy(): boolean {\n\t\treturn this.hasAttribute('busy');\n\t}\n\n\tset busy(isBusy: boolean) {\n\t\tthis.reflect('busy', isBusy);\n\t}\n\n\tget defaultPressed(): boolean {\n\t\treturn this.hasAttribute('pressed');\n\t}\n\n\tset defaultPressed(isPressed: boolean) {\n\t\tthis.reflect('pressed', isPressed);\n\t}\n\n\tget latching(): boolean {\n\t\treturn this.hasAttribute('latching');\n\t}\n\n\tset latching(isLatching: boolean) {\n\t\tthis.reflect('latching', isLatching);\n\t}\n\n\tget legend(): string | undefined {\n\t\treturn this.getAttribute('legend') ?? undefined;\n\t}\n\n\tset legend(name: string | undefined) {\n\t\tthis.reflect('legend', name);\n\t}\n\n\tget momentary(): boolean {\n\t\treturn this.hasAttribute('momentary');\n\t}\n\n\tset momentary(isMomentary: boolean) {\n\t\tthis.reflect('momentary', isMomentary);\n\t}\n\n\tget pressed(): boolean {\n\t\treturn this.#isDirty ? this.#pressed : this.defaultPressed;\n\t}\n\n\tset pressed(isPressed: boolean | undefined) {\n\t\tthis.#isDirty = true;\n\t\tthis.#pressed = isPressed === true;\n\t\tthis.render();\n\t}\n\n\tget softDisabled(): boolean {\n\t\treturn this.hasAttribute('soft-disabled');\n\t}\n\n\tset softDisabled(isSoftDisabled: boolean) {\n\t\tthis.reflect('soft-disabled', isSoftDisabled);\n\t}\n\n\tget value(): string {\n\t\treturn this.getAttribute('value') ?? 'on';\n\t}\n\n\tset value(value: string | undefined) {\n\t\tthis.reflect('value', value);\n\t}\n\n\treadonly #button = renderButton();\n\n\t#holding: Hold | undefined;\n\n\t#isDirty = false;\n\n\t#pressed = false;\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (name === 'pressed') this.#isDirty = false;\n\t\tif (this.isDisabled() || this.#isSoftDisabled()) this.#holding?.release();\n\t\tthis.render();\n\t}\n\n\toverride formResetCallback(): void {\n\t\tthis.attributeChangedCallback('pressed');\n\t}\n\n\tprotected override activate(): void {\n\t\tthis.#button.click();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst button = this.#button;\n\t\tconst cap = requireChild(button, '.sonic-button-cap', HTMLSpanElement);\n\n\t\tthis.upgradeProperties(\n\t\t\t'armed',\n\t\t\t'busy',\n\t\t\t'defaultPressed',\n\t\t\t'legend',\n\t\t\t'momentary',\n\t\t\t'softDisabled',\n\t\t\t'latching',\n\t\t\t'pressed',\n\t\t\t'value',\n\t\t);\n\t\tmirrorChildren(\n\t\t\tthis,\n\t\t\t{\n\t\t\t\tcontrol: button,\n\t\t\t\tcopy: copyNode,\n\t\t\t\tplace: (copies) => {\n\t\t\t\t\tplaceChildren(cap, copies);\n\t\t\t\t\tthis.#showLegend();\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tthis.render();\n\t\tthis.checkStyles(button, 'button.css');\n\n\t\tbutton.addEventListener(\n\t\t\t'click',\n\t\t\t(event) => {\n\t\t\t\t// A native disabled button fires no click at all\n\t\t\t\tif (this.#isSoftDisabled()) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.latching) return;\n\n\t\t\t\tthis.pressed = !this.pressed;\n\t\t\t\tthis.dispatchEvent(new Event('change', { bubbles: true }));\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#bindMomentary(button, signal);\n\t\tbindKeyPress(button, signal);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.#button;\n\t}\n\n\tprotected render(): void {\n\t\tif (!this.isBound()) return;\n\n\t\tconst button = this.#button;\n\n\t\twriteAttribute(button, 'disabled', this.isDisabled() ? '' : undefined);\n\t\twriteAttribute(button, 'aria-disabled', this.#isSoftDisabled() ? 'true' : undefined);\n\t\twriteAttribute(button, 'aria-busy', this.busy ? 'true' : undefined);\n\t\twriteAttribute(button, 'aria-pressed', this.latching ? String(this.pressed) : undefined);\n\t\tthis.toggleState('pressed', this.pressed);\n\t\tthis.forwardNaming(button, true);\n\t\tthis.#forwardPopup(button);\n\t\tthis.#showLegend();\n\n\t\t// eslint-disable-next-line unicorn/no-null -- `null` submits nothing\n\t\tconst submitted = this.latching && this.pressed ? this.value : null;\n\n\t\tthis.writeFormValue(submitted, String(this.pressed));\n\t}\n\n\tprotected restoreState(state: string): void {\n\t\tif (this.latching) this.pressed = state === 'true';\n\t}\n\n\t#bindMomentary(button: HTMLButtonElement, signal: AbortSignal): void {\n\t\tconst holding = bindHold(\n\t\t\tbutton,\n\t\t\t{\n\t\t\t\tcanHold: () => !this.isDisabled() && !this.#isSoftDisabled(),\n\t\t\t\tleave: 'blur',\n\t\t\t\tonHold: () => {\n\t\t\t\t\tthis.#press(true);\n\t\t\t\t},\n\t\t\t\tonRelease: () => {\n\t\t\t\t\tthis.#press(false);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\n\t\tthis.#holding = holding;\n\t\tbutton.addEventListener(\n\t\t\t'pointerdown',\n\t\t\t(event) => {\n\t\t\t\tif (event.button !== 0 || !this.#isMomentary()) return;\n\n\t\t\t\tcapturePointer(button, event.pointerId);\n\t\t\t\tholding.hold(event.pointerId);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tbutton.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (event.repeat || !holdKeys.has(event.key) || !this.#isMomentary()) return;\n\n\t\t\t\tholding.hold(event.key);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\n\t#forwardPopup(button: HTMLButtonElement): void {\n\t\tfor (const [name, aria] of Object.entries(popupAttributes)) {\n\t\t\twriteAttribute(button, aria, this.getAttribute(name) ?? undefined);\n\t\t}\n\t}\n\n\t#isMomentary(): boolean {\n\t\treturn this.momentary && !this.latching;\n\t}\n\n\t#isSoftDisabled(): boolean {\n\t\treturn this.softDisabled && !this.isDisabled();\n\t}\n\n\t#press(isPressed: boolean): void {\n\t\tthis.pressed = isPressed;\n\t\tthis.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#showLegend(): void {\n\t\tconst legend = this.legend;\n\n\t\tfor (const part of this.#button.querySelectorAll<HTMLElement | SVGElement>(\n\t\t\t':scope > .sonic-button-cap > [data-sonic-when]',\n\t\t)) {\n\t\t\tconst when = part.dataset.sonicWhen ?? '';\n\n\t\t\tpart.toggleAttribute('data-sonic-hidden', !pressWhens.has(when) && when !== legend);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SonicRadioGroupElement } from "./radio-group.js";
|
|
2
|
+
//#region src/elements/position-group.d.ts
|
|
3
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
4
|
+
export declare abstract class SonicPositionGroupElement extends SonicRadioGroupElement {
|
|
5
|
+
#private;
|
|
6
|
+
static readonly observedAttributes: string[];
|
|
7
|
+
get checked(): boolean;
|
|
8
|
+
set checked(isChecked: boolean | undefined);
|
|
9
|
+
get defaultChecked(): boolean;
|
|
10
|
+
set defaultChecked(isChecked: boolean);
|
|
11
|
+
get orientation(): Orientation;
|
|
12
|
+
set orientation(direction: Orientation | undefined);
|
|
13
|
+
get value(): string;
|
|
14
|
+
set value(next: string);
|
|
15
|
+
protected abstract readonly bare: HTMLButtonElement;
|
|
16
|
+
protected abstract readonly defaultOrientation: Orientation;
|
|
17
|
+
attributeChangedCallback(name: string): void;
|
|
18
|
+
formResetCallback(): void;
|
|
19
|
+
protected activate(): void;
|
|
20
|
+
protected along(event: PointerEvent): number;
|
|
21
|
+
protected checkedIndex(options: Array<HTMLButtonElement>): number;
|
|
22
|
+
protected chooseByClick(option: HTMLButtonElement): void;
|
|
23
|
+
protected chooseByKey(option: HTMLButtonElement, event: KeyboardEvent): void;
|
|
24
|
+
protected connect(signal: AbortSignal): void;
|
|
25
|
+
protected focusTarget(): HTMLElement | undefined;
|
|
26
|
+
protected hold(option: HTMLButtonElement, by: number | string): void;
|
|
27
|
+
protected isBare(): boolean;
|
|
28
|
+
protected isMomentary(option: HTMLButtonElement): boolean;
|
|
29
|
+
protected isWrapping(): boolean;
|
|
30
|
+
protected pressTarget(option: HTMLButtonElement): HTMLButtonElement;
|
|
31
|
+
protected releaseHold(): void;
|
|
32
|
+
protected render(): void;
|
|
33
|
+
protected restoreState(state: string): void;
|
|
34
|
+
protected setChecked(isChecked: boolean): void;
|
|
35
|
+
protected springBack(): void;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//# sourceMappingURL=position-group.d.ts.map
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { writeAttribute } from "../lib/write-attribute.js";
|
|
2
|
+
import { bindHold } from "../lib/hold.js";
|
|
3
|
+
import { SonicRadioGroupElement, optionValue } from "./radio-group.js";
|
|
4
|
+
|
|
5
|
+
//#region src/elements/position-group.ts
|
|
6
|
+
var SonicPositionGroupElement = class extends SonicRadioGroupElement {
|
|
7
|
+
static observedAttributes = [
|
|
8
|
+
...SonicRadioGroupElement.observedAttributes,
|
|
9
|
+
"checked",
|
|
10
|
+
"orientation"
|
|
11
|
+
];
|
|
12
|
+
get checked() {
|
|
13
|
+
return this.#isDirty ? this.#checked : this.defaultChecked;
|
|
14
|
+
}
|
|
15
|
+
set checked(isChecked) {
|
|
16
|
+
this.#isDirty = true;
|
|
17
|
+
this.#checked = isChecked === true;
|
|
18
|
+
this.render();
|
|
19
|
+
}
|
|
20
|
+
get defaultChecked() {
|
|
21
|
+
return this.hasAttribute("checked");
|
|
22
|
+
}
|
|
23
|
+
set defaultChecked(isChecked) {
|
|
24
|
+
this.reflect("checked", isChecked);
|
|
25
|
+
}
|
|
26
|
+
get orientation() {
|
|
27
|
+
const orientation = this.getAttribute("orientation");
|
|
28
|
+
return orientation === "horizontal" || orientation === "vertical" ? orientation : this.defaultOrientation;
|
|
29
|
+
}
|
|
30
|
+
set orientation(direction) {
|
|
31
|
+
this.reflect("orientation", direction);
|
|
32
|
+
}
|
|
33
|
+
get value() {
|
|
34
|
+
const value = super.value;
|
|
35
|
+
return value === "" && this.isBare() ? "on" : value;
|
|
36
|
+
}
|
|
37
|
+
set value(next) {
|
|
38
|
+
super.value = next;
|
|
39
|
+
}
|
|
40
|
+
#checked = false;
|
|
41
|
+
#holding;
|
|
42
|
+
#isDirty = false;
|
|
43
|
+
attributeChangedCallback(name) {
|
|
44
|
+
if (name === "checked") this.#isDirty = false;
|
|
45
|
+
if (this.isDisabled()) this.#holding?.release();
|
|
46
|
+
super.attributeChangedCallback(name);
|
|
47
|
+
}
|
|
48
|
+
formResetCallback() {
|
|
49
|
+
this.#isDirty = false;
|
|
50
|
+
super.formResetCallback();
|
|
51
|
+
}
|
|
52
|
+
activate() {
|
|
53
|
+
if (this.isBare()) this.bare.click();
|
|
54
|
+
else super.activate();
|
|
55
|
+
}
|
|
56
|
+
along(event) {
|
|
57
|
+
return this.orientation === "vertical" ? event.clientY : event.clientX;
|
|
58
|
+
}
|
|
59
|
+
checkedIndex(options) {
|
|
60
|
+
return options.findIndex((option) => optionValue(option) === this.value);
|
|
61
|
+
}
|
|
62
|
+
chooseByClick(option) {
|
|
63
|
+
super.chooseByClick(option);
|
|
64
|
+
if (this.isMomentary(option)) this.springBack();
|
|
65
|
+
}
|
|
66
|
+
chooseByKey(option, event) {
|
|
67
|
+
if (!this.isMomentary(option)) {
|
|
68
|
+
super.chooseByKey(option, event);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (event.repeat) return;
|
|
72
|
+
this.hold(option, event.key);
|
|
73
|
+
option.focus();
|
|
74
|
+
}
|
|
75
|
+
connect(signal) {
|
|
76
|
+
this.upgradeProperties("defaultChecked", "checked", "orientation");
|
|
77
|
+
super.connect(signal);
|
|
78
|
+
this.#holding = bindHold(this.group, {
|
|
79
|
+
canHold: () => !this.isDisabled(),
|
|
80
|
+
leave: "focusout",
|
|
81
|
+
onHold: () => {
|
|
82
|
+
this.toggleState("held", true);
|
|
83
|
+
},
|
|
84
|
+
onRelease: () => {
|
|
85
|
+
this.toggleState("held", false);
|
|
86
|
+
this.springBack();
|
|
87
|
+
}
|
|
88
|
+
}, signal);
|
|
89
|
+
}
|
|
90
|
+
focusTarget() {
|
|
91
|
+
return this.isBare() ? this.bare : super.focusTarget();
|
|
92
|
+
}
|
|
93
|
+
hold(option, by) {
|
|
94
|
+
if (this.#holding?.hold(by) === true) this.select(option);
|
|
95
|
+
}
|
|
96
|
+
isBare() {
|
|
97
|
+
return this.options().length === 0;
|
|
98
|
+
}
|
|
99
|
+
isMomentary(option) {
|
|
100
|
+
const options = this.options();
|
|
101
|
+
return (option === options[0] || option === options.at(-1)) && options.length > 1 && option.querySelector("[data-sonic-value]")?.hasAttribute("data-sonic-momentary") === true;
|
|
102
|
+
}
|
|
103
|
+
isWrapping() {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
pressTarget(option) {
|
|
107
|
+
const options = this.options();
|
|
108
|
+
const index = this.checkedIndex(options);
|
|
109
|
+
return (options.length === 2 && index >= 0 ? options[1 - index] : void 0) ?? option;
|
|
110
|
+
}
|
|
111
|
+
releaseHold() {
|
|
112
|
+
this.#holding?.release();
|
|
113
|
+
}
|
|
114
|
+
render() {
|
|
115
|
+
if (!this.isBound()) return;
|
|
116
|
+
const group = this.group;
|
|
117
|
+
const count = this.options().length;
|
|
118
|
+
if (count === 0) {
|
|
119
|
+
this.#renderBare();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.bare.remove();
|
|
123
|
+
writeAttribute(group, "role", "radiogroup");
|
|
124
|
+
writeAttribute(group, "data-sonic-position-count", String(count));
|
|
125
|
+
super.render();
|
|
126
|
+
}
|
|
127
|
+
restoreState(state) {
|
|
128
|
+
if (this.isBare()) this.checked = state === "true";
|
|
129
|
+
else super.restoreState(state);
|
|
130
|
+
}
|
|
131
|
+
setChecked(isChecked) {
|
|
132
|
+
if (isChecked === this.checked) return;
|
|
133
|
+
this.checked = isChecked;
|
|
134
|
+
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
135
|
+
}
|
|
136
|
+
springBack() {
|
|
137
|
+
const options = this.options();
|
|
138
|
+
const index = this.checkedIndex(options);
|
|
139
|
+
const held = options[index];
|
|
140
|
+
if (!held || !this.isMomentary(held)) return;
|
|
141
|
+
const rest = options[index === 0 ? 1 : index - 1];
|
|
142
|
+
if (!rest) return;
|
|
143
|
+
const isFocused = this.group.contains(this.ownerDocument.activeElement);
|
|
144
|
+
this.select(rest);
|
|
145
|
+
if (isFocused) rest.focus();
|
|
146
|
+
}
|
|
147
|
+
#renderBare() {
|
|
148
|
+
const group = this.group;
|
|
149
|
+
const bare = this.bare;
|
|
150
|
+
const isChecked = this.checked;
|
|
151
|
+
writeAttribute(group, "role", void 0);
|
|
152
|
+
writeAttribute(group, "data-sonic-position-count", void 0);
|
|
153
|
+
if (bare.parentElement !== group) group.append(bare);
|
|
154
|
+
writeAttribute(bare, "disabled", this.isDisabled() ? "" : void 0);
|
|
155
|
+
writeAttribute(bare, "aria-checked", String(isChecked));
|
|
156
|
+
this.forwardNaming(group, false);
|
|
157
|
+
this.forwardNaming(bare, true);
|
|
158
|
+
this.writeFormValue(isChecked ? this.value : null, String(isChecked));
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
export { SonicPositionGroupElement };
|
|
164
|
+
//# sourceMappingURL=position-group.js.map
|