@xsynaptic/sonic-ui 0.24.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -2
- package/README.md +5 -3
- package/dist/default/define/region.js +7 -0
- package/dist/default/define.js +1 -0
- package/dist/default/elements/envelope.js +11 -11
- package/dist/default/elements/form-element.js +10 -0
- package/dist/default/elements/readout.js +3 -2
- package/dist/default/elements/region-layer.js +251 -0
- package/dist/default/elements/region.js +157 -0
- package/dist/default/elements/sonic-element.js +26 -4
- package/dist/default/elements/split.js +2 -2
- package/dist/default/elements/toggle.js +2 -2
- package/dist/default/elements/value-element.js +9 -5
- package/dist/default/elements/value-gestures.js +7 -5
- package/dist/default/elements/wave-element.js +12 -3
- package/dist/default/elements/waveform.js +38 -2
- package/dist/default/elements/wavestrip.js +90 -17
- package/dist/default/elements/xy.js +3 -11
- package/dist/default/index.js +2 -1
- package/dist/default/lib/clock.js +1 -0
- package/dist/default/lib/drag-step.js +1 -1
- package/dist/default/lib/marker-band.js +40 -29
- package/dist/default/lib/region-drag.js +48 -0
- package/dist/default/lib/spoken-duration.js +3 -0
- package/dist/dev/define/region.d.ts +2 -0
- package/dist/dev/define/region.js +8 -0
- package/dist/dev/define/region.js.map +1 -0
- package/dist/dev/define.d.ts +3 -1
- package/dist/dev/define.js +1 -0
- package/dist/dev/elements/envelope.js +11 -11
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/form-element.d.ts +1 -0
- package/dist/dev/elements/form-element.js +10 -0
- package/dist/dev/elements/form-element.js.map +1 -1
- package/dist/dev/elements/readout.js +3 -2
- package/dist/dev/elements/readout.js.map +1 -1
- package/dist/dev/elements/region-layer.js +252 -0
- package/dist/dev/elements/region-layer.js.map +1 -0
- package/dist/dev/elements/region.d.ts +29 -0
- package/dist/dev/elements/region.js +165 -0
- package/dist/dev/elements/region.js.map +1 -0
- package/dist/dev/elements/sonic-element.d.ts +1 -0
- package/dist/dev/elements/sonic-element.js +27 -5
- package/dist/dev/elements/sonic-element.js.map +1 -1
- package/dist/dev/elements/split.js +2 -2
- package/dist/dev/elements/split.js.map +1 -1
- package/dist/dev/elements/toggle.js +2 -2
- package/dist/dev/elements/toggle.js.map +1 -1
- package/dist/dev/elements/value-element.d.ts +3 -1
- package/dist/dev/elements/value-element.js +9 -5
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/value-gestures.js +7 -5
- package/dist/dev/elements/value-gestures.js.map +1 -1
- package/dist/dev/elements/wave-element.d.ts +7 -1
- package/dist/dev/elements/wave-element.js +12 -3
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.d.ts +7 -0
- package/dist/dev/elements/waveform.js +38 -2
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +17 -1
- package/dist/dev/elements/wavestrip.js +90 -17
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.js +3 -11
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +3 -2
- package/dist/dev/index.js +2 -1
- package/dist/dev/lib/clock.js +1 -0
- package/dist/dev/lib/clock.js.map +1 -1
- package/dist/dev/lib/drag-step.js +1 -1
- package/dist/dev/lib/drag-step.js.map +1 -1
- package/dist/dev/lib/marker-band.d.ts +7 -0
- package/dist/dev/lib/marker-band.js +40 -29
- package/dist/dev/lib/marker-band.js.map +1 -1
- package/dist/dev/lib/region-drag.js +49 -0
- package/dist/dev/lib/region-drag.js.map +1 -0
- package/dist/dev/lib/spoken-duration.js +3 -0
- package/dist/dev/lib/spoken-duration.js.map +1 -1
- package/dist/styles/button.css +42 -15
- package/dist/styles/controls.css +1 -0
- package/dist/styles/dial.css +48 -33
- package/dist/styles/envelope.css +7 -6
- package/dist/styles/led.css +28 -13
- package/dist/styles/material/arc.css +2 -2
- package/dist/styles/material/cap.css +25 -15
- package/dist/styles/material/core.css +53 -1
- package/dist/styles/material/glass.css +12 -2
- package/dist/styles/material/groove.css +3 -3
- package/dist/styles/material/keycap.css +5 -5
- package/dist/styles/material/lens.css +1 -1
- package/dist/styles/material/pane.css +21 -11
- package/dist/styles/material/readout.css +23 -10
- package/dist/styles/material/{bracket.css → reticle.css} +15 -8
- package/dist/styles/material/scale.css +4 -4
- package/dist/styles/material/value.css +12 -3
- package/dist/styles/material/well.css +2 -2
- package/dist/styles/material.css +1 -1
- package/dist/styles/meter.css +24 -11
- package/dist/styles/number.css +2 -1
- package/dist/styles/panel.css +5 -6
- package/dist/styles/region.css +88 -0
- package/dist/styles/ring.css +5 -4
- package/dist/styles/screen.css +7 -5
- package/dist/styles/segmented.css +8 -7
- package/dist/styles/slider.css +40 -32
- package/dist/styles/spectrum.css +9 -1
- package/dist/styles/switch.css +52 -53
- package/dist/styles/toggle.css +33 -38
- package/dist/styles/waveform.css +5 -4
- package/dist/styles/wavestrip.css +15 -12
- package/dist/styles/xy.css +19 -19
- package/package.json +3 -2
|
@@ -2,7 +2,7 @@ import { readPxProperty } from "./read-px-property.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/lib/marker-band.ts
|
|
4
4
|
const kindPattern = /^[a-z][a-z0-9-]*$/;
|
|
5
|
-
const
|
|
5
|
+
const snapMarginPx = 4;
|
|
6
6
|
function isKind(kind) {
|
|
7
7
|
return kind !== void 0 && kindPattern.test(kind);
|
|
8
8
|
}
|
|
@@ -13,45 +13,61 @@ function writeKind(part, kind, fallback) {
|
|
|
13
13
|
}
|
|
14
14
|
part.style.setProperty("--_sonic-marker", `var(--sonic-marker-${kind}, var(${fallback}))`);
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function createPart(marker) {
|
|
17
17
|
const part = document.createElement("div");
|
|
18
|
-
part.className =
|
|
19
|
-
if (lane !== void 0) part.style.setProperty("--_sonic-marker-lane", String(lane));
|
|
20
|
-
part.style.setProperty("--_sonic-marker-from", String(from));
|
|
21
|
-
part.style.setProperty("--_sonic-marker-to", String(to));
|
|
18
|
+
part.className = marker.end === void 0 ? "sonic-wavestrip-marker" : "sonic-wavestrip-region";
|
|
22
19
|
writeKind(part, marker.kind, "--_sonic-marker-default");
|
|
23
20
|
if (marker.dimmed === true) part.dataset.sonicDimmed = "";
|
|
24
21
|
return part;
|
|
25
22
|
}
|
|
26
23
|
function createMarkerBand(band) {
|
|
27
|
-
let
|
|
24
|
+
let built;
|
|
25
|
+
let placed = [];
|
|
28
26
|
const px = (property) => readPxProperty(getComputedStyle(band), property, 0);
|
|
27
|
+
function build(markers, draw) {
|
|
28
|
+
const parts = markers.map((marker) => {
|
|
29
|
+
const part = createPart(marker);
|
|
30
|
+
if (draw && marker.end === void 0) {
|
|
31
|
+
part.style.setProperty("--_sonic-marker-paint", "transparent");
|
|
32
|
+
draw(marker, part);
|
|
33
|
+
}
|
|
34
|
+
return part;
|
|
35
|
+
});
|
|
36
|
+
band.replaceChildren(...parts);
|
|
37
|
+
built = {
|
|
38
|
+
draw,
|
|
39
|
+
markers,
|
|
40
|
+
parts
|
|
41
|
+
};
|
|
42
|
+
return parts;
|
|
43
|
+
}
|
|
29
44
|
return {
|
|
30
|
-
|
|
45
|
+
inReach: (point, widthPx) => {
|
|
31
46
|
const size = px("--_sonic-marker-size");
|
|
32
47
|
const step = px("--_sonic-marker-step");
|
|
33
|
-
|
|
34
|
-
x,
|
|
35
|
-
y
|
|
36
|
-
}, dots.map(({ at, lane }) => ({
|
|
48
|
+
return centersInReach(point, placed.map(({ at, lane }) => ({
|
|
37
49
|
x: at * widthPx,
|
|
38
50
|
y: size / 2 + lane * step
|
|
39
|
-
})), size / 2 +
|
|
40
|
-
return nearest === void 0 ? void 0 : dots[nearest]?.index;
|
|
51
|
+
})), size / 2 + snapMarginPx).flatMap((order) => placed[order]?.index ?? []);
|
|
41
52
|
},
|
|
42
|
-
render: (markers, proportions) => {
|
|
53
|
+
render: (markers, proportions, draw) => {
|
|
43
54
|
const widthPx = band.getBoundingClientRect().width;
|
|
44
55
|
const points = markers.flatMap((marker, index) => marker.end === void 0 ? [{
|
|
45
56
|
at: proportions[index]?.[0] ?? 0,
|
|
46
57
|
index
|
|
47
58
|
}] : []);
|
|
48
59
|
const lanes = markerLanes(points.map(({ at }) => at * widthPx), px("--_sonic-marker-step"));
|
|
49
|
-
|
|
60
|
+
const parts = built?.markers === markers && built.draw === draw ? built.parts : build(markers, draw);
|
|
61
|
+
placed = points.map((point, order) => ({
|
|
50
62
|
...point,
|
|
51
63
|
lane: lanes[order] ?? 0
|
|
52
64
|
}));
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
for (const [index, part] of parts.entries()) {
|
|
66
|
+
const [from, to] = proportions[index] ?? [0, 0];
|
|
67
|
+
part.style.setProperty("--_sonic-marker-from", String(from));
|
|
68
|
+
part.style.setProperty("--_sonic-marker-to", String(to));
|
|
69
|
+
}
|
|
70
|
+
for (const { index, lane } of placed) parts[index]?.style.setProperty("--_sonic-marker-lane", String(lane));
|
|
55
71
|
}
|
|
56
72
|
};
|
|
57
73
|
}
|
|
@@ -64,18 +80,13 @@ function markerLanes(positions, minDistance) {
|
|
|
64
80
|
return lane;
|
|
65
81
|
});
|
|
66
82
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (distance > nearestDistance) continue;
|
|
73
|
-
nearest = index;
|
|
74
|
-
nearestDistance = distance;
|
|
75
|
-
}
|
|
76
|
-
return nearest;
|
|
83
|
+
function centersInReach(point, centers, reach) {
|
|
84
|
+
return centers.map((center, index) => ({
|
|
85
|
+
distance: (center.x - point.x) ** 2 + (center.y - point.y) ** 2,
|
|
86
|
+
index
|
|
87
|
+
})).filter(({ distance }) => distance <= reach * reach).toSorted((first, second) => first.distance - second.distance || second.index - first.index).map(({ index }) => index);
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
//#endregion
|
|
80
|
-
export { createMarkerBand, isKind, markerLanes,
|
|
91
|
+
export { centersInReach, createMarkerBand, isKind, markerLanes, writeKind };
|
|
81
92
|
//# sourceMappingURL=marker-band.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker-band.js","names":[],"sources":["../../../src/lib/marker-band.ts"],"sourcesContent":["import { readPxProperty } from '#lib/read-px-property.ts';\n\ninterface MarkerLook {\n\tdimmed?: boolean;\n\tend?: number;\n\tkind?: string;\n}\n\
|
|
1
|
+
{"version":3,"file":"marker-band.js","names":[],"sources":["../../../src/lib/marker-band.ts"],"sourcesContent":["import { readPxProperty } from '#lib/read-px-property.ts';\n\ninterface MarkerLook {\n\tdimmed?: boolean;\n\tend?: number;\n\tkind?: string;\n}\n\nexport interface Point {\n\tx: number;\n\ty: number;\n}\n\ninterface MarkerBand<Marker extends MarkerLook> {\n\tinReach: (point: Point, widthPx: number) => Array<number>;\n\trender: (\n\t\tmarkers: ReadonlyArray<Marker>,\n\t\tproportions: ReadonlyArray<[number, number]>,\n\t\tdraw?: (marker: Marker, part: HTMLElement) => void,\n\t) => void;\n}\n\n// Interpolated into a style, so anything else falls back to the default colour\nconst kindPattern = /^[a-z][a-z0-9-]*$/;\n\nconst snapMarginPx = 4;\n\nexport function isKind(kind: string | undefined): kind is string {\n\treturn kind !== undefined && kindPattern.test(kind);\n}\n\nexport function writeKind(part: HTMLElement, kind: string | undefined, fallback: string): void {\n\tif (!isKind(kind)) {\n\t\tpart.style.removeProperty('--_sonic-marker');\n\t\treturn;\n\t}\n\n\tpart.style.setProperty('--_sonic-marker', `var(--sonic-marker-${kind}, var(${fallback}))`);\n}\n\nfunction createPart(marker: MarkerLook): HTMLElement {\n\tconst part = document.createElement('div');\n\n\tpart.className = marker.end === undefined ? 'sonic-wavestrip-marker' : 'sonic-wavestrip-region';\n\twriteKind(part, marker.kind, '--_sonic-marker-default');\n\tif (marker.dimmed === true) part.dataset.sonicDimmed = '';\n\n\treturn part;\n}\n\nexport function createMarkerBand<Marker extends MarkerLook>(band: HTMLElement): MarkerBand<Marker> {\n\ttype Draw = (marker: Marker, part: HTMLElement) => void;\n\n\tlet built:\n\t\t| undefined\n\t\t| { draw: Draw | undefined; markers: ReadonlyArray<Marker>; parts: Array<HTMLElement> };\n\tlet placed: Array<{ at: number; index: number; lane: number }> = [];\n\n\tconst px = (property: string): number => readPxProperty(getComputedStyle(band), property, 0);\n\n\tfunction build(markers: ReadonlyArray<Marker>, draw: Draw | undefined): Array<HTMLElement> {\n\t\tconst parts = markers.map((marker) => {\n\t\t\tconst part = createPart(marker);\n\n\t\t\tif (draw && marker.end === undefined) {\n\t\t\t\tpart.style.setProperty('--_sonic-marker-paint', 'transparent');\n\t\t\t\tdraw(marker, part);\n\t\t\t}\n\n\t\t\treturn part;\n\t\t});\n\n\t\tband.replaceChildren(...parts);\n\t\tbuilt = { draw, markers, parts };\n\n\t\treturn parts;\n\t}\n\n\treturn {\n\t\tinReach: (point, widthPx) => {\n\t\t\tconst size = px('--_sonic-marker-size');\n\t\t\tconst step = px('--_sonic-marker-step');\n\n\t\t\treturn centersInReach(\n\t\t\t\tpoint,\n\t\t\t\tplaced.map(({ at, lane }) => ({ x: at * widthPx, y: size / 2 + lane * step })),\n\t\t\t\tsize / 2 + snapMarginPx,\n\t\t\t).flatMap((order) => placed[order]?.index ?? []);\n\t\t},\n\t\trender: (markers, proportions, draw) => {\n\t\t\tconst widthPx = band.getBoundingClientRect().width;\n\t\t\tconst points = markers.flatMap((marker, index) =>\n\t\t\t\tmarker.end === undefined ? [{ at: proportions[index]?.[0] ?? 0, index }] : [],\n\t\t\t);\n\t\t\tconst lanes = markerLanes(\n\t\t\t\tpoints.map(({ at }) => at * widthPx),\n\t\t\t\tpx('--_sonic-marker-step'),\n\t\t\t);\n\t\t\t// A `markers` write always makes a new array, so the same array and renderer mean no write\n\t\t\tconst parts =\n\t\t\t\tbuilt?.markers === markers && built.draw === draw ? built.parts : build(markers, draw);\n\n\t\t\tplaced = points.map((point, order) => ({ ...point, lane: lanes[order] ?? 0 }));\n\t\t\tfor (const [index, part] of parts.entries()) {\n\t\t\t\tconst [from, to] = proportions[index] ?? [0, 0];\n\n\t\t\t\tpart.style.setProperty('--_sonic-marker-from', String(from));\n\t\t\t\tpart.style.setProperty('--_sonic-marker-to', String(to));\n\t\t\t}\n\t\t\tfor (const { index, lane } of placed) {\n\t\t\t\tparts[index]?.style.setProperty('--_sonic-marker-lane', String(lane));\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function markerLanes(positions: ReadonlyArray<number>, minDistance: number): Array<number> {\n\tconst lastInLane: Array<number> = [];\n\n\treturn positions.map((position) => {\n\t\tconst free = lastInLane.findIndex((last) => position - last >= minDistance);\n\t\tconst lane = free === -1 ? lastInLane.length : free;\n\n\t\tlastInLane[lane] = position;\n\n\t\treturn lane;\n\t});\n}\n\n// A later marker wins a tie, as it is drawn over the earlier one\nexport function centersInReach(\n\tpoint: Point,\n\tcenters: ReadonlyArray<Point>,\n\treach: number,\n): Array<number> {\n\treturn centers\n\t\t.map((center, index) => ({\n\t\t\tdistance: (center.x - point.x) ** 2 + (center.y - point.y) ** 2,\n\t\t\tindex,\n\t\t}))\n\t\t.filter(({ distance }) => distance <= reach * reach)\n\t\t.toSorted((first, second) => first.distance - second.distance || second.index - first.index)\n\t\t.map(({ index }) => index);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { clamp, clampProportion, trimFloat } from "./math.js";
|
|
2
|
+
import { fineFactor } from "./drag-step.js";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/region-drag.ts
|
|
5
|
+
function regionAt(bodies, x) {
|
|
6
|
+
const index = bodies.findLastIndex((body) => body !== void 0 && x >= body[0] && x <= body[1]);
|
|
7
|
+
return index === -1 ? void 0 : index;
|
|
8
|
+
}
|
|
9
|
+
function regionTravel({ end, start }, [low, high]) {
|
|
10
|
+
return [low, Math.max(low, trimFloat(high - (end - start)))];
|
|
11
|
+
}
|
|
12
|
+
function moveRegionTo(mapping, span, start) {
|
|
13
|
+
const moved = clamp(mapping.snap(start), ...regionTravel(span, mapping.bounds));
|
|
14
|
+
return {
|
|
15
|
+
end: trimFloat(moved + (span.end - span.start)),
|
|
16
|
+
start: moved
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function startRegionDrag({ position, ...fixed }) {
|
|
20
|
+
return {
|
|
21
|
+
...fixed,
|
|
22
|
+
isEngaged: false,
|
|
23
|
+
lastPosition: position,
|
|
24
|
+
startPosition: position,
|
|
25
|
+
travelPx: 0
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function stepRegionDrag(mapping, state, move) {
|
|
29
|
+
if (!(state.isEngaged || Math.abs(move.position - state.startPosition) >= state.thresholdPx)) return {
|
|
30
|
+
span: void 0,
|
|
31
|
+
state
|
|
32
|
+
};
|
|
33
|
+
const pace = move.isFine ? fineFactor : 1;
|
|
34
|
+
const travelPx = state.travelPx + (move.position - state.lastPosition) * pace;
|
|
35
|
+
const at = mapping.proportionOf(state.from.start) + travelPx / state.widthPx;
|
|
36
|
+
return {
|
|
37
|
+
span: moveRegionTo(mapping, state.from, mapping.valueAt(clampProportion(at))),
|
|
38
|
+
state: {
|
|
39
|
+
...state,
|
|
40
|
+
isEngaged: true,
|
|
41
|
+
lastPosition: move.position,
|
|
42
|
+
travelPx
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { moveRegionTo, regionAt, regionTravel, startRegionDrag, stepRegionDrag };
|
|
49
|
+
//# sourceMappingURL=region-drag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region-drag.js","names":[],"sources":["../../../src/lib/region-drag.ts"],"sourcesContent":["import type { ValueMapping } from '#lib/value-mapping.ts';\n\nimport { fineFactor } from '#lib/drag-step.ts';\nimport { clamp, clampProportion, trimFloat } from '#lib/math.ts';\n\nexport interface RegionSpan {\n\tend: number;\n\tstart: number;\n}\n\nexport interface RegionDragState {\n\tfrom: RegionSpan;\n\tisEngaged: boolean;\n\tlastPosition: number;\n\tstartPosition: number;\n\tthresholdPx: number;\n\ttravelPx: number;\n\twidthPx: number;\n}\n\ninterface RegionDragStart {\n\tfrom: RegionSpan;\n\tposition: number;\n\tthresholdPx: number;\n\twidthPx: number;\n}\n\ninterface RegionDragStep {\n\tspan: RegionSpan | undefined;\n\tstate: RegionDragState;\n}\n\n// A later body is drawn over an earlier one; `undefined` holds the place of one that takes no press\nexport function regionAt(\n\tbodies: ReadonlyArray<[number, number] | undefined>,\n\tx: number,\n): number | undefined {\n\tconst index = bodies.findLastIndex((body) => body !== undefined && x >= body[0] && x <= body[1]);\n\n\treturn index === -1 ? undefined : index;\n}\n\nexport function regionTravel(\n\t{ end, start }: RegionSpan,\n\t[low, high]: [number, number],\n): [number, number] {\n\treturn [low, Math.max(low, trimFloat(high - (end - start)))];\n}\n\nexport function moveRegionTo(mapping: ValueMapping, span: RegionSpan, start: number): RegionSpan {\n\tconst moved = clamp(mapping.snap(start), ...regionTravel(span, mapping.bounds));\n\n\treturn { end: trimFloat(moved + (span.end - span.start)), start: moved };\n}\n\nexport function startRegionDrag({ position, ...fixed }: RegionDragStart): RegionDragState {\n\treturn {\n\t\t...fixed,\n\t\tisEngaged: false,\n\t\tlastPosition: position,\n\t\tstartPosition: position,\n\t\ttravelPx: 0,\n\t};\n}\n\n// `span` stays `undefined` until the pointer has travelled the threshold, so a lift before then is a press\nexport function stepRegionDrag(\n\tmapping: ValueMapping,\n\tstate: RegionDragState,\n\tmove: { isFine: boolean; position: number },\n): RegionDragStep {\n\tconst isEngaged =\n\t\tstate.isEngaged || Math.abs(move.position - state.startPosition) >= state.thresholdPx;\n\tif (!isEngaged) return { span: undefined, state };\n\n\tconst pace = move.isFine ? fineFactor : 1;\n\tconst travelPx = state.travelPx + (move.position - state.lastPosition) * pace;\n\tconst at = mapping.proportionOf(state.from.start) + travelPx / state.widthPx;\n\n\treturn {\n\t\tspan: moveRegionTo(mapping, state.from, mapping.valueAt(clampProportion(at))),\n\t\tstate: { ...state, isEngaged: true, lastPosition: move.position, travelPx },\n\t};\n}\n"],"mappings":";;;;AAiCA,SAAgB,SACf,QACA,GACqB;CACrB,MAAM,QAAQ,OAAO,eAAe,SAAS,SAAS,UAAa,KAAK,KAAK,MAAM,KAAK,KAAK,EAAE;CAE/F,OAAO,UAAU,KAAK,SAAY;AACnC;AAEA,SAAgB,aACf,EAAE,KAAK,SACP,CAAC,KAAK,OACa;CACnB,OAAO,CAAC,KAAK,KAAK,IAAI,KAAK,UAAU,QAAQ,MAAM,MAAM,CAAC,CAAC;AAC5D;AAEA,SAAgB,aAAa,SAAuB,MAAkB,OAA2B;CAChG,MAAM,QAAQ,MAAM,QAAQ,KAAK,KAAK,GAAG,GAAG,aAAa,MAAM,QAAQ,MAAM,CAAC;CAE9E,OAAO;EAAE,KAAK,UAAU,SAAS,KAAK,MAAM,KAAK,MAAM;EAAG,OAAO;CAAM;AACxE;AAEA,SAAgB,gBAAgB,EAAE,UAAU,GAAG,SAA2C;CACzF,OAAO;EACN,GAAG;EACH,WAAW;EACX,cAAc;EACd,eAAe;EACf,UAAU;CACX;AACD;AAGA,SAAgB,eACf,SACA,OACA,MACiB;CAGjB,IAAI,EADH,MAAM,aAAa,KAAK,IAAI,KAAK,WAAW,MAAM,aAAa,KAAK,MAAM,cAC3D,OAAO;EAAE,MAAM;EAAW;CAAM;CAEhD,MAAM,OAAO,KAAK,SAAS,aAAa;CACxC,MAAM,WAAW,MAAM,YAAY,KAAK,WAAW,MAAM,gBAAgB;CACzE,MAAM,KAAK,QAAQ,aAAa,MAAM,KAAK,KAAK,IAAI,WAAW,MAAM;CAErE,OAAO;EACN,MAAM,aAAa,SAAS,MAAM,MAAM,QAAQ,QAAQ,gBAAgB,EAAE,CAAC,CAAC;EAC5E,OAAO;GAAE,GAAG;GAAO,WAAW;GAAM,cAAc,KAAK;GAAU;EAAS;CAC3E;AACD"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { formatClock } from "./clock.js";
|
|
2
|
+
|
|
1
3
|
//#region src/lib/spoken-duration.ts
|
|
2
4
|
const formatters = /* @__PURE__ */ new Map();
|
|
3
5
|
function formatterFor(language, isZero) {
|
|
@@ -18,6 +20,7 @@ function formatterFor(language, isZero) {
|
|
|
18
20
|
return formatter;
|
|
19
21
|
}
|
|
20
22
|
function spokenDuration(seconds, language = "") {
|
|
23
|
+
if (!("DurationFormat" in Intl)) return formatClock(seconds);
|
|
21
24
|
const total = Math.trunc(seconds);
|
|
22
25
|
return formatterFor(language, total === 0).format({
|
|
23
26
|
hours: Math.trunc(total / 3600),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spoken-duration.js","names":[],"sources":["../../../src/lib/spoken-duration.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"spoken-duration.js","names":[],"sources":["../../../src/lib/spoken-duration.ts"],"sourcesContent":["import { formatClock } from '#lib/clock.ts';\n\nconst formatters = new Map<string, Intl.DurationFormat>();\n\nfunction formatterFor(language: string, isZero: boolean): Intl.DurationFormat {\n\tconst key = `${language}|${String(isZero)}`;\n\tconst cached = formatters.get(key);\n\tif (cached) return cached;\n\n\t// All-zero units format to an empty string unless the seconds are forced\n\tconst options = { secondsDisplay: isZero ? 'always' : 'auto', style: 'long' } as const;\n\tlet formatter: Intl.DurationFormat;\n\n\ttry {\n\t\tformatter = new Intl.DurationFormat(language || undefined, options);\n\t} catch {\n\t\tformatter = new Intl.DurationFormat(undefined, options);\n\t}\n\tformatters.set(key, formatter);\n\n\treturn formatter;\n}\n\nexport function spokenDuration(seconds: number, language = ''): string {\n\tif (!('DurationFormat' in Intl)) return formatClock(seconds);\n\n\t// Truncated as the clock is, so every unit carries one sign; mixed signs throw\n\tconst total = Math.trunc(seconds);\n\n\treturn formatterFor(language, total === 0).format({\n\t\thours: Math.trunc(total / 3600),\n\t\tminutes: Math.trunc(total / 60) % 60,\n\t\tseconds: total % 60,\n\t});\n}\n"],"mappings":";;;AAEA,MAAM,6BAAa,IAAI,IAAiC;AAExD,SAAS,aAAa,UAAkB,QAAsC;CAC7E,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,MAAM;CACxC,MAAM,SAAS,WAAW,IAAI,GAAG;CACjC,IAAI,QAAQ,OAAO;CAGnB,MAAM,UAAU;EAAE,gBAAgB,SAAS,WAAW;EAAQ,OAAO;CAAO;CAC5E,IAAI;CAEJ,IAAI;EACH,YAAY,IAAI,KAAK,eAAe,YAAY,QAAW,OAAO;CACnE,QAAQ;EACP,YAAY,IAAI,KAAK,eAAe,QAAW,OAAO;CACvD;CACA,WAAW,IAAI,KAAK,SAAS;CAE7B,OAAO;AACR;AAEA,SAAgB,eAAe,SAAiB,WAAW,IAAY;CACtE,IAAI,EAAE,oBAAoB,OAAO,OAAO,YAAY,OAAO;CAG3D,MAAM,QAAQ,KAAK,MAAM,OAAO;CAEhC,OAAO,aAAa,UAAU,UAAU,CAAC,CAAC,CAAC,OAAO;EACjD,OAAO,KAAK,MAAM,QAAQ,IAAI;EAC9B,SAAS,KAAK,MAAM,QAAQ,EAAE,IAAI;EAClC,SAAS,QAAQ;CAClB,CAAC;AACF"}
|
package/dist/styles/button.css
CHANGED
|
@@ -85,7 +85,8 @@
|
|
|
85
85
|
font: inherit;
|
|
86
86
|
color: var(--_sonic-ink);
|
|
87
87
|
cursor: pointer;
|
|
88
|
-
user-select: none;
|
|
88
|
+
-webkit-user-select: none;
|
|
89
|
+
user-select: none;
|
|
89
90
|
background: var(--_sonic-well-floor);
|
|
90
91
|
border: 0;
|
|
91
92
|
border-radius: var(--_sonic-button-corner);
|
|
@@ -112,11 +113,13 @@
|
|
|
112
113
|
);
|
|
113
114
|
|
|
114
115
|
color: color-mix(in oklab, var(--_sonic-lit) 55%, var(--_sonic-ink));
|
|
116
|
+
}
|
|
115
117
|
|
|
116
118
|
@media (forced-colors: active) {
|
|
119
|
+
:where([armed]) > .sonic-button:not(:disabled, [aria-disabled='true']) {
|
|
117
120
|
--_sonic-keycap-glow: transparent;
|
|
118
|
-
}
|
|
119
121
|
}
|
|
122
|
+
}
|
|
120
123
|
|
|
121
124
|
/* Before the latched rule too; a button with an LED blinks the LED and keeps its legend */
|
|
122
125
|
:where([busy]) > .sonic-button:not(:disabled, [aria-disabled='true'], :has(.sonic-led)) {
|
|
@@ -153,21 +156,28 @@
|
|
|
153
156
|
)
|
|
154
157
|
)
|
|
155
158
|
);
|
|
159
|
+
}
|
|
156
160
|
|
|
157
|
-
|
|
161
|
+
.sonic-button:is([aria-pressed='true'],[aria-expanded='true'],:where([momentary]:state(pressed)) > *) .sonic-button-cap > [data-sonic-when='released'] {
|
|
158
162
|
display: none;
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
@media (forced-colors: active) {
|
|
166
|
+
|
|
167
|
+
.sonic-button:is(
|
|
168
|
+
[aria-pressed='true'],
|
|
169
|
+
[aria-expanded='true'],
|
|
170
|
+
:where([momentary]:state(pressed)) > *
|
|
171
|
+
) {
|
|
162
172
|
--_sonic-skirt: var(--_sonic-lit);
|
|
163
173
|
--_sonic-face: var(--_sonic-lit);
|
|
164
174
|
--_sonic-ink: HighlightText;
|
|
175
|
+
}
|
|
165
176
|
|
|
166
|
-
|
|
177
|
+
.sonic-button:is([aria-pressed='true'],[aria-expanded='true'],:where([momentary]:state(pressed)) > *):is(:disabled,[aria-disabled='true']) {
|
|
167
178
|
--_sonic-ink: ButtonFace;
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
|
-
}
|
|
171
181
|
|
|
172
182
|
.sonic-button:is(:active, [data-sonic-pressed], :where([momentary]:state(pressed)) > *):where(
|
|
173
183
|
:not(:disabled, [aria-disabled='true'])
|
|
@@ -232,11 +242,14 @@
|
|
|
232
242
|
--_sonic-blank-edge-off,
|
|
233
243
|
var(--_sonic-blank-edge-lit, color-mix(in oklab, currentcolor 35%, transparent))
|
|
234
244
|
);
|
|
245
|
+
}
|
|
235
246
|
|
|
236
247
|
@media (forced-colors: active) {
|
|
248
|
+
|
|
249
|
+
.sonic-button:not(:has(> .sonic-button-cap > :not(.sonic-led))) {
|
|
237
250
|
--_sonic-blank-edge: transparent;
|
|
238
|
-
}
|
|
239
251
|
}
|
|
252
|
+
}
|
|
240
253
|
|
|
241
254
|
.sonic-button-cap {
|
|
242
255
|
--_sonic-keycap-corner: max(0px, var(--_sonic-button-corner) - var(--_sonic-button-gap));
|
|
@@ -259,19 +272,20 @@
|
|
|
259
272
|
inset: var(--_sonic-button-gap);
|
|
260
273
|
gap: calc(var(--_sonic-button-size) * var(--_sonic-button-led-ratio) / 2);
|
|
261
274
|
place-content: center;
|
|
275
|
+
}
|
|
262
276
|
|
|
263
|
-
|
|
277
|
+
.sonic-button-cap > .sonic-led {
|
|
264
278
|
--_sonic-led-size: var(
|
|
265
279
|
--sonic-led-size,
|
|
266
280
|
calc(var(--_sonic-button-size) * var(--_sonic-button-led-ratio))
|
|
267
281
|
);
|
|
268
282
|
}
|
|
269
283
|
|
|
270
|
-
|
|
284
|
+
.sonic-button-cap > :not(.sonic-led) {
|
|
271
285
|
filter: var(--_sonic-engraving) var(--_sonic-button-legend-glow,);
|
|
272
286
|
}
|
|
273
287
|
|
|
274
|
-
|
|
288
|
+
.sonic-button-cap > :not(svg,.sonic-led) {
|
|
275
289
|
padding-inline: calc(var(--_sonic-button-size) * var(--_sonic-button-padding-ratio));
|
|
276
290
|
font-size: var(
|
|
277
291
|
--_sonic-button-font-own,
|
|
@@ -284,18 +298,23 @@
|
|
|
284
298
|
white-space: nowrap;
|
|
285
299
|
}
|
|
286
300
|
|
|
287
|
-
|
|
301
|
+
.sonic-button-cap > svg {
|
|
288
302
|
inline-size: auto;
|
|
289
303
|
block-size: calc(var(--_sonic-button-size) * var(--_sonic-button-icon-ratio));
|
|
290
304
|
aspect-ratio: auto 1;
|
|
291
|
-
mask-image: linear-gradient(
|
|
305
|
+
-webkit-mask-image: linear-gradient(
|
|
292
306
|
var(--_sonic-light-fall),
|
|
293
307
|
#000 15%,
|
|
294
308
|
rgb(0 0 0 / calc(1 - 0.4 * var(--_sonic-relief)))
|
|
295
309
|
);
|
|
296
|
-
|
|
310
|
+
mask-image: linear-gradient(
|
|
311
|
+
var(--_sonic-light-fall),
|
|
312
|
+
#000 15%,
|
|
313
|
+
rgb(0 0 0 / calc(1 - 0.4 * var(--_sonic-relief)))
|
|
314
|
+
);
|
|
315
|
+
-webkit-mask-repeat: no-repeat;
|
|
316
|
+
mask-repeat: no-repeat;
|
|
297
317
|
}
|
|
298
|
-
}
|
|
299
318
|
|
|
300
319
|
.sonic-button-cap:has(> :not(.sonic-led)) {
|
|
301
320
|
position: relative;
|
|
@@ -329,16 +348,24 @@
|
|
|
329
348
|
[busy] > .sonic-button:not(:disabled, [aria-disabled='true']) .sonic-led::after {
|
|
330
349
|
animation: sonic-button-busy 500ms ease-in-out var(--sonic-button-busy-delay, 0s) infinite
|
|
331
350
|
alternate;
|
|
351
|
+
}
|
|
332
352
|
|
|
333
353
|
@media (prefers-reduced-motion: reduce) {
|
|
354
|
+
|
|
355
|
+
[busy]
|
|
356
|
+
> .sonic-button:not(:disabled, [aria-disabled='true'], :has(.sonic-led))
|
|
357
|
+
> .sonic-button-cap
|
|
358
|
+
> *,
|
|
359
|
+
[busy] > .sonic-button:not(:disabled, [aria-disabled='true']) .sonic-led::after {
|
|
334
360
|
animation: none;
|
|
335
|
-
}
|
|
336
361
|
}
|
|
362
|
+
}
|
|
337
363
|
|
|
338
364
|
@media (forced-colors: active) {
|
|
339
365
|
.sonic-button-cap > :not(.sonic-led) {
|
|
340
366
|
filter: none;
|
|
341
|
-
mask: none;
|
|
367
|
+
-webkit-mask: none;
|
|
368
|
+
mask: none;
|
|
342
369
|
}
|
|
343
370
|
}
|
|
344
371
|
}
|
package/dist/styles/controls.css
CHANGED
package/dist/styles/dial.css
CHANGED
|
@@ -83,7 +83,8 @@
|
|
|
83
83
|
block-size: var(--_sonic-dial-size);
|
|
84
84
|
touch-action: var(--sonic-touch-action, pan-x);
|
|
85
85
|
cursor: ns-resize;
|
|
86
|
-
user-select: none;
|
|
86
|
+
-webkit-user-select: none;
|
|
87
|
+
user-select: none;
|
|
87
88
|
border-radius: 50%;
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -130,7 +131,7 @@
|
|
|
130
131
|
transparent 0 var(--_sonic-dial-notch-pitch)
|
|
131
132
|
);
|
|
132
133
|
border-radius: 50%;
|
|
133
|
-
mask:
|
|
134
|
+
-webkit-mask:
|
|
134
135
|
radial-gradient(
|
|
135
136
|
closest-side,
|
|
136
137
|
transparent calc(100% - var(--_sonic-dial-notch-band) * 0.8),
|
|
@@ -142,14 +143,28 @@
|
|
|
142
143
|
#000 calc(var(--_sonic-dial-sweep) + 2 * var(--_sonic-dial-notch-width)),
|
|
143
144
|
transparent 0
|
|
144
145
|
);
|
|
145
|
-
|
|
146
|
+
mask:
|
|
147
|
+
radial-gradient(
|
|
148
|
+
closest-side,
|
|
149
|
+
transparent calc(100% - var(--_sonic-dial-notch-band) * 0.8),
|
|
150
|
+
#000 0 calc(100% - var(--_sonic-dial-notch-band) * 0.25),
|
|
151
|
+
transparent 0
|
|
152
|
+
),
|
|
153
|
+
conic-gradient(
|
|
154
|
+
from calc(var(--_sonic-dial-start) - var(--_sonic-dial-notch-width)),
|
|
155
|
+
#000 calc(var(--_sonic-dial-sweep) + 2 * var(--_sonic-dial-notch-width)),
|
|
156
|
+
transparent 0
|
|
157
|
+
);
|
|
158
|
+
-webkit-mask-composite: source-in, xor;
|
|
159
|
+
mask-composite: intersect;
|
|
146
160
|
}
|
|
147
161
|
|
|
148
162
|
.sonic-dial-scale {
|
|
149
163
|
font-size: calc(var(--_sonic-dial-size) * var(--_sonic-dial-scale-font-ratio));
|
|
150
|
-
line-height:
|
|
164
|
+
line-height: 0.7em;
|
|
165
|
+
}
|
|
151
166
|
|
|
152
|
-
|
|
167
|
+
.sonic-dial-scale > * {
|
|
153
168
|
--_sonic-dial-scale-angle: calc(
|
|
154
169
|
var(--_sonic-dial-start) + var(--_sonic-scale-at, 0) * var(--_sonic-dial-sweep)
|
|
155
170
|
);
|
|
@@ -161,11 +176,11 @@
|
|
|
161
176
|
|
|
162
177
|
inset: calc(50% - var(--_sonic-dial-scale-cos) * var(--_sonic-dial-scale-radius)) auto auto
|
|
163
178
|
calc(50% + var(--_sonic-dial-scale-sin) * var(--_sonic-dial-scale-radius));
|
|
164
|
-
translate: calc(-50% + var(--_sonic-dial-scale-sin) * (50% + 0.
|
|
165
|
-
calc(-50% - var(--_sonic-dial-scale-cos) * (50% + 0.
|
|
179
|
+
translate: calc(-50% + var(--_sonic-dial-scale-sin) * (50% + 0.105em))
|
|
180
|
+
calc(-50% - var(--_sonic-dial-scale-cos) * (50% + 0.105em));
|
|
166
181
|
}
|
|
167
182
|
|
|
168
|
-
|
|
183
|
+
.sonic-dial-scale > .sonic-scale-tick {
|
|
169
184
|
--_sonic-dial-tick-length: calc(var(--_sonic-dial-scale-band) * 0.4);
|
|
170
185
|
|
|
171
186
|
inline-size: var(--_sonic-unit);
|
|
@@ -174,7 +189,6 @@
|
|
|
174
189
|
translate: calc(-50% + var(--_sonic-dial-scale-sin) * var(--_sonic-dial-tick-length) / 2)
|
|
175
190
|
calc(-50% - var(--_sonic-dial-scale-cos) * var(--_sonic-dial-tick-length) / 2);
|
|
176
191
|
}
|
|
177
|
-
}
|
|
178
192
|
|
|
179
193
|
:is(.sonic-dial-ring, .sonic-dial-modulation) {
|
|
180
194
|
--_sonic-arc-width: var(--_sonic-dial-ring-width);
|
|
@@ -182,7 +196,8 @@
|
|
|
182
196
|
position: absolute;
|
|
183
197
|
inset: calc(var(--_sonic-dial-scale-band) + var(--_sonic-dial-notch-band));
|
|
184
198
|
border-radius: 50%;
|
|
185
|
-
mask: var(--_sonic-arc-mask);
|
|
199
|
+
-webkit-mask: var(--_sonic-arc-mask);
|
|
200
|
+
mask: var(--_sonic-arc-mask);
|
|
186
201
|
}
|
|
187
202
|
|
|
188
203
|
.sonic-dial-ring {
|
|
@@ -253,17 +268,18 @@
|
|
|
253
268
|
|
|
254
269
|
display: block;
|
|
255
270
|
background: none;
|
|
256
|
-
mask: none;
|
|
271
|
+
-webkit-mask: none;
|
|
272
|
+
mask: none;
|
|
273
|
+
}
|
|
257
274
|
|
|
258
|
-
|
|
259
|
-
&::after {
|
|
275
|
+
:is(:state(modulated) > .sonic-dial > .sonic-dial-modulation)::before,:is(:state(modulated) > .sonic-dial > .sonic-dial-modulation)::after {
|
|
260
276
|
position: absolute;
|
|
261
277
|
inset: 0;
|
|
262
278
|
content: '';
|
|
263
279
|
border-radius: 50%;
|
|
264
280
|
}
|
|
265
281
|
|
|
266
|
-
|
|
282
|
+
:is(:state(modulated) > .sonic-dial > .sonic-dial-modulation)::before {
|
|
267
283
|
background:
|
|
268
284
|
conic-gradient(
|
|
269
285
|
from var(--_sonic-dial-start),
|
|
@@ -279,10 +295,11 @@
|
|
|
279
295
|
calc(var(--_sonic-dial-modulation-to, 0) * var(--_sonic-dial-sweep)),
|
|
280
296
|
transparent 0
|
|
281
297
|
);
|
|
282
|
-
mask: var(--_sonic-arc-mask);
|
|
298
|
+
-webkit-mask: var(--_sonic-arc-mask);
|
|
299
|
+
mask: var(--_sonic-arc-mask);
|
|
283
300
|
}
|
|
284
301
|
|
|
285
|
-
|
|
302
|
+
:is(:state(modulated) > .sonic-dial > .sonic-dial-modulation)::after {
|
|
286
303
|
background: linear-gradient(
|
|
287
304
|
var(--_sonic-dial-modulation-tick),
|
|
288
305
|
var(--_sonic-dial-modulation-tick)
|
|
@@ -290,7 +307,6 @@
|
|
|
290
307
|
50% 0 / var(--_sonic-unit) var(--_sonic-dial-ring-width) no-repeat;
|
|
291
308
|
rotate: calc(var(--_sonic-dial-start) + var(--_sonic-dial-modulation-value-angle));
|
|
292
309
|
}
|
|
293
|
-
}
|
|
294
310
|
|
|
295
311
|
.sonic-dial-cap {
|
|
296
312
|
position: absolute;
|
|
@@ -302,27 +318,27 @@
|
|
|
302
318
|
var(--_sonic-drop-shade),
|
|
303
319
|
var(--_sonic-rim),
|
|
304
320
|
var(--_sonic-focus-shadow);
|
|
321
|
+
}
|
|
305
322
|
|
|
306
|
-
|
|
307
|
-
&::after {
|
|
323
|
+
.sonic-dial-cap::before,.sonic-dial-cap::after {
|
|
308
324
|
position: absolute;
|
|
309
325
|
content: '';
|
|
310
326
|
border-radius: 50%;
|
|
311
327
|
}
|
|
312
328
|
|
|
313
|
-
|
|
329
|
+
.sonic-dial-cap::before {
|
|
314
330
|
inset: 0;
|
|
315
331
|
background: repeating-conic-gradient(
|
|
316
|
-
|
|
317
|
-
|
|
332
|
+
color-mix(in srgb, var(--_sonic-shade) calc(30% * var(--_sonic-relief)), transparent) 0,
|
|
333
|
+
color-mix(in srgb, var(--_sonic-shine) calc(12% * var(--_sonic-relief)), transparent)
|
|
318
334
|
calc(var(--_sonic-dial-ridge-angle) / 2),
|
|
319
|
-
|
|
335
|
+
color-mix(in srgb, var(--_sonic-shade) calc(30% * var(--_sonic-relief)), transparent)
|
|
320
336
|
var(--_sonic-dial-ridge-angle)
|
|
321
337
|
);
|
|
322
338
|
rotate: var(--_sonic-dial-angle);
|
|
323
339
|
}
|
|
324
340
|
|
|
325
|
-
|
|
341
|
+
.sonic-dial-cap::after {
|
|
326
342
|
inset: 16%;
|
|
327
343
|
background:
|
|
328
344
|
conic-gradient(
|
|
@@ -330,20 +346,19 @@
|
|
|
330
346
|
calc(
|
|
331
347
|
var(--_sonic-dial-face-drift) * var(--_sonic-dial-angle) - var(--_sonic-light-tilt)
|
|
332
348
|
),
|
|
333
|
-
|
|
349
|
+
color-mix(in srgb, var(--_sonic-shine) calc(16% * var(--_sonic-relief)), transparent),
|
|
334
350
|
transparent 12%,
|
|
335
|
-
|
|
351
|
+
color-mix(in srgb, var(--_sonic-shade) calc(10% * var(--_sonic-relief)), transparent) 25%,
|
|
336
352
|
transparent 38%,
|
|
337
|
-
|
|
353
|
+
color-mix(in srgb, var(--_sonic-shine) calc(12% * var(--_sonic-relief)), transparent) 50%,
|
|
338
354
|
transparent 62%,
|
|
339
|
-
|
|
355
|
+
color-mix(in srgb, var(--_sonic-shade) calc(10% * var(--_sonic-relief)), transparent) 75%,
|
|
340
356
|
transparent 88%,
|
|
341
|
-
|
|
357
|
+
color-mix(in srgb, var(--_sonic-shine) calc(16% * var(--_sonic-relief)), transparent)
|
|
342
358
|
),
|
|
343
359
|
var(--_sonic-face);
|
|
344
360
|
box-shadow: var(--_sonic-face-shadow);
|
|
345
361
|
}
|
|
346
|
-
}
|
|
347
362
|
|
|
348
363
|
.sonic-dial-indicator {
|
|
349
364
|
position: absolute;
|
|
@@ -351,8 +366,9 @@
|
|
|
351
366
|
pointer-events: none;
|
|
352
367
|
border-radius: 50%;
|
|
353
368
|
rotate: calc(var(--_sonic-dial-start) + var(--_sonic-dial-angle));
|
|
369
|
+
}
|
|
354
370
|
|
|
355
|
-
|
|
371
|
+
.sonic-dial-indicator::before {
|
|
356
372
|
--_sonic-dial-indicator-width: calc(
|
|
357
373
|
var(--_sonic-dial-size) * var(--_sonic-dial-indicator-ratio)
|
|
358
374
|
);
|
|
@@ -369,7 +385,7 @@
|
|
|
369
385
|
background: var(--_sonic-ink);
|
|
370
386
|
border-radius: calc(var(--_sonic-dial-indicator-width) / 2);
|
|
371
387
|
box-shadow: inset 0 0 calc(0.75 * var(--_sonic-unit))
|
|
372
|
-
|
|
388
|
+
color-mix(in srgb, var(--_sonic-shade) calc(55% * var(--_sonic-relief)), transparent);
|
|
373
389
|
clip-path: shape(
|
|
374
390
|
from 0 100%,
|
|
375
391
|
line to calc(50% - var(--_sonic-dial-indicator-tip)) var(--_sonic-dial-indicator-tip),
|
|
@@ -380,7 +396,6 @@
|
|
|
380
396
|
);
|
|
381
397
|
translate: -50% 0;
|
|
382
398
|
}
|
|
383
|
-
}
|
|
384
399
|
|
|
385
400
|
:disabled > .sonic-dial > .sonic-dial-indicator::before {
|
|
386
401
|
background: var(--_sonic-ink-disabled);
|
package/dist/styles/envelope.css
CHANGED
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
inline-size: calc(var(--_sonic-envelope-size) * var(--_sonic-envelope-aspect-ratio));
|
|
41
41
|
block-size: var(--_sonic-envelope-size);
|
|
42
42
|
container-type: size;
|
|
43
|
-
user-select: none;
|
|
43
|
+
-webkit-user-select: none;
|
|
44
|
+
user-select: none;
|
|
44
45
|
isolation: isolate;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -55,23 +56,23 @@
|
|
|
55
56
|
clip-path: inset(calc(-1 * var(--_sonic-envelope-inset)));
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
.sonic-envelope-
|
|
59
|
+
.sonic-envelope-reticle {
|
|
59
60
|
--_sonic-point-size: calc(
|
|
60
61
|
2 * var(--_sonic-envelope-size) * var(--_sonic-envelope-handle-ratio)
|
|
61
62
|
);
|
|
62
|
-
--_sonic-
|
|
63
|
+
--_sonic-reticle-size: var(--_sonic-point-size);
|
|
63
64
|
|
|
64
65
|
position: absolute;
|
|
65
66
|
inset: 0;
|
|
66
67
|
overflow: clip;
|
|
67
68
|
pointer-events: none;
|
|
69
|
+
}
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
.sonic-envelope-reticle[data-sonic-part='curve'] {
|
|
70
72
|
--_sonic-point-size: calc(
|
|
71
73
|
2 * var(--_sonic-envelope-size) * var(--_sonic-envelope-curve-ratio)
|
|
72
74
|
);
|
|
73
75
|
}
|
|
74
|
-
}
|
|
75
76
|
|
|
76
77
|
.sonic-envelope-fill {
|
|
77
78
|
fill: color-mix(in oklab, var(--_sonic-lit) 18%, transparent);
|
|
@@ -93,7 +94,7 @@
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
:is(.sonic-envelope-handle, .sonic-envelope-curve),
|
|
96
|
-
.sonic-envelope-
|
|
97
|
+
.sonic-envelope-reticle::before {
|
|
97
98
|
position: absolute;
|
|
98
99
|
inset: auto auto
|
|
99
100
|
calc(
|