From 732d71eead0b2e05c3d7067664224ab5ce3d8aae Mon Sep 17 00:00:00 2001 From: Artur Bien Date: Sat, 23 Feb 2019 21:51:16 +0100 Subject: [PATCH] extracted InputBase, styled NumberField --- src/components/DatePicker/DatePicker.js | 3 +- src/components/InputBase/InputBase.js | 51 +++++++ src/components/NumberField/NumberField.js | 124 ++++++++++++------ .../NumberField/NumberField.stories.js | 27 ++++ src/components/Select/Select.js | 2 +- src/components/TextField/TextField.js | 56 ++------ src/components/common/index.js | 18 ++- 7 files changed, 194 insertions(+), 87 deletions(-) create mode 100644 src/components/InputBase/InputBase.js diff --git a/src/components/DatePicker/DatePicker.js b/src/components/DatePicker/DatePicker.js index 2cf70ea..4a494ed 100644 --- a/src/components/DatePicker/DatePicker.js +++ b/src/components/DatePicker/DatePicker.js @@ -117,8 +117,9 @@ class DatePicker extends Component { /> diff --git a/src/components/InputBase/InputBase.js b/src/components/InputBase/InputBase.js new file mode 100644 index 0000000..22bc101 --- /dev/null +++ b/src/components/InputBase/InputBase.js @@ -0,0 +1,51 @@ +import React from "react"; +import propTypes from "prop-types"; + +import styled from "styled-components"; +import { StyledTextInput, StyledCutout } from "../common"; +import { colors, blockSizes } from "../common/theme.variables"; + +const StyledInputWrapper = styled(StyledCutout)` + height: ${blockSizes.md}; + padding: 2px; + background: ${props => (props.isDisabled ? colors.bg : colors.light)}; +`; + +const InputBase = ({ + onChange, + value, + disabled, + name, + type, + style, + shadow, + ...otherProps +}) => ( + + + +); + +InputBase.defaultProps = { + value: "", + disabled: false, + shadow: true, + onChange: undefined +}; +InputBase.propTypes = { + name: propTypes.string, + onChange: propTypes.func, + value: propTypes.oneOfType([propTypes.string, propTypes.number]).isRequired, + disabled: propTypes.bool, + shadow: propTypes.bool, + type: propTypes.oneOf(["text", "number", "tel"]) +}; +export default InputBase; diff --git a/src/components/NumberField/NumberField.js b/src/components/NumberField/NumberField.js index a1b65b1..d6f09f7 100644 --- a/src/components/NumberField/NumberField.js +++ b/src/components/NumberField/NumberField.js @@ -1,16 +1,54 @@ -import React, { Component } from "react"; +import React from "react"; import propTypes from "prop-types"; -import cx from "classnames"; -import "./NumberField.css"; +import Button from "../Button/Button"; -import TextField from "../TextField/TextField"; +import styled from "styled-components"; +import { colors, blockSizes } from "../common/theme.variables"; +import InputBase from "../InputBase/InputBase"; -class NumberField extends Component { +// ⭕⭕⭕⭕⭕ fix functionality and use hooks + +const StyledNumberFieldWrapper = styled.div` + display: inline-flex; + align-items: center; +`; + +const StyledButtonWrapper = styled.div` + height: ${blockSizes.md}; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + margin-left: 2px; + margin-top: -2px; +`; +const StyledButton = styled(Button)` + height: 50%; + width: 30px; + padding: 0; + flex-shrink: 0; + border-left-color: ${colors.lightGray}; + border-top-color: ${colors.lightGray}; + box-shadow: inset 1px 1px 0px 1px ${colors.light}, + inset -1px -1px 0 1px ${colors.darkGray}; +`; +const StyledButtonIcon = styled.span` + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%) ${props => props.invert && "rotateZ(180deg)"}; + width: 0px; + height: 0px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + display: inline-block; + border-top: 4px solid ${colors.dark}; +`; + +class NumberField extends React.Component { static defaultProps = { value: 0, - disabled: false, - width: null + disabled: false }; static propTypes = { onChange: propTypes.func.isRequired, @@ -19,6 +57,9 @@ class NumberField extends Component { max: propTypes.number, width: propTypes.oneOfType([propTypes.string, propTypes.number]), disabled: propTypes.bool, + disableKeyboardInput: propTypes.bool, + fullWidth: propTypes.bool, + shadow: propTypes.bool, className: propTypes.string }; state = { @@ -32,51 +73,56 @@ class NumberField extends Component { }; handleChange = e => { - const newValue = this.normalize(parseInt(e.target.value)); - this.props.onChange(newValue); - this.setState({ value: newValue }); + let newValue = + e.target.value === "-" ? "-" : this.normalize(e.target.value); + console.log(newValue); + newValue = newValue ? newValue : newValue === 0 ? 0 : ""; + if (e.target.validity.valid) { + this.setState({ value: newValue }); + this.props.onChange(newValue); + } }; normalize = value => { const { min, max } = this.props; if (min !== undefined && value < min) return min; if (max !== undefined && value > max) return max; - return value; + return parseInt(value); }; render() { - const { disabled, className, width, style } = this.props; + const { + disabled, + disableKeyboardInput, + className, + width, + style, + shadow + } = this.props; const { value } = this.state; - const baseClass = "NumberField"; - const rootClass = cx(baseClass, className, { - [`${baseClass}__disabled`]: disabled - }); - return ( -
- -
- - - -
-
+ + this.add(1)}> + + + this.add(-1)}> + + + + ); } } diff --git a/src/components/NumberField/NumberField.stories.js b/src/components/NumberField/NumberField.stories.js index 5584752..64b3b69 100644 --- a/src/components/NumberField/NumberField.stories.js +++ b/src/components/NumberField/NumberField.stories.js @@ -15,9 +15,36 @@ storiesOf("NumberField", module) )) .add("default", () => ( + console.log(value)} /> + )) + .add("fixed width", () => ( console.log(value)} /> + )) + .add("disabled", () => ( + console.log(value)} + /> + )) + .add("disabled keyboard input", () => ( + console.log(value)} + /> + )) + .add("no shadow", () => ( + console.log(value)} + /> )); diff --git a/src/components/Select/Select.js b/src/components/Select/Select.js index 1e18ee6..84ab081 100644 --- a/src/components/Select/Select.js +++ b/src/components/Select/Select.js @@ -47,7 +47,7 @@ const StyledDropdownIcon = styled.span` border-left: 6px solid transparent; border-right: 6px solid transparent; display: inline-block; - border-top: 6px solid #050608; + border-top: 6px solid ${colors.dark}; `; const StyledDropdownList = styled.ul` diff --git a/src/components/TextField/TextField.js b/src/components/TextField/TextField.js index eddbf14..dc3e53e 100644 --- a/src/components/TextField/TextField.js +++ b/src/components/TextField/TextField.js @@ -1,35 +1,7 @@ import React, { useState } from "react"; import propTypes from "prop-types"; -import styled from "styled-components"; -import { StyledCutout } from "../common"; -import { - blockSizes, - fontSizes, - padding, - colors -} from "../common/theme.variables"; - -const StyledInputWrapper = styled(StyledCutout)` - height: ${blockSizes.md}; - padding: 2px; - background: ${props => (props.isDisabled ? colors.bg : colors.light)}; -`; -const StyledInput = styled.input` - width: 100%; - height: 100%; - padding: 0 ${padding.sm}; - outline: none; - border: none; - background: none; - font-size: ${fontSizes.md}; - - color: ${props => (props.disabled ? colors.darkGray : colors.dark)}; - text-shadow: ${props => - props.disabled ? "1px 1px " + colors.light : "none"}; - filter: ${props => (props.disabled ? "grayscale(100%)" : "none")}; - /* negative margin to compensate for wrapper borders */ -`; +import InputBase from "../InputBase/InputBase"; const TextField = ({ onChange, @@ -45,28 +17,24 @@ const TextField = ({ }) => { const [inputValue, setInputValue] = useState(value); + console.log(value, inputValue); const onValueChange = e => { const newValue = e.target.value; setInputValue(newValue); onChange && onChange(e); }; return ( - - - + onChange={disabled ? undefined : onValueChange} + disabled={disabled} + value={inputValue} + name={name} + className={className} + type="text" + /> ); }; @@ -83,8 +51,6 @@ TextField.propTypes = { value: propTypes.oneOfType([propTypes.string, propTypes.number]).isRequired, disabled: propTypes.bool, shadow: propTypes.bool, - rows: propTypes.number, - width: propTypes.oneOfType([propTypes.string, propTypes.number]), - type: propTypes.oneOf(["text", "number"]) + width: propTypes.oneOfType([propTypes.string, propTypes.number]) }; export default TextField; diff --git a/src/components/common/index.js b/src/components/common/index.js index cb69ef5..a3a6ed9 100644 --- a/src/components/common/index.js +++ b/src/components/common/index.js @@ -1,5 +1,5 @@ import styled, { css } from "styled-components"; -import { colors, fontSizes } from "./theme.variables"; +import { colors, fontSizes, padding } from "./theme.variables"; const { bg, light, dark, lightGray, darkGray } = colors; @@ -80,3 +80,19 @@ export const StyledCutout = styled.div` props.shadow && "box-shadow: inset 3px 3px 10px rgba(0, 0, 0, 0.3);"} } `; + +export const StyledTextInput = styled.input` + width: 100%; + height: 100%; + padding: 0 ${padding.sm}; + outline: none; + border: none; + background: none; + font-size: ${fontSizes.md}; + + color: ${props => (props.disabled ? colors.darkGray : colors.dark)}; + text-shadow: ${props => + props.disabled ? "1px 1px " + colors.light : "none"}; + filter: ${props => (props.disabled ? "grayscale(100%)" : "none")}; + /* negative margin to compensate for wrapper borders */ +`;