@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.
Files changed (138) hide show
  1. package/README.md +3 -1
  2. package/dist/default/dat.js +5 -4
  3. package/dist/default/define/button.js +1 -1
  4. package/dist/default/define.js +2 -2
  5. package/dist/default/elements/button.js +6 -5
  6. package/dist/default/elements/dial.js +5 -1
  7. package/dist/default/elements/envelope.js +46 -18
  8. package/dist/default/elements/meter.js +12 -8
  9. package/dist/default/elements/number.js +1 -1
  10. package/dist/default/elements/radio-group.js +46 -47
  11. package/dist/default/elements/readout-claim.js +0 -29
  12. package/dist/default/elements/readout.js +1 -1
  13. package/dist/default/elements/scale.js +43 -0
  14. package/dist/default/elements/slider.js +16 -3
  15. package/dist/default/elements/sonic-element.js +17 -55
  16. package/dist/default/elements/switch.js +33 -39
  17. package/dist/default/elements/value-element.js +142 -187
  18. package/dist/default/elements/wave-element.js +5 -2
  19. package/dist/default/elements/waveform.js +35 -12
  20. package/dist/default/elements/wavestrip.js +59 -18
  21. package/dist/default/elements/xy.js +34 -19
  22. package/dist/default/index.js +2 -2
  23. package/dist/default/lib/adsr-shape.js +5 -0
  24. package/dist/default/lib/ballistics.js +2 -2
  25. package/dist/default/lib/canvas-surface.js +13 -2
  26. package/dist/default/lib/distribute.js +1 -1
  27. package/dist/default/lib/drag-step.js +4 -4
  28. package/dist/default/lib/frame-timeline.js +2 -1
  29. package/dist/default/lib/marker-band.js +54 -10
  30. package/dist/default/lib/marker-rider.js +10 -4
  31. package/dist/default/lib/math.js +6 -1
  32. package/dist/default/lib/mirror-children.js +64 -0
  33. package/dist/default/lib/owned-control.js +10 -0
  34. package/dist/default/lib/pointer-drag.js +8 -5
  35. package/dist/default/lib/resample-peaks.js +11 -1
  36. package/dist/default/lib/time-regions.js +4 -1
  37. package/dist/default/lib/write-attribute.js +1 -0
  38. package/dist/dev/dat.d.ts +2 -2
  39. package/dist/dev/dat.js +5 -4
  40. package/dist/dev/dat.js.map +1 -1
  41. package/dist/dev/define/button.js +1 -1
  42. package/dist/dev/define.d.ts +4 -4
  43. package/dist/dev/define.js +2 -2
  44. package/dist/dev/elements/button.js +6 -5
  45. package/dist/dev/elements/button.js.map +1 -1
  46. package/dist/dev/elements/dial.d.ts +1 -1
  47. package/dist/dev/elements/dial.js +5 -1
  48. package/dist/dev/elements/dial.js.map +1 -1
  49. package/dist/dev/elements/envelope.js +46 -18
  50. package/dist/dev/elements/envelope.js.map +1 -1
  51. package/dist/dev/elements/meter.d.ts +1 -1
  52. package/dist/dev/elements/meter.js +12 -8
  53. package/dist/dev/elements/meter.js.map +1 -1
  54. package/dist/dev/elements/number.js +1 -1
  55. package/dist/dev/elements/number.js.map +1 -1
  56. package/dist/dev/elements/radio-group.js +46 -47
  57. package/dist/dev/elements/radio-group.js.map +1 -1
  58. package/dist/dev/elements/readout-claim.js +0 -29
  59. package/dist/dev/elements/readout-claim.js.map +1 -1
  60. package/dist/dev/elements/readout.js +1 -1
  61. package/dist/dev/elements/readout.js.map +1 -1
  62. package/dist/dev/elements/scale.js +44 -0
  63. package/dist/dev/elements/scale.js.map +1 -0
  64. package/dist/dev/elements/slider.d.ts +4 -1
  65. package/dist/dev/elements/slider.js +16 -3
  66. package/dist/dev/elements/slider.js.map +1 -1
  67. package/dist/dev/elements/sonic-element.d.ts +2 -8
  68. package/dist/dev/elements/sonic-element.js +18 -55
  69. package/dist/dev/elements/sonic-element.js.map +1 -1
  70. package/dist/dev/elements/switch.js +33 -39
  71. package/dist/dev/elements/switch.js.map +1 -1
  72. package/dist/dev/elements/value-element.d.ts +6 -8
  73. package/dist/dev/elements/value-element.js +142 -187
  74. package/dist/dev/elements/value-element.js.map +1 -1
  75. package/dist/dev/elements/wave-element.d.ts +1 -0
  76. package/dist/dev/elements/wave-element.js +5 -2
  77. package/dist/dev/elements/wave-element.js.map +1 -1
  78. package/dist/dev/elements/waveform.d.ts +1 -1
  79. package/dist/dev/elements/waveform.js +35 -12
  80. package/dist/dev/elements/waveform.js.map +1 -1
  81. package/dist/dev/elements/wavestrip.d.ts +4 -0
  82. package/dist/dev/elements/wavestrip.js +59 -18
  83. package/dist/dev/elements/wavestrip.js.map +1 -1
  84. package/dist/dev/elements/xy.d.ts +3 -3
  85. package/dist/dev/elements/xy.js +34 -19
  86. package/dist/dev/elements/xy.js.map +1 -1
  87. package/dist/dev/index.d.ts +2 -2
  88. package/dist/dev/index.js +2 -2
  89. package/dist/dev/lib/adsr-shape.js +5 -0
  90. package/dist/dev/lib/adsr-shape.js.map +1 -1
  91. package/dist/dev/lib/ballistics.js +2 -2
  92. package/dist/dev/lib/ballistics.js.map +1 -1
  93. package/dist/dev/lib/canvas-surface.d.ts +1 -0
  94. package/dist/dev/lib/canvas-surface.js +13 -2
  95. package/dist/dev/lib/canvas-surface.js.map +1 -1
  96. package/dist/dev/lib/distribute.js +1 -1
  97. package/dist/dev/lib/distribute.js.map +1 -1
  98. package/dist/dev/lib/drag-step.js +4 -4
  99. package/dist/dev/lib/drag-step.js.map +1 -1
  100. package/dist/dev/lib/frame-timeline.js +2 -1
  101. package/dist/dev/lib/frame-timeline.js.map +1 -1
  102. package/dist/dev/lib/marker-band.js +54 -10
  103. package/dist/dev/lib/marker-band.js.map +1 -1
  104. package/dist/dev/lib/marker-rider.js +10 -4
  105. package/dist/dev/lib/marker-rider.js.map +1 -1
  106. package/dist/dev/lib/math.js +6 -1
  107. package/dist/dev/lib/math.js.map +1 -1
  108. package/dist/dev/lib/mirror-children.js +80 -0
  109. package/dist/dev/lib/mirror-children.js.map +1 -0
  110. package/dist/dev/lib/owned-control.js +23 -0
  111. package/dist/dev/lib/owned-control.js.map +1 -0
  112. package/dist/dev/lib/pointer-drag.js +8 -5
  113. package/dist/dev/lib/pointer-drag.js.map +1 -1
  114. package/dist/dev/lib/resample-peaks.js +11 -1
  115. package/dist/dev/lib/resample-peaks.js.map +1 -1
  116. package/dist/dev/lib/time-regions.js +4 -1
  117. package/dist/dev/lib/time-regions.js.map +1 -1
  118. package/dist/dev/lib/write-attribute.js +1 -0
  119. package/dist/dev/lib/write-attribute.js.map +1 -1
  120. package/dist/skins/amber.css +8 -0
  121. package/dist/skins/flat.css +26 -0
  122. package/dist/skins/ivory.css +1 -0
  123. package/dist/skins/lime.css +2 -0
  124. package/dist/skins/slate.css +2 -0
  125. package/dist/styles/button.css +59 -10
  126. package/dist/styles/dial.css +24 -16
  127. package/dist/styles/envelope.css +58 -13
  128. package/dist/styles/led.css +20 -4
  129. package/dist/styles/material.css +143 -55
  130. package/dist/styles/meter.css +8 -4
  131. package/dist/styles/panel.css +7 -4
  132. package/dist/styles/segmented.css +27 -5
  133. package/dist/styles/slider.css +2 -1
  134. package/dist/styles/switch.css +65 -23
  135. package/dist/styles/waveform.css +28 -5
  136. package/dist/styles/wavestrip.css +23 -6
  137. package/dist/styles/xy.css +48 -27
  138. 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":"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"}
@@ -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", end);
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: (drag: Drag) => void;\n\tgrab: (event: PointerEvent) => Drag | undefined;\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', end);\n\tsignal.addEventListener('abort', end, { once: true });\n\n\treturn { current: () => held?.drag, end };\n}\n"],"mappings":";AAaA,SAAgB,SACf,QACA,UACA,QACoB;CACpB,IAAI;CAEJ,MAAM,YAAkB;EACvB,IAAI,CAAC,MAAM;EAEX,MAAM,EAAE,SAAS;EAEjB,OAAO;EACP,SAAS,OAAO,KAAK;EACrB,SAAS,QAAQ,IAAI;CACtB;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,OAAO,IAAI;CACrB,GACA,EAAE,OAAO,CACV;CACA,UAAU,eAAe,SAAS,IAAI;CACtC,UAAU,kBAAkB,SAAS;EACpC,SAAS,OAAO,IAAI;EACpB,IAAI;CACL,CAAC;CACD,UAAU,sBAAsB,GAAG;CACnC,UAAU,aAAa,GAAG;CAC1B,OAAO,iBAAiB,SAAS,KAAK,EAAE,MAAM,KAAK,CAAC;CAEpD,OAAO;EAAE,eAAe,MAAM;EAAM;CAAI;AACzC"}
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: ArrayLike<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 resampled;\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,OAA0B,OAA8B;CAC3E,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;AACR;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"}
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"}
@@ -4,6 +4,7 @@ function writeAttribute(element, name, value) {
4
4
  element.removeAttribute(name);
5
5
  return;
6
6
  }
7
+ if (element.getAttribute(name) === value) return;
7
8
  element.setAttribute(name, value);
8
9
  }
9
10
 
@@ -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;CAEA,QAAQ,aAAa,MAAM,KAAK;AACjC"}
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,8 @@
1
+ @layer sonic {
2
+ .sonic-skin-amber {
3
+ --sonic-relief: 1;
4
+ --sonic-cap: oklch(37% 0.012 286deg);
5
+ --sonic-cap-hover: oklch(44.2% 0.015 286deg);
6
+ --sonic-ink: color-mix(in oklab, var(--sonic-cap) 30%, #fff);
7
+ }
8
+ }
@@ -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
+ }
@@ -1,5 +1,6 @@
1
1
  @layer sonic {
2
2
  .sonic-skin-ivory {
3
+ --sonic-relief: 1;
3
4
  --sonic-cap: oklch(85.5% 0.024 85deg);
4
5
  --sonic-cap-hover: oklch(90.5% 0.02 85deg);
5
6
  --sonic-ink: oklch(18.5% 0.012 60deg);
@@ -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
  }
@@ -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
  }
@@ -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(in oklab, var(--_sonic-lit) 8%, transparent);
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: color-mix(in oklab, var(--_sonic-lit) 22%, transparent);
94
+ --_sonic-keycap-glow: var(--_sonic-keycap-lit-glow);
91
95
 
92
96
  color: var(--_sonic-lit);
93
- background: linear-gradient(
94
- var(--_sonic-light-fall),
95
- color-mix(in oklab, var(--_sonic-lit) 25%, #000),
96
- color-mix(in oklab, var(--_sonic-lit) 60%, #000)
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(var(--_sonic-light-fall), #000 15%, rgb(0 0 0 / 60%));
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 */
@@ -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 / 30%) 0,
314
- rgb(255 255 255 / 12%) calc(var(--_sonic-dial-ridge-angle) / 2),
315
- rgb(0 0 0 / 30%) var(--_sonic-dial-ridge-angle)
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 / 10%) 25%,
332
+ rgb(0 0 0 / calc(0.1 * var(--_sonic-relief))) 25%,
331
333
  transparent 38%,
332
- rgb(255 255 255 / 12%) 50%,
334
+ rgb(255 255 255 / calc(0.12 * var(--_sonic-relief))) 50%,
333
335
  transparent 62%,
334
- rgb(0 0 0 / 10%) 75%,
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)) rgb(0 0 0 / 55%);
364
- clip-path: polygon(
365
- calc(50% * var(--_sonic-dial-indicator-taper)) 0,
366
- calc(100% - 50% * var(--_sonic-dial-indicator-taper)) 0,
367
- 100% 100%,
368
- 0 100%
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
  }