@xsynaptic/sonic-ui 0.2.0 → 0.4.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 (59) hide show
  1. package/README.md +2 -2
  2. package/dist/default/define/number.js +7 -0
  3. package/dist/default/define.js +1 -0
  4. package/dist/default/elements/dial.js +24 -10
  5. package/dist/default/elements/key.js +29 -4
  6. package/dist/default/elements/meter.js +63 -9
  7. package/dist/default/elements/number.js +46 -0
  8. package/dist/default/elements/range-element.js +172 -36
  9. package/dist/default/elements/slider.js +63 -3
  10. package/dist/default/index.js +2 -1
  11. package/dist/default/lib/detent.js +17 -0
  12. package/dist/default/lib/math.js +16 -0
  13. package/dist/default/lib/number-list.js +14 -0
  14. package/dist/default/lib/taper.js +17 -4
  15. package/dist/dev/define/number.d.ts +2 -0
  16. package/dist/dev/define/number.js +8 -0
  17. package/dist/dev/define/number.js.map +1 -0
  18. package/dist/dev/define.d.ts +3 -1
  19. package/dist/dev/define.js +1 -0
  20. package/dist/dev/elements/dial.d.ts +3 -0
  21. package/dist/dev/elements/dial.js +24 -10
  22. package/dist/dev/elements/dial.js.map +1 -1
  23. package/dist/dev/elements/key.d.ts +4 -0
  24. package/dist/dev/elements/key.js +29 -4
  25. package/dist/dev/elements/key.js.map +1 -1
  26. package/dist/dev/elements/meter.d.ts +6 -0
  27. package/dist/dev/elements/meter.js +63 -9
  28. package/dist/dev/elements/meter.js.map +1 -1
  29. package/dist/dev/elements/number.d.ts +16 -0
  30. package/dist/dev/elements/number.js +47 -0
  31. package/dist/dev/elements/number.js.map +1 -0
  32. package/dist/dev/elements/range-element.d.ts +12 -0
  33. package/dist/dev/elements/range-element.js +172 -36
  34. package/dist/dev/elements/range-element.js.map +1 -1
  35. package/dist/dev/elements/slider.d.ts +8 -0
  36. package/dist/dev/elements/slider.js +63 -3
  37. package/dist/dev/elements/slider.js.map +1 -1
  38. package/dist/dev/index.d.ts +2 -1
  39. package/dist/dev/index.js +2 -1
  40. package/dist/dev/lib/detent.js +18 -0
  41. package/dist/dev/lib/detent.js.map +1 -0
  42. package/dist/dev/lib/math.js +17 -0
  43. package/dist/dev/lib/math.js.map +1 -0
  44. package/dist/dev/lib/number-list.js +15 -0
  45. package/dist/dev/lib/number-list.js.map +1 -0
  46. package/dist/dev/lib/read-px-property.js.map +1 -1
  47. package/dist/dev/lib/taper.js +17 -4
  48. package/dist/dev/lib/taper.js.map +1 -1
  49. package/dist/styles/controls.css +2 -0
  50. package/dist/styles/dial.css +80 -6
  51. package/dist/styles/key.css +96 -11
  52. package/dist/styles/led.css +82 -0
  53. package/dist/styles/material.css +150 -20
  54. package/dist/styles/meter.css +120 -8
  55. package/dist/styles/number.css +81 -0
  56. package/dist/styles/screen.css +6 -39
  57. package/dist/styles/segmented.css +23 -7
  58. package/dist/styles/slider.css +143 -30
  59. package/package.json +4 -2
@@ -1,3 +1,9 @@
1
+ @property --_sonic-screen-size {
2
+ syntax: '<length>';
3
+ inherits: true;
4
+ initial-value: 40px;
5
+ }
6
+
1
7
  @layer sonic {
2
8
  .sonic-screen {
3
9
  --_sonic-screen-size: var(--sonic-screen-size, 2.5rem);
@@ -6,48 +12,9 @@
6
12
  --_sonic-screen-inset-ratio: var(--sonic-screen-inset-ratio, 0.1);
7
13
  --_sonic-unit: calc(var(--_sonic-screen-size) / 32);
8
14
 
9
- position: relative;
10
- box-sizing: border-box;
11
- display: grid;
12
- flex-shrink: 0;
13
-
14
- /* A definite cell, so percentage-sized content fills the glass; a canvas sized to its own box would feed back */
15
- grid-template: minmax(0, 1fr) / minmax(0, 1fr);
16
- place-items: center;
17
15
  inline-size: calc(var(--_sonic-screen-size) * var(--_sonic-screen-aspect-ratio));
18
16
  block-size: var(--_sonic-screen-size);
19
17
  padding: calc(var(--_sonic-screen-size) * var(--_sonic-screen-inset-ratio));
20
-
21
- /* Not the cap's ink, which a skin may darken */
22
- color: color-mix(in oklab, var(--_sonic-glass) 20%, #fff);
23
-
24
- /* A double click aimed at a neighbouring control would highlight it */
25
- user-select: none;
26
- background: radial-gradient(
27
- closest-side,
28
- color-mix(in oklab, var(--_sonic-glass) 88%, #fff),
29
- var(--_sonic-glass)
30
- )
31
- var(--_sonic-glass);
32
18
  border-radius: calc(var(--_sonic-screen-size) * var(--_sonic-screen-radius-ratio));
33
-
34
- &::after {
35
- position: absolute;
36
- inset: 0;
37
- pointer-events: none;
38
- content: '';
39
- background: linear-gradient(var(--_sonic-light-fall), rgb(255 255 255 / 7%), transparent 45%);
40
- border-radius: inherit;
41
- box-shadow:
42
- var(--_sonic-well),
43
- inset 0 0 calc(3 * var(--_sonic-unit)) rgb(0 0 0 / 45%);
44
- }
45
- }
46
-
47
- /* The glass is forced to Canvas like the page, so only a border shows its edge */
48
- @media (forced-colors: active) {
49
- .sonic-screen {
50
- border: 1px solid CanvasText;
51
- }
52
19
  }
53
20
  }
@@ -1,3 +1,9 @@
1
+ @property --_sonic-segmented-size {
2
+ syntax: '<length>';
3
+ inherits: true;
4
+ initial-value: 32px;
5
+ }
6
+
1
7
  @layer sonic {
2
8
  :is(sonic-segmented, .sonic-segmented) {
3
9
  --_sonic-segmented-size: var(--sonic-segmented-size, 2rem);
@@ -45,11 +51,7 @@
45
51
  padding: var(--_sonic-segmented-gap);
46
52
  touch-action: pan-y;
47
53
  user-select: none;
48
- background: linear-gradient(
49
- var(--_sonic-light-fall),
50
- color-mix(in oklab, var(--_sonic-unlit) 55%, #000),
51
- color-mix(in oklab, var(--_sonic-unlit) 85%, #000)
52
- );
54
+ background: var(--_sonic-well-floor);
53
55
  border-radius: var(--_sonic-segmented-corner);
54
56
  box-shadow: var(--_sonic-well);
55
57
  }
@@ -72,14 +74,14 @@
72
74
  background: transparent;
73
75
  border: 0;
74
76
  border-radius: var(--_sonic-segmented-inner-corner);
77
+ transition: color 120ms ease-out;
75
78
  }
76
79
 
77
80
  .sonic-segmented-segment:where([data-sonic-pressed], :focus-visible:active):not(:disabled),
78
81
  .sonic-segmented-segment[aria-checked='true'] {
79
82
  --_sonic-segmented-shift: calc(var(--_sonic-segmented-depth) / 2);
80
83
  --_sonic-segmented-scale: var(--_sonic-segmented-press-scale);
81
- --_sonic-segmented-drop: calc(0.5 * var(--_sonic-cast-x)) calc(0.5 * var(--_sonic-cast-y))
82
- var(--_sonic-unit) var(--_sonic-drop-shade);
84
+ --_sonic-segmented-drop: var(--_sonic-press-drop);
83
85
  }
84
86
 
85
87
  .sonic-segmented-segment[aria-checked='true'] {
@@ -97,6 +99,20 @@
97
99
  cursor: default;
98
100
  }
99
101
 
102
+ .sonic-segmented-segment:not([aria-checked='true'], :disabled):is(
103
+ :focus-visible,
104
+ :active,
105
+ [data-sonic-pressed]
106
+ ) {
107
+ color: var(--_sonic-ink-lift);
108
+ }
109
+
110
+ @media (hover: hover) {
111
+ .sonic-segmented-segment:not([aria-checked='true'], :disabled):hover {
112
+ color: var(--_sonic-ink-lift);
113
+ }
114
+ }
115
+
100
116
  /* In flow, so a long label widens its segment rather than spilling over the next */
101
117
  .sonic-segmented-cap {
102
118
  position: relative;
@@ -1,3 +1,15 @@
1
+ @property --_sonic-slider-size {
2
+ syntax: '<length>';
3
+ inherits: true;
4
+ initial-value: 32px;
5
+ }
6
+
7
+ @property --_sonic-slider-length {
8
+ syntax: '<length>';
9
+ inherits: true;
10
+ initial-value: 128px;
11
+ }
12
+
1
13
  /* The size is the thickness across the travel */
2
14
  @layer sonic {
3
15
  :is(sonic-slider, .sonic-slider) {
@@ -11,9 +23,11 @@
11
23
 
12
24
  sonic-slider:not(:defined, [hidden]) {
13
25
  display: block;
26
+ visibility: hidden;
14
27
  flex-shrink: 0;
15
28
  inline-size: var(--_sonic-slider-length);
16
29
  block-size: var(--_sonic-slider-size);
30
+ overflow: hidden;
17
31
  }
18
32
 
19
33
  sonic-slider[orientation='vertical']:not(:defined, [hidden]) {
@@ -30,13 +44,23 @@
30
44
  --_sonic-slider-radius-ratio: var(--sonic-slider-radius-ratio, 0.15);
31
45
  --_sonic-slider-bevel-ratio: var(--sonic-slider-bevel-ratio, 0.075);
32
46
  --_sonic-slider-pointer-ratio: var(--sonic-slider-pointer-ratio, 0.07);
33
- --_sonic-unit: calc(var(--_sonic-slider-size) / 32);
47
+ --_sonic-slider-scale-ratio: var(--sonic-slider-scale-ratio, 0.4);
48
+ --_sonic-slider-scale-font-ratio: var(--sonic-slider-scale-font-ratio, 0.18);
49
+ --_sonic-slider-scale-band: 0px;
50
+
51
+ /* Across the travel beside the legend, so a legend widens the box without restyling the fader */
52
+ --_sonic-slider-track: calc(var(--_sonic-slider-size) - var(--_sonic-slider-scale-band));
53
+ --_sonic-unit: calc(var(--_sonic-slider-track) / 32);
34
54
  --_sonic-slider-lit: var(--_sonic-lit);
55
+ --_sonic-slider-buffered: var(
56
+ --sonic-buffered,
57
+ color-mix(in oklab, var(--_sonic-ink) 18%, var(--_sonic-unlit))
58
+ );
35
59
  --_sonic-slider-toward: to right;
36
60
  --_sonic-slider-across: to bottom;
37
61
  --_sonic-slider-cursor: ew-resize;
38
- --_sonic-slider-groove: calc(var(--_sonic-slider-size) * var(--_sonic-slider-groove-ratio));
39
- --_sonic-slider-cap: calc(var(--_sonic-slider-size) * var(--_sonic-slider-cap-ratio));
62
+ --_sonic-slider-groove: calc(var(--_sonic-slider-track) * var(--_sonic-slider-groove-ratio));
63
+ --_sonic-slider-cap: calc(var(--_sonic-slider-track) * var(--_sonic-slider-cap-ratio));
40
64
  --_sonic-slider-travel: calc(var(--_sonic-slider-length) - var(--_sonic-slider-cap));
41
65
  --_sonic-slider-offset: calc(var(--_sonic-slider-value, 0) * var(--_sonic-slider-travel));
42
66
 
@@ -71,6 +95,10 @@
71
95
  --_sonic-slider-cursor: default;
72
96
  }
73
97
 
98
+ :has(> [data-sonic-value]) > .sonic-slider {
99
+ --_sonic-slider-scale-band: calc(var(--_sonic-slider-size) * var(--_sonic-slider-scale-ratio));
100
+ }
101
+
74
102
  [groove-press='none']:not(:state(dragging)) > .sonic-slider {
75
103
  cursor: default;
76
104
  }
@@ -80,11 +108,12 @@
80
108
  var(--_sonic-slider-travel) / (var(--_sonic-slider-positions, 2) - 1)
81
109
  );
82
110
  --_sonic-slider-mark-lip: calc(
83
- var(--_sonic-slider-groove) / 2 + var(--_sonic-slider-size) * 0.1
111
+ var(--_sonic-slider-groove) / 2 + var(--_sonic-slider-track) * 0.1
84
112
  );
85
113
 
86
114
  position: absolute;
87
- inset: 0 calc((var(--_sonic-slider-cap) - var(--_sonic-unit)) / 2);
115
+ inset: var(--_sonic-slider-scale-band) calc((var(--_sonic-slider-cap) - var(--_sonic-unit)) / 2)
116
+ 0;
88
117
  background: repeating-linear-gradient(
89
118
  var(--_sonic-slider-toward),
90
119
  var(--_sonic-etch) 0 var(--_sonic-unit),
@@ -101,55 +130,131 @@
101
130
  }
102
131
 
103
132
  [orientation='vertical'] > .sonic-slider > .sonic-slider-marks {
104
- inset: calc((var(--_sonic-slider-cap) - var(--_sonic-unit)) / 2) 0;
133
+ inset: calc((var(--_sonic-slider-cap) - var(--_sonic-unit)) / 2) 0
134
+ calc((var(--_sonic-slider-cap) - var(--_sonic-unit)) / 2) var(--_sonic-slider-scale-band);
105
135
  }
106
136
 
107
137
  :not([notched]) > .sonic-slider > .sonic-slider-marks {
108
138
  display: none;
109
139
  }
110
140
 
141
+ .sonic-slider-scale {
142
+ font-size: calc(var(--_sonic-slider-size) * var(--_sonic-slider-scale-font-ratio));
143
+
144
+ & > * {
145
+ --_sonic-slider-scale-along: calc(
146
+ var(--_sonic-slider-cap) / 2 + var(--_sonic-scale-at, 0) * var(--_sonic-slider-travel)
147
+ );
148
+ --_sonic-slider-scale-edge: calc(100% - var(--_sonic-slider-scale-band) + var(--_sonic-unit));
149
+
150
+ inset: auto auto var(--_sonic-slider-scale-edge) var(--_sonic-slider-scale-along);
151
+ translate: -50% 0;
152
+ }
153
+
154
+ & > .sonic-scale-tick {
155
+ inline-size: var(--_sonic-unit);
156
+ block-size: calc(var(--_sonic-slider-scale-band) * 0.4);
157
+ }
158
+ }
159
+
160
+ [orientation='vertical'] > .sonic-slider > .sonic-slider-scale {
161
+ & > * {
162
+ inset: auto var(--_sonic-slider-scale-edge) var(--_sonic-slider-scale-along) auto;
163
+ translate: 0 50%;
164
+ }
165
+
166
+ & > .sonic-scale-tick {
167
+ inline-size: calc(var(--_sonic-slider-scale-band) * 0.4);
168
+ block-size: var(--_sonic-unit);
169
+ }
170
+ }
171
+
111
172
  .sonic-slider-groove {
112
173
  --_sonic-slider-lit-low: min(var(--_sonic-slider-origin, 0), var(--_sonic-slider-value, 0));
113
174
  --_sonic-slider-lit-high: max(var(--_sonic-slider-origin, 0), var(--_sonic-slider-value, 0));
114
175
 
115
176
  position: absolute;
116
- inset: calc(50% - var(--_sonic-slider-groove) / 2)
117
- calc((var(--_sonic-slider-cap) - var(--_sonic-slider-groove)) / 2);
177
+ inset: calc(50% + var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-groove) / 2)
178
+ calc((var(--_sonic-slider-cap) - var(--_sonic-slider-groove)) / 2)
179
+ calc(50% - var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-groove) / 2);
118
180
 
119
181
  /* At either end of the travel the light runs on to the groove's rounded end */
120
- background: linear-gradient(
121
- var(--_sonic-slider-toward),
122
- var(--_sonic-unlit)
123
- calc(
124
- var(--_sonic-slider-lit-low) * var(--_sonic-slider-travel) + var(--_sonic-slider-groove) /
125
- 2 * sign(var(--_sonic-slider-lit-low))
126
- ),
127
- var(--_sonic-slider-lit) 0
128
- calc(
129
- var(--_sonic-slider-lit-high) * var(--_sonic-slider-travel) +
130
- var(--_sonic-slider-groove) / 2 * (2 - sign(1 - var(--_sonic-slider-lit-high)))
131
- ),
132
- var(--_sonic-unlit) 0
133
- );
182
+ background:
183
+ linear-gradient(
184
+ var(--_sonic-slider-toward),
185
+ transparent
186
+ calc(
187
+ var(--_sonic-slider-lit-low) * var(--_sonic-slider-travel) +
188
+ var(--_sonic-slider-groove) / 2 * sign(var(--_sonic-slider-lit-low))
189
+ ),
190
+ var(--_sonic-slider-lit) 0
191
+ calc(
192
+ var(--_sonic-slider-lit-high) * var(--_sonic-slider-travel) +
193
+ var(--_sonic-slider-groove) / 2 * (2 - sign(1 - var(--_sonic-slider-lit-high)))
194
+ ),
195
+ transparent 0
196
+ ),
197
+ var(--_sonic-slider-buffered-ranges, none), var(--_sonic-unlit);
134
198
  border-radius: calc(var(--_sonic-slider-groove) / 2);
135
199
  box-shadow: var(--_sonic-groove);
136
200
  }
137
201
 
138
202
  [orientation='vertical'] > .sonic-slider > .sonic-slider-groove {
139
203
  inset: calc((var(--_sonic-slider-cap) - var(--_sonic-slider-groove)) / 2)
140
- calc(50% - var(--_sonic-slider-groove) / 2);
204
+ calc(50% - var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-groove) / 2)
205
+ calc((var(--_sonic-slider-cap) - var(--_sonic-slider-groove)) / 2)
206
+ calc(50% + var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-groove) / 2);
207
+ }
208
+
209
+ .sonic-slider-modulation {
210
+ --_sonic-slider-modulation: var(
211
+ --sonic-modulation,
212
+ color-mix(in oklab, var(--_sonic-slider-lit) 60%, #000)
213
+ );
214
+ --_sonic-slider-modulation-band: calc(var(--_sonic-slider-groove) * 0.45);
215
+ --_sonic-slider-modulation-start: calc(
216
+ var(--_sonic-slider-cap) / 2 + var(--_sonic-slider-modulation-from, 0) *
217
+ var(--_sonic-slider-travel)
218
+ );
219
+ --_sonic-slider-modulation-length: calc(
220
+ (var(--_sonic-slider-modulation-to, 0) - var(--_sonic-slider-modulation-from, 0)) *
221
+ var(--_sonic-slider-travel)
222
+ );
223
+
224
+ position: absolute;
225
+ inset: calc(
226
+ 50% + var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-modulation-band) / 2
227
+ )
228
+ auto auto var(--_sonic-slider-modulation-start);
229
+ inline-size: var(--_sonic-slider-modulation-length);
230
+ block-size: var(--_sonic-slider-modulation-band);
231
+ background: var(--_sonic-slider-modulation);
232
+ border-radius: calc(var(--_sonic-slider-modulation-band) / 2);
233
+ }
234
+
235
+ [orientation='vertical'] > .sonic-slider > .sonic-slider-modulation {
236
+ inset: auto auto var(--_sonic-slider-modulation-start)
237
+ calc(50% + var(--_sonic-slider-scale-band) / 2 - var(--_sonic-slider-modulation-band) / 2);
238
+ inline-size: var(--_sonic-slider-modulation-band);
239
+ block-size: var(--_sonic-slider-modulation-length);
240
+ }
241
+
242
+ :not([modulation]) > .sonic-slider > .sonic-slider-modulation {
243
+ display: none;
141
244
  }
142
245
 
143
246
  .sonic-slider-cap {
144
247
  --_sonic-slider-pointer-width: calc(
145
- var(--_sonic-slider-size) * var(--_sonic-slider-pointer-ratio)
248
+ var(--_sonic-slider-track) * var(--_sonic-slider-pointer-ratio)
249
+ );
250
+ --_sonic-slider-bevel: calc(var(--_sonic-slider-track) * var(--_sonic-slider-bevel-ratio));
251
+ --_sonic-slider-corner: calc(var(--_sonic-slider-track) * var(--_sonic-slider-radius-ratio));
252
+ --_sonic-slider-index-inset: calc(
253
+ var(--_sonic-slider-bevel) + var(--_sonic-slider-track) * 0.1
146
254
  );
147
- --_sonic-slider-bevel: calc(var(--_sonic-slider-size) * var(--_sonic-slider-bevel-ratio));
148
- --_sonic-slider-corner: calc(var(--_sonic-slider-size) * var(--_sonic-slider-radius-ratio));
149
- --_sonic-slider-index-inset: calc(var(--_sonic-slider-bevel) + var(--_sonic-slider-size) * 0.1);
150
255
 
151
256
  position: absolute;
152
- inset: 0 auto 0 0;
257
+ inset: var(--_sonic-slider-scale-band) auto 0 0;
153
258
  inline-size: var(--_sonic-slider-cap);
154
259
  background: var(--_sonic-skirt);
155
260
  border-radius: var(--_sonic-slider-corner);
@@ -183,7 +288,7 @@
183
288
  }
184
289
 
185
290
  [orientation='vertical'] > .sonic-slider > .sonic-slider-cap {
186
- inset: auto 0 0;
291
+ inset: auto 0 0 var(--_sonic-slider-scale-band);
187
292
  inline-size: auto;
188
293
  block-size: var(--_sonic-slider-cap);
189
294
  translate: 0 calc(-1 * var(--_sonic-slider-offset));
@@ -202,10 +307,18 @@
202
307
  }
203
308
 
204
309
  @media (forced-colors: active) {
205
- :is(.sonic-slider-marks, .sonic-slider-groove) {
310
+ :is(.sonic-slider-marks, .sonic-slider-groove, .sonic-slider-modulation) {
206
311
  forced-color-adjust: none;
207
312
  }
208
313
 
314
+ .sonic-slider-modulation {
315
+ --_sonic-slider-modulation: CanvasText;
316
+ }
317
+
318
+ .sonic-slider {
319
+ --_sonic-slider-buffered: color-mix(in srgb, CanvasText 50%, GrayText);
320
+ }
321
+
209
322
  .sonic-slider-groove {
210
323
  box-shadow: none;
211
324
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xsynaptic/sonic-ui",
3
- "version": "0.2.0",
4
- "description": "Native custom elements for audio interfaces: dials, sliders, keys, a segmented switch, a peak meter and a screen panel, skinned with CSS custom properties",
3
+ "version": "0.4.0",
4
+ "description": "Native custom elements for audio interfaces, skinned with CSS custom properties",
5
5
  "keywords": [
6
6
  "custom-elements",
7
7
  "web-components",
@@ -54,7 +54,9 @@
54
54
  "./material.css": "./dist/styles/material.css",
55
55
  "./dial.css": "./dist/styles/dial.css",
56
56
  "./key.css": "./dist/styles/key.css",
57
+ "./led.css": "./dist/styles/led.css",
57
58
  "./meter.css": "./dist/styles/meter.css",
59
+ "./number.css": "./dist/styles/number.css",
58
60
  "./screen.css": "./dist/styles/screen.css",
59
61
  "./segmented.css": "./dist/styles/segmented.css",
60
62
  "./slider.css": "./dist/styles/slider.css",