@xsynaptic/sonic-ui 0.4.0 → 0.5.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.
Files changed (240) hide show
  1. package/README.md +2 -21
  2. package/dist/default/dat.js +50 -0
  3. package/dist/default/define/button.js +7 -0
  4. package/dist/default/define/envelope.js +7 -0
  5. package/dist/default/define/split.js +7 -0
  6. package/dist/default/define/switch.js +7 -0
  7. package/dist/default/define/waveform.js +7 -0
  8. package/dist/default/define/wavestrip.js +7 -0
  9. package/dist/default/define/xy.js +7 -0
  10. package/dist/default/define.js +7 -1
  11. package/dist/default/elements/button.js +165 -0
  12. package/dist/default/elements/dial.js +16 -22
  13. package/dist/default/elements/envelope.js +367 -0
  14. package/dist/default/elements/meter.js +149 -61
  15. package/dist/default/elements/number.js +21 -8
  16. package/dist/default/elements/radio-group.js +185 -0
  17. package/dist/default/elements/readout-claim.js +81 -0
  18. package/dist/default/elements/readout.js +35 -0
  19. package/dist/default/elements/segmented.js +9 -159
  20. package/dist/default/elements/slider.js +42 -51
  21. package/dist/default/elements/sonic-element.js +24 -13
  22. package/dist/default/elements/split.js +249 -0
  23. package/dist/default/elements/switch.js +279 -0
  24. package/dist/default/elements/value-element.js +691 -0
  25. package/dist/default/elements/{range-entry.js → value-entry.js} +3 -3
  26. package/dist/default/elements/wave-element.js +77 -0
  27. package/dist/default/elements/waveform.js +305 -0
  28. package/dist/default/elements/wavestrip.js +182 -0
  29. package/dist/default/elements/xy.js +473 -0
  30. package/dist/default/index.js +10 -2
  31. package/dist/default/lib/adsr-shape.js +108 -0
  32. package/dist/default/lib/ballistics.js +55 -0
  33. package/dist/default/lib/canvas-surface.js +192 -0
  34. package/dist/default/lib/copy-node.js +32 -2
  35. package/dist/default/lib/crossfade.js +22 -0
  36. package/dist/default/lib/distribute.js +215 -0
  37. package/dist/default/lib/drag-step.js +99 -0
  38. package/dist/default/lib/envelope-curve.js +9 -0
  39. package/dist/default/lib/field.js +94 -0
  40. package/dist/default/lib/focus-by-pointer.js +28 -0
  41. package/dist/default/lib/frame-timeline.js +62 -0
  42. package/dist/default/lib/hold.js +38 -0
  43. package/dist/default/lib/marker-band.js +36 -0
  44. package/dist/default/lib/marker-rider.js +114 -0
  45. package/dist/default/lib/math.js +12 -3
  46. package/dist/default/lib/modifier-press.js +11 -0
  47. package/dist/default/lib/number-list.js +6 -6
  48. package/dist/default/lib/pointer-drag.js +43 -0
  49. package/dist/default/lib/render.js +20 -5
  50. package/dist/default/lib/resample-peaks.js +36 -0
  51. package/dist/default/lib/strip-scene.js +48 -0
  52. package/dist/default/lib/taper.js +23 -17
  53. package/dist/default/lib/time-regions.js +8 -0
  54. package/dist/default/lib/tracking-clock.js +35 -0
  55. package/dist/default/lib/value-mapping.js +115 -0
  56. package/dist/default/lib/waveform-buckets.js +41 -0
  57. package/dist/dev/dat.d.ts +19 -0
  58. package/dist/dev/dat.js +51 -0
  59. package/dist/dev/dat.js.map +1 -0
  60. package/dist/dev/define/button.d.ts +2 -0
  61. package/dist/dev/define/button.js +8 -0
  62. package/dist/dev/define/button.js.map +1 -0
  63. package/dist/dev/define/dial.js.map +1 -1
  64. package/dist/dev/define/envelope.d.ts +2 -0
  65. package/dist/dev/define/envelope.js +8 -0
  66. package/dist/dev/define/envelope.js.map +1 -0
  67. package/dist/dev/define/meter.js.map +1 -1
  68. package/dist/dev/define/number.js.map +1 -1
  69. package/dist/dev/define/segmented.js.map +1 -1
  70. package/dist/dev/define/slider.js.map +1 -1
  71. package/dist/dev/define/split.d.ts +2 -0
  72. package/dist/dev/define/split.js +8 -0
  73. package/dist/dev/define/split.js.map +1 -0
  74. package/dist/dev/define/switch.d.ts +2 -0
  75. package/dist/dev/define/switch.js +8 -0
  76. package/dist/dev/define/switch.js.map +1 -0
  77. package/dist/dev/define/waveform.d.ts +2 -0
  78. package/dist/dev/define/waveform.js +8 -0
  79. package/dist/dev/define/waveform.js.map +1 -0
  80. package/dist/dev/define/wavestrip.d.ts +2 -0
  81. package/dist/dev/define/wavestrip.js +8 -0
  82. package/dist/dev/define/wavestrip.js.map +1 -0
  83. package/dist/dev/define/xy.d.ts +2 -0
  84. package/dist/dev/define/xy.js +8 -0
  85. package/dist/dev/define/xy.js.map +1 -0
  86. package/dist/dev/define.d.ts +15 -3
  87. package/dist/dev/define.js +7 -1
  88. package/dist/dev/elements/{key.d.ts → button.d.ts} +8 -6
  89. package/dist/dev/elements/button.js +166 -0
  90. package/dist/dev/elements/button.js.map +1 -0
  91. package/dist/dev/elements/dial.d.ts +6 -4
  92. package/dist/dev/elements/dial.js +16 -22
  93. package/dist/dev/elements/dial.js.map +1 -1
  94. package/dist/dev/elements/envelope.d.ts +36 -0
  95. package/dist/dev/elements/envelope.js +372 -0
  96. package/dist/dev/elements/envelope.js.map +1 -0
  97. package/dist/dev/elements/form-element.d.ts +1 -1
  98. package/dist/dev/elements/form-element.js.map +1 -1
  99. package/dist/dev/elements/meter.d.ts +10 -5
  100. package/dist/dev/elements/meter.js +149 -61
  101. package/dist/dev/elements/meter.js.map +1 -1
  102. package/dist/dev/elements/number.d.ts +7 -3
  103. package/dist/dev/elements/number.js +21 -8
  104. package/dist/dev/elements/number.js.map +1 -1
  105. package/dist/dev/elements/radio-group.d.ts +25 -0
  106. package/dist/dev/elements/radio-group.js +186 -0
  107. package/dist/dev/elements/radio-group.js.map +1 -0
  108. package/dist/dev/elements/readout-claim.js +82 -0
  109. package/dist/dev/elements/readout-claim.js.map +1 -0
  110. package/dist/dev/elements/readout.js +36 -0
  111. package/dist/dev/elements/readout.js.map +1 -0
  112. package/dist/dev/elements/segmented.d.ts +4 -10
  113. package/dist/dev/elements/segmented.js +9 -159
  114. package/dist/dev/elements/segmented.js.map +1 -1
  115. package/dist/dev/elements/slider.d.ts +6 -6
  116. package/dist/dev/elements/slider.js +42 -51
  117. package/dist/dev/elements/slider.js.map +1 -1
  118. package/dist/dev/elements/sonic-element.d.ts +4 -3
  119. package/dist/dev/elements/sonic-element.js +51 -22
  120. package/dist/dev/elements/sonic-element.js.map +1 -1
  121. package/dist/dev/elements/split.d.ts +21 -0
  122. package/dist/dev/elements/split.js +258 -0
  123. package/dist/dev/elements/split.js.map +1 -0
  124. package/dist/dev/elements/switch.d.ts +35 -0
  125. package/dist/dev/elements/switch.js +280 -0
  126. package/dist/dev/elements/switch.js.map +1 -0
  127. package/dist/dev/elements/value-element.d.ts +84 -0
  128. package/dist/dev/elements/value-element.js +692 -0
  129. package/dist/dev/elements/value-element.js.map +1 -0
  130. package/dist/dev/elements/{range-entry.js → value-entry.js} +4 -4
  131. package/dist/dev/elements/value-entry.js.map +1 -0
  132. package/dist/dev/elements/wave-element.d.ts +36 -0
  133. package/dist/dev/elements/wave-element.js +78 -0
  134. package/dist/dev/elements/wave-element.js.map +1 -0
  135. package/dist/dev/elements/waveform.d.ts +55 -0
  136. package/dist/dev/elements/waveform.js +306 -0
  137. package/dist/dev/elements/waveform.js.map +1 -0
  138. package/dist/dev/elements/wavestrip.d.ts +51 -0
  139. package/dist/dev/elements/wavestrip.js +183 -0
  140. package/dist/dev/elements/wavestrip.js.map +1 -0
  141. package/dist/dev/elements/xy.d.ts +62 -0
  142. package/dist/dev/elements/xy.js +474 -0
  143. package/dist/dev/elements/xy.js.map +1 -0
  144. package/dist/dev/index.d.ts +11 -2
  145. package/dist/dev/index.js +10 -2
  146. package/dist/dev/lib/adsr-shape.js +109 -0
  147. package/dist/dev/lib/adsr-shape.js.map +1 -0
  148. package/dist/dev/lib/ballistics.js +56 -0
  149. package/dist/dev/lib/ballistics.js.map +1 -0
  150. package/dist/dev/lib/canvas-surface.d.ts +25 -0
  151. package/dist/dev/lib/canvas-surface.js +193 -0
  152. package/dist/dev/lib/canvas-surface.js.map +1 -0
  153. package/dist/dev/lib/copy-node.js +32 -2
  154. package/dist/dev/lib/copy-node.js.map +1 -1
  155. package/dist/dev/lib/crossfade.d.ts +12 -0
  156. package/dist/dev/lib/crossfade.js +23 -0
  157. package/dist/dev/lib/crossfade.js.map +1 -0
  158. package/dist/dev/lib/distribute.d.ts +4 -0
  159. package/dist/dev/lib/distribute.js +216 -0
  160. package/dist/dev/lib/distribute.js.map +1 -0
  161. package/dist/dev/lib/drag-step.js +100 -0
  162. package/dist/dev/lib/drag-step.js.map +1 -0
  163. package/dist/dev/lib/envelope-curve.d.ts +4 -0
  164. package/dist/dev/lib/envelope-curve.js +10 -0
  165. package/dist/dev/lib/envelope-curve.js.map +1 -0
  166. package/dist/dev/lib/field.d.ts +4 -0
  167. package/dist/dev/lib/field.js +95 -0
  168. package/dist/dev/lib/field.js.map +1 -0
  169. package/dist/dev/lib/focus-by-pointer.js +29 -0
  170. package/dist/dev/lib/focus-by-pointer.js.map +1 -0
  171. package/dist/dev/lib/frame-timeline.js +63 -0
  172. package/dist/dev/lib/frame-timeline.js.map +1 -0
  173. package/dist/dev/lib/hold.js +39 -0
  174. package/dist/dev/lib/hold.js.map +1 -0
  175. package/dist/dev/lib/marker-band.js +37 -0
  176. package/dist/dev/lib/marker-band.js.map +1 -0
  177. package/dist/dev/lib/marker-rider.js +115 -0
  178. package/dist/dev/lib/marker-rider.js.map +1 -0
  179. package/dist/dev/lib/math.js +12 -3
  180. package/dist/dev/lib/math.js.map +1 -1
  181. package/dist/dev/lib/modifier-press.js +12 -0
  182. package/dist/dev/lib/modifier-press.js.map +1 -0
  183. package/dist/dev/lib/number-list.js +6 -6
  184. package/dist/dev/lib/number-list.js.map +1 -1
  185. package/dist/dev/lib/pointer-drag.js +44 -0
  186. package/dist/dev/lib/pointer-drag.js.map +1 -0
  187. package/dist/dev/lib/read-px-property.js.map +1 -1
  188. package/dist/dev/lib/render.js +20 -5
  189. package/dist/dev/lib/render.js.map +1 -1
  190. package/dist/dev/lib/resample-peaks.js +37 -0
  191. package/dist/dev/lib/resample-peaks.js.map +1 -0
  192. package/dist/dev/lib/strip-scene.js +49 -0
  193. package/dist/dev/lib/strip-scene.js.map +1 -0
  194. package/dist/dev/lib/taper.js +23 -17
  195. package/dist/dev/lib/taper.js.map +1 -1
  196. package/dist/dev/lib/time-regions.d.ts +4 -0
  197. package/dist/dev/lib/time-regions.js +9 -0
  198. package/dist/dev/lib/time-regions.js.map +1 -0
  199. package/dist/dev/lib/tracking-clock.js +36 -0
  200. package/dist/dev/lib/tracking-clock.js.map +1 -0
  201. package/dist/dev/lib/value-mapping.d.ts +23 -0
  202. package/dist/dev/lib/value-mapping.js +116 -0
  203. package/dist/dev/lib/value-mapping.js.map +1 -0
  204. package/dist/dev/lib/waveform-buckets.d.ts +9 -0
  205. package/dist/dev/lib/waveform-buckets.js +42 -0
  206. package/dist/dev/lib/waveform-buckets.js.map +1 -0
  207. package/dist/skins/ivory.css +1 -2
  208. package/dist/styles/button.css +212 -0
  209. package/dist/styles/controls.css +8 -1
  210. package/dist/styles/dial.css +88 -42
  211. package/dist/styles/envelope.css +159 -0
  212. package/dist/styles/led.css +36 -5
  213. package/dist/styles/material.css +277 -76
  214. package/dist/styles/meter.css +33 -48
  215. package/dist/styles/number.css +5 -1
  216. package/dist/styles/panel.css +59 -0
  217. package/dist/styles/ring.css +74 -0
  218. package/dist/styles/segmented.css +21 -48
  219. package/dist/styles/slider.css +175 -39
  220. package/dist/styles/switch.css +347 -0
  221. package/dist/styles/waveform.css +173 -0
  222. package/dist/styles/wavestrip.css +215 -0
  223. package/dist/styles/xy.css +204 -0
  224. package/package.json +14 -2
  225. package/dist/default/define/key.js +0 -7
  226. package/dist/default/elements/key.js +0 -169
  227. package/dist/default/elements/range-element.js +0 -546
  228. package/dist/default/lib/detent.js +0 -17
  229. package/dist/dev/define/key.d.ts +0 -2
  230. package/dist/dev/define/key.js +0 -8
  231. package/dist/dev/define/key.js.map +0 -1
  232. package/dist/dev/elements/key.js +0 -170
  233. package/dist/dev/elements/key.js.map +0 -1
  234. package/dist/dev/elements/range-element.d.ts +0 -64
  235. package/dist/dev/elements/range-element.js +0 -547
  236. package/dist/dev/elements/range-element.js.map +0 -1
  237. package/dist/dev/elements/range-entry.js.map +0 -1
  238. package/dist/dev/lib/detent.js +0 -18
  239. package/dist/dev/lib/detent.js.map +0 -1
  240. package/dist/styles/key.css +0 -242
@@ -0,0 +1,692 @@
1
+ import { clamp } from "../lib/math.js";
2
+ import { placeChildren, requireChild } from "../lib/render.js";
3
+ import { writeAttribute } from "../lib/write-attribute.js";
4
+ import { SonicFormElement } from "./form-element.js";
5
+ import { ReadoutClaim } from "./readout-claim.js";
6
+ import { Readout } from "./readout.js";
7
+ import { ValueEntry } from "./value-entry.js";
8
+ import { copyNode } from "../lib/copy-node.js";
9
+ import { dragThresholdPx, startDrag, stepDrag } from "../lib/drag-step.js";
10
+ import { focusByPointer } from "../lib/focus-by-pointer.js";
11
+ import { isMenuPress, isResetPress } from "../lib/modifier-press.js";
12
+ import { parseNumberList } from "../lib/number-list.js";
13
+ import { readPxProperty } from "../lib/read-px-property.js";
14
+ import { readRegions } from "../lib/time-regions.js";
15
+ import { resetKeys, valueMapping } from "../lib/value-mapping.js";
16
+
17
+ //#region src/elements/value-element.ts
18
+ const detentZonePx = 8;
19
+ const fallbackTravelPx = 160;
20
+ let instanceCount = 0;
21
+ const proportionAttributes = /* @__PURE__ */ new Set([
22
+ "max",
23
+ "midpoint",
24
+ "min",
25
+ "notched",
26
+ "positions",
27
+ "taper"
28
+ ]);
29
+ const roleAttributes = [
30
+ "aria-disabled",
31
+ "aria-orientation",
32
+ "aria-valuemax",
33
+ "aria-valuemin",
34
+ "aria-valuenow",
35
+ "aria-valuetext",
36
+ "role",
37
+ "tabindex"
38
+ ];
39
+ function scaleValue(mark) {
40
+ const text = mark.dataset.sonicValue?.trim();
41
+ return text ? Number(text) : NaN;
42
+ }
43
+ function scaleMark(original) {
44
+ const mark = copyNode(original);
45
+ if (!(mark instanceof HTMLElement || mark instanceof SVGElement)) return void 0;
46
+ if (!Number.isFinite(scaleValue(mark))) return void 0;
47
+ const isTick = mark.childElementCount === 0 && mark.textContent.trim() === "";
48
+ mark.classList.add(isTick ? "sonic-scale-tick" : "sonic-scale-label");
49
+ return mark;
50
+ }
51
+ let link;
52
+ function linkValue(element) {
53
+ return link(element);
54
+ }
55
+ var SonicValueElement = class extends SonicFormElement {
56
+ static observedAttributes = [
57
+ ...SonicFormElement.observedAttributes,
58
+ "detent",
59
+ "max",
60
+ "midpoint",
61
+ "min",
62
+ "notched",
63
+ "origin",
64
+ "readout",
65
+ "step",
66
+ "taper",
67
+ "value",
68
+ "positions"
69
+ ];
70
+ static {
71
+ link = (element) => ({
72
+ input: (next, isMover = false) => (isMover || !element.#isHeld()) && element.input(next),
73
+ isDisabled: () => element.isDisabled(),
74
+ isHeld: () => element.#isHeld(),
75
+ land: (resolve) => {
76
+ element.#land = resolve;
77
+ },
78
+ limit: (bounds) => {
79
+ element.#limit = bounds;
80
+ },
81
+ mapping: () => element.mapping(),
82
+ value: () => element.#value,
83
+ watch: (listener) => {
84
+ element.#watchers.add(listener);
85
+ return () => {
86
+ element.#watchers.delete(listener);
87
+ };
88
+ }
89
+ });
90
+ }
91
+ get buffered() {
92
+ return this.#buffered.map(([start, end]) => [start, end]);
93
+ }
94
+ set buffered(regions) {
95
+ this.#buffered = regions ? readRegions(regions).toSorted((first, second) => first[0] - second[0]) : [];
96
+ this.render();
97
+ }
98
+ get default() {
99
+ return this.optionalNumberAttribute("default");
100
+ }
101
+ set default(value) {
102
+ this.reflect("default", value);
103
+ }
104
+ get detent() {
105
+ return this.optionalNumberAttribute("detent");
106
+ }
107
+ set detent(value) {
108
+ this.reflect("detent", value);
109
+ }
110
+ get dimmed() {
111
+ return this.hasAttribute("dimmed");
112
+ }
113
+ set dimmed(isDimmed) {
114
+ this.reflect("dimmed", isDimmed);
115
+ }
116
+ get doublePress() {
117
+ return this.getAttribute("double-press") === "reset" ? "reset" : "entry";
118
+ }
119
+ set doublePress(gesture) {
120
+ this.reflect("double-press", gesture);
121
+ }
122
+ get formatSpokenValue() {
123
+ return this.#formatSpokenValue;
124
+ }
125
+ set formatSpokenValue(format) {
126
+ this.#formatSpokenValue = format;
127
+ this.render();
128
+ }
129
+ get formatValue() {
130
+ return this.#formatValue;
131
+ }
132
+ set formatValue(format) {
133
+ this.#formatValue = format;
134
+ this.render();
135
+ }
136
+ get keyStep() {
137
+ return this.optionalNumberAttribute("key-step");
138
+ }
139
+ set keyStep(value) {
140
+ this.reflect("key-step", value);
141
+ }
142
+ get max() {
143
+ return this.numberAttribute("max", 100);
144
+ }
145
+ set max(value) {
146
+ this.reflect("max", value);
147
+ }
148
+ get midpoint() {
149
+ return this.optionalNumberAttribute("midpoint");
150
+ }
151
+ set midpoint(value) {
152
+ this.reflect("midpoint", value);
153
+ }
154
+ get min() {
155
+ return this.numberAttribute("min", 0);
156
+ }
157
+ set min(value) {
158
+ this.reflect("min", value);
159
+ }
160
+ get notched() {
161
+ return this.hasAttribute("notched");
162
+ }
163
+ set notched(isNotched) {
164
+ this.reflect("notched", isNotched);
165
+ }
166
+ get origin() {
167
+ return this.optionalNumberAttribute("origin");
168
+ }
169
+ set origin(value) {
170
+ this.reflect("origin", value);
171
+ }
172
+ get parseValue() {
173
+ return this.#parseValue;
174
+ }
175
+ set parseValue(parse) {
176
+ this.#parseValue = parse;
177
+ }
178
+ get positions() {
179
+ return parseNumberList(this.getAttribute("positions"));
180
+ }
181
+ set positions(positions) {
182
+ this.reflect("positions", positions?.join(" "));
183
+ }
184
+ get readout() {
185
+ return this.hasAttribute("readout");
186
+ }
187
+ set readout(isShown) {
188
+ this.reflect("readout", isShown);
189
+ }
190
+ get step() {
191
+ return this.numberAttribute("step", 1);
192
+ }
193
+ set step(value) {
194
+ this.reflect("step", value);
195
+ }
196
+ get taper() {
197
+ return this.getAttribute("taper") === "log" ? "log" : "linear";
198
+ }
199
+ set taper(curve) {
200
+ this.reflect("taper", curve);
201
+ }
202
+ get value() {
203
+ return this.#value;
204
+ }
205
+ set value(next) {
206
+ if (this.#isHeld()) {
207
+ this.heldWrite(next);
208
+ return;
209
+ }
210
+ this.#write(next);
211
+ }
212
+ get valueText() {
213
+ return this.#textFor(this.#value);
214
+ }
215
+ #buffered = [];
216
+ #claim = new ReadoutClaim(() => {
217
+ this.#renderHold();
218
+ });
219
+ #drag;
220
+ #entry;
221
+ #escapeWatch;
222
+ #formatSpokenValue;
223
+ #formatValue;
224
+ #instance = String(instanceCount += 1);
225
+ #isDirty = false;
226
+ #isModulated = false;
227
+ #keyScrub;
228
+ #land;
229
+ #limit;
230
+ #modulationValue;
231
+ #parseValue;
232
+ #positions;
233
+ #readout;
234
+ #scaleMarks;
235
+ #value = 0;
236
+ #watchers = /* @__PURE__ */ new Set();
237
+ attributeChangedCallback(name) {
238
+ this.#positions = parseNumberList(this.getAttribute("positions"));
239
+ if (name === "value") {
240
+ if (this.#isHeld()) {
241
+ this.heldWrite(this.numberAttribute("value", this.min));
242
+ return;
243
+ }
244
+ this.#isDirty = false;
245
+ }
246
+ if (name === "disabled" && this.isDisabled()) {
247
+ this.#entry?.close(false);
248
+ this.#endDrag();
249
+ this.#endKeyScrub();
250
+ }
251
+ this.#value = this.mapping().snap(this.#isDirty ? this.#value : this.numberAttribute("value", this.min));
252
+ if (proportionAttributes.has(name)) this.proportionsChanged();
253
+ this.render();
254
+ }
255
+ connectedCallback() {
256
+ this.upgradeProperties("buffered", "default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "step", "taper", "positions", "detent", "formatValue", "formatSpokenValue", "keyStep", "parseValue", "value");
257
+ super.connectedCallback();
258
+ }
259
+ bindGestures(control, signal, grab) {
260
+ const entry = this.#bindEntry(control, signal);
261
+ control.addEventListener("pointerdown", (event) => {
262
+ if (!this.#canPress(event, entry)) return;
263
+ this.#endDrag();
264
+ this.toggleState("springing", false);
265
+ if (event.pointerType === "touch") event.preventDefault();
266
+ focusByPointer(control);
267
+ if (isResetPress(event)) {
268
+ this.#reset();
269
+ return;
270
+ }
271
+ const fromValue = this.#value;
272
+ const axis = grab(event);
273
+ if (!axis) return;
274
+ const drag = {
275
+ ...axis,
276
+ fromValue,
277
+ isOutside: false,
278
+ isRevealed: false,
279
+ pointerId: event.pointerId,
280
+ revealTimer: void 0,
281
+ state: this.#startDrag(control, axis, event)
282
+ };
283
+ drag.revealTimer = setTimeout(() => {
284
+ this.#reveal(drag);
285
+ }, 250);
286
+ this.#drag = drag;
287
+ control.setPointerCapture(event.pointerId);
288
+ this.toggleState("dragging", true);
289
+ }, { signal });
290
+ control.addEventListener("pointermove", (event) => {
291
+ const drag = this.#drag;
292
+ if (event.pointerId === drag?.pointerId) this.#dragTo(drag, event);
293
+ }, { signal });
294
+ const endDrag = (event) => {
295
+ if (event.pointerId === this.#drag?.pointerId) this.#endDrag();
296
+ };
297
+ control.addEventListener("pointercancel", (event) => {
298
+ const drag = this.#drag;
299
+ if (event.pointerId === drag?.pointerId && drag.isKeptOnCancel !== true) this.input(drag.fromValue);
300
+ endDrag(event);
301
+ entry.forgetPress();
302
+ }, { signal });
303
+ control.addEventListener("lostpointercapture", endDrag, { signal });
304
+ control.addEventListener("pointerup", (event) => {
305
+ const drag = this.#drag;
306
+ if (event.pointerId !== drag?.pointerId) return;
307
+ this.#endDrag();
308
+ const tap = drag.state.isEngaged ? void 0 : this.tapTarget();
309
+ if (tap !== void 0) {
310
+ entry.forgetPress();
311
+ this.#commit(tap);
312
+ return;
313
+ }
314
+ if (!entry.press(event) || this.springTarget() !== void 0) return;
315
+ if (this.doublePress === "reset") this.#reset();
316
+ else entry.open();
317
+ }, { signal });
318
+ this.#bindKeys(control, entry, signal);
319
+ signal.addEventListener("abort", () => {
320
+ this.#endDrag();
321
+ this.#endKeyScrub();
322
+ this.#concealKeyReveal();
323
+ }, { once: true });
324
+ }
325
+ bindScale(control, marks, signal) {
326
+ this.#scaleMarks = marks;
327
+ this.mirrorChildren({
328
+ control,
329
+ copy: scaleMark,
330
+ isCopied: (child) => child instanceof Element && child.matches("[data-sonic-value]"),
331
+ place: (copies) => {
332
+ placeChildren(marks, copies);
333
+ this.#renderScale();
334
+ }
335
+ }, signal);
336
+ }
337
+ controlOrientation() {}
338
+ controlRole() {
339
+ return "slider";
340
+ }
341
+ heldFrom() {
342
+ return this.#drag?.fromValue ?? this.#keyScrub?.fromValue;
343
+ }
344
+ heldWrite(_next) {}
345
+ holdChanged() {}
346
+ hoverReadout(value) {
347
+ this.#claim.hover(value);
348
+ this.#renderReadout();
349
+ this.#watchEscape(value !== void 0);
350
+ }
351
+ input(next) {
352
+ const previous = this.#value;
353
+ this.#write(this.#limit ? clamp(next, ...this.#limit) : next);
354
+ if (this.#value === previous) return false;
355
+ this.dispatchEvent(new Event("input", {
356
+ bubbles: true,
357
+ composed: true
358
+ }));
359
+ return true;
360
+ }
361
+ isRevealed() {
362
+ return this.#claim.isRevealed;
363
+ }
364
+ isWrapping() {
365
+ return false;
366
+ }
367
+ mapping() {
368
+ const { detent, midpoint } = this;
369
+ return valueMapping({
370
+ ...detent === void 0 ? {} : { detent },
371
+ ...this.#positions ? { positions: this.#positions } : {},
372
+ max: this.max,
373
+ ...midpoint === void 0 ? {} : { midpoint },
374
+ isNotched: this.notched,
375
+ isWrapping: this.isWrapping(),
376
+ min: this.min,
377
+ step: this.step,
378
+ taper: this.taper
379
+ });
380
+ }
381
+ originValue() {
382
+ return this.origin ?? this.mapping().bounds[0];
383
+ }
384
+ proportionsChanged() {}
385
+ readModulationValue() {
386
+ return this.#modulationValue;
387
+ }
388
+ readoutValue() {
389
+ return this.#claim.shown(this.#value, this.readout).value ?? this.#value;
390
+ }
391
+ render() {
392
+ this.draw();
393
+ this.#renderScale();
394
+ this.toggleState("at-origin", !this.isWrapping() && this.#value === this.mapping().snap(this.originValue()));
395
+ this.#renderAria(this.focusTarget(), this.controlOrientation());
396
+ for (const listener of this.#watchers) listener();
397
+ }
398
+ restoreState(state) {
399
+ this.value = Number(state);
400
+ }
401
+ scrubsKeyRepeat() {
402
+ return false;
403
+ }
404
+ springTarget() {}
405
+ tapTarget() {}
406
+ travelPx(control, property) {
407
+ return Math.max(1, readPxProperty(getComputedStyle(control), property, fallbackTravelPx));
408
+ }
409
+ writeModulationValue(control, prefix, next) {
410
+ if (next !== void 0 && !Number.isFinite(next)) return;
411
+ this.#modulationValue = next;
412
+ this.#writeModulationProportion(control, prefix);
413
+ }
414
+ writeProportions(control, prefix, modulation) {
415
+ const { style } = control;
416
+ const mapping = this.mapping();
417
+ const value = mapping.proportionOf(this.#value);
418
+ const reach = mapping.proportionOf(this.#value + modulation);
419
+ const { positionCount } = mapping;
420
+ style.setProperty(`--_sonic-${prefix}-value`, String(value));
421
+ style.setProperty(`--_sonic-${prefix}-origin`, String(mapping.proportionOf(this.originValue())));
422
+ style.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(value, reach)));
423
+ style.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(value, reach)));
424
+ if (positionCount === void 0) style.removeProperty(`--_sonic-${prefix}-position-count`);
425
+ else style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));
426
+ this.#writeModulationProportion(control, prefix);
427
+ }
428
+ #bindEntry(control, signal) {
429
+ const input = requireChild(control, "input", HTMLInputElement);
430
+ const bubble = control.querySelector("[popover]");
431
+ input.id = `sonic-entry-${this.#instance}`;
432
+ if (bubble) this.#readout = {
433
+ anchor: control,
434
+ bubble: new Readout(bubble)
435
+ };
436
+ const entry = new ValueEntry(input, {
437
+ commit: (text) => {
438
+ this.#commit((this.#parseValue ?? Number.parseFloat)(text));
439
+ },
440
+ text: () => this.#parseValue ? this.valueText : String(this.#value),
441
+ toggle: (isOpen) => {
442
+ this.#claim.edit(isOpen);
443
+ if (isOpen) this.forwardNaming(input, true);
444
+ this.toggleState("editing", isOpen);
445
+ this.render();
446
+ }
447
+ });
448
+ this.#entry = entry;
449
+ entry.bind(control, signal);
450
+ return entry;
451
+ }
452
+ #bindKeys(control, entry, signal) {
453
+ control.addEventListener("keydown", (event) => {
454
+ if (this.isDisabled() || event.defaultPrevented || event.target !== control) return;
455
+ this.toggleState("springing", false);
456
+ if (event.key === "Enter") {
457
+ if (this.springTarget() !== void 0) return;
458
+ event.preventDefault();
459
+ entry.open();
460
+ return;
461
+ }
462
+ const next = this.#keyTarget(event.key);
463
+ if (next === void 0) return;
464
+ event.preventDefault();
465
+ this.#keyTo(event, next);
466
+ this.#claim.reveal("keys");
467
+ this.#renderHold();
468
+ }, { signal });
469
+ control.addEventListener("keyup", (event) => {
470
+ const isMeta = event.key === "Meta";
471
+ if (isMeta || event.key === this.#keyScrub?.key) this.#endKeyScrub();
472
+ if (isMeta && this.#drag) return;
473
+ if (isMeta || this.mapping().keyTarget(event.key, this.#value) !== void 0) this.#springBack();
474
+ }, { signal });
475
+ control.addEventListener("blur", () => {
476
+ this.#endKeyScrub();
477
+ this.#concealKeyReveal();
478
+ this.#springBack();
479
+ }, { signal });
480
+ }
481
+ #canPress(event, entry) {
482
+ if (event.button !== 0 || isMenuPress(event) || this.isDisabled() || entry.isOpen) return false;
483
+ return !this.#drag || this.#drag.pointerId === event.pointerId;
484
+ }
485
+ #commit(next, direction = 0) {
486
+ const landed = Number.isFinite(next) ? this.#land?.(next, direction) ?? next : next;
487
+ if (this.input(landed)) this.dispatchEvent(new Event("change", { bubbles: true }));
488
+ }
489
+ #concealKeyReveal() {
490
+ if (this.#claim.conceal("keys")) this.#renderHold();
491
+ }
492
+ #dragTo(drag, event) {
493
+ const isOutside = drag.outside?.(event) === true;
494
+ const wasEngaged = drag.state.isEngaged;
495
+ const mapping = this.mapping();
496
+ const { state, value } = stepDrag(mapping, drag.state, {
497
+ isFine: event.shiftKey,
498
+ isOutside,
499
+ position: drag.position(event)
500
+ });
501
+ drag.state = this.#withinLimit(mapping, state);
502
+ if (value === void 0) return;
503
+ if (!wasEngaged) this.#reveal(drag);
504
+ this.input(isOutside ? drag.fromValue : value);
505
+ if (isOutside === drag.isOutside) return;
506
+ drag.isOutside = isOutside;
507
+ this.#renderDragReveal(drag);
508
+ }
509
+ #endDrag() {
510
+ const drag = this.#drag;
511
+ if (!drag) return;
512
+ clearTimeout(drag.revealTimer);
513
+ this.#drag = void 0;
514
+ this.toggleState("dragging", false);
515
+ this.#claim.conceal("drag");
516
+ this.#renderHold();
517
+ if (this.#value !== drag.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
518
+ this.#springBack();
519
+ }
520
+ #endKeyScrub() {
521
+ const scrub = this.#keyScrub;
522
+ if (!scrub) return;
523
+ this.#keyScrub = void 0;
524
+ this.#renderHold();
525
+ if (this.#value !== scrub.fromValue) this.dispatchEvent(new Event("change", { bubbles: true }));
526
+ }
527
+ #isHeld() {
528
+ return this.#drag !== void 0 || this.#keyScrub !== void 0;
529
+ }
530
+ #keyTarget(key) {
531
+ if (resetKeys.has(key)) return this.default;
532
+ return this.mapping().keyTarget(key, this.#value, this.keyStep);
533
+ }
534
+ #keyTo(event, next) {
535
+ if (event.repeat && this.scrubsKeyRepeat()) {
536
+ this.#scrubKey(event.key, next);
537
+ return;
538
+ }
539
+ this.#endKeyScrub();
540
+ this.#commit(next, next > this.#value ? 1 : -1);
541
+ }
542
+ #renderAria(control, orientation) {
543
+ this.writeFormValue(String(this.#value), String(this.#value));
544
+ if (this.#entry?.isOpen) {
545
+ for (const name of roleAttributes) control.removeAttribute(name);
546
+ this.forwardNaming(control, false);
547
+ this.#renderReadout();
548
+ return;
549
+ }
550
+ const [low, high] = this.mapping().bounds;
551
+ control.setAttribute("role", this.controlRole());
552
+ control.setAttribute("aria-valuemin", String(low));
553
+ control.setAttribute("aria-valuemax", String(high));
554
+ control.setAttribute("aria-valuenow", String(this.#value));
555
+ if (orientation) control.setAttribute("aria-orientation", orientation);
556
+ writeAttribute(control, "aria-valuetext", (this.#formatSpokenValue ?? this.#formatValue)?.(this.#value));
557
+ this.forwardNaming(control, true);
558
+ this.#renderDisabled(control);
559
+ this.#renderReadout();
560
+ }
561
+ #renderDisabled(control) {
562
+ if (this.isDisabled()) {
563
+ control.setAttribute("aria-disabled", "true");
564
+ control.removeAttribute("tabindex");
565
+ return;
566
+ }
567
+ control.removeAttribute("aria-disabled");
568
+ control.setAttribute("tabindex", "0");
569
+ }
570
+ #renderDragReveal(drag) {
571
+ if (drag.isRevealed && !drag.isOutside) this.#claim.reveal("drag");
572
+ else this.#claim.conceal("drag");
573
+ this.#renderHold();
574
+ }
575
+ #renderHold() {
576
+ this.#renderReadout();
577
+ this.holdChanged();
578
+ }
579
+ #renderReadout() {
580
+ const readout = this.#readout;
581
+ if (!readout) return;
582
+ const { isOpen, value } = this.#claim.shown(this.#value, this.readout);
583
+ readout.bubble.show({
584
+ anchor: readout.anchor,
585
+ isOpen,
586
+ text: value === void 0 ? void 0 : this.#textFor(value)
587
+ });
588
+ }
589
+ #renderScale() {
590
+ const marks = this.#scaleMarks?.children ?? [];
591
+ const mapping = this.mapping();
592
+ for (const mark of marks) {
593
+ if (!(mark instanceof HTMLElement || mark instanceof SVGElement)) continue;
594
+ const at = String(mapping.proportionOf(scaleValue(mark)));
595
+ if (mark.style.getPropertyValue("--_sonic-scale-at") !== at) mark.style.setProperty("--_sonic-scale-at", at);
596
+ }
597
+ }
598
+ #reset() {
599
+ this.#commit(this.default ?? NaN);
600
+ }
601
+ #reveal(drag) {
602
+ if (drag.isRevealed || this.#drag !== drag) return;
603
+ drag.isRevealed = true;
604
+ this.#renderDragReveal(drag);
605
+ }
606
+ #scrubKey(key, next) {
607
+ if (this.#keyScrub?.key !== key) {
608
+ this.#endKeyScrub();
609
+ this.#keyScrub = {
610
+ fromValue: this.#value,
611
+ key
612
+ };
613
+ }
614
+ this.input(next);
615
+ }
616
+ #springBack() {
617
+ const target = this.springTarget();
618
+ if (target === void 0) return;
619
+ if (this.mapping().snap(target) !== this.#value) this.toggleState("springing", true);
620
+ this.#commit(target);
621
+ }
622
+ #startDrag(control, axis, event) {
623
+ const mapping = this.mapping();
624
+ const detent = this.detent;
625
+ const start = {
626
+ from: this.#value,
627
+ position: axis.position(event),
628
+ proportion: axis.fromProportion ?? mapping.proportionOf(this.#value),
629
+ thresholdPx: dragThresholdPx(event.pointerType),
630
+ travelPx: axis.travelPx
631
+ };
632
+ if (detent === void 0) return startDrag(mapping, start);
633
+ const zonePx = readPxProperty(getComputedStyle(control), "--_sonic-detent-zone", detentZonePx);
634
+ return startDrag(mapping, {
635
+ ...start,
636
+ detent: {
637
+ value: detent,
638
+ zone: zonePx / axis.travelPx
639
+ }
640
+ });
641
+ }
642
+ #textFor(value) {
643
+ return this.#formatValue?.(value) ?? String(value);
644
+ }
645
+ #watchEscape(isHovered) {
646
+ if (!isHovered) {
647
+ this.#escapeWatch?.abort();
648
+ this.#escapeWatch = void 0;
649
+ return;
650
+ }
651
+ if (this.#escapeWatch) return;
652
+ const watch = new AbortController();
653
+ this.#escapeWatch = watch;
654
+ this.ownerDocument.addEventListener("keydown", (event) => {
655
+ if (event.key === "Escape" && this.#claim.dismiss()) this.#renderHold();
656
+ }, { signal: watch.signal });
657
+ }
658
+ #withinLimit(mapping, state) {
659
+ const limit = this.#limit;
660
+ if (!limit || mapping.isWrapping) return state;
661
+ const [low, high] = limit;
662
+ return {
663
+ ...state,
664
+ rawProportion: clamp(state.rawProportion, mapping.proportionOf(low), mapping.proportionOf(high))
665
+ };
666
+ }
667
+ #write(next) {
668
+ if (!Number.isFinite(next)) return;
669
+ this.#isDirty = true;
670
+ const clamped = this.mapping().snap(next);
671
+ if (clamped === this.#value) return;
672
+ this.#value = clamped;
673
+ this.render();
674
+ }
675
+ #writeModulationProportion(control, prefix) {
676
+ const modulationValue = this.isWrapping() ? void 0 : this.#modulationValue;
677
+ const isModulated = modulationValue !== void 0;
678
+ if (isModulated !== this.#isModulated) {
679
+ this.#isModulated = isModulated;
680
+ this.toggleState("modulated", isModulated);
681
+ }
682
+ if (modulationValue === void 0) {
683
+ control.style.removeProperty(`--_sonic-${prefix}-modulation-value`);
684
+ return;
685
+ }
686
+ control.style.setProperty(`--_sonic-${prefix}-modulation-value`, String(this.mapping().proportionOf(modulationValue)));
687
+ }
688
+ };
689
+
690
+ //#endregion
691
+ export { SonicValueElement, linkValue };
692
+ //# sourceMappingURL=value-element.js.map