-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
181 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export {KnobHeadless} from './KnobHeadless'; | ||
export {KnobHeadlessLabel} from './KnobHeadlessLabel'; | ||
export {KnobHeadlessOutput} from './KnobHeadlessOutput'; | ||
export {useKnobKeyboardControl} from './useKnobKeyboardControl'; |
98 changes: 98 additions & 0 deletions
98
packages/react-knob-headless/src/useKnobKeyboardControl.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import {clamp} from '@dsp-ts/math'; | ||
|
||
type UseKnobKeyboardControlProps = { | ||
/** | ||
* Same as `valueRaw` prop of `KnobHeadless`. | ||
*/ | ||
readonly valueRaw: number; | ||
/** | ||
* Same as `valueMin` prop of `KnobHeadless`. | ||
*/ | ||
readonly valueMin: number; | ||
/** | ||
* Same as `valueMax` prop of `KnobHeadless`. | ||
*/ | ||
readonly valueMax: number; | ||
/** | ||
* Step value. Typically it's 1% of the range. | ||
*/ | ||
readonly step: number; | ||
/** | ||
* Larger step value. Typically it's 10% of the range. | ||
*/ | ||
readonly stepLarger: number; | ||
/** | ||
* Same callback as `KnobHeadless` has, with "event" in 2nd argument. | ||
*/ | ||
readonly onValueRawChange: ( | ||
newValueRaw: number, | ||
event: React.KeyboardEvent, | ||
) => void; | ||
/** | ||
* To prevent scrolling, "event.preventDefault()" is called when the value changes, | ||
* so for most cases you don't need to change this behaviour. | ||
* However, if your application needs some more customized behaviour, you can set this prop to true and handle it on its own. | ||
*/ | ||
readonly noDefaultPrevention?: boolean; | ||
}; | ||
|
||
export const useKnobKeyboardControl = | ||
({ | ||
valueRaw, | ||
valueMin, | ||
valueMax, | ||
step, | ||
stepLarger, | ||
onValueRawChange, | ||
noDefaultPrevention = false, | ||
}: UseKnobKeyboardControlProps): React.KeyboardEventHandler => | ||
(event) => { | ||
const {code} = event; | ||
switch (code) { | ||
case 'ArrowUp': | ||
case 'ArrowRight': | ||
onValueRawChange(clamp(valueRaw + step, valueMin, valueMax), event); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
case 'ArrowDown': | ||
case 'ArrowLeft': | ||
onValueRawChange(clamp(valueRaw - step, valueMin, valueMax), event); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
case 'PageUp': | ||
onValueRawChange( | ||
clamp(valueRaw + stepLarger, valueMin, valueMax), | ||
event, | ||
); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
case 'PageDown': | ||
onValueRawChange( | ||
clamp(valueRaw - stepLarger, valueMin, valueMax), | ||
event, | ||
); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
case 'Home': | ||
onValueRawChange(valueMin, event); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
case 'End': | ||
onValueRawChange(valueMax, event); | ||
maybePreventDefault({event, noDefaultPrevention}); | ||
break; | ||
default: | ||
break; | ||
} | ||
}; | ||
|
||
const maybePreventDefault = ({ | ||
event, | ||
noDefaultPrevention, | ||
}: { | ||
event: React.KeyboardEvent; | ||
noDefaultPrevention: boolean; | ||
}): void => { | ||
if (noDefaultPrevention) return; | ||
event.preventDefault(); | ||
}; |