Audit fixes: a11y, gesture correctness, math edge cases
- Keyboard focus-visible ring on all controls (WCAG 2.4.7), suppressed for pointer grabs; focusRing prop to customize or disable - aria-orientation on track modes; data-dragging/-disabled/-readonly/ -focus-visible state attributes; disabled dims, readOnly drops the grab cursor - Escape cancels a drag and restores the pre-gesture value - Controlled mode no longer desyncs when the parent rejects onChange - Second concurrent pointer can no longer hijack a drag session; drags cancel when disabled/readOnly flips mid-gesture - Wheel: onChangeStart symmetry, settle flush on unsubscribe, dominant- axis direction (fixes macOS Shift+scroll reversal), ignored mid-drag - Shift+wheel and fine multipliers now work on stepped/values knobs - Fader/LEDFader track mapping inset-aligned with handle travel (no value jump when grabbing the cap); LEDFader zones sorted - roundTo no longer returns NaN for exponential-notation values; logTaper falls back to linear for invalid ranges; decimalsFromStep shaves float noise; findClosest([]) returns the input - Double-click reset brackets with onChangeStart/End - MetalKnob honors showValue/unit/format; VintageKnob omits them from its type; TickLabels extracted as a public primitive - SegmentDisplay: letters/hex charset, dash overflow instead of 888
This commit is contained in:
parent
60a02cb1db
commit
da352d3695
13 changed files with 378 additions and 82 deletions
|
|
@ -34,6 +34,9 @@ describe('decimalsFromStep', () => {
|
|||
expect(decimalsFromStep(0)).toBe(3);
|
||||
expect(decimalsFromStep(NaN)).toBe(3);
|
||||
});
|
||||
it('shaves float noise from computed steps', () => {
|
||||
expect(decimalsFromStep(0.1 + 0.2)).toBe(1); // 0.30000000000000004 -> 1
|
||||
});
|
||||
});
|
||||
|
||||
describe('roundTo', () => {
|
||||
|
|
@ -43,6 +46,16 @@ describe('roundTo', () => {
|
|||
expect(roundTo(123.456789, 4)).toBe(123.4568);
|
||||
expect(roundTo(5, 0)).toBe(5);
|
||||
});
|
||||
it('handles values that stringify exponentially', () => {
|
||||
expect(roundTo(1e-8, 10)).toBe(1e-8);
|
||||
expect(roundTo(2.5e-7, 7)).toBe(3e-7);
|
||||
expect(roundTo(1.5e21, 0)).toBe(1.5e21);
|
||||
expect(Number.isNaN(roundTo(1e-9, 3))).toBe(false);
|
||||
});
|
||||
it('passes non-finite values through', () => {
|
||||
expect(roundTo(NaN, 2)).toBeNaN();
|
||||
expect(roundTo(Infinity, 2)).toBe(Infinity);
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapToStep', () => {
|
||||
|
|
@ -61,6 +74,9 @@ describe('findClosest', () => {
|
|||
expect(findClosest([1, 100, 5, 50], 42)).toBe(50);
|
||||
expect(findClosest([0.25, 0.5, 1, 2, 4], 0.8)).toBe(1);
|
||||
});
|
||||
it('returns the input value for an empty list', () => {
|
||||
expect(findClosest([], 5)).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tapers', () => {
|
||||
|
|
@ -74,6 +90,11 @@ describe('tapers', () => {
|
|||
roundTo(Math.log(100) / Math.log(1000), 4),
|
||||
);
|
||||
});
|
||||
it('log taper falls back to linear for invalid ranges instead of NaN', () => {
|
||||
expect(logTaper.fromNormalized(0.5, 0, 100)).toBe(50);
|
||||
expect(logTaper.toNormalized(0, -10, 10)).toBe(0.5);
|
||||
expect(Number.isNaN(logTaper.fromNormalized(0.5, -10, 10))).toBe(false);
|
||||
});
|
||||
it('pow taper round-trips', () => {
|
||||
const t = powTaper(2);
|
||||
const n = t.toNormalized(t.fromNormalized(0.3, 0, 10), 0, 10);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue