@xsynaptic/sonic-ui 0.5.0 → 0.6.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/README.md +3 -1
- package/dist/default/dat.js +5 -4
- package/dist/default/define/button.js +1 -1
- package/dist/default/define.js +2 -2
- package/dist/default/elements/button.js +6 -5
- package/dist/default/elements/dial.js +5 -1
- package/dist/default/elements/envelope.js +46 -18
- package/dist/default/elements/meter.js +12 -8
- package/dist/default/elements/number.js +1 -1
- package/dist/default/elements/radio-group.js +46 -47
- package/dist/default/elements/readout-claim.js +0 -29
- package/dist/default/elements/readout.js +1 -1
- package/dist/default/elements/scale.js +43 -0
- package/dist/default/elements/slider.js +16 -3
- package/dist/default/elements/sonic-element.js +17 -55
- package/dist/default/elements/switch.js +33 -39
- package/dist/default/elements/value-element.js +142 -187
- package/dist/default/elements/wave-element.js +5 -2
- package/dist/default/elements/waveform.js +35 -12
- package/dist/default/elements/wavestrip.js +59 -18
- package/dist/default/elements/xy.js +34 -19
- package/dist/default/index.js +2 -2
- package/dist/default/lib/adsr-shape.js +5 -0
- package/dist/default/lib/ballistics.js +2 -2
- package/dist/default/lib/canvas-surface.js +13 -2
- package/dist/default/lib/distribute.js +1 -1
- package/dist/default/lib/drag-step.js +4 -4
- package/dist/default/lib/frame-timeline.js +2 -1
- package/dist/default/lib/marker-band.js +54 -10
- package/dist/default/lib/marker-rider.js +10 -4
- package/dist/default/lib/math.js +6 -1
- package/dist/default/lib/mirror-children.js +64 -0
- package/dist/default/lib/owned-control.js +10 -0
- package/dist/default/lib/pointer-drag.js +8 -5
- package/dist/default/lib/resample-peaks.js +11 -1
- package/dist/default/lib/time-regions.js +4 -1
- package/dist/default/lib/write-attribute.js +1 -0
- package/dist/dev/dat.d.ts +2 -2
- package/dist/dev/dat.js +5 -4
- package/dist/dev/dat.js.map +1 -1
- package/dist/dev/define/button.js +1 -1
- package/dist/dev/define.d.ts +4 -4
- package/dist/dev/define.js +2 -2
- package/dist/dev/elements/button.js +6 -5
- package/dist/dev/elements/button.js.map +1 -1
- package/dist/dev/elements/dial.d.ts +1 -1
- package/dist/dev/elements/dial.js +5 -1
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/envelope.js +46 -18
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/meter.d.ts +1 -1
- package/dist/dev/elements/meter.js +12 -8
- package/dist/dev/elements/meter.js.map +1 -1
- package/dist/dev/elements/number.js +1 -1
- package/dist/dev/elements/number.js.map +1 -1
- package/dist/dev/elements/radio-group.js +46 -47
- package/dist/dev/elements/radio-group.js.map +1 -1
- package/dist/dev/elements/readout-claim.js +0 -29
- package/dist/dev/elements/readout-claim.js.map +1 -1
- package/dist/dev/elements/readout.js +1 -1
- package/dist/dev/elements/readout.js.map +1 -1
- package/dist/dev/elements/scale.js +44 -0
- package/dist/dev/elements/scale.js.map +1 -0
- package/dist/dev/elements/slider.d.ts +4 -1
- package/dist/dev/elements/slider.js +16 -3
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/sonic-element.d.ts +2 -8
- package/dist/dev/elements/sonic-element.js +18 -55
- package/dist/dev/elements/sonic-element.js.map +1 -1
- package/dist/dev/elements/switch.js +33 -39
- package/dist/dev/elements/switch.js.map +1 -1
- package/dist/dev/elements/value-element.d.ts +6 -8
- package/dist/dev/elements/value-element.js +142 -187
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/wave-element.d.ts +1 -0
- package/dist/dev/elements/wave-element.js +5 -2
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.d.ts +1 -1
- package/dist/dev/elements/waveform.js +35 -12
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +4 -0
- package/dist/dev/elements/wavestrip.js +59 -18
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.d.ts +3 -3
- package/dist/dev/elements/xy.js +34 -19
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/index.d.ts +2 -2
- package/dist/dev/index.js +2 -2
- package/dist/dev/lib/adsr-shape.js +5 -0
- package/dist/dev/lib/adsr-shape.js.map +1 -1
- package/dist/dev/lib/ballistics.js +2 -2
- package/dist/dev/lib/ballistics.js.map +1 -1
- package/dist/dev/lib/canvas-surface.d.ts +1 -0
- package/dist/dev/lib/canvas-surface.js +13 -2
- package/dist/dev/lib/canvas-surface.js.map +1 -1
- package/dist/dev/lib/distribute.js +1 -1
- package/dist/dev/lib/distribute.js.map +1 -1
- package/dist/dev/lib/drag-step.js +4 -4
- package/dist/dev/lib/drag-step.js.map +1 -1
- package/dist/dev/lib/frame-timeline.js +2 -1
- package/dist/dev/lib/frame-timeline.js.map +1 -1
- package/dist/dev/lib/marker-band.js +54 -10
- package/dist/dev/lib/marker-band.js.map +1 -1
- package/dist/dev/lib/marker-rider.js +10 -4
- package/dist/dev/lib/marker-rider.js.map +1 -1
- package/dist/dev/lib/math.js +6 -1
- package/dist/dev/lib/math.js.map +1 -1
- package/dist/dev/lib/mirror-children.js +80 -0
- package/dist/dev/lib/mirror-children.js.map +1 -0
- package/dist/dev/lib/owned-control.js +23 -0
- package/dist/dev/lib/owned-control.js.map +1 -0
- package/dist/dev/lib/pointer-drag.js +8 -5
- package/dist/dev/lib/pointer-drag.js.map +1 -1
- package/dist/dev/lib/resample-peaks.js +11 -1
- package/dist/dev/lib/resample-peaks.js.map +1 -1
- package/dist/dev/lib/time-regions.js +4 -1
- package/dist/dev/lib/time-regions.js.map +1 -1
- package/dist/dev/lib/write-attribute.js +1 -0
- package/dist/dev/lib/write-attribute.js.map +1 -1
- package/dist/skins/amber.css +8 -0
- package/dist/skins/flat.css +26 -0
- package/dist/skins/ivory.css +1 -0
- package/dist/skins/lime.css +2 -0
- package/dist/skins/slate.css +2 -0
- package/dist/styles/button.css +59 -10
- package/dist/styles/dial.css +24 -16
- package/dist/styles/envelope.css +58 -13
- package/dist/styles/led.css +20 -4
- package/dist/styles/material.css +143 -55
- package/dist/styles/meter.css +8 -4
- package/dist/styles/panel.css +7 -4
- package/dist/styles/segmented.css +27 -5
- package/dist/styles/slider.css +2 -1
- package/dist/styles/switch.css +65 -23
- package/dist/styles/waveform.css +28 -5
- package/dist/styles/wavestrip.css +23 -6
- package/dist/styles/xy.css +48 -27
- package/package.json +2 -5
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { appendOnce, checkChildren } from "./owned-control.js";
|
|
2
|
+
import { attachSlots } from "./render.js";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/mirror-children.ts
|
|
5
|
+
const checkedMirrors = /* @__PURE__ */ new WeakSet();
|
|
6
|
+
const hostSlots = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
const interactive = "a[href], button, input, select, textarea, [tabindex]";
|
|
8
|
+
function unmirrorable(original) {
|
|
9
|
+
if (!(original instanceof Element)) return void 0;
|
|
10
|
+
return [original, ...original.querySelectorAll("*")].find((element) => element.matches(interactive) || element.localName.includes("-"));
|
|
11
|
+
}
|
|
12
|
+
function checkMirrored(host, originals) {
|
|
13
|
+
if (checkedMirrors.has(host.constructor)) return;
|
|
14
|
+
const [found] = originals.flatMap((original) => unmirrorable(original) ?? []);
|
|
15
|
+
if (!found) return;
|
|
16
|
+
checkedMirrors.add(host.constructor);
|
|
17
|
+
console.warn(`<${host.localName}> copies its children into the control, so the <${found.localName}> inside it loses its listeners and state; keep mirrored children static`);
|
|
18
|
+
}
|
|
19
|
+
function childHolding(host, node) {
|
|
20
|
+
let current = node;
|
|
21
|
+
while (current && current.parentNode !== host) current = current.parentNode;
|
|
22
|
+
return current ?? void 0;
|
|
23
|
+
}
|
|
24
|
+
function isCopiedChange(host, record, { control, isCopied }) {
|
|
25
|
+
if (record.target === host) return record.removedNodes.length > 0 || [...record.addedNodes].some((node) => node !== control);
|
|
26
|
+
const child = childHolding(host, record.target);
|
|
27
|
+
if (child === void 0) return false;
|
|
28
|
+
return isCopied(child) || record.type === "attributes" && record.target === child;
|
|
29
|
+
}
|
|
30
|
+
function mirrorChildren(host, { control, copy, isCopied = () => true, isPassed = () => false, place }, signal) {
|
|
31
|
+
const slots = hostSlots.get(host) ?? attachSlots(host);
|
|
32
|
+
let copies = /* @__PURE__ */ new Map();
|
|
33
|
+
hostSlots.set(host, slots);
|
|
34
|
+
const mirror = (touched) => {
|
|
35
|
+
appendOnce(host, control);
|
|
36
|
+
const children = [...host.childNodes].filter((child) => child !== control);
|
|
37
|
+
const slotted = children.filter((child) => child instanceof Element || child instanceof Text);
|
|
38
|
+
const kept = copies;
|
|
39
|
+
const originals = children.filter((child) => isCopied(child));
|
|
40
|
+
checkMirrored(host, originals);
|
|
41
|
+
checkChildren(host, children.filter((child) => !isCopied(child) && !isPassed(child)));
|
|
42
|
+
copies = new Map(originals.map((original) => [original, touched && !touched.has(original) && kept.has(original) ? kept.get(original) : copy(original)]));
|
|
43
|
+
place([...copies.values()].filter((made) => made !== void 0));
|
|
44
|
+
slots.shown.assign(...slotted.filter((child) => !isCopied(child)), control);
|
|
45
|
+
slots.kept.assign(...slotted.filter((child) => isCopied(child)));
|
|
46
|
+
};
|
|
47
|
+
const watch = () => {
|
|
48
|
+
observer.disconnect();
|
|
49
|
+
observer.observe(host, { childList: true });
|
|
50
|
+
for (const child of host.childNodes) {
|
|
51
|
+
if (child === control) continue;
|
|
52
|
+
observer.observe(child, {
|
|
53
|
+
attributes: true,
|
|
54
|
+
characterData: true,
|
|
55
|
+
childList: true,
|
|
56
|
+
subtree: true
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const observer = new MutationObserver((records) => {
|
|
61
|
+
const changes = records.filter((record) => isCopiedChange(host, record, {
|
|
62
|
+
control,
|
|
63
|
+
isCopied
|
|
64
|
+
}));
|
|
65
|
+
if (changes.length === 0) return;
|
|
66
|
+
if (changes.some((record) => record.target === host)) {
|
|
67
|
+
mirror();
|
|
68
|
+
watch();
|
|
69
|
+
} else mirror(new Set(changes.map((record) => childHolding(host, record.target))));
|
|
70
|
+
});
|
|
71
|
+
mirror();
|
|
72
|
+
watch();
|
|
73
|
+
signal.addEventListener("abort", () => {
|
|
74
|
+
observer.disconnect();
|
|
75
|
+
}, { once: true });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { mirrorChildren };
|
|
80
|
+
//# sourceMappingURL=mirror-children.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror-children.js","names":[],"sources":["../../../src/lib/mirror-children.ts"],"sourcesContent":["import type { MirrorSlots } from '#lib/render.ts';\n\nimport { appendOnce, checkChildren } from '#lib/owned-control.ts';\nimport { attachSlots } from '#lib/render.ts';\n\n// eslint-disable-next-line unicorn/consistent-boolean-name -- the name bundlers and other kits use\ndeclare const __DEV__: boolean;\n\nconst checkedMirrors = new WeakSet<object>();\n\nconst hostSlots = new WeakMap<HTMLElement, MirrorSlots>();\n\nconst interactive = 'a[href], button, input, select, textarea, [tabindex]';\n\ninterface Mirror {\n\tcontrol: Element;\n\tcopy: (original: ChildNode) => Node | undefined;\n\tisCopied?: (child: Node) => boolean;\n\tisPassed?: (child: Node) => boolean;\n\tplace: (copies: Array<Node>) => void;\n}\n\nfunction unmirrorable(original: Node): Element | undefined {\n\tif (!(original instanceof Element)) return undefined;\n\n\treturn [original, ...original.querySelectorAll('*')].find(\n\t\t(element) => element.matches(interactive) || element.localName.includes('-'),\n\t);\n}\n\nfunction checkMirrored(host: HTMLElement, originals: Array<Node>): void {\n\tif (!__DEV__ || checkedMirrors.has(host.constructor)) return;\n\n\tconst [found] = originals.flatMap((original) => unmirrorable(original) ?? []);\n\tif (!found) return;\n\n\tcheckedMirrors.add(host.constructor);\n\tconsole.warn(\n\t\t`<${host.localName}> copies its children into the control, so the <${found.localName}> inside it loses its listeners and state; keep mirrored children static`,\n\t);\n}\n\nfunction childHolding(host: HTMLElement, node: Node): Node | undefined {\n\tlet current: Node | null = node;\n\n\twhile (current && current.parentNode !== host) current = current.parentNode;\n\n\treturn current ?? undefined;\n}\n\nfunction isCopiedChange(\n\thost: HTMLElement,\n\trecord: MutationRecord,\n\t{ control, isCopied }: Required<Pick<Mirror, 'control' | 'isCopied'>>,\n): boolean {\n\tif (record.target === host) {\n\t\treturn (\n\t\t\trecord.removedNodes.length > 0 || [...record.addedNodes].some((node) => node !== control)\n\t\t);\n\t}\n\n\tconst child = childHolding(host, record.target);\n\n\tif (child === undefined) return false;\n\n\treturn isCopied(child) || (record.type === 'attributes' && record.target === child);\n}\n\nexport function mirrorChildren(\n\thost: HTMLElement,\n\t{ control, copy, isCopied = () => true, isPassed = () => false, place }: Mirror,\n\tsignal: AbortSignal,\n): void {\n\tconst slots = hostSlots.get(host) ?? attachSlots(host);\n\tlet copies = new Map<ChildNode, Node | undefined>();\n\n\thostSlots.set(host, slots);\n\tconst mirror = (touched?: Set<Node | undefined>): void => {\n\t\tappendOnce(host, control);\n\n\t\tconst children = [...host.childNodes].filter((child) => child !== control);\n\t\tconst slotted = children.filter(\n\t\t\t(child): child is Element | Text => child instanceof Element || child instanceof Text,\n\t\t);\n\t\tconst kept = copies;\n\t\tconst originals = children.filter((child) => isCopied(child));\n\n\t\tif (__DEV__) {\n\t\t\tcheckMirrored(host, originals);\n\t\t\tcheckChildren(\n\t\t\t\thost,\n\t\t\t\tchildren.filter((child) => !isCopied(child) && !isPassed(child)),\n\t\t\t);\n\t\t}\n\t\tcopies = new Map(\n\t\t\toriginals.map((original) => [\n\t\t\t\toriginal,\n\t\t\t\ttouched && !touched.has(original) && kept.has(original)\n\t\t\t\t\t? kept.get(original)\n\t\t\t\t\t: copy(original),\n\t\t\t]),\n\t\t);\n\t\tplace([...copies.values()].filter((made) => made !== undefined));\n\t\tslots.shown.assign(...slotted.filter((child) => !isCopied(child)), control);\n\t\tslots.kept.assign(...slotted.filter((child) => isCopied(child)));\n\t};\n\t// Each child is watched, never the control, so a value write wakes nothing\n\tconst watch = (): void => {\n\t\tobserver.disconnect();\n\t\tobserver.observe(host, { childList: true });\n\t\tfor (const child of host.childNodes) {\n\t\t\tif (child === control) continue;\n\n\t\t\tobserver.observe(child, {\n\t\t\t\tattributes: true,\n\t\t\t\tcharacterData: true,\n\t\t\t\tchildList: true,\n\t\t\t\tsubtree: true,\n\t\t\t});\n\t\t}\n\t};\n\tconst observer = new MutationObserver((records) => {\n\t\tconst changes = records.filter((record) => isCopiedChange(host, record, { control, isCopied }));\n\t\tif (changes.length === 0) return;\n\n\t\tif (changes.some((record) => record.target === host)) {\n\t\t\tmirror();\n\t\t\twatch();\n\t\t} else mirror(new Set(changes.map((record) => childHolding(host, record.target))));\n\t});\n\n\tmirror();\n\twatch();\n\tsignal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\tobserver.disconnect();\n\t\t},\n\t\t{ once: true },\n\t);\n}\n"],"mappings":";;;;AAQA,MAAM,iCAAiB,IAAI,QAAgB;AAE3C,MAAM,4BAAY,IAAI,QAAkC;AAExD,MAAM,cAAc;AAUpB,SAAS,aAAa,UAAqC;CAC1D,IAAI,EAAE,oBAAoB,UAAU,OAAO;CAE3C,OAAO,CAAC,UAAU,GAAG,SAAS,iBAAiB,GAAG,CAAC,CAAC,CAAC,MACnD,YAAY,QAAQ,QAAQ,WAAW,KAAK,QAAQ,UAAU,SAAS,GAAG,CAC5E;AACD;AAEA,SAAS,cAAc,MAAmB,WAA8B;CACvE,IAAgB,eAAe,IAAI,KAAK,WAAW,GAAG;CAEtD,MAAM,CAAC,SAAS,UAAU,SAAS,aAAa,aAAa,QAAQ,KAAK,CAAC,CAAC;CAC5E,IAAI,CAAC,OAAO;CAEZ,eAAe,IAAI,KAAK,WAAW;CACnC,QAAQ,KACP,IAAI,KAAK,UAAU,kDAAkD,MAAM,UAAU,yEACtF;AACD;AAEA,SAAS,aAAa,MAAmB,MAA8B;CACtE,IAAI,UAAuB;CAE3B,OAAO,WAAW,QAAQ,eAAe,MAAM,UAAU,QAAQ;CAEjE,OAAO,WAAW;AACnB;AAEA,SAAS,eACR,MACA,QACA,EAAE,SAAS,YACD;CACV,IAAI,OAAO,WAAW,MACrB,OACC,OAAO,aAAa,SAAS,KAAK,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC,MAAM,SAAS,SAAS,OAAO;CAI1F,MAAM,QAAQ,aAAa,MAAM,OAAO,MAAM;CAE9C,IAAI,UAAU,QAAW,OAAO;CAEhC,OAAO,SAAS,KAAK,KAAM,OAAO,SAAS,gBAAgB,OAAO,WAAW;AAC9E;AAEA,SAAgB,eACf,MACA,EAAE,SAAS,MAAM,iBAAiB,MAAM,iBAAiB,OAAO,SAChE,QACO;CACP,MAAM,QAAQ,UAAU,IAAI,IAAI,KAAK,YAAY,IAAI;CACrD,IAAI,yBAAS,IAAI,IAAiC;CAElD,UAAU,IAAI,MAAM,KAAK;CACzB,MAAM,UAAU,YAA0C;EACzD,WAAW,MAAM,OAAO;EAExB,MAAM,WAAW,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,QAAQ,UAAU,UAAU,OAAO;EACzE,MAAM,UAAU,SAAS,QACvB,UAAmC,iBAAiB,WAAW,iBAAiB,IAClF;EACA,MAAM,OAAO;EACb,MAAM,YAAY,SAAS,QAAQ,UAAU,SAAS,KAAK,CAAC;EAG3D,cAAc,MAAM,SAAS;EAC7B,cACC,MACA,SAAS,QAAQ,UAAU,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,KAAK,CAAC,CAChE;EAED,SAAS,IAAI,IACZ,UAAU,KAAK,aAAa,CAC3B,UACA,WAAW,CAAC,QAAQ,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,IACnD,KAAK,IAAI,QAAQ,IACjB,KAAK,QAAQ,CACjB,CAAC,CACF;EACA,MAAM,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,QAAQ,SAAS,SAAS,MAAS,CAAC;EAC/D,MAAM,MAAM,OAAO,GAAG,QAAQ,QAAQ,UAAU,CAAC,SAAS,KAAK,CAAC,GAAG,OAAO;EAC1E,MAAM,KAAK,OAAO,GAAG,QAAQ,QAAQ,UAAU,SAAS,KAAK,CAAC,CAAC;CAChE;CAEA,MAAM,cAAoB;EACzB,SAAS,WAAW;EACpB,SAAS,QAAQ,MAAM,EAAE,WAAW,KAAK,CAAC;EAC1C,KAAK,MAAM,SAAS,KAAK,YAAY;GACpC,IAAI,UAAU,SAAS;GAEvB,SAAS,QAAQ,OAAO;IACvB,YAAY;IACZ,eAAe;IACf,WAAW;IACX,SAAS;GACV,CAAC;EACF;CACD;CACA,MAAM,WAAW,IAAI,kBAAkB,YAAY;EAClD,MAAM,UAAU,QAAQ,QAAQ,WAAW,eAAe,MAAM,QAAQ;GAAE;GAAS;EAAS,CAAC,CAAC;EAC9F,IAAI,QAAQ,WAAW,GAAG;EAE1B,IAAI,QAAQ,MAAM,WAAW,OAAO,WAAW,IAAI,GAAG;GACrD,OAAO;GACP,MAAM;EACP,OAAO,OAAO,IAAI,IAAI,QAAQ,KAAK,WAAW,aAAa,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;CAClF,CAAC;CAED,OAAO;CACP,MAAM;CACN,OAAO,iBACN,eACM;EACL,SAAS,WAAW;CACrB,GACA,EAAE,MAAM,KAAK,CACd;AACD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/lib/owned-control.ts
|
|
2
|
+
const checkedChildren = /* @__PURE__ */ new WeakSet();
|
|
3
|
+
function isContent(child) {
|
|
4
|
+
if (child instanceof Element) return true;
|
|
5
|
+
return child instanceof Text && child.data.trim() !== "";
|
|
6
|
+
}
|
|
7
|
+
function appendOnce(host, control) {
|
|
8
|
+
const [hook] = control.classList;
|
|
9
|
+
const stale = [...host.children].filter((child) => child !== control && hook !== void 0 && child.classList.contains(hook));
|
|
10
|
+
for (const child of stale) child.remove();
|
|
11
|
+
if (control.parentNode !== host) host.append(control);
|
|
12
|
+
}
|
|
13
|
+
function checkChildren(host, undocumented) {
|
|
14
|
+
if (checkedChildren.has(host.constructor)) return;
|
|
15
|
+
const found = undocumented.find((child) => isContent(child));
|
|
16
|
+
if (!found) return;
|
|
17
|
+
checkedChildren.add(host.constructor);
|
|
18
|
+
console.warn(`<${host.localName}> uses only the children it documents, so the ${found instanceof Element ? `<${found.localName}>` : "text"} inside it is unsupported`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { appendOnce, checkChildren };
|
|
23
|
+
//# sourceMappingURL=owned-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-control.js","names":[],"sources":["../../../src/lib/owned-control.ts"],"sourcesContent":["// eslint-disable-next-line unicorn/consistent-boolean-name -- the name bundlers and other kits use\ndeclare const __DEV__: boolean;\n\nconst checkedChildren = new WeakSet<object>();\n\nfunction isContent(child: Node): boolean {\n\tif (child instanceof Element) return true;\n\n\treturn child instanceof Text && child.data.trim() !== '';\n}\n\nexport function appendOnce(host: HTMLElement, control: Element): void {\n\tconst [hook] = control.classList;\n\tconst stale = [...host.children].filter(\n\t\t(child) => child !== control && hook !== undefined && child.classList.contains(hook),\n\t);\n\n\tfor (const child of stale) child.remove();\n\tif (control.parentNode !== host) host.append(control);\n}\n\nexport function checkChildren(host: HTMLElement, undocumented: Array<Node>): void {\n\tif (!__DEV__ || checkedChildren.has(host.constructor)) return;\n\n\tconst found = undocumented.find((child) => isContent(child));\n\tif (!found) return;\n\n\tcheckedChildren.add(host.constructor);\n\tconsole.warn(\n\t\t`<${host.localName}> uses only the children it documents, so the ${\n\t\t\tfound instanceof Element ? `<${found.localName}>` : 'text'\n\t\t} inside it is unsupported`,\n\t);\n}\n"],"mappings":";AAGA,MAAM,kCAAkB,IAAI,QAAgB;AAE5C,SAAS,UAAU,OAAsB;CACxC,IAAI,iBAAiB,SAAS,OAAO;CAErC,OAAO,iBAAiB,QAAQ,MAAM,KAAK,KAAK,MAAM;AACvD;AAEA,SAAgB,WAAW,MAAmB,SAAwB;CACrE,MAAM,CAAC,QAAQ,QAAQ;CACvB,MAAM,QAAQ,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,QAC/B,UAAU,UAAU,WAAW,SAAS,UAAa,MAAM,UAAU,SAAS,IAAI,CACpF;CAEA,KAAK,MAAM,SAAS,OAAO,MAAM,OAAO;CACxC,IAAI,QAAQ,eAAe,MAAM,KAAK,OAAO,OAAO;AACrD;AAEA,SAAgB,cAAc,MAAmB,cAAiC;CACjF,IAAgB,gBAAgB,IAAI,KAAK,WAAW,GAAG;CAEvD,MAAM,QAAQ,aAAa,MAAM,UAAU,UAAU,KAAK,CAAC;CAC3D,IAAI,CAAC,OAAO;CAEZ,gBAAgB,IAAI,KAAK,WAAW;CACpC,QAAQ,KACP,IAAI,KAAK,UAAU,gDAClB,iBAAiB,UAAU,IAAI,MAAM,UAAU,KAAK,OACpD,0BACF;AACD"}
|
|
@@ -5,8 +5,8 @@ function bindDrag(target, handlers, signal) {
|
|
|
5
5
|
if (!held) return;
|
|
6
6
|
const { drag } = held;
|
|
7
7
|
held = void 0;
|
|
8
|
-
handlers.toggle(false);
|
|
9
|
-
handlers.release(drag);
|
|
8
|
+
handlers.toggle?.(false);
|
|
9
|
+
handlers.release?.(drag);
|
|
10
10
|
};
|
|
11
11
|
const whileHeld = (type, handle) => {
|
|
12
12
|
target.addEventListener(type, (event) => {
|
|
@@ -23,15 +23,18 @@ function bindDrag(target, handlers, signal) {
|
|
|
23
23
|
pointerId: event.pointerId
|
|
24
24
|
};
|
|
25
25
|
target.setPointerCapture(event.pointerId);
|
|
26
|
-
handlers.toggle(true);
|
|
26
|
+
handlers.toggle?.(true);
|
|
27
27
|
}, { signal });
|
|
28
28
|
whileHeld("pointermove", handlers.move);
|
|
29
29
|
whileHeld("pointercancel", (drag) => {
|
|
30
|
-
handlers.cancel(drag);
|
|
30
|
+
handlers.cancel?.(drag);
|
|
31
31
|
end();
|
|
32
32
|
});
|
|
33
33
|
whileHeld("lostpointercapture", end);
|
|
34
|
-
whileHeld("pointerup",
|
|
34
|
+
whileHeld("pointerup", (drag, event) => {
|
|
35
|
+
end();
|
|
36
|
+
handlers.lift?.(drag, event);
|
|
37
|
+
});
|
|
35
38
|
signal.addEventListener("abort", end, { once: true });
|
|
36
39
|
return {
|
|
37
40
|
current: () => held?.drag,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointer-drag.js","names":[],"sources":["../../../src/lib/pointer-drag.ts"],"sourcesContent":["interface DragHandlers<Drag> {\n\tcancel
|
|
1
|
+
{"version":3,"file":"pointer-drag.js","names":[],"sources":["../../../src/lib/pointer-drag.ts"],"sourcesContent":["interface DragHandlers<Drag> {\n\tcancel?: (drag: Drag) => void;\n\tgrab: (event: PointerEvent) => Drag | undefined;\n\tlift?: (drag: Drag, event: PointerEvent) => void;\n\tmove: (drag: Drag, event: PointerEvent) => void;\n\trelease?: (drag: Drag) => void;\n\ttoggle?: (isDragging: boolean) => void;\n}\n\nexport interface PointerDrag<Drag> {\n\tcurrent: () => Drag | undefined;\n\tend: () => void;\n}\n\nexport function bindDrag<Drag>(\n\ttarget: HTMLElement,\n\thandlers: DragHandlers<Drag>,\n\tsignal: AbortSignal,\n): PointerDrag<Drag> {\n\tlet held: undefined | { drag: Drag; pointerId: number };\n\n\tconst end = (): void => {\n\t\tif (!held) return;\n\n\t\tconst { drag } = held;\n\n\t\theld = undefined;\n\t\thandlers.toggle?.(false);\n\t\thandlers.release?.(drag);\n\t};\n\tconst whileHeld = (\n\t\ttype: 'lostpointercapture' | 'pointercancel' | 'pointermove' | 'pointerup',\n\t\thandle: (drag: Drag, event: PointerEvent) => void,\n\t): void => {\n\t\ttarget.addEventListener(\n\t\t\ttype,\n\t\t\t(event) => {\n\t\t\t\tif (held?.pointerId === event.pointerId) handle(held.drag, event);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t};\n\n\ttarget.addEventListener(\n\t\t'pointerdown',\n\t\t(event) => {\n\t\t\tif (event.button !== 0 || (held && held.pointerId !== event.pointerId)) return;\n\n\t\t\tend();\n\n\t\t\tconst drag = handlers.grab(event);\n\t\t\tif (drag === undefined) return;\n\n\t\t\theld = { drag, pointerId: event.pointerId };\n\t\t\ttarget.setPointerCapture(event.pointerId);\n\t\t\thandlers.toggle?.(true);\n\t\t},\n\t\t{ signal },\n\t);\n\twhileHeld('pointermove', handlers.move);\n\twhileHeld('pointercancel', (drag) => {\n\t\thandlers.cancel?.(drag);\n\t\tend();\n\t});\n\twhileHeld('lostpointercapture', end);\n\twhileHeld('pointerup', (drag, event) => {\n\t\tend();\n\t\thandlers.lift?.(drag, event);\n\t});\n\tsignal.addEventListener('abort', end, { once: true });\n\n\treturn { current: () => held?.drag, end };\n}\n"],"mappings":";AAcA,SAAgB,SACf,QACA,UACA,QACoB;CACpB,IAAI;CAEJ,MAAM,YAAkB;EACvB,IAAI,CAAC,MAAM;EAEX,MAAM,EAAE,SAAS;EAEjB,OAAO;EACP,SAAS,SAAS,KAAK;EACvB,SAAS,UAAU,IAAI;CACxB;CACA,MAAM,aACL,MACA,WACU;EACV,OAAO,iBACN,OACC,UAAU;GACV,IAAI,MAAM,cAAc,MAAM,WAAW,OAAO,KAAK,MAAM,KAAK;EACjE,GACA,EAAE,OAAO,CACV;CACD;CAEA,OAAO,iBACN,gBACC,UAAU;EACV,IAAI,MAAM,WAAW,KAAM,QAAQ,KAAK,cAAc,MAAM,WAAY;EAExE,IAAI;EAEJ,MAAM,OAAO,SAAS,KAAK,KAAK;EAChC,IAAI,SAAS,QAAW;EAExB,OAAO;GAAE;GAAM,WAAW,MAAM;EAAU;EAC1C,OAAO,kBAAkB,MAAM,SAAS;EACxC,SAAS,SAAS,IAAI;CACvB,GACA,EAAE,OAAO,CACV;CACA,UAAU,eAAe,SAAS,IAAI;CACtC,UAAU,kBAAkB,SAAS;EACpC,SAAS,SAAS,IAAI;EACtB,IAAI;CACL,CAAC;CACD,UAAU,sBAAsB,GAAG;CACnC,UAAU,cAAc,MAAM,UAAU;EACvC,IAAI;EACJ,SAAS,OAAO,MAAM,KAAK;CAC5B,CAAC;CACD,OAAO,iBAAiB,SAAS,KAAK,EAAE,MAAM,KAAK,CAAC;CAEpD,OAAO;EAAE,eAAe,MAAM;EAAM;CAAI;AACzC"}
|
|
@@ -11,7 +11,17 @@ function downsample(peaks, count) {
|
|
|
11
11
|
for (let source = start; source < end; source += 1) total += peaks[source] ?? 0;
|
|
12
12
|
resampled.push(total / (end - start));
|
|
13
13
|
}
|
|
14
|
-
return resampled;
|
|
14
|
+
return rescale(resampled, peakOf(peaks));
|
|
15
|
+
}
|
|
16
|
+
function peakOf(peaks) {
|
|
17
|
+
let loudest = 0;
|
|
18
|
+
for (const peak of peaks) loudest = Math.max(loudest, peak);
|
|
19
|
+
return loudest;
|
|
20
|
+
}
|
|
21
|
+
function rescale(bars, loudest) {
|
|
22
|
+
const tallest = peakOf(bars);
|
|
23
|
+
if (tallest <= 0) return bars;
|
|
24
|
+
return bars.map((bar) => bar * loudest / tallest);
|
|
15
25
|
}
|
|
16
26
|
function upsample(peaks, count) {
|
|
17
27
|
const resampled = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resample-peaks.js","names":[],"sources":["../../../src/lib/resample-peaks.ts"],"sourcesContent":["function bucketBounds(sourceLength: number, index: number, count: number): [number, number] {\n\tconst start = Math.floor((index * sourceLength) / count);\n\n\treturn [start, Math.max(start + 1, Math.floor(((index + 1) * sourceLength) / count))];\n}\n\nfunction downsample(peaks:
|
|
1
|
+
{"version":3,"file":"resample-peaks.js","names":[],"sources":["../../../src/lib/resample-peaks.ts"],"sourcesContent":["function bucketBounds(sourceLength: number, index: number, count: number): [number, number] {\n\tconst start = Math.floor((index * sourceLength) / count);\n\n\treturn [start, Math.max(start + 1, Math.floor(((index + 1) * sourceLength) / count))];\n}\n\nfunction downsample(peaks: ReadonlyArray<number>, count: number): Array<number> {\n\tconst resampled: Array<number> = [];\n\n\tfor (let index = 0; index < count; index += 1) {\n\t\tconst [start, end] = bucketBounds(peaks.length, index, count);\n\t\tlet total = 0;\n\n\t\tfor (let source = start; source < end; source += 1) total += peaks[source] ?? 0;\n\t\tresampled.push(total / (end - start));\n\t}\n\n\treturn rescale(resampled, peakOf(peaks));\n}\n\nfunction peakOf(peaks: ReadonlyArray<number>): number {\n\tlet loudest = 0;\n\n\tfor (const peak of peaks) loudest = Math.max(loudest, peak);\n\n\treturn loudest;\n}\n\nfunction rescale(bars: Array<number>, loudest: number): Array<number> {\n\tconst tallest = peakOf(bars);\n\tif (tallest <= 0) return bars;\n\n\treturn bars.map((bar) => (bar * loudest) / tallest);\n}\n\nfunction upsample(peaks: ArrayLike<number>, count: number): Array<number> {\n\tconst resampled: Array<number> = [];\n\tconst last = peaks.length - 1;\n\n\tfor (let index = 0; index < count; index += 1) {\n\t\tconst sourceIndex = count === 1 ? 0 : (index * last) / (count - 1);\n\t\tconst before = Math.floor(sourceIndex);\n\t\tconst weight = sourceIndex - before;\n\n\t\tresampled.push(\n\t\t\t(peaks[before] ?? 0) * (1 - weight) + (peaks[Math.min(last, before + 1)] ?? 0) * weight,\n\t\t);\n\t}\n\n\treturn resampled;\n}\n\nexport function resamplePeaks(peaks: ArrayLike<number>, count: number): Array<number> {\n\tif (count <= 0 || peaks.length === 0) return [];\n\n\tconst finite = Array.from(peaks, (peak) => (Number.isFinite(peak) ? peak : 0));\n\n\tif (count === finite.length) return finite;\n\tif (count > finite.length) return upsample(finite, count);\n\n\treturn downsample(finite, count);\n}\n"],"mappings":";AAAA,SAAS,aAAa,cAAsB,OAAe,OAAiC;CAC3F,MAAM,QAAQ,KAAK,MAAO,QAAQ,eAAgB,KAAK;CAEvD,OAAO,CAAC,OAAO,KAAK,IAAI,QAAQ,GAAG,KAAK,OAAQ,QAAQ,KAAK,eAAgB,KAAK,CAAC,CAAC;AACrF;AAEA,SAAS,WAAW,OAA8B,OAA8B;CAC/E,MAAM,YAA2B,CAAC;CAElC,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG;EAC9C,MAAM,CAAC,OAAO,OAAO,aAAa,MAAM,QAAQ,OAAO,KAAK;EAC5D,IAAI,QAAQ;EAEZ,KAAK,IAAI,SAAS,OAAO,SAAS,KAAK,UAAU,GAAG,SAAS,MAAM,WAAW;EAC9E,UAAU,KAAK,SAAS,MAAM,MAAM;CACrC;CAEA,OAAO,QAAQ,WAAW,OAAO,KAAK,CAAC;AACxC;AAEA,SAAS,OAAO,OAAsC;CACrD,IAAI,UAAU;CAEd,KAAK,MAAM,QAAQ,OAAO,UAAU,KAAK,IAAI,SAAS,IAAI;CAE1D,OAAO;AACR;AAEA,SAAS,QAAQ,MAAqB,SAAgC;CACrE,MAAM,UAAU,OAAO,IAAI;CAC3B,IAAI,WAAW,GAAG,OAAO;CAEzB,OAAO,KAAK,KAAK,QAAS,MAAM,UAAW,OAAO;AACnD;AAEA,SAAS,SAAS,OAA0B,OAA8B;CACzE,MAAM,YAA2B,CAAC;CAClC,MAAM,OAAO,MAAM,SAAS;CAE5B,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG;EAC9C,MAAM,cAAc,UAAU,IAAI,IAAK,QAAQ,QAAS,QAAQ;EAChE,MAAM,SAAS,KAAK,MAAM,WAAW;EACrC,MAAM,SAAS,cAAc;EAE7B,UAAU,MACR,MAAM,WAAW,MAAM,IAAI,WAAW,MAAM,KAAK,IAAI,MAAM,SAAS,CAAC,MAAM,KAAK,MAClF;CACD;CAEA,OAAO;AACR;AAEA,SAAgB,cAAc,OAA0B,OAA8B;CACrF,IAAI,SAAS,KAAK,MAAM,WAAW,GAAG,OAAO,CAAC;CAE9C,MAAM,SAAS,MAAM,KAAK,QAAQ,SAAU,OAAO,SAAS,IAAI,IAAI,OAAO,CAAE;CAE7E,IAAI,UAAU,OAAO,QAAQ,OAAO;CACpC,IAAI,QAAQ,OAAO,QAAQ,OAAO,SAAS,QAAQ,KAAK;CAExD,OAAO,WAAW,QAAQ,KAAK;AAChC"}
|
|
@@ -3,7 +3,10 @@ function readRegions(regions) {
|
|
|
3
3
|
if ("start" in regions) return Array.from({ length: regions.length }, (_entry, index) => [regions.start(index), regions.end(index)]);
|
|
4
4
|
return [...regions].map(([start, end]) => [start, end]);
|
|
5
5
|
}
|
|
6
|
+
function sortedRegions(regions) {
|
|
7
|
+
return regions ? readRegions(regions).toSorted((first, second) => first[0] - second[0]) : [];
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
//#endregion
|
|
8
|
-
export { readRegions };
|
|
11
|
+
export { readRegions, sortedRegions };
|
|
9
12
|
//# sourceMappingURL=time-regions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-regions.js","names":[],"sources":["../../../src/lib/time-regions.ts"],"sourcesContent":["export type TimeRegions = Iterable<readonly [number, number]> | TimeRanges;\n\nexport function readRegions(regions: TimeRegions): Array<[number, number]> {\n\tif ('start' in regions) {\n\t\treturn Array.from({ length: regions.length }, (_entry, index) => [\n\t\t\tregions.start(index),\n\t\t\tregions.end(index),\n\t\t]);\n\t}\n\n\treturn [...regions].map(([start, end]) => [start, end]);\n}\n"],"mappings":";AAEA,SAAgB,YAAY,SAA+C;CAC1E,IAAI,WAAW,SACd,OAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,CAChE,QAAQ,MAAM,KAAK,GACnB,QAAQ,IAAI,KAAK,CAClB,CAAC;CAGF,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,OAAO,GAAG,CAAC;AACvD"}
|
|
1
|
+
{"version":3,"file":"time-regions.js","names":[],"sources":["../../../src/lib/time-regions.ts"],"sourcesContent":["export type TimeRegions = Iterable<readonly [number, number]> | TimeRanges;\n\nexport function readRegions(regions: TimeRegions): Array<[number, number]> {\n\tif ('start' in regions) {\n\t\treturn Array.from({ length: regions.length }, (_entry, index) => [\n\t\t\tregions.start(index),\n\t\t\tregions.end(index),\n\t\t]);\n\t}\n\n\treturn [...regions].map(([start, end]) => [start, end]);\n}\n\nexport function sortedRegions(regions: TimeRegions | undefined): Array<[number, number]> {\n\treturn regions ? readRegions(regions).toSorted((first, second) => first[0] - second[0]) : [];\n}\n"],"mappings":";AAEA,SAAgB,YAAY,SAA+C;CAC1E,IAAI,WAAW,SACd,OAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,CAChE,QAAQ,MAAM,KAAK,GACnB,QAAQ,IAAI,KAAK,CAClB,CAAC;CAGF,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,OAAO,GAAG,CAAC;AACvD;AAEA,SAAgB,cAAc,SAA2D;CACxF,OAAO,UAAU,YAAY,OAAO,CAAC,CAAC,UAAU,OAAO,WAAW,MAAM,KAAK,OAAO,EAAE,IAAI,CAAC;AAC5F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-attribute.js","names":[],"sources":["../../../src/lib/write-attribute.ts"],"sourcesContent":["export function writeAttribute(element: Element, name: string, value: string | undefined): void {\n\tif (value === undefined) {\n\t\telement.removeAttribute(name);\n\t\treturn;\n\t}\n\n\telement.setAttribute(name, value);\n}\n"],"mappings":";AAAA,SAAgB,eAAe,SAAkB,MAAc,OAAiC;CAC/F,IAAI,UAAU,QAAW;EACxB,QAAQ,gBAAgB,IAAI;EAC5B;CACD;
|
|
1
|
+
{"version":3,"file":"write-attribute.js","names":[],"sources":["../../../src/lib/write-attribute.ts"],"sourcesContent":["export function writeAttribute(element: Element, name: string, value: string | undefined): void {\n\tif (value === undefined) {\n\t\telement.removeAttribute(name);\n\t\treturn;\n\t}\n\tif (element.getAttribute(name) === value) return;\n\n\telement.setAttribute(name, value);\n}\n"],"mappings":";AAAA,SAAgB,eAAe,SAAkB,MAAc,OAAiC;CAC/F,IAAI,UAAU,QAAW;EACxB,QAAQ,gBAAgB,IAAI;EAC5B;CACD;CACA,IAAI,QAAQ,aAAa,IAAI,MAAM,OAAO;CAE1C,QAAQ,aAAa,MAAM,KAAK;AACjC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@layer sonic {
|
|
2
|
+
.sonic-skin-flat {
|
|
3
|
+
--sonic-relief: 0;
|
|
4
|
+
--sonic-lit: oklch(58% 0.19 255deg);
|
|
5
|
+
--sonic-unlit: oklch(84% 0.006 255deg);
|
|
6
|
+
--sonic-cap: oklch(93% 0.004 255deg);
|
|
7
|
+
--sonic-cap-hover: oklch(97% 0.004 255deg);
|
|
8
|
+
--sonic-cap-edge: oklch(72% 0.01 255deg);
|
|
9
|
+
--sonic-well: var(--sonic-unlit);
|
|
10
|
+
--sonic-well-lit: var(--sonic-lit);
|
|
11
|
+
--sonic-bezel: oklch(96% 0.003 255deg);
|
|
12
|
+
--sonic-lens: var(--sonic-unlit);
|
|
13
|
+
--sonic-led-lens-ratio: 0.8;
|
|
14
|
+
--sonic-waveform-edge: var(--sonic-lit);
|
|
15
|
+
--sonic-ink: oklch(27% 0.012 255deg);
|
|
16
|
+
--sonic-focus: oklch(52% 0.21 255deg);
|
|
17
|
+
--sonic-glass: oklch(97% 0.003 255deg);
|
|
18
|
+
--sonic-glass-text: oklch(27% 0.012 255deg);
|
|
19
|
+
--sonic-glass-edge: oklch(84% 0.006 255deg);
|
|
20
|
+
--sonic-glass-texture: 0;
|
|
21
|
+
--sonic-panel: oklch(98.5% 0.002 255deg);
|
|
22
|
+
--sonic-panel-text: oklch(27% 0.012 255deg);
|
|
23
|
+
--sonic-button-depth-ratio: 0;
|
|
24
|
+
--sonic-segmented-depth-ratio: 0;
|
|
25
|
+
}
|
|
26
|
+
}
|
package/dist/skins/ivory.css
CHANGED
package/dist/skins/lime.css
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
@layer sonic {
|
|
2
2
|
.sonic-skin-lime {
|
|
3
|
+
--sonic-relief: 1;
|
|
3
4
|
--sonic-lit: oklch(83.8% 0.205 118deg);
|
|
4
5
|
--sonic-unlit: oklch(28.6% 0.0203 237deg);
|
|
5
6
|
--sonic-cap: oklch(32.4% 0.0229 237deg);
|
|
6
7
|
--sonic-cap-hover: oklch(37.2% 0.025 237deg);
|
|
8
|
+
--sonic-ink: color-mix(in oklab, var(--sonic-cap) 30%, #fff);
|
|
7
9
|
--sonic-dial-ring-ratio: 0.05;
|
|
8
10
|
--sonic-dial-gap-ratio: 0.1;
|
|
9
11
|
}
|
package/dist/skins/slate.css
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
@layer sonic {
|
|
2
2
|
.sonic-skin-slate {
|
|
3
|
+
--sonic-relief: 1;
|
|
3
4
|
--sonic-lit: oklch(79.7% 0.134 212deg);
|
|
4
5
|
--sonic-unlit: oklch(27.9% 0.037 260deg);
|
|
5
6
|
--sonic-cap: oklch(37.2% 0.039 257deg);
|
|
6
7
|
--sonic-cap-hover: oklch(44.6% 0.037 257deg);
|
|
8
|
+
--sonic-ink: color-mix(in oklab, var(--sonic-cap) 30%, #fff);
|
|
7
9
|
--sonic-dial-ring-ratio: 0.12;
|
|
8
10
|
--sonic-dial-gap-ratio: 0.07;
|
|
9
11
|
}
|
package/dist/styles/button.css
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
--_sonic-button-icon-ratio: var(--sonic-button-icon-ratio, 0.5);
|
|
38
38
|
--_sonic-button-led-ratio: var(--sonic-button-led-ratio, 0.2);
|
|
39
39
|
--_sonic-button-led-icon-ratio: var(--sonic-button-led-icon-ratio, 0.35);
|
|
40
|
-
--_sonic-button-depth-ratio: var(--sonic-button-depth-ratio, 0.03);
|
|
40
|
+
--_sonic-button-depth-ratio: var(--sonic-button-depth-ratio, calc(0.03 * var(--_sonic-relief)));
|
|
41
41
|
--_sonic-button-press-scale: var(--sonic-button-press-scale, 0.985);
|
|
42
42
|
--_sonic-unit: calc(var(--_sonic-button-size) / 32);
|
|
43
43
|
--_sonic-button-corner: calc(var(--_sonic-button-size) * var(--_sonic-button-radius-ratio));
|
|
@@ -65,7 +65,11 @@
|
|
|
65
65
|
|
|
66
66
|
/* Before the latched rule, which must win unchanged */
|
|
67
67
|
:where([armed]) > .sonic-button:not(:disabled, [aria-disabled='true']) {
|
|
68
|
-
--_sonic-keycap-glow: color-mix(
|
|
68
|
+
--_sonic-keycap-glow: color-mix(
|
|
69
|
+
in oklab,
|
|
70
|
+
var(--_sonic-lit) calc(8% * var(--_sonic-relief)),
|
|
71
|
+
transparent
|
|
72
|
+
);
|
|
69
73
|
|
|
70
74
|
color: color-mix(in oklab, var(--_sonic-lit) 55%, var(--_sonic-ink));
|
|
71
75
|
|
|
@@ -87,13 +91,24 @@
|
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
.sonic-button:is([aria-pressed='true'], :where([momentary]:state(pressed)) > *) {
|
|
90
|
-
--_sonic-keycap-glow:
|
|
94
|
+
--_sonic-keycap-glow: var(--_sonic-keycap-lit-glow);
|
|
91
95
|
|
|
92
96
|
color: var(--_sonic-lit);
|
|
93
|
-
background:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
background: var(
|
|
98
|
+
--sonic-well-lit,
|
|
99
|
+
linear-gradient(
|
|
100
|
+
var(--_sonic-light-fall),
|
|
101
|
+
color-mix(
|
|
102
|
+
in oklab,
|
|
103
|
+
color-mix(in oklab, var(--_sonic-lit) 25%, #000) calc(100% * var(--_sonic-relief)),
|
|
104
|
+
transparent
|
|
105
|
+
),
|
|
106
|
+
color-mix(
|
|
107
|
+
in oklab,
|
|
108
|
+
color-mix(in oklab, var(--_sonic-lit) 60%, #000) calc(100% * var(--_sonic-relief)),
|
|
109
|
+
transparent
|
|
110
|
+
)
|
|
111
|
+
)
|
|
97
112
|
);
|
|
98
113
|
}
|
|
99
114
|
|
|
@@ -127,6 +142,37 @@
|
|
|
127
142
|
}
|
|
128
143
|
}
|
|
129
144
|
|
|
145
|
+
.sonic-button[aria-pressed='true']:not(:disabled, [aria-disabled='true']):focus-visible {
|
|
146
|
+
color: var(--sonic-lit-hover, var(--_sonic-lit));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@media (hover: hover) {
|
|
150
|
+
.sonic-button[aria-pressed='true']:not(:disabled, [aria-disabled='true']):hover {
|
|
151
|
+
color: var(--sonic-lit-hover, var(--_sonic-lit));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.sonic-button:not(:has(> .sonic-button-cap > :not(.sonic-led))) {
|
|
156
|
+
/* Invalid with both tokens unset, which is the one case that draws */
|
|
157
|
+
--_sonic-blank-edge-off: color-mix(
|
|
158
|
+
in oklab,
|
|
159
|
+
var(--sonic-cap-edge, var(--sonic-cap)) 0%,
|
|
160
|
+
transparent
|
|
161
|
+
);
|
|
162
|
+
--_sonic-blank-edge: var(
|
|
163
|
+
--_sonic-blank-edge-off,
|
|
164
|
+
color-mix(in oklab, currentcolor 35%, transparent)
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
&:is([aria-pressed='true'], :where([momentary]:state(pressed)) > *) {
|
|
168
|
+
--_sonic-blank-edge: var(--_sonic-blank-edge-off, currentcolor);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@media (forced-colors: active) {
|
|
172
|
+
--_sonic-blank-edge: transparent;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
130
176
|
.sonic-button-cap {
|
|
131
177
|
--_sonic-keycap-corner: max(0px, var(--_sonic-button-corner) - var(--_sonic-button-gap));
|
|
132
178
|
--_sonic-keycap-bevel: calc(var(--_sonic-button-size) * var(--_sonic-button-bevel-ratio));
|
|
@@ -150,7 +196,11 @@
|
|
|
150
196
|
inline-size: calc(var(--_sonic-button-size) * var(--_sonic-button-icon-ratio));
|
|
151
197
|
block-size: calc(var(--_sonic-button-size) * var(--_sonic-button-icon-ratio));
|
|
152
198
|
filter: var(--_sonic-engraving);
|
|
153
|
-
mask-image: linear-gradient(
|
|
199
|
+
mask-image: linear-gradient(
|
|
200
|
+
var(--_sonic-light-fall),
|
|
201
|
+
#000 15%,
|
|
202
|
+
rgb(0 0 0 / calc(1 - 0.4 * var(--_sonic-relief)))
|
|
203
|
+
);
|
|
154
204
|
mask-repeat: no-repeat;
|
|
155
205
|
}
|
|
156
206
|
}
|
|
@@ -163,8 +213,7 @@
|
|
|
163
213
|
.sonic-button:is([aria-pressed='true'], :where([momentary]:state(pressed)) > *)
|
|
164
214
|
.sonic-button-cap
|
|
165
215
|
> svg {
|
|
166
|
-
filter: var(--_sonic-engraving)
|
|
167
|
-
drop-shadow(0 0 var(--_sonic-unit) color-mix(in oklab, var(--_sonic-lit) 35%, transparent));
|
|
216
|
+
filter: var(--_sonic-engraving) var(--_sonic-legend-glow);
|
|
168
217
|
}
|
|
169
218
|
|
|
170
219
|
/* fallow-ignore-next-line code-duplication -- one pressed state across the cap's parts */
|
package/dist/styles/dial.css
CHANGED
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
|
|
146
146
|
.sonic-dial-scale {
|
|
147
147
|
font-size: calc(var(--_sonic-dial-size) * var(--_sonic-dial-scale-font-ratio));
|
|
148
|
+
line-height: 1cap;
|
|
148
149
|
|
|
149
150
|
& > * {
|
|
150
151
|
--_sonic-dial-scale-angle: calc(
|
|
@@ -158,8 +159,8 @@
|
|
|
158
159
|
|
|
159
160
|
inset: calc(50% - var(--_sonic-dial-scale-cos) * var(--_sonic-dial-scale-radius)) auto auto
|
|
160
161
|
calc(50% + var(--_sonic-dial-scale-sin) * var(--_sonic-dial-scale-radius));
|
|
161
|
-
translate: calc(-50% + var(--_sonic-dial-scale-sin) * 50%)
|
|
162
|
-
calc(-50% - var(--_sonic-dial-scale-cos) * 50%);
|
|
162
|
+
translate: calc(-50% + var(--_sonic-dial-scale-sin) * (50% + 0.15cap))
|
|
163
|
+
calc(-50% - var(--_sonic-dial-scale-cos) * (50% + 0.15cap));
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
& > .sonic-scale-tick {
|
|
@@ -310,9 +311,10 @@
|
|
|
310
311
|
&::before {
|
|
311
312
|
inset: 0;
|
|
312
313
|
background: repeating-conic-gradient(
|
|
313
|
-
rgb(0 0 0 /
|
|
314
|
-
rgb(255 255 255 / 12
|
|
315
|
-
|
|
314
|
+
rgb(0 0 0 / calc(0.3 * var(--_sonic-relief))) 0,
|
|
315
|
+
rgb(255 255 255 / calc(0.12 * var(--_sonic-relief)))
|
|
316
|
+
calc(var(--_sonic-dial-ridge-angle) / 2),
|
|
317
|
+
rgb(0 0 0 / calc(0.3 * var(--_sonic-relief))) var(--_sonic-dial-ridge-angle)
|
|
316
318
|
);
|
|
317
319
|
rotate: var(--_sonic-dial-angle);
|
|
318
320
|
}
|
|
@@ -325,15 +327,15 @@
|
|
|
325
327
|
calc(
|
|
326
328
|
var(--_sonic-dial-face-drift) * var(--_sonic-dial-angle) - var(--_sonic-light-tilt)
|
|
327
329
|
),
|
|
328
|
-
rgb(255 255 255 / 16
|
|
330
|
+
rgb(255 255 255 / calc(0.16 * var(--_sonic-relief))),
|
|
329
331
|
transparent 12%,
|
|
330
|
-
rgb(0 0 0 /
|
|
332
|
+
rgb(0 0 0 / calc(0.1 * var(--_sonic-relief))) 25%,
|
|
331
333
|
transparent 38%,
|
|
332
|
-
rgb(255 255 255 / 12
|
|
334
|
+
rgb(255 255 255 / calc(0.12 * var(--_sonic-relief))) 50%,
|
|
333
335
|
transparent 62%,
|
|
334
|
-
rgb(0 0 0 /
|
|
336
|
+
rgb(0 0 0 / calc(0.1 * var(--_sonic-relief))) 75%,
|
|
335
337
|
transparent 88%,
|
|
336
|
-
rgb(255 255 255 / 16
|
|
338
|
+
rgb(255 255 255 / calc(0.16 * var(--_sonic-relief)))
|
|
337
339
|
),
|
|
338
340
|
var(--_sonic-face);
|
|
339
341
|
box-shadow: var(--_sonic-face-shadow);
|
|
@@ -351,6 +353,9 @@
|
|
|
351
353
|
--_sonic-dial-indicator-width: calc(
|
|
352
354
|
var(--_sonic-dial-size) * var(--_sonic-dial-indicator-ratio)
|
|
353
355
|
);
|
|
356
|
+
--_sonic-dial-indicator-tip: calc(
|
|
357
|
+
var(--_sonic-dial-indicator-width) * (1 - var(--_sonic-dial-indicator-taper)) / 2
|
|
358
|
+
);
|
|
354
359
|
|
|
355
360
|
position: absolute;
|
|
356
361
|
inset-block-start: 6%;
|
|
@@ -360,12 +365,15 @@
|
|
|
360
365
|
content: '';
|
|
361
366
|
background: var(--_sonic-ink);
|
|
362
367
|
border-radius: calc(var(--_sonic-dial-indicator-width) / 2);
|
|
363
|
-
box-shadow: inset 0 0 calc(0.75 * var(--_sonic-unit))
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
368
|
+
box-shadow: inset 0 0 calc(0.75 * var(--_sonic-unit))
|
|
369
|
+
rgb(0 0 0 / calc(0.55 * var(--_sonic-relief)));
|
|
370
|
+
clip-path: shape(
|
|
371
|
+
from 0 100%,
|
|
372
|
+
line to calc(50% - var(--_sonic-dial-indicator-tip)) var(--_sonic-dial-indicator-tip),
|
|
373
|
+
arc to calc(50% + var(--_sonic-dial-indicator-tip)) var(--_sonic-dial-indicator-tip) of
|
|
374
|
+
var(--_sonic-dial-indicator-tip) cw,
|
|
375
|
+
line to 100% 100%,
|
|
376
|
+
close
|
|
369
377
|
);
|
|
370
378
|
translate: -50% 0;
|
|
371
379
|
}
|