Skip to content

Commit

Permalink
feat: add new property jumpLimit
Browse files Browse the repository at this point in the history
- prevent jumping with too large value changes - e.g min to max
  • Loading branch information
pavelkukov committed Jan 31, 2021
1 parent 9bf3e41 commit d07aa2b
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 3 deletions.
1 change: 1 addition & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ module.exports = {
singleQuote: true,
printWidth: 80,
tabWidth: 4,
endOfLine: 'auto'
};
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ![Donut Knob](/docs/images/donut-konb-48.gif) React Knob (minimalistic)
# ![Donut Knob](/docs/images/donut-konb-48.gif) React Knob (for web)
**🦚 Demo**: [Donut](https://pavelkukov.github.io/react-dial-knob/?path=/story/knob-skins--donut) | [Silver](https://pavelkukov.github.io/react-dial-knob/?path=/story/knob-skins--silver) | [White](https://pavelkukov.github.io/react-dial-knob/?path=/story/knob-skins--white) | [HighContrast](https://pavelkukov.github.io/react-dial-knob/?path=/story/knob-skins--high-contrast) | [Basic](https://pavelkukov.github.io/react-dial-knob/?path=/story/knob-skins--basic)


Expand Down
2 changes: 2 additions & 0 deletions docs/KnobProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface KnobProps {
min: number
max: number
step: number
jumpLimit?: number
spaceMaxFromZero?: boolean
ariaLabelledBy?: string
ariaValueText?: string
Expand All @@ -27,6 +28,7 @@ export interface KnobProps {
* `min` - minimal value
* `max` - maximal value
* `step` - increment step
* `jumpLimit` - Maximum value change per single mouse event. Expressed as percentage - e.g 0.1 means max 10% change
* `spaceMaxFromZero` - add additional space between min, and max values. True by default. Make sense to turn it off for small number of steps - e.g 1 to 10. See Donut skin for example.
* `ariaLabelledBy` - render aria-labelledby attribute
* `ariaValueText` - render aria-valuetext attribute
Expand Down
1 change: 1 addition & 0 deletions src/Knob.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface KnobProps {
min: number
max: number
step: number
jumpLimit?: number
spaceMaxFromZero?: boolean
ariaLabelledBy?: string
ariaValueText?: string
Expand Down
36 changes: 34 additions & 2 deletions src/KnobArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class KnobArea {
step: number
diameter: number
spaceMaxFromZero: boolean
jumpLimit?: number
refElement: React.RefObject<HTMLDivElement>
windowEventListeners: {
mouse: Array<['mousemove' | 'mouseup', EventListener]>
Expand Down Expand Up @@ -64,6 +65,10 @@ class KnobArea {
this.spaceMaxFromZero =
props.spaceMaxFromZero !== undefined ? props.spaceMaxFromZero : true

if (props.jumpLimit) {
this.jumpLimit = props.jumpLimit
}

if (props.value !== this.value) {
if (props.min > this.value || props.value < props.min) {
this.value = props.min
Expand Down Expand Up @@ -101,10 +106,11 @@ class KnobArea {
}

set value(val: number) {
if (this._value === val) {
const newValue = this.getValueWithinJumpLimit(val)
if (this._value === newValue) {
return
}
this._value = val
this._value = newValue
if (this.onValueChange) {
this.onValueChange(this._value)
}
Expand Down Expand Up @@ -135,6 +141,32 @@ class KnobArea {
return 360 / this.numSteps
}

private getValueWithinJumpLimit(newValue: number): number {
if (!this.jumpLimit) {
return newValue
}
const limit = Math.max(
this.step,
Math.ceil((this.max - this.min) * this.jumpLimit),
)
if (Math.abs(newValue - this.value) > limit) {
if (
newValue > this.max * 0.9 &&
this.value < this.min + this.max * 0.1
) {
return this.min
}
if (
newValue < this.min + this.max * 0.1 &&
this.value > this.max * 0.9
) {
return this.max
}
return this.value
}
return newValue
}

private getComputedTransformXY(
el: HTMLElement,
): { x: number; y: number; scaleX: number; scaleY: number } {
Expand Down
1 change: 1 addition & 0 deletions src/skins/Basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default function Basic(props: SkinProps<BasicTheme>): JSX.Element {
min={props.min}
max={props.max}
step={props.step}
jumpLimit={props.jumpLimit}
spaceMaxFromZero={props.spaceMaxFromZero}
ariaLabelledBy={props.ariaLabelledBy}
ariaValueText={props.ariaValueText}
Expand Down
1 change: 1 addition & 0 deletions src/skins/Donut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export default function Donut(props: SkinProps<DonutTheme>): JSX.Element {
min={props.min}
max={props.max}
step={props.step}
jumpLimit={props.jumpLimit}
spaceMaxFromZero={props.spaceMaxFromZero}
ariaLabelledBy={props.ariaLabelledBy}
ariaValueText={props.ariaValueText}
Expand Down
1 change: 1 addition & 0 deletions src/skins/HighContrast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function HighContrast(
min={props.min}
max={props.max}
step={props.step}
jumpLimit={props.jumpLimit}
spaceMaxFromZero={props.spaceMaxFromZero}
ariaLabelledBy={props.ariaLabelledBy}
ariaValueText={props.ariaValueText}
Expand Down
1 change: 1 addition & 0 deletions src/skins/Silver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function Silver(props: SkinProps<unknown>): JSX.Element {
min={props.min}
max={props.max}
step={props.step}
jumpLimit={props.jumpLimit}
spaceMaxFromZero={props.spaceMaxFromZero}
ariaLabelledBy={props.ariaLabelledBy}
ariaValueText={props.ariaValueText}
Expand Down
1 change: 1 addition & 0 deletions src/skins/White.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default function White(props: SkinProps<WhiteTheme>): JSX.Element {
min={props.min}
max={props.max}
step={props.step}
jumpLimit={props.jumpLimit}
spaceMaxFromZero={props.spaceMaxFromZero}
ariaLabelledBy={props.ariaLabelledBy}
ariaValueText={props.ariaValueText}
Expand Down
8 changes: 8 additions & 0 deletions stories/utils/wrapSkinComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const wrapSkinComponent = (
max: 120,
step: 1,
diameter: 180,
jumpLimit: 1,
spaceMaxFromZero: true,
...defaults,
}
Expand All @@ -63,6 +64,12 @@ const wrapSkinComponent = (
max: max,
step: 1,
})
const jumpLimit = number('Jump Limit', defaultVals.jumpLimit, {
range: true,
min: 0,
max: 1,
step: 0.1,
})
const valueOptions = {
range: true,
min: min,
Expand All @@ -88,6 +95,7 @@ const wrapSkinComponent = (
max={max}
step={step}
value={value}
jumpLimit={jumpLimit}
spaceMaxFromZero={spaceMaxFromZero}
onValueChange={setValue}
style={{
Expand Down

0 comments on commit d07aa2b

Please sign in to comment.