From 463a11cbe85217683acc26fb2616df41950363d3 Mon Sep 17 00:00:00 2001 From: alinais Date: Wed, 1 Aug 2018 16:11:52 +0200 Subject: [PATCH 01/10] adding variation for clearable input --- .../InputExampleIconChange.shorthand.tsx | 47 +++++++++++++++++++ .../components/Input/Variations/index.tsx | 5 ++ src/components/Icon/Icon.tsx | 1 - src/components/Input/Input.tsx | 23 +++++++++ test/specs/components/Input/Input-test.ts | 10 ---- test/specs/components/Input/Input-test.tsx | 22 +++++++++ 6 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx delete mode 100644 test/specs/components/Input/Input-test.ts create mode 100644 test/specs/components/Input/Input-test.tsx diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx new file mode 100644 index 0000000000..9e1038c4cc --- /dev/null +++ b/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { Input, Icon } from '@stardust-ui/react' + +class InputExampleIconChangeShorthand extends React.Component< + {}, + { icon: string; inputValue: string } +> { + constructor() { + super({}) + this.state = { + icon: 'search', + inputValue: '', + } + } + + public handleChange = (e, { value }) => { + this.setState({ + icon: value ? 'close' : 'search', + inputValue: value, + }) + } + + public onIconClick = (e, value) => { + if (value === 'close') { + this.setState({ + icon: 'search', + inputValue: '', + }) + } + } + + public render() { + const { icon, inputValue } = this.state + + return ( + this.onIconClick(e, icon)} + /> + ) + } +} + +export default InputExampleIconChangeShorthand diff --git a/docs/src/examples/components/Input/Variations/index.tsx b/docs/src/examples/components/Input/Variations/index.tsx index 1ec7ff1bd3..70fdf29b19 100644 --- a/docs/src/examples/components/Input/Variations/index.tsx +++ b/docs/src/examples/components/Input/Variations/index.tsx @@ -14,6 +14,11 @@ const Variations = () => ( description="An input can take the full width of the parent element." examplePath="components/Input/Variations/InputExampleFluid" /> + ) diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index bf94142b62..04e10acfdb 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -8,7 +8,6 @@ export type IconXSpacing = 'none' | 'before' | 'after' | 'both' class Icon extends UIComponent { static create: Function - static className = 'ui-icon' static displayName = 'Icon' diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 302e3e4725..41c3eac929 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -40,6 +40,22 @@ class Input extends UIComponent { /** Shorthand for creating the HTML Input. */ input: customPropTypes.itemShorthand, + /** + * Called on change. + * + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props and proposed value. + */ + onChange: PropTypes.func, + + /** + * Function called when the icon is clicked. + * + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props. + */ + onIconClick: PropTypes.func, + /** The HTML input type. */ type: PropTypes.string, @@ -74,6 +90,12 @@ class Input extends UIComponent { if (props.onClick) return 0 } + handleChange = e => { + const value = _.get(e, 'target.value') + + _.invoke(this.props, 'onChange', e, { ...this.props, value }) + } + handleChildOverrides = (child, defaultProps) => ({ ...defaultProps, ...child.props, @@ -90,6 +112,7 @@ class Input extends UIComponent { return [ { ...htmlInputProps, + onChange: this.handleChange, type, }, rest, diff --git a/test/specs/components/Input/Input-test.ts b/test/specs/components/Input/Input-test.ts deleted file mode 100644 index 4201b742cd..0000000000 --- a/test/specs/components/Input/Input-test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react' - -import { isConformant } from 'test/specs/commonTests' -import { getTestingRenderedComponent } from 'test/utils' - -import Input from 'src/components/Input/Input' - -describe('Input', () => { - isConformant(Input) -}) diff --git a/test/specs/components/Input/Input-test.tsx b/test/specs/components/Input/Input-test.tsx new file mode 100644 index 0000000000..ef6236cfea --- /dev/null +++ b/test/specs/components/Input/Input-test.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +import { isConformant } from 'test/specs/commonTests' + +import Input from 'src/components/Input/Input' +import { mountWithProvider } from 'test/utils' + +describe('Input', () => { + isConformant(Input) + + describe('onIconClick', () => { + it('calls onIconClick when the icon is clicked', () => { + const onClick = jest.fn() + + const input = mountWithProvider().find( + 'Icon[name="close"]', + ) + input.simulate('click') + expect(onClick).toHaveBeenCalled() + }) + }) +}) From 554e7a983db40089e32d8fc1f5082c3757637c5e Mon Sep 17 00:00:00 2001 From: alinais Date: Fri, 3 Aug 2018 12:32:53 +0200 Subject: [PATCH 02/10] adding clearable property to Input component --- .../InputExampleIconChange.shorthand.tsx | 47 ---------------- .../InputExampleIconClearable.shorthand.tsx | 10 ++++ .../components/Input/Variations/index.tsx | 2 +- src/components/Input/Input.tsx | 53 +++++++++++++++---- 4 files changed, 53 insertions(+), 59 deletions(-) delete mode 100644 docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx create mode 100644 docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx deleted file mode 100644 index 9e1038c4cc..0000000000 --- a/docs/src/examples/components/Input/Variations/InputExampleIconChange.shorthand.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react' -import { Input, Icon } from '@stardust-ui/react' - -class InputExampleIconChangeShorthand extends React.Component< - {}, - { icon: string; inputValue: string } -> { - constructor() { - super({}) - this.state = { - icon: 'search', - inputValue: '', - } - } - - public handleChange = (e, { value }) => { - this.setState({ - icon: value ? 'close' : 'search', - inputValue: value, - }) - } - - public onIconClick = (e, value) => { - if (value === 'close') { - this.setState({ - icon: 'search', - inputValue: '', - }) - } - } - - public render() { - const { icon, inputValue } = this.state - - return ( - this.onIconClick(e, icon)} - /> - ) - } -} - -export default InputExampleIconChangeShorthand diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx new file mode 100644 index 0000000000..f4992d661d --- /dev/null +++ b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { Input } from '@stardust-ui/react' + +class InputExampleIconClearableShorthand extends React.Component<{}, { value: string }> { + public render() { + return + } +} + +export default InputExampleIconClearableShorthand diff --git a/docs/src/examples/components/Input/Variations/index.tsx b/docs/src/examples/components/Input/Variations/index.tsx index 70fdf29b19..525fac759e 100644 --- a/docs/src/examples/components/Input/Variations/index.tsx +++ b/docs/src/examples/components/Input/Variations/index.tsx @@ -17,7 +17,7 @@ const Variations = () => ( ) diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 41c3eac929..1323585e49 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -3,6 +3,7 @@ import * as React from 'react' import * as _ from 'lodash' import { + AutoControlledComponent, childrenExist, createHTMLInput, customPropTypes, @@ -16,7 +17,7 @@ import Icon from '../Icon' * An Input * @accessibility This is example usage of the accessibility tag. */ -class Input extends UIComponent { +class Input extends AutoControlledComponent { static className = 'ui-input' static displayName = 'Input' @@ -31,6 +32,12 @@ class Input extends UIComponent { /** Additional classes. */ className: PropTypes.string, + /** A property that will change the icon on the input and clear the input on click on Cancel */ + clearable: PropTypes.bool, + + /** The default value of the input string. */ + defaultValue: PropTypes.string, + /** A button can take the width of its container. */ fluid: PropTypes.bool, @@ -48,20 +55,15 @@ class Input extends UIComponent { */ onChange: PropTypes.func, - /** - * Function called when the icon is clicked. - * - * @param {SyntheticEvent} event - React's original SyntheticEvent. - * @param {object} data - All props. - */ - onIconClick: PropTypes.func, - /** The HTML input type. */ type: PropTypes.string, /** Custom styles to be applied for component. */ styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + /** The value of the input. */ + value: PropTypes.string, + /** Custom variables to be applied for component. */ variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), } @@ -70,11 +72,15 @@ class Input extends UIComponent { 'as', 'children', 'className', + 'clearable', + 'defaultValue', 'fluid', 'icon', 'input', + 'onChange', 'styles', 'type', + 'value', 'variables', ] @@ -85,6 +91,8 @@ class Input extends UIComponent { inputRef: any + static autoControlledProps = ['value'] + computeTabIndex = props => { if (!_.isNil(props.tabIndex)) return props.tabIndex if (props.onClick) return 0 @@ -92,8 +100,11 @@ class Input extends UIComponent { handleChange = e => { const value = _.get(e, 'target.value') + const { clearable } = this.props _.invoke(this.props, 'onChange', e, { ...this.props, value }) + + clearable && this.trySetState({ value }) } handleChildOverrides = (child, defaultProps) => ({ @@ -103,8 +114,18 @@ class Input extends UIComponent { handleInputRef = c => (this.inputRef = c) + handleOnIconClick = e => { + const { clearable, icon } = this.props + const { value } = this.state + + if (clearable && value.length !== 0) { + this.trySetState({ value: '' }) + } + } + partitionProps = () => { const { type } = this.props + const { value } = this.state const unhandled = getUnhandledProps(Input, this.props) const [htmlInputProps, rest] = partitionHTMLProps(unhandled) @@ -114,21 +135,30 @@ class Input extends UIComponent { ...htmlInputProps, onChange: this.handleChange, type, + value, }, rest, ] } computeIcon = () => { - const { icon } = this.props + const { clearable, icon } = this.props + const { value } = this.state + + if (clearable && !_.isNil(icon) && value.length !== 0) { + return 'close' + } if (!_.isNil(icon)) return icon + return null } handleIconOverrides = predefinedProps => { return { onClick: e => { + this.handleOnIconClick(e) + this.inputRef.focus() _.invoke(predefinedProps, 'onClick', e, this.props) }, @@ -137,10 +167,11 @@ class Input extends UIComponent { } renderComponent({ ElementType, classes, rest, styles }) { - const { children, input, type } = this.props + const { children, clearable, input, type } = this.props const [htmlInputProps, restProps] = this.partitionProps() const inputClasses = classes.input + const iconClasses = classes.icon // Render with children // ---------------------------------------- From 36ce1d5580093bd319c0abb32b6938bb3dc5b9a9 Mon Sep 17 00:00:00 2001 From: alinais Date: Fri, 3 Aug 2018 13:05:00 +0200 Subject: [PATCH 03/10] fixing merge issues; fixing the inputs without clearable prop --- .../Variations/InputExampleIconClearable.shorthand.tsx | 2 +- src/components/Icon/Icon.tsx | 1 + src/components/Input/Input.tsx | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx index f4992d661d..17cd5aea72 100644 --- a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx +++ b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Input } from '@stardust-ui/react' -class InputExampleIconClearableShorthand extends React.Component<{}, { value: string }> { +class InputExampleIconClearableShorthand extends React.Component { public render() { return } diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index 04e10acfdb..bf94142b62 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -8,6 +8,7 @@ export type IconXSpacing = 'none' | 'before' | 'after' | 'both' class Icon extends UIComponent { static create: Function + static className = 'ui-icon' static displayName = 'Icon' diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 1323585e49..1b172569cd 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -104,7 +104,7 @@ class Input extends AutoControlledComponent { _.invoke(this.props, 'onChange', e, { ...this.props, value }) - clearable && this.trySetState({ value }) + this.trySetState({ value }) } handleChildOverrides = (child, defaultProps) => ({ @@ -114,7 +114,7 @@ class Input extends AutoControlledComponent { handleInputRef = c => (this.inputRef = c) - handleOnIconClick = e => { + handleOnClear = e => { const { clearable, icon } = this.props const { value } = this.state @@ -157,7 +157,7 @@ class Input extends AutoControlledComponent { handleIconOverrides = predefinedProps => { return { onClick: e => { - this.handleOnIconClick(e) + this.handleOnClear(e) this.inputRef.focus() _.invoke(predefinedProps, 'onClick', e, this.props) From 60ef99b0b8044a7533cdb21a6c527bf41c99a5db Mon Sep 17 00:00:00 2001 From: alinais Date: Fri, 3 Aug 2018 16:13:07 +0200 Subject: [PATCH 04/10] making the Input component a normal UIComponent --- src/components/Input/Input.tsx | 24 ++++++++++++++-------- test/specs/components/Input/Input-test.tsx | 13 ++++-------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 1b172569cd..b4031f3132 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -3,7 +3,6 @@ import * as React from 'react' import * as _ from 'lodash' import { - AutoControlledComponent, childrenExist, createHTMLInput, customPropTypes, @@ -17,7 +16,7 @@ import Icon from '../Icon' * An Input * @accessibility This is example usage of the accessibility tag. */ -class Input extends AutoControlledComponent { +class Input extends UIComponent { static className = 'ui-input' static displayName = 'Input' @@ -35,9 +34,6 @@ class Input extends AutoControlledComponent { /** A property that will change the icon on the input and clear the input on click on Cancel */ clearable: PropTypes.bool, - /** The default value of the input string. */ - defaultValue: PropTypes.string, - /** A button can take the width of its container. */ fluid: PropTypes.bool, @@ -93,18 +89,28 @@ class Input extends AutoControlledComponent { static autoControlledProps = ['value'] + constructor(props, context) { + super(props, context) + + this.state = { + value: '', + } + + this.handleChange = this.handleChange.bind(this) + } + computeTabIndex = props => { if (!_.isNil(props.tabIndex)) return props.tabIndex if (props.onClick) return 0 } handleChange = e => { - const value = _.get(e, 'target.value') + const inputValue = _.get(e, 'target.value') const { clearable } = this.props - _.invoke(this.props, 'onChange', e, { ...this.props, value }) + _.invoke(this.props, 'onChange', e, { ...this.props, inputValue }) - this.trySetState({ value }) + this.setState({ value: inputValue }) } handleChildOverrides = (child, defaultProps) => ({ @@ -119,7 +125,7 @@ class Input extends AutoControlledComponent { const { value } = this.state if (clearable && value.length !== 0) { - this.trySetState({ value: '' }) + this.setState({ value: '' }) } } diff --git a/test/specs/components/Input/Input-test.tsx b/test/specs/components/Input/Input-test.tsx index ef6236cfea..9d4aa4e715 100644 --- a/test/specs/components/Input/Input-test.tsx +++ b/test/specs/components/Input/Input-test.tsx @@ -8,15 +8,10 @@ import { mountWithProvider } from 'test/utils' describe('Input', () => { isConformant(Input) - describe('onIconClick', () => { - it('calls onIconClick when the icon is clicked', () => { - const onClick = jest.fn() - - const input = mountWithProvider().find( - 'Icon[name="close"]', - ) - input.simulate('click') - expect(onClick).toHaveBeenCalled() + describe('icon shorthand', () => { + it('creates the Icon component when the icon shorthand is provided', () => { + const input = mountWithProvider().find('Icon[name="close"]') + expect(input).not.toBe(undefined) }) }) }) From 8e7a736e26492e8db75a3fa42c9ace8f4ebaf636 Mon Sep 17 00:00:00 2001 From: alinais Date: Fri, 3 Aug 2018 17:58:24 +0200 Subject: [PATCH 05/10] making the value prop working --- src/components/Input/Input.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index b4031f3132..829f08a29f 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -93,7 +93,7 @@ class Input extends UIComponent { super(props, context) this.state = { - value: '', + value: props.value || '', } this.handleChange = this.handleChange.bind(this) @@ -141,7 +141,7 @@ class Input extends UIComponent { ...htmlInputProps, onChange: this.handleChange, type, - value, + value: value || '', }, rest, ] From 440ecbc5dbe5f1d10340057ab5949005a629ad3a Mon Sep 17 00:00:00 2001 From: alinais Date: Mon, 6 Aug 2018 18:55:11 +0200 Subject: [PATCH 06/10] cleaning the Input code; cleaning the example --- .../Variations/InputExampleIconClearable.shorthand.tsx | 8 +++----- src/components/Input/Input.tsx | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx index 17cd5aea72..3cf8b29de8 100644 --- a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx +++ b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx @@ -1,10 +1,8 @@ import React from 'react' import { Input } from '@stardust-ui/react' -class InputExampleIconClearableShorthand extends React.Component { - public render() { - return - } -} +const InputExampleIconClearableShorthand = () => ( + +) export default InputExampleIconClearableShorthand diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 829f08a29f..4e95d5146f 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -95,8 +95,6 @@ class Input extends UIComponent { this.state = { value: props.value || '', } - - this.handleChange = this.handleChange.bind(this) } computeTabIndex = props => { @@ -105,12 +103,12 @@ class Input extends UIComponent { } handleChange = e => { - const inputValue = _.get(e, 'target.value') + const value = _.get(e, 'target.value') const { clearable } = this.props - _.invoke(this.props, 'onChange', e, { ...this.props, inputValue }) + _.invoke(this.props, 'onChange', e, { ...this.props, value }) - this.setState({ value: inputValue }) + this.setState({ value }) } handleChildOverrides = (child, defaultProps) => ({ From 9c0b9910c30dbdcafd790e31d7bf263b0d789329 Mon Sep 17 00:00:00 2001 From: alinais Date: Tue, 7 Aug 2018 18:39:57 +0200 Subject: [PATCH 07/10] fixing failing tests --- src/components/Input/Input.tsx | 11 ++--------- test/specs/components/Input/Input-test.tsx | 13 ++++++++++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 4e95d5146f..0fe1a5572f 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -87,8 +87,6 @@ class Input extends UIComponent { inputRef: any - static autoControlledProps = ['value'] - constructor(props, context) { super(props, context) @@ -97,11 +95,6 @@ class Input extends UIComponent { } } - computeTabIndex = props => { - if (!_.isNil(props.tabIndex)) return props.tabIndex - if (props.onClick) return 0 - } - handleChange = e => { const value = _.get(e, 'target.value') const { clearable } = this.props @@ -119,7 +112,7 @@ class Input extends UIComponent { handleInputRef = c => (this.inputRef = c) handleOnClear = e => { - const { clearable, icon } = this.props + const { clearable } = this.props const { value } = this.state if (clearable && value.length !== 0) { @@ -166,7 +159,7 @@ class Input extends UIComponent { this.inputRef.focus() _.invoke(predefinedProps, 'onClick', e, this.props) }, - tabIndex: this.computeTabIndex, + ...(predefinedProps.onClick && { tabIndex: '0' }), } } diff --git a/test/specs/components/Input/Input-test.tsx b/test/specs/components/Input/Input-test.tsx index 9d4aa4e715..63a9b2e996 100644 --- a/test/specs/components/Input/Input-test.tsx +++ b/test/specs/components/Input/Input-test.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import { isConformant } from 'test/specs/commonTests' @@ -8,9 +8,16 @@ import { mountWithProvider } from 'test/utils' describe('Input', () => { isConformant(Input) - describe('icon shorthand', () => { + describe('input', () => { + it('renders a text by default', () => { + const input = mountWithProvider().find('input[type="text"]') + expect(input).not.toBe(undefined) + }) + }) + + describe('icon', () => { it('creates the Icon component when the icon shorthand is provided', () => { - const input = mountWithProvider().find('Icon[name="close"]') + const input = mountWithProvider().find('Icon[name="close"]') expect(input).not.toBe(undefined) }) }) From 653e3c2f37987e42febab2994f0f4ac19ff3f5ad Mon Sep 17 00:00:00 2001 From: alinais Date: Tue, 7 Aug 2018 19:20:09 +0200 Subject: [PATCH 08/10] updating changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55355ad952..550833f536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Features - Add `color` variables to Header and Header.Description @kuzhelov ([#72](https://github.com/stardust-ui/react/pull/72)) +## Features +- Add Input `clearable` prop @alinais ([#37](https://github.com/stardust-ui/react/pull/37)) + ## [v0.2.6](https://github.com/stardust-ui/react/tree/v0.2.6) (2018-08-09) [Compare changes](https://github.com/stardust-ui/react/compare/v0.2.5...v0.2.6) From 739d80447ee95bf99128ccb5edb43851e140a308 Mon Sep 17 00:00:00 2001 From: alinais Date: Wed, 15 Aug 2018 16:48:48 +0200 Subject: [PATCH 09/10] updating the input variations with a simple example of clearable property usage; keeping the value provided by the user for the input as the meaningful one --- .../Input/Types/InputExample.shorthand.tsx | 2 +- .../InputExampleClearable.shorthand.tsx | 6 +++++ .../InputExampleFluid.shorthand.tsx | 2 +- .../Variations/InputExampleIcon.shorthand.tsx | 2 +- .../InputExampleIconClearable.shorthand.tsx | 2 +- .../components/Input/Variations/index.tsx | 11 +++++--- src/components/Input/Input.tsx | 25 +++++++++++-------- 7 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 docs/src/examples/components/Input/Variations/InputExampleClearable.shorthand.tsx diff --git a/docs/src/examples/components/Input/Types/InputExample.shorthand.tsx b/docs/src/examples/components/Input/Types/InputExample.shorthand.tsx index 9b812e77ee..4466ddc5b2 100644 --- a/docs/src/examples/components/Input/Types/InputExample.shorthand.tsx +++ b/docs/src/examples/components/Input/Types/InputExample.shorthand.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import { Input } from '@stardust-ui/react' const InputExample = () => diff --git a/docs/src/examples/components/Input/Variations/InputExampleClearable.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleClearable.shorthand.tsx new file mode 100644 index 0000000000..44cdbad4f7 --- /dev/null +++ b/docs/src/examples/components/Input/Variations/InputExampleClearable.shorthand.tsx @@ -0,0 +1,6 @@ +import * as React from 'react' +import { Input } from '@stardust-ui/react' + +const InputExampleClearableShorthand = () => + +export default InputExampleClearableShorthand diff --git a/docs/src/examples/components/Input/Variations/InputExampleFluid.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleFluid.shorthand.tsx index 2c1c9bcd0b..fb5f83e1a0 100644 --- a/docs/src/examples/components/Input/Variations/InputExampleFluid.shorthand.tsx +++ b/docs/src/examples/components/Input/Variations/InputExampleFluid.shorthand.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import { Input } from '@stardust-ui/react' const InputExample = () => diff --git a/docs/src/examples/components/Input/Variations/InputExampleIcon.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIcon.shorthand.tsx index a929a4a0ef..06f53d7b2e 100644 --- a/docs/src/examples/components/Input/Variations/InputExampleIcon.shorthand.tsx +++ b/docs/src/examples/components/Input/Variations/InputExampleIcon.shorthand.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import { Input } from '@stardust-ui/react' const InputExampleIcon = () => diff --git a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx index 3cf8b29de8..788793aacb 100644 --- a/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx +++ b/docs/src/examples/components/Input/Variations/InputExampleIconClearable.shorthand.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import { Input } from '@stardust-ui/react' const InputExampleIconClearableShorthand = () => ( diff --git a/docs/src/examples/components/Input/Variations/index.tsx b/docs/src/examples/components/Input/Variations/index.tsx index 525fac759e..a7e0eb0d6b 100644 --- a/docs/src/examples/components/Input/Variations/index.tsx +++ b/docs/src/examples/components/Input/Variations/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection' @@ -15,8 +15,13 @@ const Variations = () => ( examplePath="components/Input/Variations/InputExampleFluid" /> + diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 0fe1a5572f..2a9ebfc8e6 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -3,6 +3,7 @@ import * as React from 'react' import * as _ from 'lodash' import { + AutoControlledComponent, childrenExist, createHTMLInput, customPropTypes, @@ -16,7 +17,7 @@ import Icon from '../Icon' * An Input * @accessibility This is example usage of the accessibility tag. */ -class Input extends UIComponent { +class Input extends AutoControlledComponent { static className = 'ui-input' static displayName = 'Input' @@ -34,6 +35,9 @@ class Input extends UIComponent { /** A property that will change the icon on the input and clear the input on click on Cancel */ clearable: PropTypes.bool, + /** The default value of the input. */ + defaultValue: PropTypes.string, + /** A button can take the width of its container. */ fluid: PropTypes.bool, @@ -85,23 +89,22 @@ class Input extends UIComponent { type: 'text', } + static autoControlledProps = ['value'] + inputRef: any - constructor(props, context) { - super(props, context) + state: any = { value: this.props.value || '' } - this.state = { - value: props.value || '', - } + getInitialAutoControlledState() { + return { value: '' } } handleChange = e => { const value = _.get(e, 'target.value') - const { clearable } = this.props _.invoke(this.props, 'onChange', e, { ...this.props, value }) - this.setState({ value }) + !this.props.value && this.setState({ value }) } handleChildOverrides = (child, defaultProps) => ({ @@ -115,8 +118,10 @@ class Input extends UIComponent { const { clearable } = this.props const { value } = this.state - if (clearable && value.length !== 0) { + if (clearable && !this.props.value && value.length !== 0) { this.setState({ value: '' }) + } else if (clearable && this.props.value && this.props.value.length !== 0) { + this.setState({ value: this.props.value }) } } @@ -142,7 +147,7 @@ class Input extends UIComponent { const { clearable, icon } = this.props const { value } = this.state - if (clearable && !_.isNil(icon) && value.length !== 0) { + if (clearable && value.length !== 0) { return 'close' } From 97e22b1c1e3c3e0eba60fa985dd3303ed76577c0 Mon Sep 17 00:00:00 2001 From: alinais Date: Thu, 16 Aug 2018 15:40:09 +0200 Subject: [PATCH 10/10] use trySet State instead of setState --- src/components/Input/Input.tsx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 2a9ebfc8e6..7fe84c8758 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -93,18 +93,14 @@ class Input extends AutoControlledComponent { inputRef: any - state: any = { value: this.props.value || '' } - - getInitialAutoControlledState() { - return { value: '' } - } + state: any = { value: this.props.value || this.props.defaultValue || '' } handleChange = e => { const value = _.get(e, 'target.value') _.invoke(this.props, 'onChange', e, { ...this.props, value }) - !this.props.value && this.setState({ value }) + this.trySetState({ value }) } handleChildOverrides = (child, defaultProps) => ({ @@ -118,10 +114,8 @@ class Input extends AutoControlledComponent { const { clearable } = this.props const { value } = this.state - if (clearable && !this.props.value && value.length !== 0) { - this.setState({ value: '' }) - } else if (clearable && this.props.value && this.props.value.length !== 0) { - this.setState({ value: this.props.value }) + if (clearable) { + this.trySetState({ value: '' }) } }