Skip to content

Commit

Permalink
refactor(number-input): ♻️ spin button hook
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy committed Sep 7, 2020
1 parent ec58392 commit e787212
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 110 deletions.
54 changes: 2 additions & 52 deletions src/number-input/NumberInputDecrementButton.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useCallback, useState } from "react";
import { createComponent, createHook } from "reakit-system";
import { ariaAttr, callAllHandlers } from "@chakra-ui/utils";
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit/Button";

import { useSpinButton } from "./__utils";
import { NumberInputStateReturn } from "./NumberInputState";
import { NUMBERINPUT_DECREMENTBUTTON_KEYS } from "./__keys";

Expand All @@ -27,56 +26,7 @@ export const useNumberInputDecrementButton = createHook<
keys: NUMBERINPUT_DECREMENTBUTTON_KEYS,

useProps(options, htmlProps) {
const {
keepWithinRange,
focusInput,
isAtMin: isAtMinProp,
spinner,
} = options;
const {
onMouseDown,
onMouseUp,
onMouseLeave,
onTouchStart,
onTouchEnd,
...restHtmlProps
} = htmlProps;

const [isAtMin, setIsAtMin] = useState(false);

const spinDown = useCallback(
(event: any) => {
event.preventDefault();
spinner.down();
focusInput();
setIsAtMin(false);
},
[focusInput, spinner],
);

const spinStop = useCallback(
(event: any) => {
event.preventDefault();
spinner.stop();

if (isAtMinProp) {
setIsAtMin(true);
}
},
[isAtMinProp, spinner],
);

return {
tabIndex: -1,
onMouseDown: callAllHandlers(onMouseDown, spinDown),
onTouchStart: callAllHandlers(onTouchStart, spinDown),
onMouseLeave: callAllHandlers(onMouseUp, spinStop),
onMouseUp: callAllHandlers(onMouseUp, spinStop),
onTouchEnd: callAllHandlers(onTouchEnd, spinStop),
disabled: keepWithinRange && isAtMinProp && isAtMin,
"aria-disabled": ariaAttr(keepWithinRange && isAtMin),
...restHtmlProps,
};
return useSpinButton(options, htmlProps, "decrement");
},
});

Expand Down
54 changes: 2 additions & 52 deletions src/number-input/NumberInputIncrementButton.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useCallback, useState } from "react";
import { createComponent, createHook } from "reakit-system";
import { ariaAttr, callAllHandlers } from "@chakra-ui/utils";
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit/Button";

import { useSpinButton } from "./__utils";
import { NumberInputStateReturn } from "./NumberInputState";
import { NUMBERINPUT_INCREMENTBUTTON_KEYS } from "./__keys";

Expand All @@ -27,56 +26,7 @@ export const useNumberInputIncrementButton = createHook<
keys: NUMBERINPUT_INCREMENTBUTTON_KEYS,

useProps(options, htmlProps) {
const {
keepWithinRange,
focusInput,
isAtMax: isAtMaxProp,
spinner,
} = options;
const {
onMouseDown,
onMouseUp,
onMouseLeave,
onTouchStart,
onTouchEnd,
...restHtmlProps
} = htmlProps;

const [isAtMax, setIsAtMax] = useState(false);

const spinUp = useCallback(
(event: any) => {
event.preventDefault();
spinner.up();
focusInput();
setIsAtMax(false);
},
[focusInput, spinner],
);

const spinStop = useCallback(
(event: any) => {
event.preventDefault();
spinner.stop();

if (isAtMaxProp) {
setIsAtMax(true);
}
},
[isAtMaxProp, spinner],
);

return {
tabIndex: -1,
onMouseDown: callAllHandlers(onMouseDown, spinUp),
onTouchStart: callAllHandlers(onTouchStart, spinUp),
onMouseUp: callAllHandlers(onMouseUp, spinStop),
onMouseLeave: callAllHandlers(onMouseLeave, spinStop),
onTouchEnd: callAllHandlers(onTouchEnd, spinStop),
disabled: keepWithinRange && isAtMaxProp && isAtMax,
"aria-disabled": ariaAttr(keepWithinRange && isAtMax),
...restHtmlProps,
};
return useSpinButton(options, htmlProps);
},
});

Expand Down
107 changes: 101 additions & 6 deletions src/number-input/__utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useInterval } from "@chakra-ui/hooks";
import { ButtonHTMLProps, ButtonOptions } from "reakit";
import { NumberInputStateReturn } from "./NumberInputState";
import { ariaAttr, callAllHandlers } from "@chakra-ui/utils";
import { useState, useRef, useEffect, useCallback, KeyboardEvent } from "react";

const FLOATING_POINT_REGEX = /^[Ee0-9\+\-\.]$/;
Expand Down Expand Up @@ -63,12 +66,7 @@ type Action = "increment" | "decrement";
* @param increment the function to increment
* @param decrement the function to decrement
*/
export function useSpinner(
increment: Function,
decrement: Function,
isAtMin: boolean,
isAtMax: boolean,
) {
export function useSpinner(increment: Function, decrement: Function) {
/**
* To keep incrementing/decrementing on press, we call that `spinning`
*/
Expand Down Expand Up @@ -151,3 +149,100 @@ export function useSpinner(

return { up, down, stop };
}

type UseSpinButtonOptions = ButtonOptions &
Pick<
Partial<NumberInputStateReturn>,
"keepWithinRange" | "isAtMin" | "isAtMax"
> &
Pick<
NumberInputStateReturn,
"focusInput" | "increment" | "decrement" | "spinner"
>;

type UseSpinButtonHTMLProps = ButtonHTMLProps;

export function useSpinButton(
options: UseSpinButtonOptions,
htmlProps: UseSpinButtonHTMLProps,
action = "increment",
) {
const {
keepWithinRange,
focusInput,
isAtMin: isAtMinProp,
isAtMax: isAtMaxProp,
spinner,
} = options;
const {
onMouseDown,
onMouseUp,
onMouseLeave,
onTouchStart,
onTouchEnd,
...restHtmlProps
} = htmlProps;

const [isAtMin, setIsAtMin] = useState(false);
const [isAtMax, setIsAtMax] = useState(false);

const spinUp = useCallback(
(event: any) => {
event.preventDefault();
spinner.up();
focusInput();
setIsAtMax(false);
},
[focusInput, spinner],
);

const spinDown = useCallback(
(event: any) => {
event.preventDefault();
spinner.down();
focusInput();
setIsAtMin(false);
},
[focusInput, spinner],
);

const spinStop = useCallback(
(event: any) => {
event.preventDefault();
spinner.stop();

if (action === "increment") {
isAtMaxProp && setIsAtMax(true);
} else {
isAtMinProp && setIsAtMin(true);
}
},
[action, isAtMaxProp, isAtMinProp, spinner],
);

const commonReturn = {
tabIndex: -1,
onMouseUp: callAllHandlers(onMouseUp, spinStop),
onMouseLeave: callAllHandlers(onMouseLeave, spinStop),
onTouchEnd: callAllHandlers(onTouchEnd, spinStop),
...restHtmlProps,
};

if (action === "increment") {
return {
onMouseDown: callAllHandlers(onMouseDown, spinUp),
onTouchStart: callAllHandlers(onTouchStart, spinUp),
disabled: keepWithinRange && isAtMaxProp && isAtMax,
"aria-disabled": ariaAttr(keepWithinRange && isAtMaxProp && isAtMax),
...commonReturn,
};
}

return {
onMouseDown: callAllHandlers(onMouseDown, spinDown),
onTouchStart: callAllHandlers(onTouchStart, spinDown),
disabled: keepWithinRange && isAtMinProp && isAtMin,
"aria-disabled": ariaAttr(keepWithinRange && isAtMinProp && isAtMin),
...commonReturn,
};
}

0 comments on commit e787212

Please sign in to comment.