Nudging numbers will now use nudgeMultiplier even if the number has a range

Possibly fixes #314
This commit is contained in:
Aria Minaei 2023-01-02 22:10:55 +01:00
parent 438a83d2d4
commit fd3a8cec35
2 changed files with 34 additions and 11 deletions

View file

@ -326,7 +326,9 @@ export const number = (
label: opts.label, label: opts.label,
nudgeFn: opts.nudgeFn ?? defaultNumberNudgeFn, nudgeFn: opts.nudgeFn ?? defaultNumberNudgeFn,
nudgeMultiplier: nudgeMultiplier:
typeof opts.nudgeMultiplier === 'number' ? opts.nudgeMultiplier : 1, typeof opts.nudgeMultiplier === 'number'
? opts.nudgeMultiplier
: undefined,
interpolate: _interpolateNumber, interpolate: _interpolateNumber,
deserializeAndSanitize: numberDeserializer(opts.range), deserializeAndSanitize: numberDeserializer(opts.range),
} }
@ -703,7 +705,10 @@ export interface PropTypeConfig_Number
extends ISimplePropType<'number', number> { extends ISimplePropType<'number', number> {
range?: [min: number, max: number] range?: [min: number, max: number]
nudgeFn: NumberNudgeFn nudgeFn: NumberNudgeFn
nudgeMultiplier: number /**
* See {@link defaultNumberNudgeFn} to see how `nudgeMultiplier` is treated.
*/
nudgeMultiplier: number | undefined
} }
export type NumberNudgeFn = (p: { export type NumberNudgeFn = (p: {
@ -713,6 +718,16 @@ export type NumberNudgeFn = (p: {
config: PropTypeConfig_Number config: PropTypeConfig_Number
}) => number }) => number
/**
* This is the default nudging behavior. It'll be used if `config.nudgeFn` is empty in {@link number} `types.number(defaultValue, config)`.
*
* Its behavior is as follows:
* - If `config.nudgeMultiplier` is set, then it'll be used as the unit of incrementing/decrementing the prop's value.
* For example, if `types.number(0, {nudgeMultiplier: 0.5})`, then nudging the number will make its value go up/down by 0.5, so: 0, 0.5, 1.0, -0.5, ...
* Note that if the prop's value is, say, 0.1, then nudging it will still make its value go up/down by 0.5, so: 0.6, 1.1, -0.6, ...
* - Otherwise, the amount of nudge will be determined based on whether the number has a range.
*
*/
const defaultNumberNudgeFn: NumberNudgeFn = ({ const defaultNumberNudgeFn: NumberNudgeFn = ({
config, config,
deltaX, deltaX,
@ -720,13 +735,18 @@ const defaultNumberNudgeFn: NumberNudgeFn = ({
magnitude, magnitude,
}) => { }) => {
const {range} = config const {range} = config
if (range && !range.includes(Infinity) && !range.includes(-Infinity)) { console.log(deltaX, deltaFraction, config)
return (
deltaFraction * (range[1] - range[0]) * magnitude * config.nudgeMultiplier if (
) !config.nudgeMultiplier &&
range &&
!range.includes(Infinity) &&
!range.includes(-Infinity)
) {
return deltaFraction * (range[1] - range[0]) * magnitude
} }
return deltaX * magnitude * config.nudgeMultiplier return deltaX * magnitude * (config.nudgeMultiplier ?? 1)
} }
export interface PropTypeConfig_Boolean export interface PropTypeConfig_Boolean

View file

@ -1,5 +1,5 @@
import {clamp, isInteger, round} from 'lodash-es' import {clamp, isInteger, round} from 'lodash-es'
import type {MutableRefObject} from 'react'; import type {MutableRefObject} from 'react'
import {useEffect} from 'react' import {useEffect} from 'react'
import {useState} from 'react' import {useState} from 'react'
import React, {useMemo, useRef} from 'react' import React, {useMemo, useRef} from 'react'
@ -232,9 +232,12 @@ const BasicNumberInput: React.FC<{
bodyCursorBeforeDrag.current = document.body.style.cursor bodyCursorBeforeDrag.current = document.body.style.cursor
return { return {
// note: we use mx because we need to constrain the `valueDuringDragging`
// and dx will keep accumulating past any constraints
onDrag(_dx: number, _dy: number, e: MouseEvent, mx: number) { onDrag(_dx: number, _dy: number, e: MouseEvent, mx: number) {
// We use `mx` here because it allows us to offer better UX when dragging
// a value beyond its range. If we were to use `_dx`, and the number had a range,
// and the user nudged the number beyond its range, they would have to un-nudge all
// the way back until the number's value is within its range. But with `mx`,
// as soon as they reverse their mouse drag, the number will jump back to its range.
const deltaX = e.altKey ? mx / 10 : mx const deltaX = e.altKey ? mx / 10 : mx
const newValue = const newValue =
valueDuringDragging + valueDuringDragging +