@xsynaptic/sonic-ui 0.1.0 → 0.2.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 (117) hide show
  1. package/README.md +8 -1
  2. package/dist/default/define/dial.js +7 -0
  3. package/dist/default/define/key.js +7 -0
  4. package/dist/default/define/meter.js +7 -0
  5. package/dist/default/define/segmented.js +7 -0
  6. package/dist/default/define/slider.js +7 -0
  7. package/dist/default/elements/define-once.js +7 -0
  8. package/dist/{elements → default/elements}/dial.js +15 -3
  9. package/dist/default/elements/form-element.js +56 -0
  10. package/dist/default/elements/key.js +144 -0
  11. package/dist/{elements → default/elements}/meter.js +27 -16
  12. package/dist/default/elements/range-element.js +410 -0
  13. package/dist/{elements → default/elements}/range-entry.js +5 -4
  14. package/dist/default/elements/segmented.js +173 -0
  15. package/dist/{elements → default/elements}/slider.js +23 -8
  16. package/dist/default/elements/sonic-element.js +153 -0
  17. package/dist/{index.js → default/index.js} +2 -1
  18. package/dist/default/lib/copy-node.js +30 -0
  19. package/dist/default/lib/percent.js +12 -0
  20. package/dist/default/lib/read-px-property.js +8 -0
  21. package/dist/{lib → default/lib}/render.js +9 -2
  22. package/dist/default/lib/taper.js +32 -0
  23. package/dist/default/lib/write-attribute.js +11 -0
  24. package/dist/dev/define/dial.js.map +1 -0
  25. package/dist/dev/define/key.js.map +1 -0
  26. package/dist/dev/define/meter.js.map +1 -0
  27. package/dist/dev/define/segmented.js.map +1 -0
  28. package/dist/dev/define/slider.js.map +1 -0
  29. package/dist/dev/define.js +5 -0
  30. package/dist/dev/elements/define-once.js.map +1 -0
  31. package/dist/{elements → dev/elements}/dial.d.ts +4 -0
  32. package/dist/dev/elements/dial.js +70 -0
  33. package/dist/dev/elements/dial.js.map +1 -0
  34. package/dist/dev/elements/form-element.d.ts +22 -0
  35. package/dist/dev/elements/form-element.js +57 -0
  36. package/dist/dev/elements/form-element.js.map +1 -0
  37. package/dist/dev/elements/key.d.ts +30 -0
  38. package/dist/{elements → dev/elements}/key.js +71 -25
  39. package/dist/dev/elements/key.js.map +1 -0
  40. package/dist/{elements → dev/elements}/meter.d.ts +6 -0
  41. package/dist/dev/elements/meter.js +131 -0
  42. package/dist/dev/elements/meter.js.map +1 -0
  43. package/dist/{elements → dev/elements}/range-element.d.ts +25 -5
  44. package/dist/{elements → dev/elements}/range-element.js +116 -53
  45. package/dist/dev/elements/range-element.js.map +1 -0
  46. package/dist/dev/elements/range-entry.js +75 -0
  47. package/dist/dev/elements/range-entry.js.map +1 -0
  48. package/dist/{elements → dev/elements}/segmented.d.ts +5 -2
  49. package/dist/dev/elements/segmented.js +174 -0
  50. package/dist/dev/elements/segmented.js.map +1 -0
  51. package/dist/{elements → dev/elements}/slider.d.ts +6 -0
  52. package/dist/dev/elements/slider.js +86 -0
  53. package/dist/dev/elements/slider.js.map +1 -0
  54. package/dist/dev/elements/sonic-element.d.ts +33 -0
  55. package/dist/dev/elements/sonic-element.js +169 -0
  56. package/dist/dev/elements/sonic-element.js.map +1 -0
  57. package/dist/{index.d.ts → dev/index.d.ts} +2 -1
  58. package/dist/dev/index.js +8 -0
  59. package/dist/dev/lib/copy-node.js +31 -0
  60. package/dist/dev/lib/copy-node.js.map +1 -0
  61. package/dist/dev/lib/percent.d.ts +5 -0
  62. package/dist/dev/lib/percent.js +13 -0
  63. package/dist/dev/lib/percent.js.map +1 -0
  64. package/dist/dev/lib/read-px-property.js.map +1 -0
  65. package/dist/dev/lib/render.js +27 -0
  66. package/dist/dev/lib/render.js.map +1 -0
  67. package/dist/dev/lib/taper.js.map +1 -0
  68. package/dist/dev/lib/write-attribute.js.map +1 -0
  69. package/dist/skins/ivory.css +3 -3
  70. package/dist/skins/slate.css +4 -4
  71. package/dist/styles/controls.css +0 -1
  72. package/dist/styles/dial.css +33 -13
  73. package/dist/styles/key.css +30 -10
  74. package/dist/styles/material.css +58 -10
  75. package/dist/styles/meter.css +25 -5
  76. package/dist/styles/screen.css +7 -1
  77. package/dist/styles/segmented.css +24 -7
  78. package/dist/styles/slider.css +17 -4
  79. package/package.json +13 -12
  80. package/dist/define/dial.js.map +0 -1
  81. package/dist/define/key.js.map +0 -1
  82. package/dist/define/meter.js.map +0 -1
  83. package/dist/define/segmented.js.map +0 -1
  84. package/dist/define/slider.js.map +0 -1
  85. package/dist/elements/define-once.js.map +0 -1
  86. package/dist/elements/dial.js.map +0 -1
  87. package/dist/elements/key.d.ts +0 -17
  88. package/dist/elements/key.js.map +0 -1
  89. package/dist/elements/meter.js.map +0 -1
  90. package/dist/elements/range-element.js.map +0 -1
  91. package/dist/elements/range-entry.js.map +0 -1
  92. package/dist/elements/segmented.js +0 -104
  93. package/dist/elements/segmented.js.map +0 -1
  94. package/dist/elements/slider.js.map +0 -1
  95. package/dist/elements/sonic-element.d.ts +0 -20
  96. package/dist/elements/sonic-element.js +0 -94
  97. package/dist/elements/sonic-element.js.map +0 -1
  98. package/dist/lib/read-px-property.js.map +0 -1
  99. package/dist/lib/render.js.map +0 -1
  100. package/dist/lib/taper.js.map +0 -1
  101. package/dist/lib/write-attribute.js.map +0 -1
  102. /package/dist/{define.js → default/define.js} +0 -0
  103. /package/dist/{define → dev/define}/dial.d.ts +0 -0
  104. /package/dist/{define → dev/define}/dial.js +0 -0
  105. /package/dist/{define → dev/define}/key.d.ts +0 -0
  106. /package/dist/{define → dev/define}/key.js +0 -0
  107. /package/dist/{define → dev/define}/meter.d.ts +0 -0
  108. /package/dist/{define → dev/define}/meter.js +0 -0
  109. /package/dist/{define → dev/define}/segmented.d.ts +0 -0
  110. /package/dist/{define → dev/define}/segmented.js +0 -0
  111. /package/dist/{define → dev/define}/slider.d.ts +0 -0
  112. /package/dist/{define → dev/define}/slider.js +0 -0
  113. /package/dist/{define.d.ts → dev/define.d.ts} +0 -0
  114. /package/dist/{elements → dev/elements}/define-once.js +0 -0
  115. /package/dist/{lib → dev/lib}/read-px-property.js +0 -0
  116. /package/dist/{lib → dev/lib}/taper.js +0 -0
  117. /package/dist/{lib → dev/lib}/write-attribute.js +0 -0
@@ -1,7 +1,7 @@
1
- import { RangeEntry } from "./range-entry.js";
2
- import { writeAttribute } from "../lib/write-attribute.js";
3
- import { SonicElement } from "./sonic-element.js";
4
1
  import { requireChild } from "../lib/render.js";
2
+ import { writeAttribute } from "../lib/write-attribute.js";
3
+ import { SonicFormElement } from "./form-element.js";
4
+ import { RangeEntry } from "./range-entry.js";
5
5
  import { clampUnit, linearTaper, logTaper, skewTaper } from "../lib/taper.js";
6
6
 
7
7
  //#region src/elements/range-element.ts
@@ -11,7 +11,7 @@ const pageSteps = 10;
11
11
  const revealMs = 250;
12
12
  const revealPx = 4;
13
13
  const canPopover = "togglePopover" in HTMLElement.prototype;
14
- let anchorCount = 0;
14
+ let instanceCount = 0;
15
15
  const resetKeys = /* @__PURE__ */ new Set(["Backspace", "Delete"]);
16
16
  const keySteps = /* @__PURE__ */ new Map([
17
17
  ["ArrowDown", -1],
@@ -31,9 +31,9 @@ const sliderAttributes = [
31
31
  "role",
32
32
  "tabindex"
33
33
  ];
34
- var SonicRangeElement = class extends SonicElement {
34
+ var SonicRangeElement = class extends SonicFormElement {
35
35
  static observedAttributes = [
36
- ...SonicElement.observedAttributes,
36
+ ...SonicFormElement.observedAttributes,
37
37
  "max",
38
38
  "midpoint",
39
39
  "min",
@@ -44,6 +44,24 @@ var SonicRangeElement = class extends SonicElement {
44
44
  "taper",
45
45
  "value"
46
46
  ];
47
+ get default() {
48
+ return this.optionalNumberAttribute("default");
49
+ }
50
+ set default(value) {
51
+ this.reflect("default", value);
52
+ }
53
+ get dimmed() {
54
+ return this.hasAttribute("dimmed");
55
+ }
56
+ set dimmed(isDimmed) {
57
+ this.reflect("dimmed", isDimmed);
58
+ }
59
+ get doublePress() {
60
+ return this.getAttribute("double-press") === "reset" ? "reset" : "type";
61
+ }
62
+ set doublePress(gesture) {
63
+ this.reflect("double-press", gesture);
64
+ }
47
65
  get formatValue() {
48
66
  return this.#formatValue;
49
67
  }
@@ -51,12 +69,60 @@ var SonicRangeElement = class extends SonicElement {
51
69
  this.#formatValue = format;
52
70
  this.render();
53
71
  }
72
+ get max() {
73
+ return this.numberAttribute("max", 100);
74
+ }
75
+ set max(value) {
76
+ this.reflect("max", value);
77
+ }
78
+ get midpoint() {
79
+ return this.optionalNumberAttribute("midpoint");
80
+ }
81
+ set midpoint(value) {
82
+ this.reflect("midpoint", value);
83
+ }
84
+ get min() {
85
+ return this.numberAttribute("min", 0);
86
+ }
87
+ set min(value) {
88
+ this.reflect("min", value);
89
+ }
90
+ get notched() {
91
+ return this.hasAttribute("notched");
92
+ }
93
+ set notched(isNotched) {
94
+ this.reflect("notched", isNotched);
95
+ }
96
+ get origin() {
97
+ return this.optionalNumberAttribute("origin");
98
+ }
99
+ set origin(value) {
100
+ this.reflect("origin", value);
101
+ }
54
102
  get parseValue() {
55
103
  return this.#parseValue;
56
104
  }
57
105
  set parseValue(parse) {
58
106
  this.#parseValue = parse;
59
107
  }
108
+ get readout() {
109
+ return this.hasAttribute("readout");
110
+ }
111
+ set readout(isShown) {
112
+ this.reflect("readout", isShown);
113
+ }
114
+ get step() {
115
+ return this.numberAttribute("step", 1);
116
+ }
117
+ set step(value) {
118
+ this.reflect("step", value);
119
+ }
120
+ get taper() {
121
+ return this.getAttribute("taper") === "log" ? "log" : "linear";
122
+ }
123
+ set taper(curve) {
124
+ this.reflect("taper", curve);
125
+ }
60
126
  get value() {
61
127
  return this.#value;
62
128
  }
@@ -64,10 +130,10 @@ var SonicRangeElement = class extends SonicElement {
64
130
  if (this.#drag) return;
65
131
  this.#write(next);
66
132
  }
67
- #anchor = `--sonic-readout-${String(anchorCount += 1)}`;
68
133
  #drag;
69
134
  #entry;
70
135
  #formatValue;
136
+ #instance = String(instanceCount += 1);
71
137
  #isDirty = false;
72
138
  #keyRevealTimer;
73
139
  #parseValue;
@@ -78,23 +144,22 @@ var SonicRangeElement = class extends SonicElement {
78
144
  if (this.#drag) return;
79
145
  this.#isDirty = false;
80
146
  }
81
- if (name === "disabled" && this.disabled) {
147
+ if (name === "disabled" && this.isDisabled()) {
82
148
  this.#entry?.close(false);
83
149
  this.#endDrag();
84
150
  }
85
- this.#value = this.#clamp(this.#isDirty ? this.#value : this.numberAttribute("value", this.min()));
151
+ this.#value = this.#clamp(this.#isDirty ? this.#value : this.numberAttribute("value", this.min));
86
152
  this.render();
87
153
  }
88
154
  connectedCallback() {
89
- this.upgradeProperty("formatValue");
90
- this.upgradeProperty("parseValue");
91
- this.upgradeProperty("value");
155
+ this.upgradeProperties("default", "dimmed", "doublePress", "max", "midpoint", "min", "notched", "origin", "readout", "step", "taper", "formatValue", "parseValue", "value");
92
156
  super.connectedCallback();
93
157
  }
94
158
  bindGestures(control, signal, grab) {
95
159
  const entry = this.#bindEntry(control, signal);
96
160
  control.addEventListener("pointerdown", (event) => {
97
- if (event.button !== 0 || this.disabled || entry.isOpen) return;
161
+ if (event.button !== 0 || this.isDisabled() || entry.isOpen) return;
162
+ if (event.pointerType === "touch") event.preventDefault();
98
163
  control.focus();
99
164
  if (event.metaKey || event.ctrlKey) {
100
165
  this.#reset();
@@ -144,7 +209,7 @@ var SonicRangeElement = class extends SonicElement {
144
209
  if (event.pointerId !== this.#drag?.pointerId) return;
145
210
  this.#endDrag();
146
211
  if (!entry.press(event)) return;
147
- if (this.getAttribute("double-press") === "reset") this.#reset();
212
+ if (this.doublePress === "reset") this.#reset();
148
213
  else entry.open();
149
214
  }, { signal });
150
215
  this.#bindKeys(control, entry, signal);
@@ -154,10 +219,10 @@ var SonicRangeElement = class extends SonicElement {
154
219
  }, { once: true });
155
220
  }
156
221
  clampRange(next) {
157
- return Math.min(this.max(), Math.max(this.min(), next));
222
+ return Math.min(this.#max(), Math.max(this.min, next));
158
223
  }
159
224
  fraction(value) {
160
- return (this.#taper() ?? linearTaper(this.min(), this.max())).position(value);
225
+ return (this.#taper() ?? linearTaper(this.min, this.#max())).position(value);
161
226
  }
162
227
  input(next) {
163
228
  const previous = this.#value;
@@ -169,24 +234,19 @@ var SonicRangeElement = class extends SonicElement {
169
234
  }));
170
235
  return true;
171
236
  }
172
- max() {
173
- return Math.max(this.min(), this.numberAttribute("max", 100));
174
- }
175
- min() {
176
- return this.numberAttribute("min", 0);
177
- }
178
237
  originFraction() {
179
- return this.fraction(this.numberAttribute("origin", this.min()));
238
+ return this.fraction(this.origin ?? this.min);
180
239
  }
181
240
  positions() {
182
- const positions = Math.round(this.range() / this.#step()) + 1;
183
- if (!this.hasAttribute("notched") || !Number.isFinite(positions) || positions < 2) return;
241
+ const positions = Math.round(this.range() / this.step) + 1;
242
+ if (!this.notched || !Number.isFinite(positions) || positions < 2) return;
184
243
  return positions;
185
244
  }
186
245
  range() {
187
- return this.max() - this.min();
246
+ return this.#max() - this.min;
188
247
  }
189
248
  renderAria(control, orientation) {
249
+ this.writeFormValue(String(this.#value), String(this.#value));
190
250
  if (this.#entry?.isOpen) {
191
251
  for (const name of sliderAttributes) control.removeAttribute(name);
192
252
  this.forwardNaming(control, false);
@@ -194,8 +254,8 @@ var SonicRangeElement = class extends SonicElement {
194
254
  return;
195
255
  }
196
256
  control.setAttribute("role", "slider");
197
- control.setAttribute("aria-valuemin", String(this.min()));
198
- control.setAttribute("aria-valuemax", String(this.max()));
257
+ control.setAttribute("aria-valuemin", String(this.min));
258
+ control.setAttribute("aria-valuemax", String(this.#max()));
199
259
  control.setAttribute("aria-valuenow", String(this.#value));
200
260
  if (orientation) control.setAttribute("aria-orientation", orientation);
201
261
  writeAttribute(control, "aria-valuetext", this.#formatValue?.(this.#value));
@@ -203,18 +263,23 @@ var SonicRangeElement = class extends SonicElement {
203
263
  this.#renderDisabled(control);
204
264
  this.#renderReadout();
205
265
  }
266
+ restoreState(state) {
267
+ this.value = Number(state);
268
+ }
206
269
  valueAt(fraction) {
207
- return (this.#taper() ?? linearTaper(this.min(), this.max())).value(fraction);
270
+ return (this.#taper() ?? linearTaper(this.min, this.#max())).value(fraction);
208
271
  }
209
272
  #bindEntry(control, signal) {
210
273
  const input = requireChild(control, "input", HTMLInputElement);
211
274
  const bubble = requireChild(control, "[popover]", HTMLElement);
275
+ const anchor = `--sonic-readout-${this.#instance}`;
276
+ input.id = `sonic-entry-${this.#instance}`;
212
277
  this.#readout = {
213
278
  bubble,
214
279
  text: requireChild(bubble, "span", HTMLElement)
215
280
  };
216
- control.style.setProperty("anchor-name", this.#anchor);
217
- bubble.style.setProperty("position-anchor", this.#anchor);
281
+ control.style.setProperty("anchor-name", anchor);
282
+ bubble.style.setProperty("position-anchor", anchor);
218
283
  const entry = new RangeEntry(input, {
219
284
  commit: (text) => {
220
285
  this.#commit((this.#parseValue ?? Number.parseFloat)(text));
@@ -232,7 +297,7 @@ var SonicRangeElement = class extends SonicElement {
232
297
  }
233
298
  #bindKeys(control, entry, signal) {
234
299
  control.addEventListener("keydown", (event) => {
235
- if (this.disabled || event.defaultPrevented || event.target !== control) return;
300
+ if (this.isDisabled() || event.defaultPrevented || event.target !== control) return;
236
301
  if (event.key === "Enter") {
237
302
  event.preventDefault();
238
303
  entry.open();
@@ -249,8 +314,8 @@ var SonicRangeElement = class extends SonicElement {
249
314
  }, { signal });
250
315
  }
251
316
  #clamp(next) {
252
- const min = this.min();
253
- const step = this.#step();
317
+ const min = this.min;
318
+ const step = this.step;
254
319
  const stepped = step > 0 ? min + Math.round((next - min) / step) * step : next;
255
320
  return this.clampRange(Number(stepped.toPrecision(12)));
256
321
  }
@@ -273,22 +338,25 @@ var SonicRangeElement = class extends SonicElement {
273
338
  this.#renderReadout();
274
339
  }
275
340
  #isValueShown() {
276
- return (this.#drag?.isRevealed === true || this.#keyRevealTimer !== void 0) && this.hasAttribute("readout");
341
+ return (this.#drag?.isRevealed === true || this.#keyRevealTimer !== void 0) && this.readout;
277
342
  }
278
343
  #keyTarget(key) {
279
- if (key === "Home") return this.min();
280
- if (key === "End") return this.max();
281
- if (resetKeys.has(key)) return this.#resetValue();
344
+ if (key === "Home") return this.min;
345
+ if (key === "End") return this.#max();
346
+ if (resetKeys.has(key)) return this.default;
282
347
  const steps = keySteps.get(key);
283
348
  if (steps === void 0) return void 0;
284
- const step = this.#step() > 0 ? this.#step() : this.range() / 100;
349
+ const step = this.step > 0 ? this.step : this.range() / 100;
285
350
  const taper = this.#taper();
286
351
  if (!taper) return this.#value + steps * step;
287
352
  const next = this.#clamp(taper.value(taper.position(this.#value) + steps / 100));
288
353
  return next === this.#value ? this.#value + Math.sign(steps) * step : next;
289
354
  }
355
+ #max() {
356
+ return Math.max(this.min, this.max);
357
+ }
290
358
  #renderDisabled(control) {
291
- if (this.disabled) {
359
+ if (this.isDisabled()) {
292
360
  control.setAttribute("aria-disabled", "true");
293
361
  control.removeAttribute("tabindex");
294
362
  return;
@@ -305,11 +373,7 @@ var SonicRangeElement = class extends SonicElement {
305
373
  readout.bubble.togglePopover(isEditing || this.#isValueShown());
306
374
  }
307
375
  #reset() {
308
- this.#commit(this.numberAttribute("default", NaN));
309
- }
310
- #resetValue() {
311
- const value = this.numberAttribute("default", NaN);
312
- return Number.isFinite(value) ? value : void 0;
376
+ this.#commit(this.default ?? NaN);
313
377
  }
314
378
  #reveal(drag) {
315
379
  if (drag.isRevealed || this.#drag !== drag) return;
@@ -323,14 +387,11 @@ var SonicRangeElement = class extends SonicElement {
323
387
  }, keyRevealMs);
324
388
  this.#renderReadout();
325
389
  }
326
- #step() {
327
- return this.numberAttribute("step", 1);
328
- }
329
390
  #taper() {
330
- if (this.hasAttribute("notched")) return void 0;
331
- const min = this.min();
332
- const max = this.max();
333
- return (this.getAttribute("taper") === "log" ? logTaper(min, max) : void 0) ?? skewTaper(min, max, this.numberAttribute("midpoint", NaN));
391
+ if (this.notched) return void 0;
392
+ const min = this.min;
393
+ const max = this.#max();
394
+ return (this.taper === "log" ? logTaper(min, max) : void 0) ?? skewTaper(min, max, this.midpoint ?? NaN);
334
395
  }
335
396
  #valueText() {
336
397
  return this.#formatValue?.(this.#value) ?? String(this.#value);
@@ -338,7 +399,9 @@ var SonicRangeElement = class extends SonicElement {
338
399
  #write(next) {
339
400
  if (!Number.isFinite(next)) return;
340
401
  this.#isDirty = true;
341
- this.#value = this.#clamp(next);
402
+ const clamped = this.#clamp(next);
403
+ if (clamped === this.#value) return;
404
+ this.#value = clamped;
342
405
  this.render();
343
406
  }
344
407
  };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range-element.js","names":[],"sources":["../../../src/elements/range-element.ts"],"sourcesContent":["import type { Taper } from '#lib/taper.ts';\n\nimport { SonicFormElement } from '#elements/form-element.ts';\nimport { RangeEntry } from '#elements/range-entry.ts';\nimport { requireChild } from '#lib/render.ts';\nimport { clampUnit, linearTaper, logTaper, skewTaper } from '#lib/taper.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\n// `position` grows with the value\nexport interface RangeAxis {\n\tposition: (event: PointerEvent) => number;\n\ttravelPx: number;\n}\n\ninterface RangeDrag extends RangeAxis {\n\tfromValue: number;\n\tisRevealed: boolean;\n\tlastPosition: number;\n\tpointerId: number;\n\t// Unstepped, or a slow drag rounds back to where it started\n\trawFraction: number;\n\trevealTimer: ReturnType<typeof setTimeout> | undefined;\n\tstartPosition: number;\n}\n\nconst fineScale = 0.1;\nconst keyRevealMs = 1000;\nconst pageSteps = 10;\nconst revealMs = 250;\nconst revealPx = 4;\n\n// happy-dom has no popover API\nconst canPopover = 'togglePopover' in HTMLElement.prototype;\n\n// A shared anchor name resolves to the last one on the page\nlet instanceCount = 0;\n\n// A Mac keyboard's Delete sends Backspace\nconst resetKeys = new Set(['Backspace', 'Delete']);\n\nconst keySteps = new Map([\n\t['ArrowDown', -1],\n\t['ArrowLeft', -1],\n\t['ArrowRight', 1],\n\t['ArrowUp', 1],\n\t['PageDown', -pageSteps],\n\t['PageUp', pageSteps],\n]);\n\n// A slider's children are presentational, so these come off while the entry is open\nconst sliderAttributes = [\n\t'aria-disabled',\n\t'aria-orientation',\n\t'aria-valuemax',\n\t'aria-valuemin',\n\t'aria-valuenow',\n\t'aria-valuetext',\n\t'role',\n\t'tabindex',\n];\n\n// As on `<input type=\"range\">`, the property never writes the `value` attribute back\nexport abstract class SonicRangeElement extends SonicFormElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicFormElement.observedAttributes,\n\t\t'max',\n\t\t'midpoint',\n\t\t'min',\n\t\t'notched',\n\t\t'origin',\n\t\t'readout',\n\t\t'step',\n\t\t'taper',\n\t\t'value',\n\t];\n\n\tget default(): number | undefined {\n\t\treturn this.optionalNumberAttribute('default');\n\t}\n\n\tset default(value: number | undefined) {\n\t\tthis.reflect('default', value);\n\t}\n\n\tget dimmed(): boolean {\n\t\treturn this.hasAttribute('dimmed');\n\t}\n\n\tset dimmed(isDimmed: boolean) {\n\t\tthis.reflect('dimmed', isDimmed);\n\t}\n\n\t// Named for the absent attribute, as `input.type` reads `text`\n\tget doublePress(): 'reset' | 'type' {\n\t\treturn this.getAttribute('double-press') === 'reset' ? 'reset' : 'type';\n\t}\n\n\tset doublePress(gesture: 'reset' | 'type' | undefined) {\n\t\tthis.reflect('double-press', gesture);\n\t}\n\n\tget formatValue(): ((value: number) => string) | undefined {\n\t\treturn this.#formatValue;\n\t}\n\n\tset formatValue(format: ((value: number) => string) | undefined) {\n\t\tthis.#formatValue = format;\n\t\tthis.render();\n\t}\n\n\t// Unclamped by `min`, so reading it back never pins the range\n\tget max(): number {\n\t\treturn this.numberAttribute('max', 100);\n\t}\n\n\tset max(value: number | undefined) {\n\t\tthis.reflect('max', value);\n\t}\n\n\tget midpoint(): number | undefined {\n\t\treturn this.optionalNumberAttribute('midpoint');\n\t}\n\n\tset midpoint(value: number | undefined) {\n\t\tthis.reflect('midpoint', value);\n\t}\n\n\tget min(): number {\n\t\treturn this.numberAttribute('min', 0);\n\t}\n\n\tset min(value: number | undefined) {\n\t\tthis.reflect('min', value);\n\t}\n\n\tget notched(): boolean {\n\t\treturn this.hasAttribute('notched');\n\t}\n\n\tset notched(isNotched: boolean) {\n\t\tthis.reflect('notched', isNotched);\n\t}\n\n\t// `undefined` while unset, so reading it back never pins it to `min`\n\tget origin(): number | undefined {\n\t\treturn this.optionalNumberAttribute('origin');\n\t}\n\n\tset origin(value: number | undefined) {\n\t\tthis.reflect('origin', value);\n\t}\n\n\tget parseValue(): ((text: string) => number) | undefined {\n\t\treturn this.#parseValue;\n\t}\n\n\tset parseValue(parse: ((text: string) => number) | undefined) {\n\t\tthis.#parseValue = parse;\n\t}\n\n\tget readout(): boolean {\n\t\treturn this.hasAttribute('readout');\n\t}\n\n\tset readout(isShown: boolean) {\n\t\tthis.reflect('readout', isShown);\n\t}\n\n\tget step(): number {\n\t\treturn this.numberAttribute('step', 1);\n\t}\n\n\tset step(value: number | undefined) {\n\t\tthis.reflect('step', value);\n\t}\n\n\tget taper(): 'linear' | 'log' {\n\t\treturn this.getAttribute('taper') === 'log' ? 'log' : 'linear';\n\t}\n\n\tset taper(curve: 'linear' | 'log' | undefined) {\n\t\tthis.reflect('taper', curve);\n\t}\n\n\tget value(): number {\n\t\treturn this.#value;\n\t}\n\n\t// A drag owns the value, so a timer's write can't pull the cap from under the pointer\n\tset value(next: number) {\n\t\tif (this.#drag) return;\n\n\t\tthis.#write(next);\n\t}\n\n\t#drag: RangeDrag | undefined;\n\n\t#entry: RangeEntry | undefined;\n\n\t#formatValue: ((value: number) => string) | undefined;\n\n\treadonly #instance = String((instanceCount += 1));\n\n\t// Re-read from the attribute until the property is set, since `max` may arrive after `value`\n\t#isDirty = false;\n\n\t#keyRevealTimer: ReturnType<typeof setTimeout> | undefined;\n\n\t#parseValue: ((text: string) => number) | undefined;\n\n\t#readout: undefined | { bubble: HTMLElement; text: HTMLElement };\n\n\t#value = 0;\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (name === 'value') {\n\t\t\tif (this.#drag) return;\n\n\t\t\tthis.#isDirty = false;\n\t\t}\n\t\tif (name === 'disabled' && this.isDisabled()) {\n\t\t\tthis.#entry?.close(false);\n\t\t\tthis.#endDrag();\n\t\t}\n\n\t\tthis.#value = this.#clamp(\n\t\t\tthis.#isDirty ? this.#value : this.numberAttribute('value', this.min),\n\t\t);\n\t\tthis.render();\n\t}\n\n\t// The range before `value`, or a value set with its `max` before upgrade clamps to the old one\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(\n\t\t\t'default',\n\t\t\t'dimmed',\n\t\t\t'doublePress',\n\t\t\t'max',\n\t\t\t'midpoint',\n\t\t\t'min',\n\t\t\t'notched',\n\t\t\t'origin',\n\t\t\t'readout',\n\t\t\t'step',\n\t\t\t'taper',\n\t\t\t'formatValue',\n\t\t\t'parseValue',\n\t\t\t'value',\n\t\t);\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected bindGestures(\n\t\tcontrol: HTMLElement,\n\t\tsignal: AbortSignal,\n\t\tgrab: (event: PointerEvent) => RangeAxis | undefined,\n\t): void {\n\t\tconst entry = this.#bindEntry(control, signal);\n\n\t\tcontrol.addEventListener(\n\t\t\t'pointerdown',\n\t\t\t(event) => {\n\t\t\t\tif (event.button !== 0 || this.isDisabled() || entry.isOpen) return;\n\n\t\t\t\t// A click listener above makes WebKit send a tap's compatibility mousedown, which blurs the entry a double tap just opened\n\t\t\t\tif (event.pointerType === 'touch') event.preventDefault();\n\t\t\t\tcontrol.focus();\n\t\t\t\tif (event.metaKey || event.ctrlKey) {\n\t\t\t\t\tthis.#reset();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst fromValue = this.#value;\n\t\t\t\tconst axis = grab(event);\n\t\t\t\tif (!axis) return;\n\n\t\t\t\tconst startPosition = axis.position(event);\n\t\t\t\tconst drag: RangeDrag = {\n\t\t\t\t\tfromValue,\n\t\t\t\t\tisRevealed: false,\n\t\t\t\t\tlastPosition: startPosition,\n\t\t\t\t\tpointerId: event.pointerId,\n\t\t\t\t\tposition: axis.position,\n\t\t\t\t\trawFraction: this.fraction(this.#value),\n\t\t\t\t\trevealTimer: undefined,\n\t\t\t\t\tstartPosition,\n\t\t\t\t\ttravelPx: axis.travelPx,\n\t\t\t\t};\n\n\t\t\t\tdrag.revealTimer = setTimeout(() => {\n\t\t\t\t\tthis.#reveal(drag);\n\t\t\t\t}, revealMs);\n\t\t\t\tthis.#drag = drag;\n\t\t\t\tcontrol.setPointerCapture(event.pointerId);\n\t\t\t\tthis.toggleState('dragging', true);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'pointermove',\n\t\t\t(event) => {\n\t\t\t\tconst drag = this.#drag;\n\t\t\t\tif (event.pointerId !== drag?.pointerId) return;\n\n\t\t\t\tconst position = drag.position(event);\n\t\t\t\tconst scale = event.shiftKey ? fineScale : 1;\n\n\t\t\t\t// Per move, so pressing Shift mid-drag changes pace without a jump\n\t\t\t\tdrag.rawFraction = clampUnit(\n\t\t\t\t\tdrag.rawFraction + ((position - drag.lastPosition) / drag.travelPx) * scale,\n\t\t\t\t);\n\t\t\t\tdrag.lastPosition = position;\n\t\t\t\tif (Math.abs(position - drag.startPosition) >= revealPx) this.#reveal(drag);\n\t\t\t\tthis.input(this.valueAt(drag.rawFraction));\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\n\t\tconst endDrag = (event: PointerEvent): void => {\n\t\t\tif (event.pointerId === this.#drag?.pointerId) this.#endDrag();\n\t\t};\n\n\t\tcontrol.addEventListener(\n\t\t\t'pointercancel',\n\t\t\t(event) => {\n\t\t\t\tendDrag(event);\n\t\t\t\tentry.forgetPress();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\t// Other code can release capture without a `pointerup`\n\t\tcontrol.addEventListener('lostpointercapture', endDrag, { signal });\n\t\tcontrol.addEventListener(\n\t\t\t'pointerup',\n\t\t\t(event) => {\n\t\t\t\tif (event.pointerId !== this.#drag?.pointerId) return;\n\n\t\t\t\tthis.#endDrag();\n\t\t\t\tif (!entry.press(event)) return;\n\n\t\t\t\tif (this.doublePress === 'reset') this.#reset();\n\t\t\t\telse entry.open();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#bindKeys(control, entry, signal);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#endDrag();\n\t\t\t\tthis.#hideForKeys();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\tprotected clampRange(next: number): number {\n\t\treturn Math.min(this.#max(), Math.max(this.min, next));\n\t}\n\n\tprotected fraction(value: number): number {\n\t\treturn (this.#taper() ?? linearTaper(this.min, this.#max())).position(value);\n\t}\n\n\tprotected input(next: number): boolean {\n\t\tconst previous = this.#value;\n\n\t\tthis.#write(next);\n\t\tif (this.#value === previous) return false;\n\n\t\tthis.dispatchEvent(new Event('input', { bubbles: true, composed: true }));\n\n\t\treturn true;\n\t}\n\n\tprotected originFraction(): number {\n\t\treturn this.fraction(this.origin ?? this.min);\n\t}\n\n\tprotected positions(): number | undefined {\n\t\tconst positions = Math.round(this.range() / this.step) + 1;\n\n\t\tif (!this.notched || !Number.isFinite(positions) || positions < 2) return;\n\n\t\treturn positions;\n\t}\n\n\tprotected range(): number {\n\t\treturn this.#max() - this.min;\n\t}\n\n\t// Per render rather than per write, so a range with no `value` attribute submits its minimum too\n\tprotected renderAria(control: HTMLElement, orientation?: 'horizontal' | 'vertical'): void {\n\t\tthis.writeFormValue(String(this.#value), String(this.#value));\n\t\tif (this.#entry?.isOpen) {\n\t\t\tfor (const name of sliderAttributes) control.removeAttribute(name);\n\t\t\tthis.forwardNaming(control, false);\n\t\t\tthis.#renderReadout();\n\t\t\treturn;\n\t\t}\n\n\t\tcontrol.setAttribute('role', 'slider');\n\t\tcontrol.setAttribute('aria-valuemin', String(this.min));\n\t\tcontrol.setAttribute('aria-valuemax', String(this.#max()));\n\t\tcontrol.setAttribute('aria-valuenow', String(this.#value));\n\t\tif (orientation) control.setAttribute('aria-orientation', orientation);\n\t\twriteAttribute(control, 'aria-valuetext', this.#formatValue?.(this.#value));\n\t\tthis.forwardNaming(control, true);\n\t\tthis.#renderDisabled(control);\n\t\tthis.#renderReadout();\n\t}\n\n\tprotected restoreState(state: string): void {\n\t\tthis.value = Number(state);\n\t}\n\n\tprotected valueAt(fraction: number): number {\n\t\treturn (this.#taper() ?? linearTaper(this.min, this.#max())).value(fraction);\n\t}\n\n\t#bindEntry(control: HTMLElement, signal: AbortSignal): RangeEntry {\n\t\tconst input = requireChild(control, 'input', HTMLInputElement);\n\t\tconst bubble = requireChild(control, '[popover]', HTMLElement);\n\n\t\tconst anchor = `--sonic-readout-${this.#instance}`;\n\n\t\t// Chrome's issues panel flags a form field with no id or name; a `name` would submit it\n\t\tinput.id = `sonic-entry-${this.#instance}`;\n\t\tthis.#readout = { bubble, text: requireChild(bubble, 'span', HTMLElement) };\n\t\tcontrol.style.setProperty('anchor-name', anchor);\n\t\tbubble.style.setProperty('position-anchor', anchor);\n\n\t\tconst entry = new RangeEntry(input, {\n\t\t\tcommit: (text) => {\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-number-coercion -- `Number('')` is 0; an emptied field should leave the value alone\n\t\t\t\tthis.#commit((this.#parseValue ?? Number.parseFloat)(text));\n\t\t\t},\n\t\t\t// `Number.parseFloat` reads \"5 kHz\" as 5\n\t\t\ttext: () => (this.#parseValue ? this.#valueText() : String(this.#value)),\n\t\t\ttoggle: (isOpen) => {\n\t\t\t\tif (isOpen) this.forwardNaming(input, true);\n\t\t\t\tthis.toggleState('editing', isOpen);\n\t\t\t\tthis.render();\n\t\t\t},\n\t\t});\n\n\t\tthis.#entry = entry;\n\t\tentry.bind(control, signal);\n\n\t\treturn entry;\n\t}\n\n\t#bindKeys(control: HTMLElement, entry: RangeEntry, signal: AbortSignal): void {\n\t\tcontrol.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (this.isDisabled() || event.defaultPrevented || event.target !== control) return;\n\n\t\t\t\tif (event.key === 'Enter') {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tentry.open();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst next = this.#keyTarget(event.key);\n\t\t\t\tif (next === undefined) return;\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.#commit(next);\n\t\t\t\tthis.#revealForKeys();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tcontrol.addEventListener(\n\t\t\t'blur',\n\t\t\t() => {\n\t\t\t\tthis.#hideForKeys();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\n\t#clamp(next: number): number {\n\t\tconst min = this.min;\n\t\tconst step = this.step;\n\t\tconst stepped = step > 0 ? min + Math.round((next - min) / step) * step : next;\n\n\t\t// A step like 0.01 leaves float residue\n\t\treturn this.clampRange(Number(stepped.toPrecision(12)));\n\t}\n\n\t#commit(next: number): void {\n\t\tif (this.input(next)) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#endDrag(): void {\n\t\tconst drag = this.#drag;\n\t\tif (!drag) return;\n\n\t\tclearTimeout(drag.revealTimer);\n\t\tthis.#drag = undefined;\n\t\tthis.toggleState('dragging', false);\n\t\tthis.#renderReadout();\n\t\tif (this.#value !== drag.fromValue) this.dispatchEvent(new Event('change', { bubbles: true }));\n\t}\n\n\t#hideForKeys(): void {\n\t\tclearTimeout(this.#keyRevealTimer);\n\t\tif (this.#keyRevealTimer === undefined) return;\n\n\t\tthis.#keyRevealTimer = undefined;\n\t\tthis.#renderReadout();\n\t}\n\n\t#isValueShown(): boolean {\n\t\tconst isRevealed = this.#drag?.isRevealed === true || this.#keyRevealTimer !== undefined;\n\n\t\treturn isRevealed && this.readout;\n\t}\n\n\t#keyTarget(key: string): number | undefined {\n\t\tif (key === 'Home') return this.min;\n\t\tif (key === 'End') return this.#max();\n\t\tif (resetKeys.has(key)) return this.default;\n\n\t\tconst steps = keySteps.get(key);\n\t\tif (steps === undefined) return undefined;\n\n\t\tconst step = this.step > 0 ? this.step : this.range() / 100;\n\t\tconst taper = this.#taper();\n\t\tif (!taper) return this.#value + steps * step;\n\n\t\t// By travel, since steps at the wide end would take forever; at least one step, or the snap holds it in place\n\t\tconst next = this.#clamp(taper.value(taper.position(this.#value) + steps / 100));\n\n\t\treturn next === this.#value ? this.#value + Math.sign(steps) * step : next;\n\t}\n\n\t#max(): number {\n\t\treturn Math.max(this.min, this.max);\n\t}\n\n\t#renderDisabled(control: HTMLElement): void {\n\t\tif (this.isDisabled()) {\n\t\t\tcontrol.setAttribute('aria-disabled', 'true');\n\t\t\tcontrol.removeAttribute('tabindex');\n\t\t\treturn;\n\t\t}\n\n\t\tcontrol.removeAttribute('aria-disabled');\n\t\tcontrol.setAttribute('tabindex', '0');\n\t}\n\n\t#renderReadout(): void {\n\t\tconst readout = this.#readout;\n\t\tif (!readout || !canPopover || !this.isConnected) return;\n\n\t\tconst isEditing = this.#entry?.isOpen === true;\n\n\t\treadout.text.hidden = isEditing;\n\t\tif (!isEditing) readout.text.textContent = this.#valueText();\n\t\treadout.bubble.togglePopover(isEditing || this.#isValueShown());\n\t}\n\n\t#reset(): void {\n\t\tthis.#commit(this.default ?? NaN);\n\t}\n\n\t#reveal(drag: RangeDrag): void {\n\t\tif (drag.isRevealed || this.#drag !== drag) return;\n\n\t\tdrag.isRevealed = true;\n\t\tthis.#renderReadout();\n\t}\n\n\t#revealForKeys(): void {\n\t\tclearTimeout(this.#keyRevealTimer);\n\t\tthis.#keyRevealTimer = setTimeout(() => {\n\t\t\tthis.#hideForKeys();\n\t\t}, keyRevealMs);\n\t\tthis.#renderReadout();\n\t}\n\n\t// Notches are evenly spaced, so a notched control stays linear\n\t#taper(): Taper | undefined {\n\t\tif (this.notched) return undefined;\n\n\t\tconst min = this.min;\n\t\tconst max = this.#max();\n\t\tconst log = this.taper === 'log' ? logTaper(min, max) : undefined;\n\n\t\treturn log ?? skewTaper(min, max, this.midpoint ?? NaN);\n\t}\n\n\t#valueText(): string {\n\t\treturn this.#formatValue?.(this.#value) ?? String(this.#value);\n\t}\n\n\t#write(next: number): void {\n\t\tif (!Number.isFinite(next)) return;\n\n\t\tthis.#isDirty = true;\n\n\t\tconst clamped = this.#clamp(next);\n\t\tif (clamped === this.#value) return;\n\n\t\tthis.#value = clamped;\n\t\tthis.render();\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ //#region src/elements/range-entry.ts
2
+ const doublePressMs = 500;
3
+ const doublePressPx = 4;
4
+ function isDoublePress(previous, next) {
5
+ if (!previous) return false;
6
+ return next.time - previous.time < doublePressMs && Math.hypot(next.x - previous.x, next.y - previous.y) < doublePressPx;
7
+ }
8
+ var RangeEntry = class {
9
+ get isOpen() {
10
+ return this.#isOpen;
11
+ }
12
+ #input;
13
+ #isOpen = false;
14
+ #lastPress;
15
+ #openedText = "";
16
+ #options;
17
+ constructor(input, options) {
18
+ this.#input = input;
19
+ this.#options = options;
20
+ }
21
+ bind(control, signal) {
22
+ const input = this.#input;
23
+ input.addEventListener("keydown", (event) => {
24
+ if (event.isComposing || event.key !== "Enter" && event.key !== "Escape") return;
25
+ event.preventDefault();
26
+ this.close(event.key === "Enter");
27
+ control.focus();
28
+ }, { signal });
29
+ input.addEventListener("blur", () => {
30
+ this.close(true);
31
+ }, { signal });
32
+ for (const type of ["change", "input"]) input.addEventListener(type, (event) => {
33
+ event.stopPropagation();
34
+ }, { signal });
35
+ signal.addEventListener("abort", () => {
36
+ this.close(false);
37
+ }, { once: true });
38
+ }
39
+ close(isCommitting) {
40
+ if (!this.#isOpen) return;
41
+ this.#isOpen = false;
42
+ this.#input.hidden = true;
43
+ this.#options.toggle(false);
44
+ if (isCommitting && this.#input.value !== this.#openedText) this.#options.commit(this.#input.value);
45
+ }
46
+ forgetPress() {
47
+ this.#lastPress = void 0;
48
+ }
49
+ open() {
50
+ const input = this.#input;
51
+ this.#isOpen = true;
52
+ this.#openedText = this.#options.text();
53
+ input.value = this.#openedText;
54
+ input.hidden = false;
55
+ this.#options.toggle(true);
56
+ input.focus();
57
+ input.select();
58
+ }
59
+ press(event) {
60
+ const press = {
61
+ time: event.timeStamp,
62
+ x: event.clientX,
63
+ y: event.clientY
64
+ };
65
+ const previous = this.#lastPress;
66
+ this.#lastPress = press;
67
+ if (!isDoublePress(previous, press)) return false;
68
+ this.#lastPress = void 0;
69
+ return true;
70
+ }
71
+ };
72
+
73
+ //#endregion
74
+ export { RangeEntry };
75
+ //# sourceMappingURL=range-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range-entry.js","names":[],"sources":["../../../src/elements/range-entry.ts"],"sourcesContent":["interface Press {\n\ttime: number;\n\tx: number;\n\ty: number;\n}\n\ninterface RangeEntryOptions {\n\tcommit: (text: string) => void;\n\ttext: () => string;\n\ttoggle: (isOpen: boolean) => void;\n}\n\n// Not `dblclick`, which iOS may not deliver under `touch-action: none`\nconst doublePressMs = 500;\nconst doublePressPx = 4;\n\nfunction isDoublePress(previous: Press | undefined, next: Press): boolean {\n\tif (!previous) return false;\n\n\treturn (\n\t\tnext.time - previous.time < doublePressMs &&\n\t\tMath.hypot(next.x - previous.x, next.y - previous.y) < doublePressPx\n\t);\n}\n\nexport class RangeEntry {\n\tget isOpen(): boolean {\n\t\treturn this.#isOpen;\n\t}\n\n\treadonly #input: HTMLInputElement;\n\n\t#isOpen = false;\n\n\t#lastPress: Press | undefined;\n\n\t#openedText = '';\n\n\treadonly #options: RangeEntryOptions;\n\n\tconstructor(input: HTMLInputElement, options: RangeEntryOptions) {\n\t\tthis.#input = input;\n\t\tthis.#options = options;\n\t}\n\n\tbind(control: HTMLElement, signal: AbortSignal): void {\n\t\tconst input = this.#input;\n\n\t\tinput.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (event.isComposing || (event.key !== 'Enter' && event.key !== 'Escape')) return;\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.close(event.key === 'Enter');\n\t\t\t\tcontrol.focus();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tinput.addEventListener(\n\t\t\t'blur',\n\t\t\t() => {\n\t\t\t\tthis.close(true);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\n\t\t// The field's own events would reach the host's listeners as if the value had moved\n\t\tfor (const type of ['change', 'input']) {\n\t\t\tinput.addEventListener(\n\t\t\t\ttype,\n\t\t\t\t(event) => {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t},\n\t\t\t\t{ signal },\n\t\t\t);\n\t\t}\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.close(false);\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t// Closes first, so the committed value renders with the control's role back in place\n\tclose(isCommitting: boolean): void {\n\t\tif (!this.#isOpen) return;\n\n\t\tthis.#isOpen = false;\n\t\tthis.#input.hidden = true;\n\t\tthis.#options.toggle(false);\n\t\t// A format that rounds would otherwise write its rounding back\n\t\tif (isCommitting && this.#input.value !== this.#openedText)\n\t\t\tthis.#options.commit(this.#input.value);\n\t}\n\n\tforgetPress(): void {\n\t\tthis.#lastPress = undefined;\n\t}\n\n\topen(): void {\n\t\tconst input = this.#input;\n\n\t\tthis.#isOpen = true;\n\t\tthis.#openedText = this.#options.text();\n\t\tinput.value = this.#openedText;\n\t\tinput.hidden = false;\n\t\tthis.#options.toggle(true);\n\t\tinput.focus();\n\t\tinput.select();\n\t}\n\n\tpress(event: PointerEvent): boolean {\n\t\tconst press = { time: event.timeStamp, x: event.clientX, y: event.clientY };\n\t\tconst previous = this.#lastPress;\n\n\t\tthis.#lastPress = press;\n\t\tif (!isDoublePress(previous, press)) return false;\n\n\t\tthis.#lastPress = undefined;\n\n\t\treturn true;\n\t}\n}\n"],"mappings":";AAaA,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AAEtB,SAAS,cAAc,UAA6B,MAAsB;CACzE,IAAI,CAAC,UAAU,OAAO;CAEtB,OACC,KAAK,OAAO,SAAS,OAAO,iBAC5B,KAAK,MAAM,KAAK,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,CAAC,IAAI;AAEzD;AAEA,IAAa,aAAb,MAAwB;CACvB,IAAI,SAAkB;EACrB,OAAO,KAAK;CACb;CAEA,AAAS;CAET,UAAU;CAEV;CAEA,cAAc;CAEd,AAAS;CAET,YAAY,OAAyB,SAA4B;EAChE,KAAK,SAAS;EACd,KAAK,WAAW;CACjB;CAEA,KAAK,SAAsB,QAA2B;EACrD,MAAM,QAAQ,KAAK;EAEnB,MAAM,iBACL,YACC,UAAU;GACV,IAAI,MAAM,eAAgB,MAAM,QAAQ,WAAW,MAAM,QAAQ,UAAW;GAE5E,MAAM,eAAe;GACrB,KAAK,MAAM,MAAM,QAAQ,OAAO;GAChC,QAAQ,MAAM;EACf,GACA,EAAE,OAAO,CACV;EACA,MAAM,iBACL,cACM;GACL,KAAK,MAAM,IAAI;EAChB,GACA,EAAE,OAAO,CACV;EAGA,KAAK,MAAM,QAAQ,CAAC,UAAU,OAAO,GACpC,MAAM,iBACL,OACC,UAAU;GACV,MAAM,gBAAgB;EACvB,GACA,EAAE,OAAO,CACV;EAED,OAAO,iBACN,eACM;GACL,KAAK,MAAM,KAAK;EACjB,GACA,EAAE,MAAM,KAAK,CACd;CACD;CAGA,MAAM,cAA6B;EAClC,IAAI,CAAC,KAAK,SAAS;EAEnB,KAAK,UAAU;EACf,KAAK,OAAO,SAAS;EACrB,KAAK,SAAS,OAAO,KAAK;EAE1B,IAAI,gBAAgB,KAAK,OAAO,UAAU,KAAK,aAC9C,KAAK,SAAS,OAAO,KAAK,OAAO,KAAK;CACxC;CAEA,cAAoB;EACnB,KAAK,aAAa;CACnB;CAEA,OAAa;EACZ,MAAM,QAAQ,KAAK;EAEnB,KAAK,UAAU;EACf,KAAK,cAAc,KAAK,SAAS,KAAK;EACtC,MAAM,QAAQ,KAAK;EACnB,MAAM,SAAS;EACf,KAAK,SAAS,OAAO,IAAI;EACzB,MAAM,MAAM;EACZ,MAAM,OAAO;CACd;CAEA,MAAM,OAA8B;EACnC,MAAM,QAAQ;GAAE,MAAM,MAAM;GAAW,GAAG,MAAM;GAAS,GAAG,MAAM;EAAQ;EAC1E,MAAM,WAAW,KAAK;EAEtB,KAAK,aAAa;EAClB,IAAI,CAAC,cAAc,UAAU,KAAK,GAAG,OAAO;EAE5C,KAAK,aAAa;EAElB,OAAO;CACR;AACD"}
@@ -1,17 +1,20 @@
1
- import { SonicElement } from "./sonic-element.js";
1
+ import { SonicFormElement } from "./form-element.js";
2
2
  //#region src/elements/segmented.d.ts
3
3
  declare global {
4
4
  interface HTMLElementTagNameMap {
5
5
  'sonic-segmented': SonicSegmented;
6
6
  }
7
7
  }
8
- export declare class SonicSegmented extends SonicElement {
8
+ export declare class SonicSegmented extends SonicFormElement {
9
9
  #private;
10
10
  static readonly observedAttributes: string[];
11
11
  get value(): string;
12
12
  set value(next: string);
13
13
  attributeChangedCallback(name: string): void;
14
14
  protected connect(signal: AbortSignal): void;
15
+ protected focusTarget(): HTMLElement | undefined;
16
+ protected render(): void;
17
+ protected restoreState(state: string): void;
15
18
  }
16
19
  //#endregion
17
20
  //# sourceMappingURL=segmented.d.ts.map