mirror of
https://gitlab.nic.cz/turris/reforis/foris-js.git
synced 2024-12-24 00:01:36 +01:00
Resolve "Increment/decrement value in NumberInput when +/- button is kept pushed."
This commit is contained in:
parent
0af56ec84c
commit
afa8c160a3
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "foris",
|
"name": "foris",
|
||||||
"version": "0.1.0-beta.7",
|
"version": "0.1.0-beta.8",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "foris",
|
"name": "foris",
|
||||||
"version": "0.1.0-beta.7",
|
"version": "0.1.0-beta.8",
|
||||||
"description": "Set of components and utils for Foris and its plugins.",
|
"description": "Set of components and utils for Foris and its plugins.",
|
||||||
"author": "CZ.NIC, z.s.p.o.",
|
"author": "CZ.NIC, z.s.p.o.",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
import { useConditionalTimeout } from "utils/hooks";
|
||||||
import { Input } from "./Input";
|
import { Input } from "./Input";
|
||||||
import "./NumberInput.css";
|
import "./NumberInput.css";
|
||||||
|
|
||||||
|
@ -33,15 +34,25 @@ NumberInput.defaultProps = {
|
||||||
value: 0,
|
value: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function NumberInput({ onChange, inlineText, ...props }) {
|
export function NumberInput({
|
||||||
|
onChange, inlineText, value, ...props
|
||||||
|
}) {
|
||||||
|
function updateValue(initialValue, difference) {
|
||||||
|
onChange({ target: { value: initialValue + difference } });
|
||||||
|
}
|
||||||
|
|
||||||
|
const enableIncrease = useConditionalTimeout({ callback: updateValue }, value, 1);
|
||||||
|
const enableDecrease = useConditionalTimeout({ callback: updateValue }, value, -1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input type="number" onChange={onChange} {...props}>
|
<Input type="number" onChange={onChange} value={value} {...props}>
|
||||||
<div className="input-group-append">
|
<div className="input-group-append">
|
||||||
{inlineText && <p className="input-group-text">{inlineText}</p>}
|
{inlineText && <p className="input-group-text">{inlineText}</p>}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-outline-secondary"
|
className="btn btn-outline-secondary"
|
||||||
onClick={() => onChange({ target: { value: props.value + 1 } })}
|
onMouseDown={() => enableIncrease(true)}
|
||||||
|
onMouseUp={() => enableIncrease(false)}
|
||||||
aria-label="Increase"
|
aria-label="Increase"
|
||||||
>
|
>
|
||||||
<i className="fas fa-plus" />
|
<i className="fas fa-plus" />
|
||||||
|
@ -49,7 +60,8 @@ export function NumberInput({ onChange, inlineText, ...props }) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-outline-secondary"
|
className="btn btn-outline-secondary"
|
||||||
onClick={() => onChange({ target: { value: props.value - 1 } })}
|
onMouseDown={() => enableDecrease(true)}
|
||||||
|
onMouseUp={() => enableDecrease(false)}
|
||||||
aria-label="Decrease"
|
aria-label="Decrease"
|
||||||
>
|
>
|
||||||
<i className="fas fa-minus" />
|
<i className="fas fa-minus" />
|
||||||
|
|
|
@ -7,39 +7,39 @@
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { render, fireEvent } from "customTestRender";
|
import { render, fireEvent, getByLabelText, wait } from "customTestRender";
|
||||||
|
|
||||||
import { NumberInput } from "../NumberInput";
|
import { NumberInput } from "../NumberInput";
|
||||||
|
|
||||||
describe("<NumberInput/>", () => {
|
describe("<NumberInput/>", () => {
|
||||||
const onChangeMock = jest.fn();
|
const onChangeMock = jest.fn();
|
||||||
let container;
|
let componentContainer;
|
||||||
let getByLabelText;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
({ container, getByLabelText } = render(
|
const { container } = render(
|
||||||
<NumberInput
|
<NumberInput
|
||||||
label="Test label"
|
label="Test label"
|
||||||
helpText="Some help text"
|
helpText="Some help text"
|
||||||
value={1}
|
value={1}
|
||||||
onChange={onChangeMock}
|
onChange={onChangeMock}
|
||||||
/>
|
/>
|
||||||
));
|
);
|
||||||
|
componentContainer = container;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Render number input", () => {
|
it("Render number input", () => {
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(componentContainer.firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Increase number with button", () => {
|
it("Increase number with button", async () => {
|
||||||
const increaseButton = getByLabelText("Increase");
|
const increaseButton = getByLabelText(componentContainer, "Increase");
|
||||||
fireEvent.click(increaseButton);
|
fireEvent.mouseDown(increaseButton);
|
||||||
expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 2}});
|
await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 2}}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Decrease number with button", () => {
|
it("Decrease number with button", async () => {
|
||||||
const decreaseButton = getByLabelText("Decrease");
|
const decreaseButton = getByLabelText(componentContainer, "Decrease");
|
||||||
fireEvent.click(decreaseButton);
|
fireEvent.mouseDown(decreaseButton);
|
||||||
expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 0}});
|
await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 0}}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
20
src/utils/hooks.js
Normal file
20
src/utils/hooks.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||||
|
*
|
||||||
|
* This is free software, licensed under the GNU General Public License v3.
|
||||||
|
* See /LICENSE for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
/** Execute callback when condition is set to true. */
|
||||||
|
export function useConditionalTimeout({ callback, timeout = 125 }, ...callbackArgs) {
|
||||||
|
const [condition, setCondition] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (condition) {
|
||||||
|
const interval = setTimeout(() => callback(...callbackArgs), timeout);
|
||||||
|
return () => setTimeout(interval);
|
||||||
|
}
|
||||||
|
}, [condition, callback, timeout, callbackArgs]);
|
||||||
|
return setCondition;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user