@xsynaptic/sonic-ui 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +0 -2
  2. package/dist/default/elements/dial.js +12 -3
  3. package/dist/default/elements/envelope.js +2 -2
  4. package/dist/default/elements/modulation.js +45 -0
  5. package/dist/default/elements/readout-claim.js +8 -3
  6. package/dist/default/elements/slider.js +15 -17
  7. package/dist/default/elements/value-element.js +89 -330
  8. package/dist/default/elements/value-gestures.js +301 -0
  9. package/dist/default/elements/waveform.js +5 -2
  10. package/dist/default/elements/wavestrip.js +5 -15
  11. package/dist/default/elements/xy.js +9 -20
  12. package/dist/default/lib/asked-value.js +21 -0
  13. package/dist/default/lib/canvas-surface.js +3 -0
  14. package/dist/default/lib/marker-rider.js +6 -3
  15. package/dist/default/lib/read-ms-property.js +10 -0
  16. package/dist/dev/elements/dial.js +12 -3
  17. package/dist/dev/elements/dial.js.map +1 -1
  18. package/dist/dev/elements/envelope.js +2 -2
  19. package/dist/dev/elements/envelope.js.map +1 -1
  20. package/dist/dev/elements/modulation.js +46 -0
  21. package/dist/dev/elements/modulation.js.map +1 -0
  22. package/dist/dev/elements/readout-claim.js +8 -3
  23. package/dist/dev/elements/readout-claim.js.map +1 -1
  24. package/dist/dev/elements/slider.d.ts +0 -1
  25. package/dist/dev/elements/slider.js +15 -17
  26. package/dist/dev/elements/slider.js.map +1 -1
  27. package/dist/dev/elements/value-element.d.ts +8 -13
  28. package/dist/dev/elements/value-element.js +89 -330
  29. package/dist/dev/elements/value-element.js.map +1 -1
  30. package/dist/dev/elements/value-gestures.d.ts +10 -0
  31. package/dist/dev/elements/value-gestures.js +302 -0
  32. package/dist/dev/elements/value-gestures.js.map +1 -0
  33. package/dist/dev/elements/waveform.js +5 -2
  34. package/dist/dev/elements/waveform.js.map +1 -1
  35. package/dist/dev/elements/wavestrip.d.ts +0 -1
  36. package/dist/dev/elements/wavestrip.js +5 -15
  37. package/dist/dev/elements/wavestrip.js.map +1 -1
  38. package/dist/dev/elements/xy.js +9 -20
  39. package/dist/dev/elements/xy.js.map +1 -1
  40. package/dist/dev/lib/asked-value.js +22 -0
  41. package/dist/dev/lib/asked-value.js.map +1 -0
  42. package/dist/dev/lib/canvas-surface.d.ts +1 -0
  43. package/dist/dev/lib/canvas-surface.js +3 -0
  44. package/dist/dev/lib/canvas-surface.js.map +1 -1
  45. package/dist/dev/lib/marker-rider.js +6 -3
  46. package/dist/dev/lib/marker-rider.js.map +1 -1
  47. package/dist/dev/lib/read-ms-property.js +11 -0
  48. package/dist/dev/lib/read-ms-property.js.map +1 -0
  49. package/dist/styles/material.css +18 -0
  50. package/dist/styles/waveform.css +10 -0
  51. package/dist/styles/wavestrip.css +4 -1
  52. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"envelope.js","names":[],"sources":["../../../src/elements/envelope.ts"],"sourcesContent":["import type { ValueLink } from '#elements/value-element.ts';\nimport type { AdsrCurves, AdsrProportions, AdsrShape } from '#lib/adsr-shape.ts';\nimport type { FieldAxis, FieldDragState, FieldMappings, FieldPoint } from '#lib/field.ts';\nimport type { PointerDrag } from '#lib/pointer-drag.ts';\n\nimport { ReadoutClaim } from '#elements/readout-claim.ts';\nimport { Readout } from '#elements/readout.ts';\nimport { SonicElement } from '#elements/sonic-element.ts';\nimport { linkValue, SonicValueElement } from '#elements/value-element.ts';\nimport { adsrPath, adsrShape, adsrStages, timeStages } from '#lib/adsr-shape.ts';\nimport { dragThresholdPx } from '#lib/drag-step.ts';\nimport { pointerMove, pointerPosition, startFieldDrag, stepFieldDrag } from '#lib/field.ts';\nimport { bindDrag } from '#lib/pointer-drag.ts';\nimport { requireChild, template } from '#lib/render.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\n// eslint-disable-next-line unicorn/consistent-boolean-name -- the name bundlers and other kits use\ndeclare const __DEV__: boolean;\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-envelope': SonicEnvelope;\n\t}\n}\n\ninterface Binding {\n\telement: SonicValueElement;\n\tlink: ValueLink;\n\tunwatch: () => void;\n}\n\ninterface Drive {\n\taxis: FieldAxis;\n\tbinding: Binding;\n}\n\ninterface HandleDrag {\n\tdrives: Array<Drive & { from: number }>;\n\tisFlipped: boolean;\n\tpart: HTMLElement;\n\tstate: FieldDragState;\n}\n\nconst curveStages = ['attack', 'decay', 'release'] as const;\n\nconst bindable = [...adsrStages, 'attack-curve', 'decay-curve', 'release-curve'] as const;\n\nconst bindableNames = new Set<string>(bindable);\n\nfunction flip<Point extends FieldPoint>(point: Point, isFlipped: boolean): Point {\n\treturn isFlipped ? { ...point, y: -point.y } : point;\n}\n\nfunction isParent(node: Node): node is Node & ParentNode {\n\treturn 'querySelector' in node;\n}\n\nconst emptyPath = { fill: '', floor: { from: 0, to: 0 }, stroke: '' };\n\nfunction stageParts<Stage extends string>(\n\tenvelope: Element,\n\thook: string,\n\tstages: ReadonlyArray<Stage>,\n): Map<Stage, HTMLDivElement> {\n\treturn new Map(\n\t\tstages.map((stage) => [\n\t\t\tstage,\n\t\t\trequireChild(envelope, `.${hook}[data-sonic-stage=\"${stage}\"]`, HTMLDivElement),\n\t\t]),\n\t);\n}\n\nconst renderEnvelope = template(\n\t/* HTML */ `\n\t\t<div class=\"sonic-envelope\" aria-hidden=\"true\">\n\t\t\t<div class=\"sonic-envelope-bracket\"></div>\n\t\t\t<svg class=\"sonic-envelope-graph\" preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\">\n\t\t\t\t<path class=\"sonic-envelope-fill\" />\n\t\t\t\t<rect class=\"sonic-envelope-fill sonic-envelope-floor\" y=\"1\" />\n\t\t\t\t<path class=\"sonic-envelope-line\" />\n\t\t\t</svg>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"delay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"attack\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"hold\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"decay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"release\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"attack\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"decay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"release\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-readout\" popover=\"manual\"><span></span></div>\n\t\t</div>\n\t`,\n\tHTMLDivElement,\n);\n\nexport class SonicEnvelope extends SonicElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicElement.observedAttributes,\n\t\t...bindable,\n\t\t'readout',\n\t];\n\n\tget attack(): string {\n\t\treturn this.getAttribute('attack') ?? '';\n\t}\n\n\tset attack(id: string | undefined) {\n\t\tthis.reflect('attack', id);\n\t}\n\n\tget attackCurve(): string {\n\t\treturn this.getAttribute('attack-curve') ?? '';\n\t}\n\n\tset attackCurve(id: string | undefined) {\n\t\tthis.reflect('attack-curve', id);\n\t}\n\n\tget decay(): string {\n\t\treturn this.getAttribute('decay') ?? '';\n\t}\n\n\tset decay(id: string | undefined) {\n\t\tthis.reflect('decay', id);\n\t}\n\n\tget decayCurve(): string {\n\t\treturn this.getAttribute('decay-curve') ?? '';\n\t}\n\n\tset decayCurve(id: string | undefined) {\n\t\tthis.reflect('decay-curve', id);\n\t}\n\n\tget delay(): string {\n\t\treturn this.getAttribute('delay') ?? '';\n\t}\n\n\tset delay(id: string | undefined) {\n\t\tthis.reflect('delay', id);\n\t}\n\n\tget hold(): string {\n\t\treturn this.getAttribute('hold') ?? '';\n\t}\n\n\tset hold(id: string | undefined) {\n\t\tthis.reflect('hold', id);\n\t}\n\n\tget readout(): boolean {\n\t\treturn this.hasAttribute('readout');\n\t}\n\n\tset readout(isOn: boolean) {\n\t\tthis.reflect('readout', isOn);\n\t}\n\n\tget release(): string {\n\t\treturn this.getAttribute('release') ?? '';\n\t}\n\n\tset release(id: string | undefined) {\n\t\tthis.reflect('release', id);\n\t}\n\n\tget releaseCurve(): string {\n\t\treturn this.getAttribute('release-curve') ?? '';\n\t}\n\n\tset releaseCurve(id: string | undefined) {\n\t\tthis.reflect('release-curve', id);\n\t}\n\n\tget sustain(): string {\n\t\treturn this.getAttribute('sustain') ?? '';\n\t}\n\n\tset sustain(id: string | undefined) {\n\t\tthis.reflect('sustain', id);\n\t}\n\n\treadonly #bindings = new Map<string, Binding>();\n\n\treadonly #envelope = renderEnvelope();\n\n\treadonly #bracket = requireChild(this.#envelope, '.sonic-envelope-bracket', HTMLDivElement);\n\n\treadonly #claim = new ReadoutClaim(() => {\n\t\tthis.#renderReadout();\n\t});\n\n\treadonly #curveHandles = stageParts(this.#envelope, 'sonic-envelope-curve', curveStages);\n\n\treadonly #fill = requireChild(this.#envelope, '.sonic-envelope-fill', SVGElement);\n\n\treadonly #floor = requireChild(this.#envelope, '.sonic-envelope-floor', SVGElement);\n\n\treadonly #graph = requireChild(this.#envelope, '.sonic-envelope-graph', SVGElement);\n\n\treadonly #handles = stageParts(this.#envelope, 'sonic-envelope-handle', timeStages);\n\n\t#held: HTMLElement | undefined;\n\n\t#isDriving = false;\n\n\treadonly #line = requireChild(this.#envelope, '.sonic-envelope-line', SVGElement);\n\n\t#pointerDrag: PointerDrag<HandleDrag> | undefined;\n\n\treadonly #readout = new Readout(\n\t\trequireChild(this.#envelope, '.sonic-envelope-readout', HTMLDivElement),\n\t);\n\n\t#shape: AdsrShape = adsrShape({});\n\n\t#signal: AbortSignal | undefined;\n\n\treadonly #waiting = new Set<unknown>();\n\n\treadonly #warned = new Set<string>();\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (!this.#signal) return;\n\t\tif (name === 'disabled') {\n\t\t\tthis.#pointerDrag?.end();\n\t\t\tthis.#draw();\n\t\t\treturn;\n\t\t}\n\t\tif (bindableNames.has(name)) this.#bind();\n\t\telse this.#renderReadout();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(...adsrStages, 'attackCurve', 'decayCurve', 'readout', 'releaseCurve');\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst envelope = this.#envelope;\n\n\t\tthis.#signal = signal;\n\t\tthis.keepControl(envelope, signal);\n\t\tthis.#bind();\n\t\tthis.checkStyles(envelope, 'envelope.css');\n\t\tthis.#bindPointer(envelope, signal);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#signal = undefined;\n\t\t\t\tthis.#unbind();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#bind(): void {\n\t\tthis.#pointerDrag?.end();\n\t\tthis.#unbind();\n\t\tfor (const name of bindable) {\n\t\t\tconst element = this.#resolve(name);\n\t\t\tif (!element) continue;\n\n\t\t\tconst link = linkValue(element);\n\t\t\tconst unwatch = link.watch(() => {\n\t\t\t\tif (!this.#isDriving) this.#draw();\n\t\t\t});\n\n\t\t\tthis.#bindings.set(name, { element, link, unwatch });\n\t\t}\n\t\tthis.#draw();\n\t}\n\n\t#bindPointer(envelope: HTMLElement, signal: AbortSignal): void {\n\t\tthis.#pointerDrag = bindDrag(\n\t\t\tenvelope,\n\t\t\t{\n\t\t\t\tcancel: (drag) => {\n\t\t\t\t\tfor (const { binding, from } of drag.drives) binding.link.input(from);\n\t\t\t\t},\n\t\t\t\tgrab: (event) => this.#grab(event),\n\t\t\t\tmove: (drag, event) => {\n\t\t\t\t\tthis.#moveDrag(drag, event);\n\t\t\t\t},\n\t\t\t\trelease: (drag) => {\n\t\t\t\t\tthis.#claim.press(false);\n\t\t\t\t\tfor (const { binding, from } of drag.drives) {\n\t\t\t\t\t\tif (binding.link.value() === from) continue;\n\n\t\t\t\t\t\tbinding.element.dispatchEvent(new Event('change', { bubbles: true }));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttoggle: (isDragging) => {\n\t\t\t\t\tthis.toggleState('dragging', isDragging);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t}\n\n\t#curveDrives(stage: string): Array<Drive> {\n\t\tconst binding = this.#bindings.get(`${stage}-curve`);\n\n\t\treturn binding ? [{ axis: 'y', binding }] : [];\n\t}\n\n\t#draw(): void {\n\t\tconst shape = this.#readShape();\n\t\tconst path = this.#bindings.size === 0 ? emptyPath : adsrPath(shape);\n\n\t\tthis.#shape = shape;\n\t\twriteAttribute(this.#line, 'd', path.stroke);\n\t\twriteAttribute(this.#fill, 'd', path.fill);\n\t\twriteAttribute(this.#floor, 'x', String(path.floor.from));\n\t\twriteAttribute(this.#floor, 'width', String(path.floor.to - path.floor.from));\n\t\tfor (const [stage, part] of this.#handles) {\n\t\t\tthis.#drawPoint(part, {\n\t\t\t\tat: shape.handles.find((point) => point.stage === stage),\n\t\t\t\tdrives: this.#drives(stage),\n\t\t\t});\n\t\t}\n\t\tfor (const [stage, part] of this.#curveHandles) {\n\t\t\tthis.#drawPoint(part, {\n\t\t\t\tat: shape.curveHandles.find((point) => point.stage === stage),\n\t\t\t\tdrives: this.#curveDrives(stage),\n\t\t\t});\n\t\t}\n\t\tthis.#drawBracket();\n\t\tthis.#renderReadout();\n\t}\n\n\t#drawBracket(): void {\n\t\tconst part = this.#held;\n\t\tif (!part) return;\n\n\t\tfor (const name of ['--_sonic-envelope-x', '--_sonic-envelope-y']) {\n\t\t\tthis.#bracket.style.setProperty(name, part.style.getPropertyValue(name));\n\t\t}\n\t\twriteAttribute(\n\t\t\tthis.#bracket,\n\t\t\t'data-sonic-part',\n\t\t\tpart.classList.contains('sonic-envelope-curve') ? 'curve' : undefined,\n\t\t);\n\t}\n\n\t#drawPoint(\n\t\tpart: HTMLDivElement,\n\t\tpoint: { at: FieldPoint | undefined; drives: Array<Drive> },\n\t): void {\n\t\tconst { at, drives } = point;\n\n\t\twriteAttribute(part, 'hidden', at ? undefined : '');\n\t\tif (!at) return;\n\n\t\tconst isStill = this.isDisabled() || drives.every(({ binding }) => binding.link.isDisabled());\n\n\t\tpart.style.setProperty('--_sonic-envelope-x', String(at.x));\n\t\tpart.style.setProperty('--_sonic-envelope-y', String(at.y));\n\t\twriteAttribute(part, 'data-sonic-axes', drives.map(({ axis }) => axis).join(''));\n\t\twriteAttribute(part, 'data-sonic-disabled', isStill ? '' : undefined);\n\t}\n\n\t#drives(stage: string): Array<Drive> {\n\t\tconst x = this.#bindings.get(stage);\n\t\tconst y = stage === 'decay' ? this.#bindings.get('sustain') : undefined;\n\n\t\treturn [\n\t\t\t...(x ? [{ axis: 'x' as const, binding: x }] : []),\n\t\t\t...(y ? [{ axis: 'y' as const, binding: y }] : []),\n\t\t];\n\t}\n\n\t#grab(event: PointerEvent): HandleDrag | undefined {\n\t\tconst pressed = this.#pressed(event);\n\t\tif (!pressed || pressed.drives.length === 0) return undefined;\n\n\t\tconst { drives, isFlipped, part } = pressed;\n\n\t\tthis.#claim.press(true);\n\t\tthis.#held = part;\n\t\tthis.#drawBracket();\n\t\tconst box = this.#graph.getBoundingClientRect();\n\t\tconst travel = { x: Math.max(1, box.width * this.#shape.share), y: Math.max(1, box.height) };\n\t\tconst start = (axis: FieldAxis) => {\n\t\t\tconst link = drives.find((drive) => drive.axis === axis)?.binding.link;\n\t\t\tif (!link) return;\n\n\t\t\tconst mapping = link.mapping();\n\t\t\tconst from = link.value();\n\n\t\t\treturn { from, mapping, proportion: mapping.proportionOf(from), travelPx: travel[axis] };\n\t\t};\n\n\t\treturn {\n\t\t\tdrives: drives.map((drive) => ({ ...drive, from: drive.binding.link.value() })),\n\t\t\tisFlipped,\n\t\t\tpart,\n\t\t\tstate: startFieldDrag({\n\t\t\t\tposition: flip(pointerPosition(event), isFlipped),\n\t\t\t\tthresholdPx: dragThresholdPx(event.pointerType),\n\t\t\t\tx: start('x'),\n\t\t\t\ty: start('y'),\n\t\t\t}),\n\t\t};\n\t}\n\n\t#moveDrag(drag: HandleDrag, event: PointerEvent): void {\n\t\tconst mappings: FieldMappings = {};\n\n\t\tfor (const { axis, binding } of drag.drives) mappings[axis] = binding.link.mapping();\n\n\t\tconst step = stepFieldDrag(mappings, drag.state, flip(pointerMove(event), drag.isFlipped));\n\n\t\tdrag.state = step.state;\n\t\tif (step.state.isEngaged) this.#claim.reveal('drag');\n\t\tthis.#isDriving = true;\n\t\tfor (const { axis, binding } of drag.drives) {\n\t\t\tconst next = step[axis];\n\n\t\t\tif (next !== undefined) binding.link.input(next);\n\t\t}\n\t\tthis.#isDriving = false;\n\t\tthis.#draw();\n\t}\n\n\t#pressed(\n\t\tevent: PointerEvent,\n\t): (Pick<HandleDrag, 'isFlipped' | 'part'> & { drives: Array<Drive> }) | undefined {\n\t\tconst part =\n\t\t\tevent.target instanceof Element\n\t\t\t\t? event.target.closest<HTMLElement>('.sonic-envelope-handle, .sonic-envelope-curve')\n\t\t\t\t: undefined;\n\t\tconst stage = part?.dataset.sonicStage;\n\t\tif (!part || stage === undefined || this.isDisabled()) return undefined;\n\n\t\tconst isCurveHandle = part.classList.contains('sonic-envelope-curve');\n\t\tconst drives = isCurveHandle ? this.#curveDrives(stage) : this.#drives(stage);\n\n\t\treturn {\n\t\t\tdrives: drives.filter(({ binding }) => !binding.link.isDisabled()),\n\t\t\tisFlipped: isCurveHandle && stage === 'attack',\n\t\t\tpart,\n\t\t};\n\t}\n\n\t#readShape(): AdsrShape {\n\t\tconst proportions: AdsrProportions = {};\n\t\tconst curves: AdsrCurves = {};\n\n\t\tfor (const stage of adsrStages) {\n\t\t\tconst link = this.#bindings.get(stage)?.link;\n\n\t\t\tproportions[stage] = link?.mapping().proportionOf(link.value());\n\t\t}\n\t\tfor (const stage of curveStages) {\n\t\t\tcurves[stage] = this.#bindings.get(`${stage}-curve`)?.link.value();\n\t\t}\n\n\t\treturn adsrShape(proportions, curves);\n\t}\n\n\t#rebindOnce(key: unknown, arrives: (rebind: () => void) => void): void {\n\t\tif (this.#waiting.has(key)) return;\n\n\t\tthis.#waiting.add(key);\n\t\tarrives(() => {\n\t\t\tthis.#waiting.delete(key);\n\t\t\tif (this.#signal) this.#bind();\n\t\t});\n\t}\n\n\t#renderReadout(): void {\n\t\tconst drag = this.#pointerDrag?.current();\n\n\t\tif (!drag) {\n\t\t\tthis.#readout.close();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readout.show({\n\t\t\tanchor: drag.part,\n\t\t\tisOpen: this.#claim.isRevealed && this.readout,\n\t\t\ttext: drag.drives.map(({ binding }) => binding.element.valueText).join(', '),\n\t\t});\n\t}\n\n\t#resolve(name: string): SonicValueElement | undefined {\n\t\tconst id = this.getAttribute(name);\n\t\tconst root = this.getRootNode();\n\t\tif (!id || !isParent(root)) return undefined;\n\n\t\tconst found = root.querySelector(`#${CSS.escape(id)}`);\n\t\tif (found instanceof SonicValueElement) return found;\n\n\t\tthis.#wait(id, found);\n\n\t\treturn undefined;\n\t}\n\n\t#unbind(): void {\n\t\tfor (const { unwatch } of this.#bindings.values()) unwatch();\n\n\t\tthis.#bindings.clear();\n\t}\n\n\t#wait(id: string, found: Element | null): void {\n\t\tconst tag = found?.localName;\n\t\tconst { ownerDocument } = this;\n\n\t\tif (tag?.includes('-') && !customElements.get(tag)) {\n\t\t\tthis.#rebindOnce(tag, (rebind) => {\n\t\t\t\tvoid customElements.whenDefined(tag).then(rebind);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (!found && ownerDocument.readyState === 'loading') {\n\t\t\tthis.#rebindOnce(ownerDocument, (rebind) => {\n\t\t\t\townerDocument.addEventListener('DOMContentLoaded', rebind, { once: true });\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#warn(id);\n\t}\n\n\t#warn(id: string): void {\n\t\tif (!__DEV__) return;\n\t\tif (this.#warned.has(id)) return;\n\n\t\tthis.#warned.add(id);\n\t\tconsole.warn(`<sonic-envelope> found no dial, slider or number box with the id \"${id}\"`);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"envelope.js","names":[],"sources":["../../../src/elements/envelope.ts"],"sourcesContent":["import type { ValueLink } from '#elements/value-element.ts';\nimport type { AdsrCurves, AdsrProportions, AdsrShape } from '#lib/adsr-shape.ts';\nimport type { FieldAxis, FieldDragState, FieldMappings, FieldPoint } from '#lib/field.ts';\nimport type { PointerDrag } from '#lib/pointer-drag.ts';\n\nimport { ReadoutClaim, revealDelay } from '#elements/readout-claim.ts';\nimport { Readout } from '#elements/readout.ts';\nimport { SonicElement } from '#elements/sonic-element.ts';\nimport { linkValue, SonicValueElement } from '#elements/value-element.ts';\nimport { adsrPath, adsrShape, adsrStages, timeStages } from '#lib/adsr-shape.ts';\nimport { dragThresholdPx } from '#lib/drag-step.ts';\nimport { pointerMove, pointerPosition, startFieldDrag, stepFieldDrag } from '#lib/field.ts';\nimport { bindDrag } from '#lib/pointer-drag.ts';\nimport { requireChild, template } from '#lib/render.ts';\nimport { writeAttribute } from '#lib/write-attribute.ts';\n\n// eslint-disable-next-line unicorn/consistent-boolean-name -- the name bundlers and other kits use\ndeclare const __DEV__: boolean;\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-envelope': SonicEnvelope;\n\t}\n}\n\ninterface Binding {\n\telement: SonicValueElement;\n\tlink: ValueLink;\n\tunwatch: () => void;\n}\n\ninterface Drive {\n\taxis: FieldAxis;\n\tbinding: Binding;\n}\n\ninterface HandleDrag {\n\tdrives: Array<Drive & { from: number }>;\n\tisFlipped: boolean;\n\tpart: HTMLElement;\n\tstate: FieldDragState;\n}\n\nconst curveStages = ['attack', 'decay', 'release'] as const;\n\nconst bindable = [...adsrStages, 'attack-curve', 'decay-curve', 'release-curve'] as const;\n\nconst bindableNames = new Set<string>(bindable);\n\nfunction flip<Point extends FieldPoint>(point: Point, isFlipped: boolean): Point {\n\treturn isFlipped ? { ...point, y: -point.y } : point;\n}\n\nfunction isParent(node: Node): node is Node & ParentNode {\n\treturn 'querySelector' in node;\n}\n\nconst emptyPath = { fill: '', floor: { from: 0, to: 0 }, stroke: '' };\n\nfunction stageParts<Stage extends string>(\n\tenvelope: Element,\n\thook: string,\n\tstages: ReadonlyArray<Stage>,\n): Map<Stage, HTMLDivElement> {\n\treturn new Map(\n\t\tstages.map((stage) => [\n\t\t\tstage,\n\t\t\trequireChild(envelope, `.${hook}[data-sonic-stage=\"${stage}\"]`, HTMLDivElement),\n\t\t]),\n\t);\n}\n\nconst renderEnvelope = template(\n\t/* HTML */ `\n\t\t<div class=\"sonic-envelope\" aria-hidden=\"true\">\n\t\t\t<div class=\"sonic-envelope-bracket\"></div>\n\t\t\t<svg class=\"sonic-envelope-graph\" preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\">\n\t\t\t\t<path class=\"sonic-envelope-fill\" />\n\t\t\t\t<rect class=\"sonic-envelope-fill sonic-envelope-floor\" y=\"1\" />\n\t\t\t\t<path class=\"sonic-envelope-line\" />\n\t\t\t</svg>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"delay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"attack\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"hold\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"decay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-handle\" data-sonic-stage=\"release\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"attack\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"decay\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-curve\" data-sonic-stage=\"release\" hidden></div>\n\t\t\t<div class=\"sonic-envelope-readout\" popover=\"manual\"><span></span></div>\n\t\t</div>\n\t`,\n\tHTMLDivElement,\n);\n\nexport class SonicEnvelope extends SonicElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicElement.observedAttributes,\n\t\t...bindable,\n\t\t'readout',\n\t];\n\n\tget attack(): string {\n\t\treturn this.getAttribute('attack') ?? '';\n\t}\n\n\tset attack(id: string | undefined) {\n\t\tthis.reflect('attack', id);\n\t}\n\n\tget attackCurve(): string {\n\t\treturn this.getAttribute('attack-curve') ?? '';\n\t}\n\n\tset attackCurve(id: string | undefined) {\n\t\tthis.reflect('attack-curve', id);\n\t}\n\n\tget decay(): string {\n\t\treturn this.getAttribute('decay') ?? '';\n\t}\n\n\tset decay(id: string | undefined) {\n\t\tthis.reflect('decay', id);\n\t}\n\n\tget decayCurve(): string {\n\t\treturn this.getAttribute('decay-curve') ?? '';\n\t}\n\n\tset decayCurve(id: string | undefined) {\n\t\tthis.reflect('decay-curve', id);\n\t}\n\n\tget delay(): string {\n\t\treturn this.getAttribute('delay') ?? '';\n\t}\n\n\tset delay(id: string | undefined) {\n\t\tthis.reflect('delay', id);\n\t}\n\n\tget hold(): string {\n\t\treturn this.getAttribute('hold') ?? '';\n\t}\n\n\tset hold(id: string | undefined) {\n\t\tthis.reflect('hold', id);\n\t}\n\n\tget readout(): boolean {\n\t\treturn this.hasAttribute('readout');\n\t}\n\n\tset readout(isOn: boolean) {\n\t\tthis.reflect('readout', isOn);\n\t}\n\n\tget release(): string {\n\t\treturn this.getAttribute('release') ?? '';\n\t}\n\n\tset release(id: string | undefined) {\n\t\tthis.reflect('release', id);\n\t}\n\n\tget releaseCurve(): string {\n\t\treturn this.getAttribute('release-curve') ?? '';\n\t}\n\n\tset releaseCurve(id: string | undefined) {\n\t\tthis.reflect('release-curve', id);\n\t}\n\n\tget sustain(): string {\n\t\treturn this.getAttribute('sustain') ?? '';\n\t}\n\n\tset sustain(id: string | undefined) {\n\t\tthis.reflect('sustain', id);\n\t}\n\n\treadonly #bindings = new Map<string, Binding>();\n\n\treadonly #envelope = renderEnvelope();\n\n\treadonly #bracket = requireChild(this.#envelope, '.sonic-envelope-bracket', HTMLDivElement);\n\n\treadonly #claim = new ReadoutClaim(() => {\n\t\tthis.#renderReadout();\n\t});\n\n\treadonly #curveHandles = stageParts(this.#envelope, 'sonic-envelope-curve', curveStages);\n\n\treadonly #fill = requireChild(this.#envelope, '.sonic-envelope-fill', SVGElement);\n\n\treadonly #floor = requireChild(this.#envelope, '.sonic-envelope-floor', SVGElement);\n\n\treadonly #graph = requireChild(this.#envelope, '.sonic-envelope-graph', SVGElement);\n\n\treadonly #handles = stageParts(this.#envelope, 'sonic-envelope-handle', timeStages);\n\n\t#held: HTMLElement | undefined;\n\n\t#isDriving = false;\n\n\treadonly #line = requireChild(this.#envelope, '.sonic-envelope-line', SVGElement);\n\n\t#pointerDrag: PointerDrag<HandleDrag> | undefined;\n\n\treadonly #readout = new Readout(\n\t\trequireChild(this.#envelope, '.sonic-envelope-readout', HTMLDivElement),\n\t);\n\n\t#shape: AdsrShape = adsrShape({});\n\n\t#signal: AbortSignal | undefined;\n\n\treadonly #waiting = new Set<unknown>();\n\n\treadonly #warned = new Set<string>();\n\n\tattributeChangedCallback(name: string): void {\n\t\tif (!this.#signal) return;\n\t\tif (name === 'disabled') {\n\t\t\tthis.#pointerDrag?.end();\n\t\t\tthis.#draw();\n\t\t\treturn;\n\t\t}\n\t\tif (bindableNames.has(name)) this.#bind();\n\t\telse this.#renderReadout();\n\t}\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(...adsrStages, 'attackCurve', 'decayCurve', 'readout', 'releaseCurve');\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst envelope = this.#envelope;\n\n\t\tthis.#signal = signal;\n\t\tthis.keepControl(envelope, signal);\n\t\tthis.#bind();\n\t\tthis.checkStyles(envelope, 'envelope.css');\n\t\tthis.#bindPointer(envelope, signal);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tthis.#signal = undefined;\n\t\t\t\tthis.#unbind();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#bind(): void {\n\t\tthis.#pointerDrag?.end();\n\t\tthis.#unbind();\n\t\tfor (const name of bindable) {\n\t\t\tconst element = this.#resolve(name);\n\t\t\tif (!element) continue;\n\n\t\t\tconst link = linkValue(element);\n\t\t\tconst unwatch = link.watch(() => {\n\t\t\t\tif (!this.#isDriving) this.#draw();\n\t\t\t});\n\n\t\t\tthis.#bindings.set(name, { element, link, unwatch });\n\t\t}\n\t\tthis.#draw();\n\t}\n\n\t#bindPointer(envelope: HTMLElement, signal: AbortSignal): void {\n\t\tthis.#pointerDrag = bindDrag(\n\t\t\tenvelope,\n\t\t\t{\n\t\t\t\tcancel: (drag) => {\n\t\t\t\t\tfor (const { binding, from } of drag.drives) binding.link.input(from);\n\t\t\t\t},\n\t\t\t\tgrab: (event) => this.#grab(event),\n\t\t\t\tmove: (drag, event) => {\n\t\t\t\t\tthis.#moveDrag(drag, event);\n\t\t\t\t},\n\t\t\t\trelease: (drag) => {\n\t\t\t\t\tthis.#claim.press(false);\n\t\t\t\t\tfor (const { binding, from } of drag.drives) {\n\t\t\t\t\t\tif (binding.link.value() === from) continue;\n\n\t\t\t\t\t\tbinding.element.dispatchEvent(new Event('change', { bubbles: true }));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttoggle: (isDragging) => {\n\t\t\t\t\tthis.toggleState('dragging', isDragging);\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t}\n\n\t#curveDrives(stage: string): Array<Drive> {\n\t\tconst binding = this.#bindings.get(`${stage}-curve`);\n\n\t\treturn binding ? [{ axis: 'y', binding }] : [];\n\t}\n\n\t#draw(): void {\n\t\tconst shape = this.#readShape();\n\t\tconst path = this.#bindings.size === 0 ? emptyPath : adsrPath(shape);\n\n\t\tthis.#shape = shape;\n\t\twriteAttribute(this.#line, 'd', path.stroke);\n\t\twriteAttribute(this.#fill, 'd', path.fill);\n\t\twriteAttribute(this.#floor, 'x', String(path.floor.from));\n\t\twriteAttribute(this.#floor, 'width', String(path.floor.to - path.floor.from));\n\t\tfor (const [stage, part] of this.#handles) {\n\t\t\tthis.#drawPoint(part, {\n\t\t\t\tat: shape.handles.find((point) => point.stage === stage),\n\t\t\t\tdrives: this.#drives(stage),\n\t\t\t});\n\t\t}\n\t\tfor (const [stage, part] of this.#curveHandles) {\n\t\t\tthis.#drawPoint(part, {\n\t\t\t\tat: shape.curveHandles.find((point) => point.stage === stage),\n\t\t\t\tdrives: this.#curveDrives(stage),\n\t\t\t});\n\t\t}\n\t\tthis.#drawBracket();\n\t\tthis.#renderReadout();\n\t}\n\n\t#drawBracket(): void {\n\t\tconst part = this.#held;\n\t\tif (!part) return;\n\n\t\tfor (const name of ['--_sonic-envelope-x', '--_sonic-envelope-y']) {\n\t\t\tthis.#bracket.style.setProperty(name, part.style.getPropertyValue(name));\n\t\t}\n\t\twriteAttribute(\n\t\t\tthis.#bracket,\n\t\t\t'data-sonic-part',\n\t\t\tpart.classList.contains('sonic-envelope-curve') ? 'curve' : undefined,\n\t\t);\n\t}\n\n\t#drawPoint(\n\t\tpart: HTMLDivElement,\n\t\tpoint: { at: FieldPoint | undefined; drives: Array<Drive> },\n\t): void {\n\t\tconst { at, drives } = point;\n\n\t\twriteAttribute(part, 'hidden', at ? undefined : '');\n\t\tif (!at) return;\n\n\t\tconst isStill = this.isDisabled() || drives.every(({ binding }) => binding.link.isDisabled());\n\n\t\tpart.style.setProperty('--_sonic-envelope-x', String(at.x));\n\t\tpart.style.setProperty('--_sonic-envelope-y', String(at.y));\n\t\twriteAttribute(part, 'data-sonic-axes', drives.map(({ axis }) => axis).join(''));\n\t\twriteAttribute(part, 'data-sonic-disabled', isStill ? '' : undefined);\n\t}\n\n\t#drives(stage: string): Array<Drive> {\n\t\tconst x = this.#bindings.get(stage);\n\t\tconst y = stage === 'decay' ? this.#bindings.get('sustain') : undefined;\n\n\t\treturn [\n\t\t\t...(x ? [{ axis: 'x' as const, binding: x }] : []),\n\t\t\t...(y ? [{ axis: 'y' as const, binding: y }] : []),\n\t\t];\n\t}\n\n\t#grab(event: PointerEvent): HandleDrag | undefined {\n\t\tconst pressed = this.#pressed(event);\n\t\tif (!pressed || pressed.drives.length === 0) return undefined;\n\n\t\tconst { drives, isFlipped, part } = pressed;\n\n\t\tthis.#claim.press(true, revealDelay(this.#envelope));\n\t\tthis.#held = part;\n\t\tthis.#drawBracket();\n\t\tconst box = this.#graph.getBoundingClientRect();\n\t\tconst travel = { x: Math.max(1, box.width * this.#shape.share), y: Math.max(1, box.height) };\n\t\tconst start = (axis: FieldAxis) => {\n\t\t\tconst link = drives.find((drive) => drive.axis === axis)?.binding.link;\n\t\t\tif (!link) return;\n\n\t\t\tconst mapping = link.mapping();\n\t\t\tconst from = link.value();\n\n\t\t\treturn { from, mapping, proportion: mapping.proportionOf(from), travelPx: travel[axis] };\n\t\t};\n\n\t\treturn {\n\t\t\tdrives: drives.map((drive) => ({ ...drive, from: drive.binding.link.value() })),\n\t\t\tisFlipped,\n\t\t\tpart,\n\t\t\tstate: startFieldDrag({\n\t\t\t\tposition: flip(pointerPosition(event), isFlipped),\n\t\t\t\tthresholdPx: dragThresholdPx(event.pointerType),\n\t\t\t\tx: start('x'),\n\t\t\t\ty: start('y'),\n\t\t\t}),\n\t\t};\n\t}\n\n\t#moveDrag(drag: HandleDrag, event: PointerEvent): void {\n\t\tconst mappings: FieldMappings = {};\n\n\t\tfor (const { axis, binding } of drag.drives) mappings[axis] = binding.link.mapping();\n\n\t\tconst step = stepFieldDrag(mappings, drag.state, flip(pointerMove(event), drag.isFlipped));\n\n\t\tdrag.state = step.state;\n\t\tif (step.state.isEngaged) this.#claim.reveal('drag');\n\t\tthis.#isDriving = true;\n\t\tfor (const { axis, binding } of drag.drives) {\n\t\t\tconst next = step[axis];\n\n\t\t\tif (next !== undefined) binding.link.input(next);\n\t\t}\n\t\tthis.#isDriving = false;\n\t\tthis.#draw();\n\t}\n\n\t#pressed(\n\t\tevent: PointerEvent,\n\t): (Pick<HandleDrag, 'isFlipped' | 'part'> & { drives: Array<Drive> }) | undefined {\n\t\tconst part =\n\t\t\tevent.target instanceof Element\n\t\t\t\t? event.target.closest<HTMLElement>('.sonic-envelope-handle, .sonic-envelope-curve')\n\t\t\t\t: undefined;\n\t\tconst stage = part?.dataset.sonicStage;\n\t\tif (!part || stage === undefined || this.isDisabled()) return undefined;\n\n\t\tconst isCurveHandle = part.classList.contains('sonic-envelope-curve');\n\t\tconst drives = isCurveHandle ? this.#curveDrives(stage) : this.#drives(stage);\n\n\t\treturn {\n\t\t\tdrives: drives.filter(({ binding }) => !binding.link.isDisabled()),\n\t\t\tisFlipped: isCurveHandle && stage === 'attack',\n\t\t\tpart,\n\t\t};\n\t}\n\n\t#readShape(): AdsrShape {\n\t\tconst proportions: AdsrProportions = {};\n\t\tconst curves: AdsrCurves = {};\n\n\t\tfor (const stage of adsrStages) {\n\t\t\tconst link = this.#bindings.get(stage)?.link;\n\n\t\t\tproportions[stage] = link?.mapping().proportionOf(link.value());\n\t\t}\n\t\tfor (const stage of curveStages) {\n\t\t\tcurves[stage] = this.#bindings.get(`${stage}-curve`)?.link.value();\n\t\t}\n\n\t\treturn adsrShape(proportions, curves);\n\t}\n\n\t#rebindOnce(key: unknown, arrives: (rebind: () => void) => void): void {\n\t\tif (this.#waiting.has(key)) return;\n\n\t\tthis.#waiting.add(key);\n\t\tarrives(() => {\n\t\t\tthis.#waiting.delete(key);\n\t\t\tif (this.#signal) this.#bind();\n\t\t});\n\t}\n\n\t#renderReadout(): void {\n\t\tconst drag = this.#pointerDrag?.current();\n\n\t\tif (!drag) {\n\t\t\tthis.#readout.close();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readout.show({\n\t\t\tanchor: drag.part,\n\t\t\tisOpen: this.#claim.isRevealed && this.readout,\n\t\t\ttext: drag.drives.map(({ binding }) => binding.element.valueText).join(', '),\n\t\t});\n\t}\n\n\t#resolve(name: string): SonicValueElement | undefined {\n\t\tconst id = this.getAttribute(name);\n\t\tconst root = this.getRootNode();\n\t\tif (!id || !isParent(root)) return undefined;\n\n\t\tconst found = root.querySelector(`#${CSS.escape(id)}`);\n\t\tif (found instanceof SonicValueElement) return found;\n\n\t\tthis.#wait(id, found);\n\n\t\treturn undefined;\n\t}\n\n\t#unbind(): void {\n\t\tfor (const { unwatch } of this.#bindings.values()) unwatch();\n\n\t\tthis.#bindings.clear();\n\t}\n\n\t#wait(id: string, found: Element | null): void {\n\t\tconst tag = found?.localName;\n\t\tconst { ownerDocument } = this;\n\n\t\tif (tag?.includes('-') && !customElements.get(tag)) {\n\t\t\tthis.#rebindOnce(tag, (rebind) => {\n\t\t\t\tvoid customElements.whenDefined(tag).then(rebind);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (!found && ownerDocument.readyState === 'loading') {\n\t\t\tthis.#rebindOnce(ownerDocument, (rebind) => {\n\t\t\t\townerDocument.addEventListener('DOMContentLoaded', rebind, { once: true });\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#warn(id);\n\t}\n\n\t#warn(id: string): void {\n\t\tif (!__DEV__) return;\n\t\tif (this.#warned.has(id)) return;\n\n\t\tthis.#warned.add(id);\n\t\tconsole.warn(`<sonic-envelope> found no dial, slider or number box with the id \"${id}\"`);\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { toNumber } from "../lib/math.js";
2
+
3
+ //#region src/elements/modulation.ts
4
+ function createModulation(control, prefix, toggle) {
5
+ const { style } = control;
6
+ let isModulated = false;
7
+ let modulationValue;
8
+ const writeProportion = (mapping) => {
9
+ const shown = mapping.isWrapping ? void 0 : modulationValue;
10
+ const isShown = shown !== void 0;
11
+ if (isShown !== isModulated) {
12
+ isModulated = isShown;
13
+ toggle(isShown);
14
+ }
15
+ if (shown === void 0) {
16
+ style.removeProperty(`--_sonic-${prefix}-modulation-value`);
17
+ return;
18
+ }
19
+ style.setProperty(`--_sonic-${prefix}-modulation-value`, String(mapping.proportionOf(shown)));
20
+ };
21
+ return {
22
+ draw: ({ mapping, modulation, origin, value }) => {
23
+ const at = mapping.proportionOf(value);
24
+ const reach = mapping.proportionOf(value + modulation);
25
+ const { positionCount } = mapping;
26
+ style.setProperty(`--_sonic-${prefix}-value`, String(at));
27
+ style.setProperty(`--_sonic-${prefix}-origin`, String(mapping.proportionOf(origin)));
28
+ style.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(at, reach)));
29
+ style.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(at, reach)));
30
+ if (positionCount === void 0) style.removeProperty(`--_sonic-${prefix}-position-count`);
31
+ else style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));
32
+ writeProportion(mapping);
33
+ },
34
+ value: () => modulationValue,
35
+ write: (next, mapping) => {
36
+ const value = next === void 0 || next === null ? void 0 : toNumber(next);
37
+ if (value !== void 0 && !Number.isFinite(value)) return;
38
+ modulationValue = value;
39
+ if (mapping) writeProportion(mapping);
40
+ }
41
+ };
42
+ }
43
+
44
+ //#endregion
45
+ export { createModulation };
46
+ //# sourceMappingURL=modulation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modulation.js","names":[],"sources":["../../../src/elements/modulation.ts"],"sourcesContent":["import type { ValueMapping } from '#lib/value-mapping.ts';\n\nimport { toNumber } from '#lib/math.ts';\n\ninterface Modulation {\n\tdraw: (drawn: ModulationDraw) => void;\n\tvalue: () => number | undefined;\n\twrite: (next: null | number | undefined, mapping: undefined | ValueMapping) => void;\n}\n\ninterface ModulationDraw {\n\tmapping: ValueMapping;\n\tmodulation: number;\n\torigin: number;\n\tvalue: number;\n}\n\nexport function createModulation(\n\tcontrol: HTMLElement,\n\tprefix: 'dial' | 'slider',\n\ttoggle: (isModulated: boolean) => void,\n): Modulation {\n\tconst { style } = control;\n\tlet isModulated = false;\n\tlet modulationValue: number | undefined;\n\n\tconst writeProportion = (mapping: ValueMapping): void => {\n\t\tconst shown = mapping.isWrapping ? undefined : modulationValue;\n\t\tconst isShown = shown !== undefined;\n\n\t\tif (isShown !== isModulated) {\n\t\t\tisModulated = isShown;\n\t\t\ttoggle(isShown);\n\t\t}\n\t\tif (shown === undefined) {\n\t\t\tstyle.removeProperty(`--_sonic-${prefix}-modulation-value`);\n\t\t\treturn;\n\t\t}\n\n\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-value`, String(mapping.proportionOf(shown)));\n\t};\n\n\treturn {\n\t\tdraw: ({ mapping, modulation, origin, value }) => {\n\t\t\tconst at = mapping.proportionOf(value);\n\t\t\tconst reach = mapping.proportionOf(value + modulation);\n\t\t\tconst { positionCount } = mapping;\n\n\t\t\tstyle.setProperty(`--_sonic-${prefix}-value`, String(at));\n\t\t\tstyle.setProperty(`--_sonic-${prefix}-origin`, String(mapping.proportionOf(origin)));\n\t\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-from`, String(Math.min(at, reach)));\n\t\t\tstyle.setProperty(`--_sonic-${prefix}-modulation-to`, String(Math.max(at, reach)));\n\t\t\tif (positionCount === undefined) style.removeProperty(`--_sonic-${prefix}-position-count`);\n\t\t\telse style.setProperty(`--_sonic-${prefix}-position-count`, String(positionCount));\n\t\t\twriteProportion(mapping);\n\t\t},\n\t\tvalue: () => modulationValue,\n\t\t// No mapping before the control is drawn; the value is held until then\n\t\twrite: (next, mapping) => {\n\t\t\tconst value = next === undefined || next === null ? undefined : toNumber(next);\n\t\t\tif (value !== undefined && !Number.isFinite(value)) return;\n\n\t\t\tmodulationValue = value;\n\t\t\tif (mapping) writeProportion(mapping);\n\t\t},\n\t};\n}\n"],"mappings":";;;AAiBA,SAAgB,iBACf,SACA,QACA,QACa;CACb,MAAM,EAAE,UAAU;CAClB,IAAI,cAAc;CAClB,IAAI;CAEJ,MAAM,mBAAmB,YAAgC;EACxD,MAAM,QAAQ,QAAQ,aAAa,SAAY;EAC/C,MAAM,UAAU,UAAU;EAE1B,IAAI,YAAY,aAAa;GAC5B,cAAc;GACd,OAAO,OAAO;EACf;EACA,IAAI,UAAU,QAAW;GACxB,MAAM,eAAe,YAAY,OAAO,kBAAkB;GAC1D;EACD;EAEA,MAAM,YAAY,YAAY,OAAO,oBAAoB,OAAO,QAAQ,aAAa,KAAK,CAAC,CAAC;CAC7F;CAEA,OAAO;EACN,OAAO,EAAE,SAAS,YAAY,QAAQ,YAAY;GACjD,MAAM,KAAK,QAAQ,aAAa,KAAK;GACrC,MAAM,QAAQ,QAAQ,aAAa,QAAQ,UAAU;GACrD,MAAM,EAAE,kBAAkB;GAE1B,MAAM,YAAY,YAAY,OAAO,SAAS,OAAO,EAAE,CAAC;GACxD,MAAM,YAAY,YAAY,OAAO,UAAU,OAAO,QAAQ,aAAa,MAAM,CAAC,CAAC;GACnF,MAAM,YAAY,YAAY,OAAO,mBAAmB,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC;GACnF,MAAM,YAAY,YAAY,OAAO,iBAAiB,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC;GACjF,IAAI,kBAAkB,QAAW,MAAM,eAAe,YAAY,OAAO,gBAAgB;QACpF,MAAM,YAAY,YAAY,OAAO,kBAAkB,OAAO,aAAa,CAAC;GACjF,gBAAgB,OAAO;EACxB;EACA,aAAa;EAEb,QAAQ,MAAM,YAAY;GACzB,MAAM,QAAQ,SAAS,UAAa,SAAS,OAAO,SAAY,SAAS,IAAI;GAC7E,IAAI,UAAU,UAAa,CAAC,OAAO,SAAS,KAAK,GAAG;GAEpD,kBAAkB;GAClB,IAAI,SAAS,gBAAgB,OAAO;EACrC;CACD;AACD"}
@@ -1,6 +1,11 @@
1
+ import { readMsProperty } from "../lib/read-ms-property.js";
2
+
1
3
  //#region src/elements/readout-claim.ts
2
4
  const keyRevealMs = 1e3;
3
5
  const revealMs = 250;
6
+ function revealDelay(control) {
7
+ return Math.max(0, readMsProperty(getComputedStyle(control), "--_sonic-reveal-delay", revealMs));
8
+ }
4
9
  var ReadoutClaim = class {
5
10
  get isRevealed() {
6
11
  return this.#isDragging || this.#keyTimer !== void 0;
@@ -24,7 +29,7 @@ var ReadoutClaim = class {
24
29
  this.#keyTimer = void 0;
25
30
  return wasTimed;
26
31
  }
27
- press(isDown) {
32
+ press(isDown, delayMs = revealMs) {
28
33
  this.conceal("drag");
29
34
  if (!isDown) {
30
35
  this.#onLapse();
@@ -33,7 +38,7 @@ var ReadoutClaim = class {
33
38
  this.#holdTimer = setTimeout(() => {
34
39
  this.reveal("drag");
35
40
  this.#onLapse();
36
- }, 250);
41
+ }, delayMs);
37
42
  }
38
43
  reveal(by) {
39
44
  if (by === "drag") {
@@ -49,5 +54,5 @@ var ReadoutClaim = class {
49
54
  };
50
55
 
51
56
  //#endregion
52
- export { ReadoutClaim };
57
+ export { ReadoutClaim, revealDelay };
53
58
  //# sourceMappingURL=readout-claim.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"readout-claim.js","names":[],"sources":["../../../src/elements/readout-claim.ts"],"sourcesContent":["const keyRevealMs = 1000;\n\nexport const revealMs = 250;\n\nexport class ReadoutClaim {\n\tget isRevealed(): boolean {\n\t\treturn this.#isDragging || this.#keyTimer !== undefined;\n\t}\n\n\t#holdTimer: ReturnType<typeof setTimeout> | undefined;\n\n\t#isDragging = false;\n\n\t#keyTimer: ReturnType<typeof setTimeout> | undefined;\n\n\treadonly #onLapse: () => void;\n\n\tconstructor(onLapse: () => void) {\n\t\tthis.#onLapse = onLapse;\n\t}\n\n\tconceal(by: 'drag' | 'keys'): boolean {\n\t\tif (by === 'drag') {\n\t\t\tconst wasDragging = this.#isDragging;\n\n\t\t\tclearTimeout(this.#holdTimer);\n\t\t\tthis.#isDragging = false;\n\n\t\t\treturn wasDragging;\n\t\t}\n\n\t\tclearTimeout(this.#keyTimer);\n\n\t\tconst wasTimed = this.#keyTimer !== undefined;\n\n\t\tthis.#keyTimer = undefined;\n\n\t\treturn wasTimed;\n\t}\n\n\tpress(isDown: boolean): void {\n\t\tthis.conceal('drag');\n\t\tif (!isDown) {\n\t\t\tthis.#onLapse();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#holdTimer = setTimeout(() => {\n\t\t\tthis.reveal('drag');\n\t\t\tthis.#onLapse();\n\t\t}, revealMs);\n\t}\n\n\treveal(by: 'drag' | 'keys'): void {\n\t\tif (by === 'drag') {\n\t\t\tthis.#isDragging = true;\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(this.#keyTimer);\n\t\tthis.#keyTimer = setTimeout(() => {\n\t\t\tthis.#keyTimer = undefined;\n\t\t\tthis.#onLapse();\n\t\t}, keyRevealMs);\n\t}\n}\n"],"mappings":";AAAA,MAAM,cAAc;AAEpB,MAAa,WAAW;AAExB,IAAa,eAAb,MAA0B;CACzB,IAAI,aAAsB;EACzB,OAAO,KAAK,eAAe,KAAK,cAAc;CAC/C;CAEA;CAEA,cAAc;CAEd;CAEA,AAAS;CAET,YAAY,SAAqB;EAChC,KAAK,WAAW;CACjB;CAEA,QAAQ,IAA8B;EACrC,IAAI,OAAO,QAAQ;GAClB,MAAM,cAAc,KAAK;GAEzB,aAAa,KAAK,UAAU;GAC5B,KAAK,cAAc;GAEnB,OAAO;EACR;EAEA,aAAa,KAAK,SAAS;EAE3B,MAAM,WAAW,KAAK,cAAc;EAEpC,KAAK,YAAY;EAEjB,OAAO;CACR;CAEA,MAAM,QAAuB;EAC5B,KAAK,QAAQ,MAAM;EACnB,IAAI,CAAC,QAAQ;GACZ,KAAK,SAAS;GACd;EACD;EAEA,KAAK,aAAa,iBAAiB;GAClC,KAAK,OAAO,MAAM;GAClB,KAAK,SAAS;EACf,MAAW;CACZ;CAEA,OAAO,IAA2B;EACjC,IAAI,OAAO,QAAQ;GAClB,KAAK,cAAc;GACnB;EACD;EAEA,aAAa,KAAK,SAAS;EAC3B,KAAK,YAAY,iBAAiB;GACjC,KAAK,YAAY;GACjB,KAAK,SAAS;EACf,GAAG,WAAW;CACf;AACD"}
1
+ {"version":3,"file":"readout-claim.js","names":[],"sources":["../../../src/elements/readout-claim.ts"],"sourcesContent":["import { readMsProperty } from '#lib/read-ms-property.ts';\n\nconst keyRevealMs = 1000;\n\nconst revealMs = 250;\n\nexport function revealDelay(control: Element): number {\n\treturn Math.max(0, readMsProperty(getComputedStyle(control), '--_sonic-reveal-delay', revealMs));\n}\n\nexport class ReadoutClaim {\n\tget isRevealed(): boolean {\n\t\treturn this.#isDragging || this.#keyTimer !== undefined;\n\t}\n\n\t#holdTimer: ReturnType<typeof setTimeout> | undefined;\n\n\t#isDragging = false;\n\n\t#keyTimer: ReturnType<typeof setTimeout> | undefined;\n\n\treadonly #onLapse: () => void;\n\n\tconstructor(onLapse: () => void) {\n\t\tthis.#onLapse = onLapse;\n\t}\n\n\tconceal(by: 'drag' | 'keys'): boolean {\n\t\tif (by === 'drag') {\n\t\t\tconst wasDragging = this.#isDragging;\n\n\t\t\tclearTimeout(this.#holdTimer);\n\t\t\tthis.#isDragging = false;\n\n\t\t\treturn wasDragging;\n\t\t}\n\n\t\tclearTimeout(this.#keyTimer);\n\n\t\tconst wasTimed = this.#keyTimer !== undefined;\n\n\t\tthis.#keyTimer = undefined;\n\n\t\treturn wasTimed;\n\t}\n\n\tpress(isDown: boolean, delayMs = revealMs): void {\n\t\tthis.conceal('drag');\n\t\tif (!isDown) {\n\t\t\tthis.#onLapse();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#holdTimer = setTimeout(() => {\n\t\t\tthis.reveal('drag');\n\t\t\tthis.#onLapse();\n\t\t}, delayMs);\n\t}\n\n\treveal(by: 'drag' | 'keys'): void {\n\t\tif (by === 'drag') {\n\t\t\tthis.#isDragging = true;\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(this.#keyTimer);\n\t\tthis.#keyTimer = setTimeout(() => {\n\t\t\tthis.#keyTimer = undefined;\n\t\t\tthis.#onLapse();\n\t\t}, keyRevealMs);\n\t}\n}\n"],"mappings":";;;AAEA,MAAM,cAAc;AAEpB,MAAM,WAAW;AAEjB,SAAgB,YAAY,SAA0B;CACrD,OAAO,KAAK,IAAI,GAAG,eAAe,iBAAiB,OAAO,GAAG,yBAAyB,QAAQ,CAAC;AAChG;AAEA,IAAa,eAAb,MAA0B;CACzB,IAAI,aAAsB;EACzB,OAAO,KAAK,eAAe,KAAK,cAAc;CAC/C;CAEA;CAEA,cAAc;CAEd;CAEA,AAAS;CAET,YAAY,SAAqB;EAChC,KAAK,WAAW;CACjB;CAEA,QAAQ,IAA8B;EACrC,IAAI,OAAO,QAAQ;GAClB,MAAM,cAAc,KAAK;GAEzB,aAAa,KAAK,UAAU;GAC5B,KAAK,cAAc;GAEnB,OAAO;EACR;EAEA,aAAa,KAAK,SAAS;EAE3B,MAAM,WAAW,KAAK,cAAc;EAEpC,KAAK,YAAY;EAEjB,OAAO;CACR;CAEA,MAAM,QAAiB,UAAU,UAAgB;EAChD,KAAK,QAAQ,MAAM;EACnB,IAAI,CAAC,QAAQ;GACZ,KAAK,SAAS;GACd;EACD;EAEA,KAAK,aAAa,iBAAiB;GAClC,KAAK,OAAO,MAAM;GAClB,KAAK,SAAS;EACf,GAAG,OAAO;CACX;CAEA,OAAO,IAA2B;EACjC,IAAI,OAAO,QAAQ;GAClB,KAAK,cAAc;GACnB;EACD;EAEA,aAAa,KAAK,SAAS;EAC3B,KAAK,YAAY,iBAAiB;GACjC,KAAK,YAAY;GACjB,KAAK,SAAS;EACf,GAAG,WAAW;CACf;AACD"}
@@ -30,7 +30,6 @@ export declare class SonicSlider extends SonicValueElement {
30
30
  protected focusTarget(): HTMLElement;
31
31
  protected heldWrite(next: number): void;
32
32
  protected holdChanged(): void;
33
- protected previewValue(): number | undefined;
34
33
  protected scrubsKeyRepeat(): boolean;
35
34
  protected springTarget(): number | undefined;
36
35
  }
@@ -1,8 +1,8 @@
1
1
  import { clampProportion } from "../lib/math.js";
2
2
  import { requireChild, template } from "../lib/render.js";
3
+ import { createModulation } from "./modulation.js";
3
4
  import { SonicValueElement } from "./value-element.js";
4
5
  import { bindScale } from "./scale.js";
5
- import { bindHoverPreview } from "../lib/hover-preview.js";
6
6
  import { sortedRegions } from "../lib/time-regions.js";
7
7
 
8
8
  //#region src/elements/slider.ts
@@ -59,10 +59,10 @@ var SonicSlider = class extends SonicValueElement {
59
59
  this.reflect("modulation", amount);
60
60
  }
61
61
  get modulationValue() {
62
- return this.readModulationValue();
62
+ return this.#modulation.value();
63
63
  }
64
64
  set modulationValue(value) {
65
- this.writeModulationValue(this.#slider, "slider", value);
65
+ this.#modulation.write(value, this.isBound() ? this.mapping() : void 0);
66
66
  }
67
67
  get orientation() {
68
68
  return this.getAttribute("orientation") === "vertical" ? "vertical" : "horizontal";
@@ -83,8 +83,10 @@ var SonicSlider = class extends SonicValueElement {
83
83
  this.reflect("spring", isSpring);
84
84
  }
85
85
  #buffered = [];
86
- #hover;
87
86
  #slider = renderSlider();
87
+ #modulation = createModulation(this.#slider, "slider", (isModulated) => {
88
+ this.toggleState("modulated", isModulated);
89
+ });
88
90
  connectedCallback() {
89
91
  this.upgradeProperties("buffered", "groovePress", "modulationValue", "modulation", "orientation", "scrub", "spring");
90
92
  super.connectedCallback();
@@ -99,14 +101,9 @@ var SonicSlider = class extends SonicValueElement {
99
101
  slider.addEventListener("transitionend", (event) => {
100
102
  if (event.propertyName === "--_sonic-slider-value") this.toggleState("springing", false);
101
103
  }, { signal });
102
- this.#hover = bindHoverPreview(slider, {
104
+ this.bindHover(slider, signal, {
103
105
  canShow: () => this.scrub && this.readout && this.orientation === "horizontal",
104
- dismiss: () => {
105
- this.render();
106
- },
107
- isTaken: () => this.isEditing() || this.isRevealed(),
108
- show: () => {
109
- this.renderReadout();
106
+ place: () => {
110
107
  this.#placeReadout(slider);
111
108
  },
112
109
  valueAt: (event) => {
@@ -115,7 +112,7 @@ var SonicSlider = class extends SonicValueElement {
115
112
  const mapping = this.mapping();
116
113
  return mapping.snap(mapping.valueAt(at));
117
114
  }
118
- }, signal);
115
+ });
119
116
  this.render();
120
117
  this.checkStyles(slider, "slider.css");
121
118
  this.bindGestures(slider, signal, (event) => {
@@ -130,8 +127,12 @@ var SonicSlider = class extends SonicValueElement {
130
127
  return this.orientation;
131
128
  }
132
129
  draw() {
133
- if (this.isEditing() || this.isRevealed()) this.#hover?.clear();
134
- this.writeProportions(this.#slider, "slider", this.modulation);
130
+ this.#modulation.draw({
131
+ mapping: this.mapping(),
132
+ modulation: this.modulation,
133
+ origin: this.originValue(),
134
+ value: this.value
135
+ });
135
136
  this.#renderBuffered(this.#slider);
136
137
  this.#renderScrub(this.#slider);
137
138
  this.#placeReadout(this.#slider);
@@ -146,9 +147,6 @@ var SonicSlider = class extends SonicValueElement {
146
147
  holdChanged() {
147
148
  if (this.scrub) this.render();
148
149
  }
149
- previewValue() {
150
- return this.#hover?.value();
151
- }
152
150
  scrubsKeyRepeat() {
153
151
  return this.scrub;
154
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"slider.js","names":[],"sources":["../../../src/elements/slider.ts"],"sourcesContent":["import type { ValueAxis } from '#elements/value-element.ts';\nimport type { HoverPreview } from '#lib/hover-preview.ts';\nimport type { TimeRegions } from '#lib/time-regions.ts';\n\nimport { bindScale } from '#elements/scale.ts';\nimport { SonicValueElement } from '#elements/value-element.ts';\nimport { bindHoverPreview } from '#lib/hover-preview.ts';\nimport { clampProportion } from '#lib/math.ts';\nimport { requireChild, template } from '#lib/render.ts';\nimport { sortedRegions } from '#lib/time-regions.ts';\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-slider': SonicSlider;\n\t}\n}\n\ninterface SliderAxis extends ValueAxis {\n\tstartPx: number;\n}\n\nfunction grooveStop(proportion: number): string {\n\tif (proportion <= 0) return '0%';\n\tif (proportion >= 1) return '100%';\n\n\treturn `calc(${String(proportion)} * var(--_sonic-slider-travel) + var(--_sonic-slider-groove) / 2)`;\n}\n\nconst renderSlider = template(\n\t/* HTML */ `\n\t\t<div class=\"sonic-slider\" role=\"slider\" tabindex=\"0\">\n\t\t\t<div class=\"sonic-slider-scale\" aria-hidden=\"true\"></div>\n\t\t\t<div class=\"sonic-slider-notches\"></div>\n\t\t\t<div class=\"sonic-slider-groove\"></div>\n\t\t\t<div class=\"sonic-slider-modulation\"></div>\n\t\t\t<div class=\"sonic-slider-cap\"></div>\n\t\t\t<div class=\"sonic-slider-readout\" popover=\"manual\">\n\t\t\t\t<span></span>\n\t\t\t\t<input\n\t\t\t\t\tautocomplete=\"off\"\n\t\t\t\t\tclass=\"sonic-slider-entry\"\n\t\t\t\t\tenterkeyhint=\"done\"\n\t\t\t\t\thidden\n\t\t\t\t\tspellcheck=\"false\"\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t`,\n\tHTMLDivElement,\n);\n\nexport class SonicSlider extends SonicValueElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicValueElement.observedAttributes,\n\t\t'modulation',\n\t\t'orientation',\n\t\t'scrub',\n\t\t'spring',\n\t];\n\n\t// fallow-ignore-next-line code-duplication -- one accessor pair per property\n\tget buffered(): Array<[number, number]> {\n\t\treturn this.#buffered.map(([start, end]) => [start, end]);\n\t}\n\n\tset buffered(regions: TimeRegions | undefined) {\n\t\tthis.#buffered = sortedRegions(regions);\n\t\tthis.render();\n\t}\n\n\tget groovePress(): 'jump' | 'none' {\n\t\treturn this.getAttribute('groove-press') === 'none' ? 'none' : 'jump';\n\t}\n\n\tset groovePress(gesture: 'jump' | 'none' | undefined) {\n\t\tthis.reflect('groove-press', gesture);\n\t}\n\n\tget modulation(): number {\n\t\treturn this.numberAttribute('modulation', 0);\n\t}\n\n\tset modulation(amount: number | undefined) {\n\t\tthis.reflect('modulation', amount);\n\t}\n\n\tget modulationValue(): number | undefined {\n\t\treturn this.readModulationValue();\n\t}\n\n\tset modulationValue(value: null | number | undefined) {\n\t\tthis.writeModulationValue(this.#slider, 'slider', value);\n\t}\n\n\tget orientation(): 'horizontal' | 'vertical' {\n\t\treturn this.getAttribute('orientation') === 'vertical' ? 'vertical' : 'horizontal';\n\t}\n\n\tset orientation(direction: 'horizontal' | 'vertical' | undefined) {\n\t\tthis.reflect('orientation', direction);\n\t}\n\n\tget scrub(): boolean {\n\t\treturn this.hasAttribute('scrub');\n\t}\n\n\tset scrub(isScrubbing: boolean) {\n\t\tthis.reflect('scrub', isScrubbing);\n\t}\n\n\tget spring(): boolean {\n\t\treturn this.hasAttribute('spring');\n\t}\n\n\tset spring(isSpring: boolean) {\n\t\tthis.reflect('spring', isSpring);\n\t}\n\n\t#buffered: Array<[number, number]> = [];\n\n\t#hover: HoverPreview | undefined;\n\n\treadonly #slider = renderSlider();\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(\n\t\t\t'buffered',\n\t\t\t'groovePress',\n\t\t\t'modulationValue',\n\t\t\t'modulation',\n\t\t\t'orientation',\n\t\t\t'scrub',\n\t\t\t'spring',\n\t\t);\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst slider = this.#slider;\n\t\tconst cap = requireChild(slider, '.sonic-slider-cap', HTMLDivElement);\n\n\t\tbindScale(\n\t\t\tthis,\n\t\t\t{ control: slider, marks: requireChild(slider, '.sonic-slider-scale', HTMLDivElement) },\n\t\t\tsignal,\n\t\t);\n\t\tslider.addEventListener(\n\t\t\t'transitionend',\n\t\t\t(event) => {\n\t\t\t\tif (event.propertyName === '--_sonic-slider-value') this.toggleState('springing', false);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.#hover = bindHoverPreview(\n\t\t\tslider,\n\t\t\t{\n\t\t\t\tcanShow: () => this.scrub && this.readout && this.orientation === 'horizontal',\n\t\t\t\tdismiss: () => {\n\t\t\t\t\tthis.render();\n\t\t\t\t},\n\t\t\t\tisTaken: () => this.isEditing() || this.isRevealed(),\n\t\t\t\tshow: () => {\n\t\t\t\t\tthis.renderReadout();\n\t\t\t\t\tthis.#placeReadout(slider);\n\t\t\t\t},\n\t\t\t\tvalueAt: (event) => {\n\t\t\t\t\tconst axis = this.#axis(slider, cap);\n\t\t\t\t\tconst at = clampProportion((axis.position(event) - axis.startPx) / axis.travelPx);\n\t\t\t\t\tconst mapping = this.mapping();\n\n\t\t\t\t\treturn mapping.snap(mapping.valueAt(at));\n\t\t\t\t},\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tthis.render();\n\t\tthis.checkStyles(slider, 'slider.css');\n\t\tthis.bindGestures(slider, signal, (event) => {\n\t\t\tconst axis = this.#axis(slider, cap);\n\t\t\tif (event.target instanceof Node && cap.contains(event.target)) return axis;\n\n\t\t\tif (this.groovePress === 'none') return;\n\n\t\t\tthis.input(this.mapping().valueAt((axis.position(event) - axis.startPx) / axis.travelPx));\n\n\t\t\treturn axis;\n\t\t});\n\t}\n\n\tprotected override controlOrientation(): 'horizontal' | 'vertical' {\n\t\treturn this.orientation;\n\t}\n\n\tprotected draw(): void {\n\t\tif (this.isEditing() || this.isRevealed()) this.#hover?.clear();\n\t\tthis.writeProportions(this.#slider, 'slider', this.modulation);\n\t\tthis.#renderBuffered(this.#slider);\n\t\tthis.#renderScrub(this.#slider);\n\t\tthis.#placeReadout(this.#slider);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.#slider;\n\t}\n\n\tprotected override heldWrite(next: number): void {\n\t\tsuper.heldWrite(next);\n\t\tif (this.scrub) this.render();\n\t}\n\n\tprotected override holdChanged(): void {\n\t\tif (this.scrub) this.render();\n\t}\n\n\tprotected override previewValue(): number | undefined {\n\t\treturn this.#hover?.value();\n\t}\n\n\tprotected override scrubsKeyRepeat(): boolean {\n\t\treturn this.scrub;\n\t}\n\n\tprotected override springTarget(): number | undefined {\n\t\treturn this.spring ? this.originValue() : undefined;\n\t}\n\n\t#axis(slider: HTMLElement, cap: HTMLElement): SliderAxis {\n\t\tconst box = slider.getBoundingClientRect();\n\t\tconst capBox = cap.getBoundingClientRect();\n\n\t\treturn this.orientation === 'vertical'\n\t\t\t? {\n\t\t\t\t\tposition: (event) => -event.clientY,\n\t\t\t\t\tstartPx: capBox.height / 2 - box.bottom,\n\t\t\t\t\ttravelPx: Math.max(1, box.height - capBox.height),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tposition: (event) => event.clientX,\n\t\t\t\t\tstartPx: box.left + capBox.width / 2,\n\t\t\t\t\ttravelPx: Math.max(1, box.width - capBox.width),\n\t\t\t\t};\n\t}\n\n\t#placeReadout(slider: HTMLElement): void {\n\t\tif (!this.scrub) {\n\t\t\tslider.style.removeProperty('--_sonic-slider-readout-value');\n\t\t\treturn;\n\t\t}\n\n\t\tslider.style.setProperty(\n\t\t\t'--_sonic-slider-readout-value',\n\t\t\tString(this.mapping().proportionOf(this.readoutValue())),\n\t\t);\n\t}\n\n\t#renderBuffered(slider: HTMLElement): void {\n\t\tconst buffered = this.#buffered;\n\n\t\tif (buffered.length === 0) {\n\t\t\tslider.style.removeProperty('--_sonic-slider-buffered-regions');\n\t\t\treturn;\n\t\t}\n\n\t\tconst { proportionOf } = this.mapping();\n\t\tconst stops = buffered.flatMap(([start, end]) => {\n\t\t\tconst from = grooveStop(proportionOf(Math.min(start, end)));\n\t\t\tconst to = grooveStop(proportionOf(Math.max(start, end)));\n\n\t\t\treturn [\n\t\t\t\t`transparent ${from}`,\n\t\t\t\t`var(--_sonic-slider-buffered) ${from} ${to}`,\n\t\t\t\t`transparent ${to}`,\n\t\t\t];\n\t\t});\n\n\t\tslider.style.setProperty(\n\t\t\t'--_sonic-slider-buffered-regions',\n\t\t\t`linear-gradient(var(--_sonic-slider-toward), ${stops.join(', ')})`,\n\t\t);\n\t}\n\n\t#renderScrub(slider: HTMLElement): void {\n\t\tconst { style } = slider;\n\t\tconst { proportionOf } = this.mapping();\n\t\tconst isHeld = this.scrub && this.heldFrom() !== undefined;\n\t\tconst played = proportionOf(this.playback());\n\t\tconst scrubbed = proportionOf(this.value);\n\n\t\tif (isHeld) style.setProperty('--_sonic-slider-played', String(played));\n\t\telse style.removeProperty('--_sonic-slider-played');\n\n\t\tif (played === scrubbed || !isHeld || !this.isRevealed()) {\n\t\t\tstyle.removeProperty('--_sonic-slider-scrub-region');\n\t\t\treturn;\n\t\t}\n\n\t\tconst from = grooveStop(Math.min(played, scrubbed));\n\t\tconst to = grooveStop(Math.max(played, scrubbed));\n\n\t\tstyle.setProperty(\n\t\t\t'--_sonic-slider-scrub-region',\n\t\t\t`linear-gradient(var(--_sonic-slider-toward), transparent ${from}, var(--_sonic-slider-scrub) ${from} ${to}, transparent ${to})`,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"slider.js","names":[],"sources":["../../../src/elements/slider.ts"],"sourcesContent":["import type { ValueAxis } from '#elements/value-gestures.ts';\nimport type { TimeRegions } from '#lib/time-regions.ts';\n\nimport { createModulation } from '#elements/modulation.ts';\nimport { bindScale } from '#elements/scale.ts';\nimport { SonicValueElement } from '#elements/value-element.ts';\nimport { clampProportion } from '#lib/math.ts';\nimport { requireChild, template } from '#lib/render.ts';\nimport { sortedRegions } from '#lib/time-regions.ts';\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sonic-slider': SonicSlider;\n\t}\n}\n\ninterface SliderAxis extends ValueAxis {\n\tstartPx: number;\n}\n\nfunction grooveStop(proportion: number): string {\n\tif (proportion <= 0) return '0%';\n\tif (proportion >= 1) return '100%';\n\n\treturn `calc(${String(proportion)} * var(--_sonic-slider-travel) + var(--_sonic-slider-groove) / 2)`;\n}\n\nconst renderSlider = template(\n\t/* HTML */ `\n\t\t<div class=\"sonic-slider\" role=\"slider\" tabindex=\"0\">\n\t\t\t<div class=\"sonic-slider-scale\" aria-hidden=\"true\"></div>\n\t\t\t<div class=\"sonic-slider-notches\"></div>\n\t\t\t<div class=\"sonic-slider-groove\"></div>\n\t\t\t<div class=\"sonic-slider-modulation\"></div>\n\t\t\t<div class=\"sonic-slider-cap\"></div>\n\t\t\t<div class=\"sonic-slider-readout\" popover=\"manual\">\n\t\t\t\t<span></span>\n\t\t\t\t<input\n\t\t\t\t\tautocomplete=\"off\"\n\t\t\t\t\tclass=\"sonic-slider-entry\"\n\t\t\t\t\tenterkeyhint=\"done\"\n\t\t\t\t\thidden\n\t\t\t\t\tspellcheck=\"false\"\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t`,\n\tHTMLDivElement,\n);\n\nexport class SonicSlider extends SonicValueElement {\n\tstatic override readonly observedAttributes = [\n\t\t...SonicValueElement.observedAttributes,\n\t\t'modulation',\n\t\t'orientation',\n\t\t'scrub',\n\t\t'spring',\n\t];\n\n\t// fallow-ignore-next-line code-duplication -- one accessor pair per property\n\tget buffered(): Array<[number, number]> {\n\t\treturn this.#buffered.map(([start, end]) => [start, end]);\n\t}\n\n\tset buffered(regions: TimeRegions | undefined) {\n\t\tthis.#buffered = sortedRegions(regions);\n\t\tthis.render();\n\t}\n\n\tget groovePress(): 'jump' | 'none' {\n\t\treturn this.getAttribute('groove-press') === 'none' ? 'none' : 'jump';\n\t}\n\n\tset groovePress(gesture: 'jump' | 'none' | undefined) {\n\t\tthis.reflect('groove-press', gesture);\n\t}\n\n\tget modulation(): number {\n\t\treturn this.numberAttribute('modulation', 0);\n\t}\n\n\tset modulation(amount: number | undefined) {\n\t\tthis.reflect('modulation', amount);\n\t}\n\n\tget modulationValue(): number | undefined {\n\t\treturn this.#modulation.value();\n\t}\n\n\tset modulationValue(value: null | number | undefined) {\n\t\tthis.#modulation.write(value, this.isBound() ? this.mapping() : undefined);\n\t}\n\n\tget orientation(): 'horizontal' | 'vertical' {\n\t\treturn this.getAttribute('orientation') === 'vertical' ? 'vertical' : 'horizontal';\n\t}\n\n\tset orientation(direction: 'horizontal' | 'vertical' | undefined) {\n\t\tthis.reflect('orientation', direction);\n\t}\n\n\tget scrub(): boolean {\n\t\treturn this.hasAttribute('scrub');\n\t}\n\n\tset scrub(isScrubbing: boolean) {\n\t\tthis.reflect('scrub', isScrubbing);\n\t}\n\n\tget spring(): boolean {\n\t\treturn this.hasAttribute('spring');\n\t}\n\n\tset spring(isSpring: boolean) {\n\t\tthis.reflect('spring', isSpring);\n\t}\n\n\t#buffered: Array<[number, number]> = [];\n\n\treadonly #slider = renderSlider();\n\n\treadonly #modulation = createModulation(this.#slider, 'slider', (isModulated) => {\n\t\tthis.toggleState('modulated', isModulated);\n\t});\n\n\toverride connectedCallback(): void {\n\t\tthis.upgradeProperties(\n\t\t\t'buffered',\n\t\t\t'groovePress',\n\t\t\t'modulationValue',\n\t\t\t'modulation',\n\t\t\t'orientation',\n\t\t\t'scrub',\n\t\t\t'spring',\n\t\t);\n\t\tsuper.connectedCallback();\n\t}\n\n\tprotected connect(signal: AbortSignal): void {\n\t\tconst slider = this.#slider;\n\t\tconst cap = requireChild(slider, '.sonic-slider-cap', HTMLDivElement);\n\n\t\tbindScale(\n\t\t\tthis,\n\t\t\t{ control: slider, marks: requireChild(slider, '.sonic-slider-scale', HTMLDivElement) },\n\t\t\tsignal,\n\t\t);\n\t\tslider.addEventListener(\n\t\t\t'transitionend',\n\t\t\t(event) => {\n\t\t\t\tif (event.propertyName === '--_sonic-slider-value') this.toggleState('springing', false);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tthis.bindHover(slider, signal, {\n\t\t\tcanShow: () => this.scrub && this.readout && this.orientation === 'horizontal',\n\t\t\tplace: () => {\n\t\t\t\tthis.#placeReadout(slider);\n\t\t\t},\n\t\t\tvalueAt: (event) => {\n\t\t\t\tconst axis = this.#axis(slider, cap);\n\t\t\t\tconst at = clampProportion((axis.position(event) - axis.startPx) / axis.travelPx);\n\t\t\t\tconst mapping = this.mapping();\n\n\t\t\t\treturn mapping.snap(mapping.valueAt(at));\n\t\t\t},\n\t\t});\n\t\tthis.render();\n\t\tthis.checkStyles(slider, 'slider.css');\n\t\tthis.bindGestures(slider, signal, (event) => {\n\t\t\tconst axis = this.#axis(slider, cap);\n\t\t\tif (event.target instanceof Node && cap.contains(event.target)) return axis;\n\n\t\t\tif (this.groovePress === 'none') return;\n\n\t\t\tthis.input(this.mapping().valueAt((axis.position(event) - axis.startPx) / axis.travelPx));\n\n\t\t\treturn axis;\n\t\t});\n\t}\n\n\tprotected override controlOrientation(): 'horizontal' | 'vertical' {\n\t\treturn this.orientation;\n\t}\n\n\tprotected draw(): void {\n\t\tthis.#modulation.draw({\n\t\t\tmapping: this.mapping(),\n\t\t\tmodulation: this.modulation,\n\t\t\torigin: this.originValue(),\n\t\t\tvalue: this.value,\n\t\t});\n\t\tthis.#renderBuffered(this.#slider);\n\t\tthis.#renderScrub(this.#slider);\n\t\tthis.#placeReadout(this.#slider);\n\t}\n\n\tprotected override focusTarget(): HTMLElement {\n\t\treturn this.#slider;\n\t}\n\n\tprotected override heldWrite(next: number): void {\n\t\tsuper.heldWrite(next);\n\t\tif (this.scrub) this.render();\n\t}\n\n\tprotected override holdChanged(): void {\n\t\tif (this.scrub) this.render();\n\t}\n\n\tprotected override scrubsKeyRepeat(): boolean {\n\t\treturn this.scrub;\n\t}\n\n\tprotected override springTarget(): number | undefined {\n\t\treturn this.spring ? this.originValue() : undefined;\n\t}\n\n\t#axis(slider: HTMLElement, cap: HTMLElement): SliderAxis {\n\t\tconst box = slider.getBoundingClientRect();\n\t\tconst capBox = cap.getBoundingClientRect();\n\n\t\treturn this.orientation === 'vertical'\n\t\t\t? {\n\t\t\t\t\tposition: (event) => -event.clientY,\n\t\t\t\t\tstartPx: capBox.height / 2 - box.bottom,\n\t\t\t\t\ttravelPx: Math.max(1, box.height - capBox.height),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tposition: (event) => event.clientX,\n\t\t\t\t\tstartPx: box.left + capBox.width / 2,\n\t\t\t\t\ttravelPx: Math.max(1, box.width - capBox.width),\n\t\t\t\t};\n\t}\n\n\t#placeReadout(slider: HTMLElement): void {\n\t\tif (!this.scrub) {\n\t\t\tslider.style.removeProperty('--_sonic-slider-readout-value');\n\t\t\treturn;\n\t\t}\n\n\t\tslider.style.setProperty(\n\t\t\t'--_sonic-slider-readout-value',\n\t\t\tString(this.mapping().proportionOf(this.readoutValue())),\n\t\t);\n\t}\n\n\t#renderBuffered(slider: HTMLElement): void {\n\t\tconst buffered = this.#buffered;\n\n\t\tif (buffered.length === 0) {\n\t\t\tslider.style.removeProperty('--_sonic-slider-buffered-regions');\n\t\t\treturn;\n\t\t}\n\n\t\tconst { proportionOf } = this.mapping();\n\t\tconst stops = buffered.flatMap(([start, end]) => {\n\t\t\tconst from = grooveStop(proportionOf(Math.min(start, end)));\n\t\t\tconst to = grooveStop(proportionOf(Math.max(start, end)));\n\n\t\t\treturn [\n\t\t\t\t`transparent ${from}`,\n\t\t\t\t`var(--_sonic-slider-buffered) ${from} ${to}`,\n\t\t\t\t`transparent ${to}`,\n\t\t\t];\n\t\t});\n\n\t\tslider.style.setProperty(\n\t\t\t'--_sonic-slider-buffered-regions',\n\t\t\t`linear-gradient(var(--_sonic-slider-toward), ${stops.join(', ')})`,\n\t\t);\n\t}\n\n\t#renderScrub(slider: HTMLElement): void {\n\t\tconst { style } = slider;\n\t\tconst { proportionOf } = this.mapping();\n\t\tconst isHeld = this.scrub && this.heldFrom() !== undefined;\n\t\tconst played = proportionOf(this.playback());\n\t\tconst scrubbed = proportionOf(this.value);\n\n\t\tif (isHeld) style.setProperty('--_sonic-slider-played', String(played));\n\t\telse style.removeProperty('--_sonic-slider-played');\n\n\t\tif (played === scrubbed || !isHeld || !this.isRevealed()) {\n\t\t\tstyle.removeProperty('--_sonic-slider-scrub-region');\n\t\t\treturn;\n\t\t}\n\n\t\tconst from = grooveStop(Math.min(played, scrubbed));\n\t\tconst to = grooveStop(Math.max(played, scrubbed));\n\n\t\tstyle.setProperty(\n\t\t\t'--_sonic-slider-scrub-region',\n\t\t\t`linear-gradient(var(--_sonic-slider-toward), transparent ${from}, var(--_sonic-slider-scrub) ${from} ${to}, transparent ${to})`,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
@@ -1,12 +1,11 @@
1
1
  import { SonicFormElement } from "./form-element.js";
2
2
  import { ValueMapping } from "../lib/value-mapping.js";
3
+ import { ValueAxis } from "./value-gestures.js";
3
4
  //#region src/elements/value-element.d.ts
4
- export interface ValueAxis {
5
- fromProportion?: number;
6
- isKeptOnCancel?: boolean;
7
- outside?: (event: PointerEvent) => boolean;
8
- position: (event: PointerEvent) => number;
9
- travelPx: number;
5
+ interface HoverBinding {
6
+ canShow: () => boolean;
7
+ place: () => void;
8
+ valueAt: (event: PointerEvent) => number | undefined;
10
9
  }
11
10
  export declare abstract class SonicValueElement extends SonicFormElement {
12
11
  #private;
@@ -17,8 +16,8 @@ export declare abstract class SonicValueElement extends SonicFormElement {
17
16
  set detent(value: number | undefined);
18
17
  get dimmed(): boolean;
19
18
  set dimmed(isDimmed: boolean);
20
- get doublePress(): 'entry' | 'reset';
21
- set doublePress(gesture: 'entry' | 'reset' | undefined);
19
+ get doublePress(): 'entry' | 'none' | 'reset';
20
+ set doublePress(gesture: 'entry' | 'none' | 'reset' | undefined);
22
21
  get formatSpokenValue(): ((value: number) => string) | undefined;
23
22
  set formatSpokenValue(format: ((value: number) => string) | undefined);
24
23
  get formatValue(): ((value: number) => string) | undefined;
@@ -54,6 +53,7 @@ export declare abstract class SonicValueElement extends SonicFormElement {
54
53
  attributeChangedCallback(name: string): void;
55
54
  connectedCallback(): void;
56
55
  protected bindGestures(control: HTMLElement, signal: AbortSignal, grab: (event: PointerEvent) => undefined | ValueAxis): void;
56
+ protected bindHover(control: HTMLElement, signal: AbortSignal, { canShow, place, valueAt }: HoverBinding): void;
57
57
  protected controlOrientation(): 'horizontal' | 'vertical' | undefined;
58
58
  protected controlRole(): 'slider' | 'spinbutton';
59
59
  protected abstract draw(): void;
@@ -62,15 +62,12 @@ export declare abstract class SonicValueElement extends SonicFormElement {
62
62
  protected heldWrite(next: number): void;
63
63
  protected holdChanged(): void;
64
64
  protected input(next: number): boolean;
65
- protected isEditing(): boolean;
66
65
  protected isRevealed(): boolean;
67
66
  protected isWrapping(): boolean;
68
67
  protected mapping(): ValueMapping;
69
68
  protected originValue(): number;
70
69
  protected playback(): number;
71
- protected previewValue(): number | undefined;
72
70
  protected proportionsChanged(): void;
73
- protected readModulationValue(): number | undefined;
74
71
  protected readoutValue(): number;
75
72
  protected render(): void;
76
73
  protected renderReadout(): void;
@@ -79,8 +76,6 @@ export declare abstract class SonicValueElement extends SonicFormElement {
79
76
  protected springTarget(): number | undefined;
80
77
  protected tapTarget(): number | undefined;
81
78
  protected travelPx(control: HTMLElement, property: `--_sonic-${string}`): number;
82
- protected writeModulationValue(control: HTMLElement, prefix: 'dial' | 'slider', next: null | number | undefined): void;
83
- protected writeProportions(control: HTMLElement, prefix: 'dial' | 'slider', modulation: number): void;
84
79
  }
85
80
  //#endregion
86
81
  //# sourceMappingURL=value-element.d.ts.map