@xsynaptic/sonic-ui 0.8.0 → 0.10.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.
- package/README.md +0 -2
- package/dist/default/elements/dial.js +12 -3
- package/dist/default/elements/display-element.js +14 -2
- package/dist/default/elements/envelope.js +2 -2
- package/dist/default/elements/modulation.js +45 -0
- package/dist/default/elements/readout-claim.js +8 -3
- package/dist/default/elements/slider.js +16 -18
- package/dist/default/elements/spectrum.js +1 -0
- package/dist/default/elements/value-element.js +108 -330
- package/dist/default/elements/value-gestures.js +301 -0
- package/dist/default/elements/wave-element.js +5 -26
- package/dist/default/elements/waveform.js +6 -2
- package/dist/default/elements/wavestrip.js +5 -16
- package/dist/default/elements/xy.js +9 -20
- package/dist/default/lib/asked-value.js +21 -0
- package/dist/default/lib/canvas-surface.js +3 -0
- package/dist/default/lib/fill-watch.js +29 -0
- package/dist/default/lib/hover-preview.js +8 -3
- package/dist/default/lib/marker-rider.js +6 -3
- package/dist/default/lib/read-ms-property.js +10 -0
- package/dist/dev/elements/dial.js +12 -3
- package/dist/dev/elements/dial.js.map +1 -1
- package/dist/dev/elements/display-element.d.ts +4 -1
- package/dist/dev/elements/display-element.js +14 -2
- package/dist/dev/elements/display-element.js.map +1 -1
- package/dist/dev/elements/envelope.js +2 -2
- package/dist/dev/elements/envelope.js.map +1 -1
- package/dist/dev/elements/modulation.js +46 -0
- package/dist/dev/elements/modulation.js.map +1 -0
- package/dist/dev/elements/readout-claim.js +8 -3
- package/dist/dev/elements/readout-claim.js.map +1 -1
- package/dist/dev/elements/slider.d.ts +0 -1
- package/dist/dev/elements/slider.js +16 -18
- package/dist/dev/elements/slider.js.map +1 -1
- package/dist/dev/elements/spectrum.d.ts +1 -0
- package/dist/dev/elements/spectrum.js +1 -0
- package/dist/dev/elements/spectrum.js.map +1 -1
- package/dist/dev/elements/value-element.d.ts +11 -13
- package/dist/dev/elements/value-element.js +108 -330
- package/dist/dev/elements/value-element.js.map +1 -1
- package/dist/dev/elements/value-gestures.d.ts +10 -0
- package/dist/dev/elements/value-gestures.js +302 -0
- package/dist/dev/elements/value-gestures.js.map +1 -0
- package/dist/dev/elements/wave-element.js +5 -26
- package/dist/dev/elements/wave-element.js.map +1 -1
- package/dist/dev/elements/waveform.js +6 -2
- package/dist/dev/elements/waveform.js.map +1 -1
- package/dist/dev/elements/wavestrip.d.ts +0 -1
- package/dist/dev/elements/wavestrip.js +5 -16
- package/dist/dev/elements/wavestrip.js.map +1 -1
- package/dist/dev/elements/xy.js +9 -20
- package/dist/dev/elements/xy.js.map +1 -1
- package/dist/dev/lib/asked-value.js +22 -0
- package/dist/dev/lib/asked-value.js.map +1 -0
- package/dist/dev/lib/canvas-surface.d.ts +1 -0
- package/dist/dev/lib/canvas-surface.js +3 -0
- package/dist/dev/lib/canvas-surface.js.map +1 -1
- package/dist/dev/lib/fill-watch.js +30 -0
- package/dist/dev/lib/fill-watch.js.map +1 -0
- package/dist/dev/lib/hover-preview.js +8 -3
- package/dist/dev/lib/hover-preview.js.map +1 -1
- package/dist/dev/lib/marker-rider.js +6 -3
- package/dist/dev/lib/marker-rider.js.map +1 -1
- package/dist/dev/lib/read-ms-property.js +11 -0
- package/dist/dev/lib/read-ms-property.js.map +1 -0
- package/dist/styles/envelope.css +1 -1
- package/dist/styles/led.css +1 -1
- package/dist/styles/material.css +42 -8
- package/dist/styles/spectrum.css +5 -0
- package/dist/styles/switch.css +42 -33
- package/dist/styles/waveform.css +31 -2
- package/dist/styles/wavestrip.css +13 -7
- package/dist/styles/xy.css +4 -4
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-surface.js","names":["named"],"sources":["../../../src/lib/canvas-surface.ts"],"sourcesContent":["import { readPxProperty } from '#lib/read-px-property.ts';\n\ntype PrivateProperty = `--_sonic-${string}`;\n\nexport interface SurfaceSize {\n\tdpr: number;\n\theight: number;\n\twidth: number;\n}\n\nexport interface SurfaceLook<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n> {\n\tcolours: Record<Colour, string>;\n\tisReducedMotion: boolean;\n\tlengths: Record<Length, number>;\n\tnumbers: Record<Numeric, number>;\n}\n\nexport interface SurfaceFrame<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n> {\n\tframeMs: number;\n\tisDirty: boolean;\n\tisRebuilt: boolean;\n\tlook: SurfaceLook<Colour, Length, Numeric>;\n\tsize: SurfaceSize;\n}\n\nexport interface Surface {\n\tinvalidate: () => void;\n\trebuild: () => void;\n\trequestFrame: () => void;\n\treadonly size: SurfaceSize;\n}\n\ninterface SurfaceOptions<Colour extends string, Length extends string, Numeric extends string> {\n\tcanvas: HTMLCanvasElement;\n\tcolours: Record<Colour, PrivateProperty>;\n\tlengths?: Record<Length, PrivateProperty>;\n\tnumbers?: Record<Numeric, PrivateProperty>;\n\tpaint: (context: CanvasRenderingContext2D, frame: SurfaceFrame<Colour, Length, Numeric>) => void;\n\tresize?: (size: SurfaceSize) => void;\n\tsignal: AbortSignal;\n}\n\nfunction deviceRatio(): number {\n\treturn globalThis.devicePixelRatio || 1;\n}\n\n// WebKit reports none, and an emulated device scale reports it in CSS px, so it counts only where it agrees\nfunction deviceBox(\n\tentry: ResizeObserverEntry,\n\tcss: ResizeObserverSize,\n): ResizeObserverSize | undefined {\n\tconst device =\n\t\t'devicePixelContentBoxSize' in entry ? entry.devicePixelContentBoxSize[0] : undefined;\n\tconst dpr = deviceRatio();\n\tif (!device || Math.abs(device.inlineSize - css.inlineSize * dpr) > 1) return undefined;\n\n\treturn Math.abs(device.blockSize - css.blockSize * dpr) > 1 ? undefined : device;\n}\n\n// `Object.fromEntries` widens the keys to `string`\nfunction readEach<Name extends string, Value>(\n\tproperties: Partial<Record<Name, PrivateProperty>>,\n\tread: (property: PrivateProperty) => Value,\n): Record<Name, Value> {\n\tconst named: Readonly<Record<string, PrivateProperty | undefined>> = properties;\n\n\treturn Object.fromEntries(\n\t\tObject.entries(named).flatMap(([name, property]) =>\n\t\t\tproperty === undefined ? [] : [[name, read(property)]],\n\t\t),\n\t) as Record<Name, Value>;\n}\n\nclass CanvasSurface<\n\tColour extends string,\n\tLength extends string,\n\tNumeric extends string,\n> implements Surface {\n\tget size(): SurfaceSize {\n\t\treturn this.#size;\n\t}\n\n\t// happy-dom has no canvas context\n\treadonly #context: CanvasRenderingContext2D | undefined;\n\n\t#cssBox: undefined | { height: number; width: number };\n\n\t#frame: number | undefined;\n\n\t#isDirty = true;\n\n\t#isRebuildWanted = true;\n\n\t#isVisible = true;\n\n\t#look: SurfaceLook<Colour, Length, Numeric> | undefined;\n\n\treadonly #options: SurfaceOptions<Colour, Length, Numeric>;\n\n\treadonly #reducedMotion = matchMedia('(prefers-reduced-motion: reduce)');\n\n\t#size: SurfaceSize = { dpr: deviceRatio(), height: 0, width: 0 };\n\n\tconstructor(options: SurfaceOptions<Colour, Length, Numeric>) {\n\t\tconst { canvas, signal } = options;\n\n\t\tthis.#options = options;\n\t\tthis.#context = canvas.getContext('2d') ?? undefined;\n\t\tthis.#armTransitions();\n\t\tthis.#observeSize();\n\t\tthis.#observeView();\n\t\tthis.#watchResolution();\n\t\tthis.#reducedMotion.addEventListener(\n\t\t\t'change',\n\t\t\t() => {\n\t\t\t\tthis.rebuild();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\t// `transitionstart` drops events when a change replaces a pending transition in WebKit\n\t\tcanvas.addEventListener(\n\t\t\t'transitionrun',\n\t\t\t() => {\n\t\t\t\tthis.rebuild();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tif (this.#frame !== undefined) cancelAnimationFrame(this.#frame);\n\t\t\t\tthis.#frame = undefined;\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t\tthis.#schedule();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.#isDirty = true;\n\t\tthis.#schedule();\n\t}\n\n\trebuild(): void {\n\t\tthis.#isRebuildWanted = true;\n\t\tthis.invalidate();\n\t}\n\n\trequestFrame(): void {\n\t\tthis.#schedule();\n\t}\n\n\t#armTransitions(): void {\n\t\tconst { canvas, colours, numbers = {} } = this.#options;\n\t\tconst { style } = canvas;\n\t\tconst watched = [...Object.values(colours), ...Object.values(numbers)];\n\n\t\tstyle.setProperty('transition-property', watched.join(', '));\n\t\tstyle.setProperty('transition-duration', '0.001ms');\n\t\tstyle.setProperty('transition-timing-function', 'step-start');\n\t\tstyle.setProperty('transition-behavior', 'allow-discrete');\n\t}\n\n\t#current(): { isRebuilt: boolean; look: SurfaceLook<Colour, Length, Numeric> } {\n\t\tif (this.#look && !this.#isRebuildWanted) return { isRebuilt: false, look: this.#look };\n\n\t\treturn { isRebuilt: true, look: this.#read() };\n\t}\n\n\t#draw(frameMs: number): void {\n\t\tthis.#frame = undefined;\n\n\t\tconst size = this.#size;\n\t\tif (size.width === 0 || size.height === 0) return;\n\n\t\tconst { canvas, paint } = this.#options;\n\t\tconst { isRebuilt, look } = this.#current();\n\t\tconst isDirty = this.#isDirty;\n\n\t\tthis.#look = look;\n\t\tthis.#isDirty = false;\n\t\tthis.#isRebuildWanted = false;\n\t\t// Assigning either clears the canvas and its state\n\t\tif (canvas.width !== size.width) canvas.width = size.width;\n\t\tif (canvas.height !== size.height) canvas.height = size.height;\n\t\tif (this.#context) paint(this.#context, { frameMs, isDirty, isRebuilt, look, size });\n\t}\n\n\t#measure(entry: ResizeObserverEntry): void {\n\t\tconst [box] = entry.contentBoxSize;\n\t\tif (!box) return;\n\n\t\tconst device = deviceBox(entry, box);\n\n\t\tif (device) {\n\t\t\tthis.#cssBox = undefined;\n\t\t\tthis.#resize(device.inlineSize, device.blockSize);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#cssBox = { height: box.blockSize, width: box.inlineSize };\n\t\tthis.#rescale();\n\t}\n\n\t#observeSize(): void {\n\t\tconst { canvas, signal } = this.#options;\n\t\tconst observer = new ResizeObserver((entries) => {\n\t\t\tconst entry = entries.at(-1);\n\n\t\t\tif (entry) this.#measure(entry);\n\t\t});\n\n\t\ttry {\n\t\t\tobserver.observe(canvas, { box: 'device-pixel-content-box' });\n\t\t} catch {\n\t\t\t// WebKit throws a TypeError on the option\n\t\t\tobserver.observe(canvas, { box: 'content-box' });\n\t\t}\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tobserver.disconnect();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#observeView(): void {\n\t\tconst { canvas, signal } = this.#options;\n\t\tconst observer = new IntersectionObserver((entries) => {\n\t\t\tconst entry = entries.at(-1);\n\t\t\tif (!entry) return;\n\n\t\t\tconst wasVisible = this.#isVisible;\n\n\t\t\tthis.#isVisible = entry.isIntersecting;\n\t\t\tif (!entry.isIntersecting && this.#frame !== undefined) {\n\t\t\t\tcancelAnimationFrame(this.#frame);\n\t\t\t\tthis.#frame = undefined;\n\t\t\t}\n\n\t\t\t// Chromium fires no transition inside a skipped `content-visibility` subtree\n\t\t\tif (!wasVisible && entry.isIntersecting) this.rebuild();\n\t\t});\n\n\t\tobserver.observe(canvas);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tobserver.disconnect();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#read(): SurfaceLook<Colour, Length, Numeric> {\n\t\tconst { canvas, colours, lengths = {}, numbers = {} } = this.#options;\n\t\tconst styles = getComputedStyle(canvas);\n\n\t\treturn {\n\t\t\tcolours: readEach(colours, (property) =>\n\t\t\t\tstyles\n\t\t\t\t\t.getPropertyValue(property)\n\t\t\t\t\t.trim()\n\t\t\t\t\t.replaceAll('currentcolor', () => styles.color),\n\t\t\t),\n\t\t\tisReducedMotion: this.#reducedMotion.matches,\n\t\t\tlengths: readEach<Length, number>(lengths, (property) => readPxProperty(styles, property, 0)),\n\t\t\tnumbers: readEach<Numeric, number>(numbers, (property) =>\n\t\t\t\treadPxProperty(styles, property, 0),\n\t\t\t),\n\t\t};\n\t}\n\n\t#rescale(): void {\n\t\tconst box = this.#cssBox;\n\t\tif (!box) {\n\t\t\tthis.#resize(this.#size.width, this.#size.height);\n\t\t\treturn;\n\t\t}\n\n\t\tconst dpr = deviceRatio();\n\n\t\tthis.#resize(Math.round(box.width * dpr), Math.round(box.height * dpr));\n\t}\n\n\t#resize(width: number, height: number): void {\n\t\tconst previous = this.#size;\n\t\tconst dpr = deviceRatio();\n\t\tif (previous.width === width && previous.height === height && previous.dpr === dpr) return;\n\n\t\tthis.#size = { dpr, height, width };\n\t\tthis.#options.resize?.(this.#size);\n\t\tif (previous.width === 0 || previous.height === 0) this.rebuild();\n\t\telse this.invalidate();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#options.signal.aborted || this.#frame !== undefined || !this.#isVisible) return;\n\n\t\tthis.#frame = requestAnimationFrame((frameMs) => {\n\t\t\tthis.#draw(frameMs);\n\t\t});\n\t}\n\n\t#watchResolution(): void {\n\t\tconst { signal } = this.#options;\n\n\t\tmatchMedia(`(resolution: ${String(deviceRatio())}dppx)`).addEventListener(\n\t\t\t'change',\n\t\t\t() => {\n\t\t\t\tthis.#watchResolution();\n\t\t\t\tthis.#rescale();\n\t\t\t},\n\t\t\t{ once: true, signal },\n\t\t);\n\t}\n}\n\nexport function bindSurface<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n>(options: SurfaceOptions<Colour, Length, Numeric>): Surface {\n\treturn new CanvasSurface(options);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canvas-surface.js","names":["named"],"sources":["../../../src/lib/canvas-surface.ts"],"sourcesContent":["import { readPxProperty } from '#lib/read-px-property.ts';\n\ntype PrivateProperty = `--_sonic-${string}`;\n\nexport interface SurfaceSize {\n\tdpr: number;\n\theight: number;\n\twidth: number;\n}\n\nexport interface SurfaceLook<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n> {\n\tcolours: Record<Colour, string>;\n\tisReducedMotion: boolean;\n\tlengths: Record<Length, number>;\n\tnumbers: Record<Numeric, number>;\n}\n\nexport interface SurfaceFrame<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n> {\n\tframeMs: number;\n\tisDirty: boolean;\n\tisRebuilt: boolean;\n\tlook: SurfaceLook<Colour, Length, Numeric>;\n\tsize: SurfaceSize;\n}\n\nexport interface Surface {\n\tinvalidate: () => void;\n\treadonly isVisible: boolean;\n\trebuild: () => void;\n\trequestFrame: () => void;\n\treadonly size: SurfaceSize;\n}\n\ninterface SurfaceOptions<Colour extends string, Length extends string, Numeric extends string> {\n\tcanvas: HTMLCanvasElement;\n\tcolours: Record<Colour, PrivateProperty>;\n\tlengths?: Record<Length, PrivateProperty>;\n\tnumbers?: Record<Numeric, PrivateProperty>;\n\tpaint: (context: CanvasRenderingContext2D, frame: SurfaceFrame<Colour, Length, Numeric>) => void;\n\tresize?: (size: SurfaceSize) => void;\n\tsignal: AbortSignal;\n}\n\nfunction deviceRatio(): number {\n\treturn globalThis.devicePixelRatio || 1;\n}\n\n// WebKit reports none, and an emulated device scale reports it in CSS px, so it counts only where it agrees\nfunction deviceBox(\n\tentry: ResizeObserverEntry,\n\tcss: ResizeObserverSize,\n): ResizeObserverSize | undefined {\n\tconst device =\n\t\t'devicePixelContentBoxSize' in entry ? entry.devicePixelContentBoxSize[0] : undefined;\n\tconst dpr = deviceRatio();\n\tif (!device || Math.abs(device.inlineSize - css.inlineSize * dpr) > 1) return undefined;\n\n\treturn Math.abs(device.blockSize - css.blockSize * dpr) > 1 ? undefined : device;\n}\n\n// `Object.fromEntries` widens the keys to `string`\nfunction readEach<Name extends string, Value>(\n\tproperties: Partial<Record<Name, PrivateProperty>>,\n\tread: (property: PrivateProperty) => Value,\n): Record<Name, Value> {\n\tconst named: Readonly<Record<string, PrivateProperty | undefined>> = properties;\n\n\treturn Object.fromEntries(\n\t\tObject.entries(named).flatMap(([name, property]) =>\n\t\t\tproperty === undefined ? [] : [[name, read(property)]],\n\t\t),\n\t) as Record<Name, Value>;\n}\n\nclass CanvasSurface<\n\tColour extends string,\n\tLength extends string,\n\tNumeric extends string,\n> implements Surface {\n\tget isVisible(): boolean {\n\t\treturn this.#isVisible;\n\t}\n\n\tget size(): SurfaceSize {\n\t\treturn this.#size;\n\t}\n\n\t// happy-dom has no canvas context\n\treadonly #context: CanvasRenderingContext2D | undefined;\n\n\t#cssBox: undefined | { height: number; width: number };\n\n\t#frame: number | undefined;\n\n\t#isDirty = true;\n\n\t#isRebuildWanted = true;\n\n\t#isVisible = true;\n\n\t#look: SurfaceLook<Colour, Length, Numeric> | undefined;\n\n\treadonly #options: SurfaceOptions<Colour, Length, Numeric>;\n\n\treadonly #reducedMotion = matchMedia('(prefers-reduced-motion: reduce)');\n\n\t#size: SurfaceSize = { dpr: deviceRatio(), height: 0, width: 0 };\n\n\tconstructor(options: SurfaceOptions<Colour, Length, Numeric>) {\n\t\tconst { canvas, signal } = options;\n\n\t\tthis.#options = options;\n\t\tthis.#context = canvas.getContext('2d') ?? undefined;\n\t\tthis.#armTransitions();\n\t\tthis.#observeSize();\n\t\tthis.#observeView();\n\t\tthis.#watchResolution();\n\t\tthis.#reducedMotion.addEventListener(\n\t\t\t'change',\n\t\t\t() => {\n\t\t\t\tthis.rebuild();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\t// `transitionstart` drops events when a change replaces a pending transition in WebKit\n\t\tcanvas.addEventListener(\n\t\t\t'transitionrun',\n\t\t\t() => {\n\t\t\t\tthis.rebuild();\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tif (this.#frame !== undefined) cancelAnimationFrame(this.#frame);\n\t\t\t\tthis.#frame = undefined;\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t\tthis.#schedule();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.#isDirty = true;\n\t\tthis.#schedule();\n\t}\n\n\trebuild(): void {\n\t\tthis.#isRebuildWanted = true;\n\t\tthis.invalidate();\n\t}\n\n\trequestFrame(): void {\n\t\tthis.#schedule();\n\t}\n\n\t#armTransitions(): void {\n\t\tconst { canvas, colours, numbers = {} } = this.#options;\n\t\tconst { style } = canvas;\n\t\tconst watched = [...Object.values(colours), ...Object.values(numbers)];\n\n\t\tstyle.setProperty('transition-property', watched.join(', '));\n\t\tstyle.setProperty('transition-duration', '0.001ms');\n\t\tstyle.setProperty('transition-timing-function', 'step-start');\n\t\tstyle.setProperty('transition-behavior', 'allow-discrete');\n\t}\n\n\t#current(): { isRebuilt: boolean; look: SurfaceLook<Colour, Length, Numeric> } {\n\t\tif (this.#look && !this.#isRebuildWanted) return { isRebuilt: false, look: this.#look };\n\n\t\treturn { isRebuilt: true, look: this.#read() };\n\t}\n\n\t#draw(frameMs: number): void {\n\t\tthis.#frame = undefined;\n\n\t\tconst size = this.#size;\n\t\tif (size.width === 0 || size.height === 0) return;\n\n\t\tconst { canvas, paint } = this.#options;\n\t\tconst { isRebuilt, look } = this.#current();\n\t\tconst isDirty = this.#isDirty;\n\n\t\tthis.#look = look;\n\t\tthis.#isDirty = false;\n\t\tthis.#isRebuildWanted = false;\n\t\t// Assigning either clears the canvas and its state\n\t\tif (canvas.width !== size.width) canvas.width = size.width;\n\t\tif (canvas.height !== size.height) canvas.height = size.height;\n\t\tif (this.#context) paint(this.#context, { frameMs, isDirty, isRebuilt, look, size });\n\t}\n\n\t#measure(entry: ResizeObserverEntry): void {\n\t\tconst [box] = entry.contentBoxSize;\n\t\tif (!box) return;\n\n\t\tconst device = deviceBox(entry, box);\n\n\t\tif (device) {\n\t\t\tthis.#cssBox = undefined;\n\t\t\tthis.#resize(device.inlineSize, device.blockSize);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#cssBox = { height: box.blockSize, width: box.inlineSize };\n\t\tthis.#rescale();\n\t}\n\n\t#observeSize(): void {\n\t\tconst { canvas, signal } = this.#options;\n\t\tconst observer = new ResizeObserver((entries) => {\n\t\t\tconst entry = entries.at(-1);\n\n\t\t\tif (entry) this.#measure(entry);\n\t\t});\n\n\t\ttry {\n\t\t\tobserver.observe(canvas, { box: 'device-pixel-content-box' });\n\t\t} catch {\n\t\t\t// WebKit throws a TypeError on the option\n\t\t\tobserver.observe(canvas, { box: 'content-box' });\n\t\t}\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tobserver.disconnect();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#observeView(): void {\n\t\tconst { canvas, signal } = this.#options;\n\t\tconst observer = new IntersectionObserver((entries) => {\n\t\t\tconst entry = entries.at(-1);\n\t\t\tif (!entry) return;\n\n\t\t\tconst wasVisible = this.#isVisible;\n\n\t\t\tthis.#isVisible = entry.isIntersecting;\n\t\t\tif (!entry.isIntersecting && this.#frame !== undefined) {\n\t\t\t\tcancelAnimationFrame(this.#frame);\n\t\t\t\tthis.#frame = undefined;\n\t\t\t}\n\n\t\t\t// Chromium fires no transition inside a skipped `content-visibility` subtree\n\t\t\tif (!wasVisible && entry.isIntersecting) this.rebuild();\n\t\t});\n\n\t\tobserver.observe(canvas);\n\t\tsignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tobserver.disconnect();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t#read(): SurfaceLook<Colour, Length, Numeric> {\n\t\tconst { canvas, colours, lengths = {}, numbers = {} } = this.#options;\n\t\tconst styles = getComputedStyle(canvas);\n\n\t\treturn {\n\t\t\tcolours: readEach(colours, (property) =>\n\t\t\t\tstyles\n\t\t\t\t\t.getPropertyValue(property)\n\t\t\t\t\t.trim()\n\t\t\t\t\t.replaceAll('currentcolor', () => styles.color),\n\t\t\t),\n\t\t\tisReducedMotion: this.#reducedMotion.matches,\n\t\t\tlengths: readEach<Length, number>(lengths, (property) => readPxProperty(styles, property, 0)),\n\t\t\tnumbers: readEach<Numeric, number>(numbers, (property) =>\n\t\t\t\treadPxProperty(styles, property, 0),\n\t\t\t),\n\t\t};\n\t}\n\n\t#rescale(): void {\n\t\tconst box = this.#cssBox;\n\t\tif (!box) {\n\t\t\tthis.#resize(this.#size.width, this.#size.height);\n\t\t\treturn;\n\t\t}\n\n\t\tconst dpr = deviceRatio();\n\n\t\tthis.#resize(Math.round(box.width * dpr), Math.round(box.height * dpr));\n\t}\n\n\t#resize(width: number, height: number): void {\n\t\tconst previous = this.#size;\n\t\tconst dpr = deviceRatio();\n\t\tif (previous.width === width && previous.height === height && previous.dpr === dpr) return;\n\n\t\tthis.#size = { dpr, height, width };\n\t\tthis.#options.resize?.(this.#size);\n\t\tif (previous.width === 0 || previous.height === 0) this.rebuild();\n\t\telse this.invalidate();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#options.signal.aborted || this.#frame !== undefined || !this.#isVisible) return;\n\n\t\tthis.#frame = requestAnimationFrame((frameMs) => {\n\t\t\tthis.#draw(frameMs);\n\t\t});\n\t}\n\n\t#watchResolution(): void {\n\t\tconst { signal } = this.#options;\n\n\t\tmatchMedia(`(resolution: ${String(deviceRatio())}dppx)`).addEventListener(\n\t\t\t'change',\n\t\t\t() => {\n\t\t\t\tthis.#watchResolution();\n\t\t\t\tthis.#rescale();\n\t\t\t},\n\t\t\t{ once: true, signal },\n\t\t);\n\t}\n}\n\nexport function bindSurface<\n\tColour extends string,\n\tLength extends string = never,\n\tNumeric extends string = never,\n>(options: SurfaceOptions<Colour, Length, Numeric>): Surface {\n\treturn new CanvasSurface(options);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/lib/fill-watch.ts
|
|
2
|
+
function bindFill(control, sizeProperty, signal) {
|
|
3
|
+
let watch;
|
|
4
|
+
const stop = () => {
|
|
5
|
+
watch?.disconnect();
|
|
6
|
+
watch = void 0;
|
|
7
|
+
};
|
|
8
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
9
|
+
return (isFilling) => {
|
|
10
|
+
if (signal.aborted || isFilling === (watch !== void 0)) return;
|
|
11
|
+
stop();
|
|
12
|
+
if (!isFilling) {
|
|
13
|
+
control.style.removeProperty(sizeProperty);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const started = new ResizeObserver((entries) => {
|
|
17
|
+
const box = entries.at(-1)?.borderBoxSize[0];
|
|
18
|
+
if (!box) return;
|
|
19
|
+
requestAnimationFrame(() => {
|
|
20
|
+
if (watch === started) control.style.setProperty(sizeProperty, `${String(box.blockSize)}px`);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
watch = started;
|
|
24
|
+
started.observe(control);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
export { bindFill };
|
|
30
|
+
//# sourceMappingURL=fill-watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-watch.js","names":[],"sources":["../../../src/lib/fill-watch.ts"],"sourcesContent":["export function bindFill(\n\tcontrol: HTMLElement,\n\tsizeProperty: `--_sonic-${string}`,\n\tsignal: AbortSignal,\n): (isFilling: boolean) => void {\n\tlet watch: ResizeObserver | undefined;\n\n\tconst stop = (): void => {\n\t\twatch?.disconnect();\n\t\twatch = undefined;\n\t};\n\n\tsignal.addEventListener('abort', stop, { once: true });\n\n\treturn (isFilling) => {\n\t\tif (signal.aborted || isFilling === (watch !== undefined)) return;\n\n\t\tstop();\n\t\tif (!isFilling) {\n\t\t\tcontrol.style.removeProperty(sizeProperty);\n\t\t\treturn;\n\t\t}\n\n\t\tconst started = new ResizeObserver((entries) => {\n\t\t\tconst box = entries.at(-1)?.borderBoxSize[0];\n\t\t\tif (!box) return;\n\n\t\t\t// Written a frame on, or the canvas resizes inside this delivery and WebKit reports a loop\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (watch === started) {\n\t\t\t\t\tcontrol.style.setProperty(sizeProperty, `${String(box.blockSize)}px`);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\twatch = started;\n\t\tstarted.observe(control);\n\t};\n}\n"],"mappings":";AAAA,SAAgB,SACf,SACA,cACA,QAC+B;CAC/B,IAAI;CAEJ,MAAM,aAAmB;EACxB,OAAO,WAAW;EAClB,QAAQ;CACT;CAEA,OAAO,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;CAErD,QAAQ,cAAc;EACrB,IAAI,OAAO,WAAW,eAAe,UAAU,SAAY;EAE3D,KAAK;EACL,IAAI,CAAC,WAAW;GACf,QAAQ,MAAM,eAAe,YAAY;GACzC;EACD;EAEA,MAAM,UAAU,IAAI,gBAAgB,YAAY;GAC/C,MAAM,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,cAAc;GAC1C,IAAI,CAAC,KAAK;GAGV,4BAA4B;IAC3B,IAAI,UAAU,SACb,QAAQ,MAAM,YAAY,cAAc,GAAG,OAAO,IAAI,SAAS,EAAE,GAAG;GAEtE,CAAC;EACF,CAAC;EAED,QAAQ;EACR,QAAQ,QAAQ,OAAO;CACxB;AACD"}
|
|
@@ -3,6 +3,11 @@ function bindHoverPreview(target, options, signal) {
|
|
|
3
3
|
let hover;
|
|
4
4
|
let isDismissed = false;
|
|
5
5
|
let escapeWatch;
|
|
6
|
+
const hold = (value) => {
|
|
7
|
+
if (value === hover) return;
|
|
8
|
+
hover = value;
|
|
9
|
+
options.changed();
|
|
10
|
+
};
|
|
6
11
|
const watchEscape = (isHovered) => {
|
|
7
12
|
if (!isHovered) {
|
|
8
13
|
escapeWatch?.abort();
|
|
@@ -13,14 +18,14 @@ function bindHoverPreview(target, options, signal) {
|
|
|
13
18
|
escapeWatch = new AbortController();
|
|
14
19
|
target.ownerDocument.addEventListener("keydown", (event) => {
|
|
15
20
|
if (hover === void 0 || event.key !== "Escape") return;
|
|
16
|
-
hover = void 0;
|
|
17
21
|
isDismissed = true;
|
|
22
|
+
hold(void 0);
|
|
18
23
|
options.dismiss();
|
|
19
24
|
}, { signal: escapeWatch.signal });
|
|
20
25
|
};
|
|
21
26
|
const hoverAt = (value) => {
|
|
22
27
|
if (value === void 0) isDismissed = false;
|
|
23
|
-
if (!isDismissed && !options.isTaken())
|
|
28
|
+
if (!isDismissed && !options.isTaken()) hold(value);
|
|
24
29
|
options.show();
|
|
25
30
|
watchEscape(value !== void 0);
|
|
26
31
|
};
|
|
@@ -36,7 +41,7 @@ function bindHoverPreview(target, options, signal) {
|
|
|
36
41
|
}, { once: true });
|
|
37
42
|
return {
|
|
38
43
|
clear: () => {
|
|
39
|
-
|
|
44
|
+
hold(void 0);
|
|
40
45
|
},
|
|
41
46
|
value: () => hover
|
|
42
47
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-preview.js","names":[],"sources":["../../../src/lib/hover-preview.ts"],"sourcesContent":["interface HoverOptions {\n\tcanShow: () => boolean;\n\tdismiss: () => void;\n\tisTaken: () => boolean;\n\tshow: () => void;\n\tvalueAt: (event: PointerEvent) => number | undefined;\n}\n\nexport interface HoverPreview {\n\tclear: () => void;\n\tvalue: () => number | undefined;\n}\n\nexport function bindHoverPreview(\n\ttarget: HTMLElement,\n\toptions: HoverOptions,\n\tsignal: AbortSignal,\n): HoverPreview {\n\tlet hover: number | undefined;\n\tlet isDismissed = false;\n\tlet escapeWatch: AbortController | undefined;\n\n\t// A hover holds no focus, so the key is heard on the document (WCAG 1.4.13)\n\tconst watchEscape = (isHovered: boolean): void => {\n\t\tif (!isHovered) {\n\t\t\tescapeWatch?.abort();\n\t\t\tescapeWatch = undefined;\n\t\t\treturn;\n\t\t}\n\t\tif (escapeWatch) return;\n\n\t\tescapeWatch = new AbortController();\n\t\ttarget.ownerDocument.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (hover === undefined || event.key !== 'Escape') return;\n\n\t\t\t\t// Stays dismissed until the hover ends, or the next pointer move would bring it straight back\n\t\t\t\
|
|
1
|
+
{"version":3,"file":"hover-preview.js","names":[],"sources":["../../../src/lib/hover-preview.ts"],"sourcesContent":["interface HoverOptions {\n\tcanShow: () => boolean;\n\tchanged: () => void;\n\tdismiss: () => void;\n\tisTaken: () => boolean;\n\tshow: () => void;\n\tvalueAt: (event: PointerEvent) => number | undefined;\n}\n\nexport interface HoverPreview {\n\tclear: () => void;\n\tvalue: () => number | undefined;\n}\n\nexport function bindHoverPreview(\n\ttarget: HTMLElement,\n\toptions: HoverOptions,\n\tsignal: AbortSignal,\n): HoverPreview {\n\tlet hover: number | undefined;\n\tlet isDismissed = false;\n\tlet escapeWatch: AbortController | undefined;\n\n\tconst hold = (value: number | undefined): void => {\n\t\tif (value === hover) return;\n\n\t\thover = value;\n\t\toptions.changed();\n\t};\n\n\t// A hover holds no focus, so the key is heard on the document (WCAG 1.4.13)\n\tconst watchEscape = (isHovered: boolean): void => {\n\t\tif (!isHovered) {\n\t\t\tescapeWatch?.abort();\n\t\t\tescapeWatch = undefined;\n\t\t\treturn;\n\t\t}\n\t\tif (escapeWatch) return;\n\n\t\tescapeWatch = new AbortController();\n\t\ttarget.ownerDocument.addEventListener(\n\t\t\t'keydown',\n\t\t\t(event) => {\n\t\t\t\tif (hover === undefined || event.key !== 'Escape') return;\n\n\t\t\t\t// Stays dismissed until the hover ends, or the next pointer move would bring it straight back\n\t\t\t\tisDismissed = true;\n\t\t\t\thold(undefined);\n\t\t\t\toptions.dismiss();\n\t\t\t},\n\t\t\t{ signal: escapeWatch.signal },\n\t\t);\n\t};\n\tconst hoverAt = (value: number | undefined): void => {\n\t\tif (value === undefined) isDismissed = false;\n\t\tif (!isDismissed && !options.isTaken()) hold(value);\n\t\toptions.show();\n\t\twatchEscape(value !== undefined);\n\t};\n\n\ttarget.addEventListener(\n\t\t'pointermove',\n\t\t(event) => {\n\t\t\tif (event.pointerType === 'touch' || event.buttons !== 0 || !options.canShow()) return;\n\n\t\t\thoverAt(options.valueAt(event));\n\t\t},\n\t\t{ signal },\n\t);\n\tfor (const type of ['pointerdown', 'pointerleave']) {\n\t\ttarget.addEventListener(\n\t\t\ttype,\n\t\t\t() => {\n\t\t\t\thoverAt(undefined);\n\t\t\t},\n\t\t\t{ signal },\n\t\t);\n\t}\n\tsignal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\twatchEscape(false);\n\t\t},\n\t\t{ once: true },\n\t);\n\n\treturn {\n\t\tclear: () => {\n\t\t\thold(undefined);\n\t\t},\n\t\tvalue: () => hover,\n\t};\n}\n"],"mappings":";AAcA,SAAgB,iBACf,QACA,SACA,QACe;CACf,IAAI;CACJ,IAAI,cAAc;CAClB,IAAI;CAEJ,MAAM,QAAQ,UAAoC;EACjD,IAAI,UAAU,OAAO;EAErB,QAAQ;EACR,QAAQ,QAAQ;CACjB;CAGA,MAAM,eAAe,cAA6B;EACjD,IAAI,CAAC,WAAW;GACf,aAAa,MAAM;GACnB,cAAc;GACd;EACD;EACA,IAAI,aAAa;EAEjB,cAAc,IAAI,gBAAgB;EAClC,OAAO,cAAc,iBACpB,YACC,UAAU;GACV,IAAI,UAAU,UAAa,MAAM,QAAQ,UAAU;GAGnD,cAAc;GACd,KAAK,MAAS;GACd,QAAQ,QAAQ;EACjB,GACA,EAAE,QAAQ,YAAY,OAAO,CAC9B;CACD;CACA,MAAM,WAAW,UAAoC;EACpD,IAAI,UAAU,QAAW,cAAc;EACvC,IAAI,CAAC,eAAe,CAAC,QAAQ,QAAQ,GAAG,KAAK,KAAK;EAClD,QAAQ,KAAK;EACb,YAAY,UAAU,MAAS;CAChC;CAEA,OAAO,iBACN,gBACC,UAAU;EACV,IAAI,MAAM,gBAAgB,WAAW,MAAM,YAAY,KAAK,CAAC,QAAQ,QAAQ,GAAG;EAEhF,QAAQ,QAAQ,QAAQ,KAAK,CAAC;CAC/B,GACA,EAAE,OAAO,CACV;CACA,KAAK,MAAM,QAAQ,CAAC,eAAe,cAAc,GAChD,OAAO,iBACN,YACM;EACL,QAAQ,MAAS;CAClB,GACA,EAAE,OAAO,CACV;CAED,OAAO,iBACN,eACM;EACL,YAAY,KAAK;CAClB,GACA,EAAE,MAAM,KAAK,CACd;CAEA,OAAO;EACN,aAAa;GACZ,KAAK,MAAS;EACf;EACA,aAAa;CACd;AACD"}
|
|
@@ -11,7 +11,7 @@ function parkedPlacement(labels, index, [view, arrivingX]) {
|
|
|
11
11
|
const parked = labels[index];
|
|
12
12
|
if (!parked) return void 0;
|
|
13
13
|
const next = labels[index + 1];
|
|
14
|
-
const x = Math.max(view.
|
|
14
|
+
const x = Math.max(view.parkPx, lineX(parked.start, view) + view.insetPx);
|
|
15
15
|
const approachPx = next ? lineX(next.start, view) - lineX(view.playheadSeconds, view) : Infinity;
|
|
16
16
|
return {
|
|
17
17
|
index,
|
|
@@ -90,11 +90,12 @@ function measureWidths(control, className, texts) {
|
|
|
90
90
|
return widths;
|
|
91
91
|
}
|
|
92
92
|
function createLabelRider(control, options) {
|
|
93
|
-
const { className, colourProperty, fadeProperty, insetProperty } = options;
|
|
93
|
+
const { className, colourProperty, fadeProperty, insetProperty, parkProperty } = options;
|
|
94
94
|
const parked = labelSlot(requireChild(control, `.${className}`, HTMLElement));
|
|
95
95
|
const arriving = labelSlot(requireChild(control, `.${className} + .${className}`, HTMLElement));
|
|
96
96
|
let fadeShare = .25;
|
|
97
97
|
let insetPx = 0;
|
|
98
|
+
let parkPx = 0;
|
|
98
99
|
let measured = [];
|
|
99
100
|
return {
|
|
100
101
|
measure: (labels) => {
|
|
@@ -102,6 +103,7 @@ function createLabelRider(control, options) {
|
|
|
102
103
|
const styles = getComputedStyle(control);
|
|
103
104
|
fadeShare = readPxProperty(styles, fadeProperty, .25);
|
|
104
105
|
insetPx = readPxProperty(styles, insetProperty, 0);
|
|
106
|
+
parkPx = readPxProperty(styles, parkProperty, 0);
|
|
105
107
|
measured = labels.map((label, index) => ({
|
|
106
108
|
...label,
|
|
107
109
|
widthPx: widths[index] ?? 0
|
|
@@ -111,7 +113,8 @@ function createLabelRider(control, options) {
|
|
|
111
113
|
const layout = layoutRider(measured, {
|
|
112
114
|
...window,
|
|
113
115
|
fadeShare,
|
|
114
|
-
insetPx
|
|
116
|
+
insetPx,
|
|
117
|
+
parkPx
|
|
115
118
|
});
|
|
116
119
|
writeLabel(parked, [measured, colourProperty], layout.parked);
|
|
117
120
|
writeLabel(arriving, [measured, colourProperty], layout.arriving);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker-rider.js","names":[],"sources":["../../../src/lib/marker-rider.ts"],"sourcesContent":["import { writeKind } from '#lib/marker-band.ts';\nimport { clamp } from '#lib/math.ts';\nimport { readPxProperty } from '#lib/read-px-property.ts';\nimport { requireChild } from '#lib/render.ts';\n\ninterface RiderWindow {\n\tplayheadSeconds: number;\n\tstartSeconds: number;\n\twidthPx: number;\n\twindowSeconds: number;\n}\n\nexport interface RiderView extends RiderWindow {\n\tfadeShare: number;\n\tinsetPx: number;\n}\n\nexport interface RiderLabel {\n\tisDimmed: boolean;\n\tkind?: string;\n\tstart: number;\n\ttext: string;\n\twidthPx: number;\n}\n\ninterface LabelPlacement {\n\tindex: number;\n\topacity: number;\n\tshownPx: number;\n\tx: number;\n}\n\ninterface RiderLayout {\n\tarriving?: LabelPlacement;\n\tparked?: LabelPlacement;\n}\n\ninterface LabelSlot {\n\telement: HTMLElement;\n\tkind: string | undefined;\n\topacity: number;\n\tshownPx: number;\n\tx: number;\n}\n\nfunction lineX(seconds: number, view: RiderView): number {\n\treturn ((seconds - view.startSeconds) / view.windowSeconds) * view.widthPx;\n}\n\nfunction parkedPlacement(\n\tlabels: ReadonlyArray<RiderLabel>,\n\tindex: number,\n\t[view, arrivingX]: [RiderView, number],\n): LabelPlacement | undefined {\n\tconst parked = labels[index];\n\tif (!parked) return undefined;\n\n\tconst next = labels[index + 1];\n\tconst x = Math.max(view.
|
|
1
|
+
{"version":3,"file":"marker-rider.js","names":[],"sources":["../../../src/lib/marker-rider.ts"],"sourcesContent":["import { writeKind } from '#lib/marker-band.ts';\nimport { clamp } from '#lib/math.ts';\nimport { readPxProperty } from '#lib/read-px-property.ts';\nimport { requireChild } from '#lib/render.ts';\n\ninterface RiderWindow {\n\tplayheadSeconds: number;\n\tstartSeconds: number;\n\twidthPx: number;\n\twindowSeconds: number;\n}\n\nexport interface RiderView extends RiderWindow {\n\tfadeShare: number;\n\tinsetPx: number;\n\tparkPx: number;\n}\n\nexport interface RiderLabel {\n\tisDimmed: boolean;\n\tkind?: string;\n\tstart: number;\n\ttext: string;\n\twidthPx: number;\n}\n\ninterface LabelPlacement {\n\tindex: number;\n\topacity: number;\n\tshownPx: number;\n\tx: number;\n}\n\ninterface RiderLayout {\n\tarriving?: LabelPlacement;\n\tparked?: LabelPlacement;\n}\n\ninterface LabelSlot {\n\telement: HTMLElement;\n\tkind: string | undefined;\n\topacity: number;\n\tshownPx: number;\n\tx: number;\n}\n\nfunction lineX(seconds: number, view: RiderView): number {\n\treturn ((seconds - view.startSeconds) / view.windowSeconds) * view.widthPx;\n}\n\nfunction parkedPlacement(\n\tlabels: ReadonlyArray<RiderLabel>,\n\tindex: number,\n\t[view, arrivingX]: [RiderView, number],\n): LabelPlacement | undefined {\n\tconst parked = labels[index];\n\tif (!parked) return undefined;\n\n\tconst next = labels[index + 1];\n\tconst x = Math.max(view.parkPx, lineX(parked.start, view) + view.insetPx);\n\tconst approachPx = next ? lineX(next.start, view) - lineX(view.playheadSeconds, view) : Infinity;\n\n\treturn {\n\t\tindex,\n\t\topacity: view.fadeShare > 0 ? clamp(approachPx / (view.widthPx * view.fadeShare), 0, 1) : 1,\n\t\tshownPx: Math.min(parked.widthPx, arrivingX - x, view.widthPx - x),\n\t\tx,\n\t};\n}\n\nfunction isDrawable(length: number): boolean {\n\treturn Number.isFinite(length) && length > 0;\n}\n\nexport function layoutRider(labels: ReadonlyArray<RiderLabel>, view: RiderView): RiderLayout {\n\tif (!isDrawable(view.windowSeconds) || !isDrawable(view.widthPx)) return {};\n\n\tconst parkedIndex = labels.findLastIndex((label) => label.start <= view.playheadSeconds);\n\tconst next = labels[parkedIndex + 1];\n\tconst arrivingX = next ? lineX(next.start, view) + view.insetPx : Infinity;\n\tconst parked = parkedPlacement(labels, parkedIndex, [view, arrivingX]);\n\tconst arriving: LabelPlacement | undefined =\n\t\tnext && arrivingX < view.widthPx\n\t\t\t? {\n\t\t\t\t\tindex: parkedIndex + 1,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\tshownPx: Math.min(next.widthPx, view.widthPx - arrivingX),\n\t\t\t\t\tx: arrivingX,\n\t\t\t\t}\n\t\t\t: undefined;\n\n\treturn { ...(arriving ? { arriving } : {}), ...(parked ? { parked } : {}) };\n}\n\nfunction labelSlot(element: HTMLElement): LabelSlot {\n\treturn { element, kind: undefined, opacity: NaN, shownPx: NaN, x: NaN };\n}\n\nfunction writePlacement(\n\tslot: LabelSlot,\n\t{ opacity, shownPx, x }: LabelPlacement,\n\twidthPx: number,\n): void {\n\tconst { style } = slot.element;\n\n\tif (slot.x !== x) {\n\t\tslot.x = x;\n\t\tstyle.setProperty('translate', `${x.toFixed(2)}px`);\n\t}\n\tif (slot.shownPx !== shownPx) {\n\t\tslot.shownPx = shownPx;\n\t\tstyle.setProperty(\n\t\t\t'clip-path',\n\t\t\tshownPx < widthPx ? `inset(0 calc(100% - ${shownPx.toFixed(2)}px) 0 0)` : '',\n\t\t);\n\t}\n\tif (slot.opacity !== opacity) {\n\t\tslot.opacity = opacity;\n\t\tstyle.setProperty('opacity', opacity < 1 ? opacity.toFixed(3) : '');\n\t}\n}\n\nfunction writeLabel(\n\tslot: LabelSlot,\n\t[labels, colourProperty]: [ReadonlyArray<RiderLabel>, string],\n\tplacement: LabelPlacement | undefined,\n): void {\n\tconst { element } = slot;\n\tconst label = placement && placement.shownPx > 0 ? labels[placement.index] : undefined;\n\n\tif (element.hidden !== !label) element.hidden = !label;\n\tif (!label || !placement) return;\n\n\tif (element.textContent !== label.text) element.textContent = label.text;\n\telement.toggleAttribute('data-sonic-dimmed', label.isDimmed);\n\tif (slot.kind !== label.kind) {\n\t\tslot.kind = label.kind;\n\t\twriteKind(element, label.kind, colourProperty);\n\t}\n\twritePlacement(slot, placement, label.widthPx);\n}\n\nfunction measureWidths(\n\tcontrol: HTMLElement,\n\tclassName: string,\n\ttexts: Array<string>,\n): Array<number> {\n\tconst probes = texts.map((text) => {\n\t\tconst probe = document.createElement('div');\n\n\t\tprobe.className = className;\n\t\tprobe.textContent = text;\n\n\t\treturn probe;\n\t});\n\n\tcontrol.append(...probes);\n\n\tconst widths = probes.map((probe) => probe.getBoundingClientRect().width);\n\n\tfor (const probe of probes) probe.remove();\n\n\treturn widths;\n}\n\nexport function createLabelRider(\n\tcontrol: HTMLElement,\n\toptions: {\n\t\tclassName: string;\n\t\tcolourProperty: `--_sonic-${string}`;\n\t\tfadeProperty: `--_sonic-${string}`;\n\t\tinsetProperty: `--_sonic-${string}`;\n\t\tparkProperty: `--_sonic-${string}`;\n\t},\n): {\n\tmeasure: (labels: ReadonlyArray<Omit<RiderLabel, 'widthPx'>>) => void;\n\tplace: (window: RiderWindow) => void;\n} {\n\tconst { className, colourProperty, fadeProperty, insetProperty, parkProperty } = options;\n\tconst parked = labelSlot(requireChild(control, `.${className}`, HTMLElement));\n\tconst arriving = labelSlot(requireChild(control, `.${className} + .${className}`, HTMLElement));\n\tlet fadeShare = 0.25;\n\tlet insetPx = 0;\n\tlet parkPx = 0;\n\tlet measured: Array<RiderLabel> = [];\n\n\treturn {\n\t\tmeasure: (labels) => {\n\t\t\tconst widths = measureWidths(\n\t\t\t\tcontrol,\n\t\t\t\tclassName,\n\t\t\t\tlabels.map(({ text }) => text),\n\t\t\t);\n\n\t\t\tconst styles = getComputedStyle(control);\n\n\t\t\tfadeShare = readPxProperty(styles, fadeProperty, 0.25);\n\t\t\tinsetPx = readPxProperty(styles, insetProperty, 0);\n\t\t\tparkPx = readPxProperty(styles, parkProperty, 0);\n\t\t\tmeasured = labels\n\t\t\t\t.map((label, index) => ({ ...label, widthPx: widths[index] ?? 0 }))\n\t\t\t\t.toSorted((first, second) => first.start - second.start);\n\t\t},\n\t\tplace: (window) => {\n\t\t\tconst layout = layoutRider(measured, { ...window, fadeShare, insetPx, parkPx });\n\n\t\t\twriteLabel(parked, [measured, colourProperty], layout.parked);\n\t\t\twriteLabel(arriving, [measured, colourProperty], layout.arriving);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/lib/read-ms-property.ts
|
|
2
|
+
function readMsProperty(styles, property, fallback) {
|
|
3
|
+
const text = styles.getPropertyValue(property).trim();
|
|
4
|
+
const parsed = Number.parseFloat(text);
|
|
5
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
6
|
+
return text.endsWith("ms") ? parsed : parsed * 1e3;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { readMsProperty };
|
|
11
|
+
//# sourceMappingURL=read-ms-property.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-ms-property.js","names":[],"sources":["../../../src/lib/read-ms-property.ts"],"sourcesContent":["// Registered `<time>` properties only; engines differ on whether one computes to s or ms\nexport function readMsProperty(\n\tstyles: CSSStyleDeclaration,\n\tproperty: string,\n\tfallback: number,\n): number {\n\tconst text = styles.getPropertyValue(property).trim();\n\t// eslint-disable-next-line unicorn/prefer-number-coercion -- parsing has to stop at the unit\n\tconst parsed = Number.parseFloat(text);\n\tif (!Number.isFinite(parsed)) return fallback;\n\n\treturn text.endsWith('ms') ? parsed : parsed * 1000;\n}\n"],"mappings":";AACA,SAAgB,eACf,QACA,UACA,UACS;CACT,MAAM,OAAO,OAAO,iBAAiB,QAAQ,CAAC,CAAC,KAAK;CAEpD,MAAM,SAAS,OAAO,WAAW,IAAI;CACrC,IAAI,CAAC,OAAO,SAAS,MAAM,GAAG,OAAO;CAErC,OAAO,KAAK,SAAS,IAAI,IAAI,SAAS,SAAS;AAChD"}
|
package/dist/styles/envelope.css
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
--_sonic-point-ring: var(--_sonic-lit);
|
|
107
107
|
--_sonic-point-core: var(--_sonic-lit);
|
|
108
108
|
--_sonic-point-lift: color-mix(in oklab, var(--_sonic-lit) 85%, #fff);
|
|
109
|
-
--_sonic-point-edge: max(1px, var(--_sonic-point-stroke, 0px));
|
|
109
|
+
--_sonic-point-edge: max(1px, round(var(--_sonic-point-stroke, 0px), var(--_sonic-snap)));
|
|
110
110
|
--_sonic-point-halo: transparent;
|
|
111
111
|
|
|
112
112
|
z-index: 1;
|
package/dist/styles/led.css
CHANGED
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
background:
|
|
104
104
|
radial-gradient(
|
|
105
105
|
closest-side,
|
|
106
|
-
color-mix(in oklab, var(--_sonic-lit) calc(
|
|
106
|
+
color-mix(in oklab, var(--_sonic-lit) calc(40% * var(--_sonic-relief)), transparent)
|
|
107
107
|
calc(var(--_sonic-led-lens-ratio) * 100%),
|
|
108
108
|
transparent
|
|
109
109
|
),
|
package/dist/styles/material.css
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
initial-value: 8px;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
@property --_sonic-reveal-delay {
|
|
14
|
+
syntax: '<time>';
|
|
15
|
+
inherits: true;
|
|
16
|
+
initial-value: 250ms;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
@keyframes sonic-glass-breathe {
|
|
14
20
|
to {
|
|
15
21
|
opacity: calc(0.4 * min(1, var(--_sonic-glass-texture)));
|
|
@@ -47,6 +53,15 @@
|
|
|
47
53
|
--_sonic-light-fall: calc(180deg - var(--_sonic-light-tilt));
|
|
48
54
|
--_sonic-cast-x: calc(sin(var(--_sonic-light-tilt)) * var(--_sonic-unit));
|
|
49
55
|
--_sonic-cast-y: calc(cos(var(--_sonic-light-tilt)) * var(--_sonic-unit));
|
|
56
|
+
--_sonic-snap: 1px;
|
|
57
|
+
|
|
58
|
+
@media (resolution >= 2dppx) {
|
|
59
|
+
--_sonic-snap: 0.5px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (resolution >= 3dppx) {
|
|
63
|
+
--_sonic-snap: calc(1px / 3);
|
|
64
|
+
}
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
:is(
|
|
@@ -144,7 +159,8 @@
|
|
|
144
159
|
rgb(0 0 0 / calc(0.35 * var(--_sonic-relief))),
|
|
145
160
|
calc(0.5 * var(--_sonic-cast-x)) calc(0.5 * var(--_sonic-cast-y)) var(--_sonic-unit)
|
|
146
161
|
rgb(255 255 255 / calc(0.12 * var(--_sonic-relief)));
|
|
147
|
-
--_sonic-rim:
|
|
162
|
+
--_sonic-rim-width: max(1px, round(0.75 * var(--_sonic-unit), var(--_sonic-snap)));
|
|
163
|
+
--_sonic-rim: 0 0 0 var(--_sonic-rim-width)
|
|
148
164
|
var(
|
|
149
165
|
--sonic-cap-edge,
|
|
150
166
|
color-mix(in oklab, var(--_sonic-cap) calc(100% - 60% * var(--_sonic-relief)), #000)
|
|
@@ -167,6 +183,18 @@
|
|
|
167
183
|
--_sonic-readout-size: var(--sonic-readout-size, 1.5rem);
|
|
168
184
|
}
|
|
169
185
|
|
|
186
|
+
:is(
|
|
187
|
+
.sonic-dial,
|
|
188
|
+
.sonic-envelope,
|
|
189
|
+
.sonic-number,
|
|
190
|
+
.sonic-slider,
|
|
191
|
+
.sonic-waveform,
|
|
192
|
+
.sonic-wavestrip,
|
|
193
|
+
.sonic-xy
|
|
194
|
+
) {
|
|
195
|
+
--_sonic-reveal-delay: var(--sonic-reveal-delay, 250ms);
|
|
196
|
+
}
|
|
197
|
+
|
|
170
198
|
:is(.sonic-dial, .sonic-slider, .sonic-waveform, .sonic-wavestrip) {
|
|
171
199
|
--_sonic-lit-off: var(
|
|
172
200
|
--sonic-dimmed,
|
|
@@ -219,10 +247,13 @@
|
|
|
219
247
|
);
|
|
220
248
|
|
|
221
249
|
/* Invalid with the token unset, so the default takes over */
|
|
222
|
-
--_sonic-glass-edge-
|
|
250
|
+
--_sonic-glass-edge-colour: var(--sonic-glass-edge);
|
|
251
|
+
--_sonic-glass-edge-width: var(--sonic-glass-edge-width);
|
|
252
|
+
--_sonic-glass-edge-set: var(--_sonic-glass-edge-width, 1px) solid
|
|
253
|
+
var(--_sonic-glass-edge-colour);
|
|
223
254
|
--_sonic-glass-edge: var(
|
|
224
255
|
--_sonic-glass-edge-set,
|
|
225
|
-
calc(1px * (1 - var(--_sonic-relief))) solid
|
|
256
|
+
var(--_sonic-glass-edge-width, calc(1px * (1 - var(--_sonic-relief)))) solid
|
|
226
257
|
color-mix(in oklab, currentcolor 35%, transparent)
|
|
227
258
|
);
|
|
228
259
|
|
|
@@ -381,12 +412,12 @@
|
|
|
381
412
|
--_sonic-keycap-glow: transparent;
|
|
382
413
|
--_sonic-keycap-lit-glow: color-mix(
|
|
383
414
|
in oklab,
|
|
384
|
-
var(--_sonic-lit) calc(
|
|
415
|
+
var(--_sonic-lit) calc(15% * var(--_sonic-relief)),
|
|
385
416
|
transparent
|
|
386
417
|
);
|
|
387
418
|
--_sonic-legend-glow: drop-shadow(
|
|
388
419
|
0 0 var(--_sonic-unit)
|
|
389
|
-
color-mix(in oklab, var(--_sonic-lit) calc(
|
|
420
|
+
color-mix(in oklab, var(--_sonic-lit) calc(24% * var(--_sonic-relief)), transparent)
|
|
390
421
|
);
|
|
391
422
|
}
|
|
392
423
|
|
|
@@ -409,7 +440,7 @@
|
|
|
409
440
|
box-shadow:
|
|
410
441
|
var(--_sonic-keycap-drop),
|
|
411
442
|
var(--_sonic-rim),
|
|
412
|
-
0 0 0
|
|
443
|
+
0 0 0 var(--_sonic-rim-width) var(--_sonic-blank-edge, transparent),
|
|
413
444
|
var(--_sonic-focus-shadow);
|
|
414
445
|
scale: var(--_sonic-keycap-scale);
|
|
415
446
|
translate: 0 var(--_sonic-keycap-shift);
|
|
@@ -514,6 +545,8 @@
|
|
|
514
545
|
) {
|
|
515
546
|
--_sonic-unit: calc(var(--_sonic-readout-size) / 32);
|
|
516
547
|
--_sonic-glass: var(--sonic-readout-glass, var(--_sonic-glass-base));
|
|
548
|
+
--_sonic-glass-edge-colour: var(--sonic-readout-edge, var(--sonic-glass-edge));
|
|
549
|
+
--_sonic-glass-edge-width: var(--sonic-readout-edge-width, var(--sonic-glass-edge-width));
|
|
517
550
|
|
|
518
551
|
box-sizing: border-box;
|
|
519
552
|
place-items: center;
|
|
@@ -540,7 +573,8 @@
|
|
|
540
573
|
box-shadow:
|
|
541
574
|
calc(2 * var(--_sonic-cast-x)) calc(2 * var(--_sonic-cast-y)) calc(6 * var(--_sonic-unit))
|
|
542
575
|
rgb(0 0 0 / calc(0.55 * var(--_sonic-relief))),
|
|
543
|
-
inset 0 0 0 max(1px, var(--_sonic-unit)
|
|
576
|
+
inset 0 0 0 max(1px, round(var(--_sonic-unit), var(--_sonic-snap)))
|
|
577
|
+
rgb(255 255 255 / calc(0.08 * var(--_sonic-relief)));
|
|
544
578
|
opacity: 0;
|
|
545
579
|
translate: 0 calc(0.15 * var(--_sonic-readout-size));
|
|
546
580
|
transition:
|
|
@@ -669,7 +703,7 @@
|
|
|
669
703
|
--_sonic-face: ButtonFace;
|
|
670
704
|
--_sonic-sheen: none;
|
|
671
705
|
--_sonic-face-shadow: none;
|
|
672
|
-
--_sonic-rim: 0 0 0
|
|
706
|
+
--_sonic-rim: 0 0 0 var(--_sonic-rim-width) var(--_sonic-ink);
|
|
673
707
|
--_sonic-drop-shade: transparent;
|
|
674
708
|
--_sonic-focus-glow: 0 0 transparent;
|
|
675
709
|
}
|
package/dist/styles/spectrum.css
CHANGED
package/dist/styles/switch.css
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
initial-value: 32px;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
@property --_sonic-switch-at {
|
|
8
|
+
syntax: '<number>';
|
|
9
|
+
inherits: true;
|
|
10
|
+
initial-value: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
@layer sonic {
|
|
8
14
|
:is(sonic-switch, .sonic-switch) {
|
|
9
15
|
--_sonic-switch-size: var(--sonic-switch-size, 2rem);
|
|
@@ -52,6 +58,11 @@
|
|
|
52
58
|
place-items: center;
|
|
53
59
|
line-height: 1;
|
|
54
60
|
user-select: none;
|
|
61
|
+
transition: --_sonic-switch-at 90ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
62
|
+
|
|
63
|
+
@media (prefers-reduced-motion: reduce) {
|
|
64
|
+
transition: none;
|
|
65
|
+
}
|
|
55
66
|
|
|
56
67
|
& > * {
|
|
57
68
|
grid-area: 1 / 1;
|
|
@@ -243,7 +254,7 @@
|
|
|
243
254
|
);
|
|
244
255
|
border-radius: 50%;
|
|
245
256
|
box-shadow:
|
|
246
|
-
0 0 0
|
|
257
|
+
0 0 0 var(--_sonic-rim-width)
|
|
247
258
|
var(
|
|
248
259
|
--sonic-cap-edge,
|
|
249
260
|
color-mix(
|
|
@@ -257,11 +268,9 @@
|
|
|
257
268
|
}
|
|
258
269
|
|
|
259
270
|
.sonic-switch-bat {
|
|
260
|
-
--_sonic-switch-lean: max(var(--_sonic-switch-at
|
|
261
|
-
--_sonic-switch-
|
|
262
|
-
|
|
263
|
-
block-size 90ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
264
|
-
background-position 90ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
271
|
+
--_sonic-switch-lean: max(var(--_sonic-switch-at), -1 * var(--_sonic-switch-at));
|
|
272
|
+
--_sonic-switch-throw: calc(var(--_sonic-switch-at) * var(--_sonic-switch-reach));
|
|
273
|
+
--_sonic-switch-pivot: calc((var(--_sonic-switch-size) - var(--_sonic-switch-shaft)) / 2);
|
|
265
274
|
--_sonic-switch-sheen: linear-gradient(
|
|
266
275
|
var(--_sonic-light-fall),
|
|
267
276
|
color-mix(in oklab, var(--_sonic-switch-metal) calc(100% - 45% * var(--_sonic-relief)), #fff)
|
|
@@ -269,7 +278,7 @@
|
|
|
269
278
|
var(--_sonic-switch-metal) 45%,
|
|
270
279
|
var(--_sonic-switch-metal-shade) 88%
|
|
271
280
|
);
|
|
272
|
-
--_sonic-switch-outline: max(1px, 0.4 * var(--_sonic-unit));
|
|
281
|
+
--_sonic-switch-outline: max(1px, round(0.4 * var(--_sonic-unit), var(--_sonic-snap)));
|
|
273
282
|
--_sonic-switch-rim: var(
|
|
274
283
|
--sonic-cap-edge,
|
|
275
284
|
color-mix(in oklab, var(--_sonic-switch-cap) calc(100% - 30% * var(--_sonic-relief)), #000)
|
|
@@ -286,10 +295,6 @@
|
|
|
286
295
|
var(--_sonic-drop-shade)
|
|
287
296
|
);
|
|
288
297
|
|
|
289
|
-
@media (prefers-reduced-motion: reduce) {
|
|
290
|
-
--_sonic-switch-transition: none;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
298
|
&::before,
|
|
294
299
|
&::after {
|
|
295
300
|
position: absolute;
|
|
@@ -300,29 +305,30 @@
|
|
|
300
305
|
background-size: var(--_sonic-switch-size) var(--_sonic-switch-size);
|
|
301
306
|
border-radius: 999px;
|
|
302
307
|
box-shadow: 0 0 0 var(--_sonic-switch-outline) var(--_sonic-switch-rim);
|
|
303
|
-
transition: var(--_sonic-switch-transition);
|
|
304
308
|
}
|
|
305
309
|
|
|
306
310
|
&::before {
|
|
307
|
-
--_sonic-switch-shaft-
|
|
308
|
-
var(--_sonic-switch-
|
|
309
|
-
var(--_sonic-switch-
|
|
311
|
+
--_sonic-switch-shaft-top: calc(
|
|
312
|
+
var(--_sonic-switch-pivot) + var(--_sonic-switch-along-y) *
|
|
313
|
+
min(0px, var(--_sonic-switch-throw))
|
|
310
314
|
);
|
|
311
|
-
--_sonic-switch-shaft-
|
|
312
|
-
var(--_sonic-switch-
|
|
313
|
-
var(--_sonic-switch-
|
|
315
|
+
--_sonic-switch-shaft-left: calc(
|
|
316
|
+
var(--_sonic-switch-pivot) + var(--_sonic-switch-along-x) *
|
|
317
|
+
min(0px, var(--_sonic-switch-throw))
|
|
314
318
|
);
|
|
315
319
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
translate: calc(
|
|
321
|
-
var(--_sonic-switch-along-x) * var(--_sonic-switch-at, 0) * var(--_sonic-switch-reach) / 2
|
|
320
|
+
inset: var(--_sonic-switch-shaft-top)
|
|
321
|
+
calc(
|
|
322
|
+
var(--_sonic-switch-pivot) - var(--_sonic-switch-along-x) *
|
|
323
|
+
max(0px, var(--_sonic-switch-throw))
|
|
322
324
|
)
|
|
323
325
|
calc(
|
|
324
|
-
var(--_sonic-switch-
|
|
325
|
-
|
|
326
|
+
var(--_sonic-switch-pivot) - var(--_sonic-switch-along-y) *
|
|
327
|
+
max(0px, var(--_sonic-switch-throw))
|
|
328
|
+
)
|
|
329
|
+
var(--_sonic-switch-shaft-left);
|
|
330
|
+
background-position: calc(-1 * var(--_sonic-switch-shaft-left))
|
|
331
|
+
calc(-1 * var(--_sonic-switch-shaft-top));
|
|
326
332
|
}
|
|
327
333
|
|
|
328
334
|
&::after {
|
|
@@ -335,10 +341,8 @@
|
|
|
335
341
|
rgb(0 0 0 / calc(0.3 * var(--_sonic-relief))),
|
|
336
342
|
0 0 0 var(--_sonic-switch-outline) var(--_sonic-switch-rim),
|
|
337
343
|
var(--_sonic-focus-shadow);
|
|
338
|
-
translate: calc(
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
calc(var(--_sonic-switch-along-y) * var(--_sonic-switch-at, 0) * var(--_sonic-switch-reach));
|
|
344
|
+
translate: calc(var(--_sonic-switch-along-x) * var(--_sonic-switch-throw))
|
|
345
|
+
calc(var(--_sonic-switch-along-y) * var(--_sonic-switch-throw));
|
|
342
346
|
}
|
|
343
347
|
}
|
|
344
348
|
|
|
@@ -347,9 +351,14 @@
|
|
|
347
351
|
}
|
|
348
352
|
|
|
349
353
|
.sonic-switch:has(> .sonic-switch-position:disabled) {
|
|
350
|
-
--_sonic-switch-
|
|
351
|
-
|
|
352
|
-
|
|
354
|
+
--_sonic-switch-disabled: color-mix(
|
|
355
|
+
in oklab,
|
|
356
|
+
var(--_sonic-ink) 30%,
|
|
357
|
+
oklch(from var(--_sonic-ink) clamp(0, (0.6 - l) * 1000, 1) 0 0deg)
|
|
358
|
+
);
|
|
359
|
+
--_sonic-switch-cap: var(--sonic-cap, var(--_sonic-switch-disabled));
|
|
360
|
+
--_sonic-switch-metal: var(--_sonic-switch-disabled);
|
|
361
|
+
--_sonic-switch-metal-shade: var(--_sonic-switch-disabled);
|
|
353
362
|
}
|
|
354
363
|
|
|
355
364
|
@media (forced-colors: active) {
|
package/dist/styles/waveform.css
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
initial-value: 0;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
@property --_sonic-waveform-label-park {
|
|
20
|
+
syntax: '<length>';
|
|
21
|
+
inherits: true;
|
|
22
|
+
initial-value: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
@property --_sonic-waveform-wave {
|
|
20
26
|
syntax: '<color>';
|
|
21
27
|
inherits: true;
|
|
@@ -81,7 +87,11 @@
|
|
|
81
87
|
var(--_sonic-waveform-size) * var(--sonic-waveform-inset-ratio, 0.06)
|
|
82
88
|
);
|
|
83
89
|
--_sonic-unit: calc(var(--_sonic-waveform-size) / 48);
|
|
84
|
-
--_sonic-
|
|
90
|
+
--_sonic-glass-depth: var(--sonic-glass-depth, calc(0.6 * var(--_sonic-relief)));
|
|
91
|
+
--_sonic-waveform-line: var(
|
|
92
|
+
--sonic-waveform-playhead-width,
|
|
93
|
+
max(1px, round(var(--_sonic-unit), var(--_sonic-snap)))
|
|
94
|
+
);
|
|
85
95
|
--_sonic-waveform-lit: var(--_sonic-lit);
|
|
86
96
|
--_sonic-waveform-wave: var(--_sonic-waveform-lit);
|
|
87
97
|
--_sonic-waveform-wave-edge: var(
|
|
@@ -97,6 +107,14 @@
|
|
|
97
107
|
--_sonic-waveform-label-inset: calc(
|
|
98
108
|
var(--_sonic-waveform-size) * var(--sonic-waveform-label-inset-ratio, 0.04)
|
|
99
109
|
);
|
|
110
|
+
--_sonic-waveform-label-lift: var(
|
|
111
|
+
--sonic-waveform-label-inset-block,
|
|
112
|
+
var(--_sonic-waveform-label-inset)
|
|
113
|
+
);
|
|
114
|
+
--_sonic-waveform-label-park: var(
|
|
115
|
+
--sonic-waveform-label-inset-inline,
|
|
116
|
+
var(--_sonic-waveform-label-inset)
|
|
117
|
+
);
|
|
100
118
|
|
|
101
119
|
inline-size: var(--_sonic-waveform-length);
|
|
102
120
|
block-size: var(--_sonic-waveform-size);
|
|
@@ -141,6 +159,13 @@
|
|
|
141
159
|
block-size: 100%;
|
|
142
160
|
}
|
|
143
161
|
|
|
162
|
+
.sonic-waveform-scrim {
|
|
163
|
+
position: absolute;
|
|
164
|
+
inset: var(--_sonic-waveform-inset);
|
|
165
|
+
pointer-events: none;
|
|
166
|
+
background: var(--sonic-waveform-scrim, none);
|
|
167
|
+
}
|
|
168
|
+
|
|
144
169
|
:is(.sonic-waveform-playhead, .sonic-waveform-ghost) {
|
|
145
170
|
position: absolute;
|
|
146
171
|
inset-block: var(--_sonic-waveform-inset);
|
|
@@ -160,7 +185,7 @@
|
|
|
160
185
|
|
|
161
186
|
.sonic-waveform-label {
|
|
162
187
|
position: absolute;
|
|
163
|
-
inset-block-end: calc(var(--_sonic-waveform-inset) + var(--_sonic-waveform-label-
|
|
188
|
+
inset-block-end: calc(var(--_sonic-waveform-inset) + var(--_sonic-waveform-label-lift));
|
|
164
189
|
inset-inline-start: var(--_sonic-waveform-inset);
|
|
165
190
|
padding: 0.2em 0.35em;
|
|
166
191
|
margin: -0.2em -0.35em;
|
|
@@ -199,6 +224,10 @@
|
|
|
199
224
|
forced-color-adjust: none;
|
|
200
225
|
}
|
|
201
226
|
|
|
227
|
+
.sonic-waveform-scrim {
|
|
228
|
+
background: none;
|
|
229
|
+
}
|
|
230
|
+
|
|
202
231
|
.sonic-waveform-label {
|
|
203
232
|
color: CanvasText;
|
|
204
233
|
|