diff --git a/docs/app/Components/Sidebar/Sidebar.js b/docs/app/Components/Sidebar/Sidebar.js index 28ec50930a..1a4698a187 100644 --- a/docs/app/Components/Sidebar/Sidebar.js +++ b/docs/app/Components/Sidebar/Sidebar.js @@ -51,12 +51,21 @@ export default class Sidebar extends Component { componentDidMount() { document.addEventListener('keydown', this.handleDocumentKeyDown) + this.setSearchInput() + } + + componentDidUpdate(prevProps, prevState) { + this.setSearchInput() } componentWillUnmount() { document.removeEventListener('keydown', this.handleDocumentKeyDown) } + setSearchInput() { + this._searchInput = findDOMNode(this).querySelector('.ui.input input') + } + handleDocumentKeyDown = (e) => { const code = keyboardKey.getCode(e) const isAZ = code >= 65 && code <= 90 @@ -203,9 +212,6 @@ export default class Sidebar extends Component { value={query} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} - ref={(c) => { - if (c !== null) this._searchInput = findDOMNode(c).querySelector('input') - }} /> {query ? this.renderSearchItems() : this.menuItemsByType} diff --git a/docs/app/Examples/collections/Menu/Content/Inputs.js b/docs/app/Examples/collections/Menu/Content/Inputs.js index bda8809315..29e17415ec 100644 --- a/docs/app/Examples/collections/Menu/Content/Inputs.js +++ b/docs/app/Examples/collections/Menu/Content/Inputs.js @@ -1,7 +1,5 @@ import React from 'react' -import { Button, Input, Menu } from 'stardust' - -// TODO: Update usage after update to v1 API +import { Input, Menu } from 'stardust' const Inputs = () => { return ( @@ -11,9 +9,7 @@ const Inputs = () => { - - - + ) diff --git a/docs/app/Examples/collections/Menu/Types/Pointing.js b/docs/app/Examples/collections/Menu/Types/Pointing.js index 77d44295a5..7cf167a142 100644 --- a/docs/app/Examples/collections/Menu/Types/Pointing.js +++ b/docs/app/Examples/collections/Menu/Types/Pointing.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Menu, Segment } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class Pointing extends Component { state = { activeItem: 'home' } @@ -19,7 +17,7 @@ export default class Pointing extends Component { - + diff --git a/docs/app/Examples/collections/Menu/Types/Secondary.js b/docs/app/Examples/collections/Menu/Types/Secondary.js index ccb0db594c..9577ced482 100644 --- a/docs/app/Examples/collections/Menu/Types/Secondary.js +++ b/docs/app/Examples/collections/Menu/Types/Secondary.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class Secondary extends Component { state = { activeItem: 'home' } @@ -18,7 +16,7 @@ export default class Secondary extends Component { - + diff --git a/docs/app/Examples/collections/Menu/Types/TabularOnTop.js b/docs/app/Examples/collections/Menu/Types/TabularOnTop.js index c2e6fbf8de..7c4ed5c91a 100644 --- a/docs/app/Examples/collections/Menu/Types/TabularOnTop.js +++ b/docs/app/Examples/collections/Menu/Types/TabularOnTop.js @@ -1,7 +1,5 @@ import React, { Component } from 'react' -import { Menu, Segment } from 'stardust' - -// TODO: Update usage after its will implemented +import { Input, Menu, Segment } from 'stardust' export default class TabularOnTop extends Component { state = { activeItem: 'bio' } @@ -18,10 +16,7 @@ export default class TabularOnTop extends Component { -
- - -
+
diff --git a/docs/app/Examples/collections/Menu/Types/Vertical.js b/docs/app/Examples/collections/Menu/Types/Vertical.js index 7cede26154..c7a8c2d5eb 100644 --- a/docs/app/Examples/collections/Menu/Types/Vertical.js +++ b/docs/app/Examples/collections/Menu/Types/Vertical.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Label, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class Vertical extends Component { state = { activeItem: 'inbox' } @@ -28,7 +26,7 @@ export default class Vertical extends Component { Updates
- + ) diff --git a/docs/app/Examples/collections/Menu/Variations/SizeVerticalLarge.js b/docs/app/Examples/collections/Menu/Variations/SizeVerticalLarge.js index 8f9f310b26..3efa965582 100644 --- a/docs/app/Examples/collections/Menu/Variations/SizeVerticalLarge.js +++ b/docs/app/Examples/collections/Menu/Variations/SizeVerticalLarge.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Label, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class SizeVerticalLarge extends Component { state = { activeItem: 'inbox' } @@ -28,7 +26,7 @@ export default class SizeVerticalLarge extends Component { Updates
- + ) diff --git a/docs/app/Examples/collections/Menu/Variations/SizeVerticalMassive.js b/docs/app/Examples/collections/Menu/Variations/SizeVerticalMassive.js index 29cda336e1..6ef5dbab7e 100644 --- a/docs/app/Examples/collections/Menu/Variations/SizeVerticalMassive.js +++ b/docs/app/Examples/collections/Menu/Variations/SizeVerticalMassive.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Label, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class SizeLargeMassive extends Component { state = { activeItem: 'inbox' } @@ -28,7 +26,7 @@ export default class SizeLargeMassive extends Component { Updates
- + ) diff --git a/docs/app/Examples/collections/Menu/Variations/SizeVerticalMini.js b/docs/app/Examples/collections/Menu/Variations/SizeVerticalMini.js index cacbf58433..f4ac3d0fdb 100644 --- a/docs/app/Examples/collections/Menu/Variations/SizeVerticalMini.js +++ b/docs/app/Examples/collections/Menu/Variations/SizeVerticalMini.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Label, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class SizeVerticalMini extends Component { state = { activeItem: 'inbox' } @@ -28,7 +26,7 @@ export default class SizeVerticalMini extends Component { Updates - + ) diff --git a/docs/app/Examples/collections/Menu/Variations/SizeVerticalSmall.js b/docs/app/Examples/collections/Menu/Variations/SizeVerticalSmall.js index f560cc9c8c..627ce6481d 100644 --- a/docs/app/Examples/collections/Menu/Variations/SizeVerticalSmall.js +++ b/docs/app/Examples/collections/Menu/Variations/SizeVerticalSmall.js @@ -1,8 +1,6 @@ import React, { Component } from 'react' import { Input, Label, Menu } from 'stardust' -// TODO: Update usage after its update to v1 API - export default class SizeVerticalSmall extends Component { state = { activeItem: 'inbox' } @@ -28,7 +26,7 @@ export default class SizeVerticalSmall extends Component { Updates - + ) diff --git a/docs/app/Examples/elements/Input/InputExamples.js b/docs/app/Examples/elements/Input/InputExamples.js deleted file mode 100644 index 1b17999009..0000000000 --- a/docs/app/Examples/elements/Input/InputExamples.js +++ /dev/null @@ -1,16 +0,0 @@ -import React, { Component } from 'react' -import InputTypesExamples from './Types/InputTypesExamples' -import InputStatesExamples from './States/InputStatesExamples' -import InputVariationsExamples from './Variations/InputVariationsExamples' - -export default class InputExamples extends Component { - render() { - return ( -
- - - -
- ) - } -} diff --git a/docs/app/Examples/elements/Input/States/InputDisabled.js b/docs/app/Examples/elements/Input/States/InputDisabled.js new file mode 100644 index 0000000000..630000cab5 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/InputDisabled.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputDisabled = () => ( + +) + +export default InputDisabled diff --git a/docs/app/Examples/elements/Input/States/InputDisabledExample.js b/docs/app/Examples/elements/Input/States/InputDisabledExample.js deleted file mode 100644 index a594eae78e..0000000000 --- a/docs/app/Examples/elements/Input/States/InputDisabledExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputDisabledExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/States/InputError.js b/docs/app/Examples/elements/Input/States/InputError.js new file mode 100644 index 0000000000..4bdb11eaa6 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/InputError.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputError = () => ( + +) + +export default InputError diff --git a/docs/app/Examples/elements/Input/States/InputErrorExample.js b/docs/app/Examples/elements/Input/States/InputErrorExample.js deleted file mode 100644 index 448501adfd..0000000000 --- a/docs/app/Examples/elements/Input/States/InputErrorExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputErrorExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/States/InputFocus.js b/docs/app/Examples/elements/Input/States/InputFocus.js new file mode 100644 index 0000000000..580919a683 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/InputFocus.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputFocus = () => ( + +) + +export default InputFocus diff --git a/docs/app/Examples/elements/Input/States/InputFocusExample.js b/docs/app/Examples/elements/Input/States/InputFocusExample.js deleted file mode 100644 index 194c1eb570..0000000000 --- a/docs/app/Examples/elements/Input/States/InputFocusExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputFocusExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/States/InputLeftLoading.js b/docs/app/Examples/elements/Input/States/InputLeftLoading.js new file mode 100644 index 0000000000..89fda47204 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/InputLeftLoading.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLeftLoading = () => ( + +) + +export default InputLeftLoading diff --git a/docs/app/Examples/elements/Input/States/InputLoading.js b/docs/app/Examples/elements/Input/States/InputLoading.js new file mode 100644 index 0000000000..98b54ea613 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/InputLoading.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLoading = () => ( + +) + +export default InputLoading diff --git a/docs/app/Examples/elements/Input/States/InputLoadingExample.js b/docs/app/Examples/elements/Input/States/InputLoadingExample.js deleted file mode 100644 index 2576fe0b9e..0000000000 --- a/docs/app/Examples/elements/Input/States/InputLoadingExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputLoadingExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/States/InputStatesExamples.js b/docs/app/Examples/elements/Input/States/InputStatesExamples.js deleted file mode 100644 index 84a478cfec..0000000000 --- a/docs/app/Examples/elements/Input/States/InputStatesExamples.js +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react' -import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' -import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' - -export default class InputStatesExamples extends Component { - render() { - return ( - - - - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/States/index.js b/docs/app/Examples/elements/Input/States/index.js new file mode 100644 index 0000000000..de58c95f23 --- /dev/null +++ b/docs/app/Examples/elements/Input/States/index.js @@ -0,0 +1,37 @@ +import React from 'react' +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +import { Message } from 'src' + +const InputStates = () => ( + + + + + Loading inputs automatically modify the input's icon on loading state to show loading indication + + + + + + +) + +export default InputStates diff --git a/docs/app/Examples/elements/Input/Types/InputInput.js b/docs/app/Examples/elements/Input/Types/InputInput.js new file mode 100644 index 0000000000..da2b44d0ca --- /dev/null +++ b/docs/app/Examples/elements/Input/Types/InputInput.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputInput = () => ( + +) + +export default InputInput diff --git a/docs/app/Examples/elements/Input/Types/InputInputExample.js b/docs/app/Examples/elements/Input/Types/InputInputExample.js deleted file mode 100644 index d5f798ff84..0000000000 --- a/docs/app/Examples/elements/Input/Types/InputInputExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputInputExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Types/InputTypesExamples.js b/docs/app/Examples/elements/Input/Types/InputTypesExamples.js deleted file mode 100644 index 6eb46c2a9b..0000000000 --- a/docs/app/Examples/elements/Input/Types/InputTypesExamples.js +++ /dev/null @@ -1,17 +0,0 @@ -import React, { Component } from 'react' -import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' -import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' - -export default class InputTypesExamples extends Component { - render() { - return ( - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Types/index.js b/docs/app/Examples/elements/Input/Types/index.js new file mode 100644 index 0000000000..50f9b7eada --- /dev/null +++ b/docs/app/Examples/elements/Input/Types/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const InputTypes = () => ( + + + +) + +export default InputTypes diff --git a/docs/app/Examples/elements/Input/Variations/InputAction.js b/docs/app/Examples/elements/Input/Variations/InputAction.js new file mode 100644 index 0000000000..27576245cc --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputAction.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputAction = () => ( + +) + +export default InputAction diff --git a/docs/app/Examples/elements/Input/Variations/InputActionDropdown.js b/docs/app/Examples/elements/Input/Variations/InputActionDropdown.js new file mode 100644 index 0000000000..28713199a8 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputActionDropdown.js @@ -0,0 +1,19 @@ +import React from 'react' +import { Dropdown, Input } from 'stardust' + +const options = [ + { text: 'This Page', value: 'page' }, + { text: 'This Organization', value: 'org' }, + { text: 'Entire Site', value: 'site' }, +] + +const InputActionDropdown = () => ( + } + icon='search' + iconPosition='left' + placeholder='Search...' + /> +) + +export default InputActionDropdown diff --git a/docs/app/Examples/elements/Input/Variations/InputActionExample.js b/docs/app/Examples/elements/Input/Variations/InputActionExample.js deleted file mode 100644 index 262694ad62..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputActionExample.js +++ /dev/null @@ -1,18 +0,0 @@ -import React, { Component } from 'react' -import { Button, Select, Input } from 'stardust' - -export default class InputActionExample extends Component { - render() { - const options = [ - { value: 'all', text: 'All' }, - { value: 'articles', text: 'Articles' }, - { value: 'products', text: 'Products' }, - ] - return ( - - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputActionIconButton.js b/docs/app/Examples/elements/Input/Variations/InputActionIconButton.js new file mode 100644 index 0000000000..58c8cd6bb3 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputActionIconButton.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputActionIconButton = () => ( + +) + +export default InputActionIconButton diff --git a/docs/app/Examples/elements/Input/Variations/InputActionLabeledButton.js b/docs/app/Examples/elements/Input/Variations/InputActionLabeledButton.js new file mode 100644 index 0000000000..e2113569f0 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputActionLabeledButton.js @@ -0,0 +1,11 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputActionLabeledButton = () => ( + +) + +export default InputActionLabeledButton diff --git a/docs/app/Examples/elements/Input/Variations/InputActions.js b/docs/app/Examples/elements/Input/Variations/InputActions.js new file mode 100644 index 0000000000..ac573ea767 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputActions.js @@ -0,0 +1,18 @@ +import React from 'react' +import { Button, Select, Input } from 'stardust' + +const options = [ + { text: 'All', value: 'all' }, + { text: 'Articles', value: 'articles' }, + { text: 'Products', value: 'products' }, +] + +const InputActions = () => ( + + + +) + +export default InputFluid diff --git a/docs/app/Examples/elements/Input/Variations/InputFluidExample.js b/docs/app/Examples/elements/Input/Variations/InputFluidExample.js deleted file mode 100644 index f69f9778c7..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputFluidExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputFluidExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputIcon.js b/docs/app/Examples/elements/Input/Variations/InputIcon.js new file mode 100644 index 0000000000..72c6410553 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputIcon.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputIcon = () => ( + +) + +export default InputIcon diff --git a/docs/app/Examples/elements/Input/Variations/InputIconChild.js b/docs/app/Examples/elements/Input/Variations/InputIconChild.js new file mode 100644 index 0000000000..9392378c0c --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputIconChild.js @@ -0,0 +1,19 @@ +import React from 'react' +import { Icon, Input } from 'stardust' + +const InputIconChild = () => ( +
+ + + + +
+
+ + + + +
+) + +export default InputIconChild diff --git a/docs/app/Examples/elements/Input/Variations/InputIconElement.js b/docs/app/Examples/elements/Input/Variations/InputIconElement.js new file mode 100644 index 0000000000..0ce0262955 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputIconElement.js @@ -0,0 +1,11 @@ +import React from 'react' +import { Icon, Input } from 'stardust' + +const InputIconElement = () => ( + } + placeholder='Search...' + /> +) + +export default InputIconElement diff --git a/docs/app/Examples/elements/Input/Variations/InputIconExample.js b/docs/app/Examples/elements/Input/Variations/InputIconExample.js deleted file mode 100644 index a56f20c3f4..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputIconExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputIconExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputIconPosition.js b/docs/app/Examples/elements/Input/Variations/InputIconPosition.js new file mode 100644 index 0000000000..ed336a3d64 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputIconPosition.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputIconPosition = () => ( + +) + +export default InputIconPosition diff --git a/docs/app/Examples/elements/Input/Variations/InputIconProps.js b/docs/app/Examples/elements/Input/Variations/InputIconProps.js new file mode 100644 index 0000000000..f9c5691b49 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputIconProps.js @@ -0,0 +1,11 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputIconProps = () => ( + +) + +export default InputIconProps diff --git a/docs/app/Examples/elements/Input/Variations/InputInverted.js b/docs/app/Examples/elements/Input/Variations/InputInverted.js new file mode 100644 index 0000000000..e66678c9d3 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputInverted.js @@ -0,0 +1,10 @@ +import React from 'react' +import { Segment, Input } from 'stardust' + +const InputInverted = () => ( + + + +) + +export default InputInverted diff --git a/docs/app/Examples/elements/Input/Variations/InputInvertedExample.js b/docs/app/Examples/elements/Input/Variations/InputInvertedExample.js deleted file mode 100644 index c81efec052..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputInvertedExample.js +++ /dev/null @@ -1,12 +0,0 @@ -import React, { Component } from 'react' -import { Segment, Input } from 'stardust' - -export default class InputInvertedExample extends Component { - render() { - return ( - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputLabeled.js b/docs/app/Examples/elements/Input/Variations/InputLabeled.js new file mode 100644 index 0000000000..88a1cce993 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputLabeled.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLabeled = () => ( + +) + +export default InputLabeled diff --git a/docs/app/Examples/elements/Input/Variations/InputLabeledExample.js b/docs/app/Examples/elements/Input/Variations/InputLabeledExample.js deleted file mode 100644 index fd46800d76..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputLabeledExample.js +++ /dev/null @@ -1,12 +0,0 @@ -import React, { Component } from 'react' -import { Input, Label } from 'stardust' - -export default class InputLabeledExample extends Component { - render() { - return ( - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputLeftActionLabeledButton.js b/docs/app/Examples/elements/Input/Variations/InputLeftActionLabeledButton.js new file mode 100644 index 0000000000..b0a7849bec --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputLeftActionLabeledButton.js @@ -0,0 +1,13 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLeftActionLabeledButton = () => ( + +) + +export default InputLeftActionLabeledButton diff --git a/docs/app/Examples/elements/Input/Variations/InputLeftCornerLabeled.js b/docs/app/Examples/elements/Input/Variations/InputLeftCornerLabeled.js new file mode 100644 index 0000000000..b43716d7b8 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputLeftCornerLabeled.js @@ -0,0 +1,12 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLeftCornerLabeled = () => ( + +) + +export default InputLeftCornerLabeled diff --git a/docs/app/Examples/elements/Input/Variations/InputRightCornerLabeled.js b/docs/app/Examples/elements/Input/Variations/InputRightCornerLabeled.js new file mode 100644 index 0000000000..8550e3de92 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputRightCornerLabeled.js @@ -0,0 +1,12 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputLeftCornerLabeled = () => ( + +) + +export default InputLeftCornerLabeled diff --git a/docs/app/Examples/elements/Input/Variations/InputRightLabeled.js b/docs/app/Examples/elements/Input/Variations/InputRightLabeled.js new file mode 100644 index 0000000000..71d4041b3c --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputRightLabeled.js @@ -0,0 +1,18 @@ +import React from 'react' +import { Dropdown, Input } from 'stardust' + +const options = [ + { text: '.com', value: '.com' }, + { text: '.net', value: '.net' }, + { text: '.org', value: '.org' }, +] + +const InputRightLabeled = () => ( + } + labelPosition='right' + placeholder='Find domain' + /> +) + +export default InputRightLabeled diff --git a/docs/app/Examples/elements/Input/Variations/InputRightLabeledBasic.js b/docs/app/Examples/elements/Input/Variations/InputRightLabeledBasic.js new file mode 100644 index 0000000000..44835a0f81 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputRightLabeledBasic.js @@ -0,0 +1,12 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputRightLabeledBasic = () => ( + +) + +export default InputRightLabeledBasic diff --git a/docs/app/Examples/elements/Input/Variations/InputRightLabeledExample.js b/docs/app/Examples/elements/Input/Variations/InputRightLabeledExample.js deleted file mode 100644 index 1241d7668f..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputRightLabeledExample.js +++ /dev/null @@ -1,12 +0,0 @@ -import React, { Component } from 'react' -import { Input, Label } from 'stardust' - -export default class InputRightLabeledExample extends Component { - render() { - return ( - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputRightLabeledTag.js b/docs/app/Examples/elements/Input/Variations/InputRightLabeledTag.js new file mode 100644 index 0000000000..a5ac0b8b44 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputRightLabeledTag.js @@ -0,0 +1,14 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputRightLabeledTag = () => ( + +) + +export default InputRightLabeledTag diff --git a/docs/app/Examples/elements/Input/Variations/InputRightLeftLabeled.js b/docs/app/Examples/elements/Input/Variations/InputRightLeftLabeled.js new file mode 100644 index 0000000000..0b72305670 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputRightLeftLabeled.js @@ -0,0 +1,12 @@ +import React from 'react' +import { Input, Label } from 'stardust' + +const InputRightLeftLabeled = () => ( + + + + + +) + +export default InputRightLeftLabeled diff --git a/docs/app/Examples/elements/Input/Variations/InputSize.js b/docs/app/Examples/elements/Input/Variations/InputSize.js new file mode 100644 index 0000000000..a3311c284b --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputSize.js @@ -0,0 +1,25 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputSize = () => ( +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+) + +export default InputSize diff --git a/docs/app/Examples/elements/Input/Variations/InputSizeExample.js b/docs/app/Examples/elements/Input/Variations/InputSizeExample.js deleted file mode 100644 index 7bece9a1a0..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputSizeExample.js +++ /dev/null @@ -1,23 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputSizeExample extends Component { - render() { - return ( -
- -
- -
- -
- -
- -
- -
-
- ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputTransparent.js b/docs/app/Examples/elements/Input/Variations/InputTransparent.js new file mode 100644 index 0000000000..cd6cb3e466 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/InputTransparent.js @@ -0,0 +1,8 @@ +import React from 'react' +import { Input } from 'stardust' + +const InputTransparent = () => ( + +) + +export default InputTransparent diff --git a/docs/app/Examples/elements/Input/Variations/InputTransparentExample.js b/docs/app/Examples/elements/Input/Variations/InputTransparentExample.js deleted file mode 100644 index 9ab2ebb87c..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputTransparentExample.js +++ /dev/null @@ -1,10 +0,0 @@ -import React, { Component } from 'react' -import { Input } from 'stardust' - -export default class InputTransparentExample extends Component { - render() { - return ( - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/InputVariationsExamples.js b/docs/app/Examples/elements/Input/Variations/InputVariationsExamples.js deleted file mode 100644 index ca21ed4c47..0000000000 --- a/docs/app/Examples/elements/Input/Variations/InputVariationsExamples.js +++ /dev/null @@ -1,54 +0,0 @@ -import React, { Component } from 'react' -import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' -import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' - -export default class InputVariationsExamples extends Component { - render() { - return ( - - - - - - - - - - - - - ) - } -} diff --git a/docs/app/Examples/elements/Input/Variations/index.js b/docs/app/Examples/elements/Input/Variations/index.js new file mode 100644 index 0000000000..f4f87c6a09 --- /dev/null +++ b/docs/app/Examples/elements/Input/Variations/index.js @@ -0,0 +1,104 @@ +import React from 'react' +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +import { Message } from 'src' + +const InputVariations = () => ( + + + + + + + + When using children, you must add your own {''}. + + + + + + + + Multiple Labels require children. + When using children, you must add your own {''}. + + + + + + + + + + + Multiple Actions require children. + When using children, you must add your own {''}. + + + + + + + + + + +) + +export default InputVariations diff --git a/docs/app/Examples/elements/Input/index.js b/docs/app/Examples/elements/Input/index.js new file mode 100644 index 0000000000..2cc35d446a --- /dev/null +++ b/docs/app/Examples/elements/Input/index.js @@ -0,0 +1,14 @@ +import React from 'react' +import Types from './Types' +import States from './States' +import Variations from './Variations' + +const Inputs = () => ( +
+ + + +
+) + +export default Inputs diff --git a/docs/app/routes.js b/docs/app/routes.js index 0d550b5466..6ed083cc94 100644 --- a/docs/app/routes.js +++ b/docs/app/routes.js @@ -7,9 +7,8 @@ import ComponentDoc from './Components/ComponentDoc/ComponentDoc' import PageNotFound from './Views/PageNotFound' import Introduction from './Views/Introduction' -// TODO remove these once PRs are merged and docs are updated to use index.js files -import { Input, List } from 'stardust' -const InputDoc = () => +// TODO remove List once PR is merged and docs are updated to use index.js files +import { List } from 'stardust' const ListDoc = () => const routes = ( @@ -17,9 +16,8 @@ const routes = ( - {/* TODO remove routes once open PRs are merged and docs are updated to use index.js files */} + {/* TODO remove List route once open PR is merged and docs are updated to use index.js files */} - diff --git a/src/collections/Form/FormField.js b/src/collections/Form/FormField.js index c81cb4b516..41b7bcfa5e 100644 --- a/src/collections/Form/FormField.js +++ b/src/collections/Form/FormField.js @@ -1,5 +1,4 @@ import cx from 'classnames' -import _ from 'lodash' import React, { PropTypes, createElement } from 'react' import { @@ -71,7 +70,7 @@ function FormField(props) { } // pass label prop to controls that support it - if (control === Checkbox || control === Radio || _.has(control, 'propTypes.label')) { + if (control === Checkbox || control === Radio) { return ( {createElement(control, { ...controlProps, label })} diff --git a/src/elements/Input/Input.js b/src/elements/Input/Input.js index c641ff1beb..c4f96ee803 100644 --- a/src/elements/Input/Input.js +++ b/src/elements/Input/Input.js @@ -1,118 +1,231 @@ import _ from 'lodash' -import classNames from 'classnames' -import React, { Component, PropTypes, Children } from 'react' +import React, { PropTypes } from 'react' +import cx from 'classnames' import { + createHTMLInput, customPropTypes, getElementType, getUnhandledProps, META, + SUI, + useKeyOnly, + useValueAndKey, } from '../../lib' -import { Icon } from '../../elements' +import { Button, Icon, Label } from '../../elements' -const inputPropNames = [ +export const htmlInputPropNames = [ // React 'selected', 'defaultValue', 'defaultChecked', - // HTML - 'accept', - 'alt', + // Limited HTML props 'autoComplete', 'autoFocus', 'checked', - 'dirname', - 'disabled', + // 'disabled', do not pass (duplicates SUI CSS opacity rule) 'form', - 'height', - 'list', 'max', 'maxLength', 'min', - 'multiple', 'name', 'pattern', 'placeholder', 'readOnly', 'required', - 'size', - 'src', 'step', 'type', 'value', - 'width', ] /** * An Input is a field used to elicit a response from a user + * @see Button * @see Form + * @see Icon + * @see Label */ -export default class Input extends Component { - static propTypes = { - /** An element type to render as (string or function). */ - as: customPropTypes.as, - - children: PropTypes.node, - className: PropTypes.string, - icon: PropTypes.string, - input: PropTypes.object, - type: PropTypes.string, - } +function Input(props) { + const { + action, + actionPosition, + children, + className, + disabled, + error, + focus, + fluid, + icon, + iconPosition, + inverted, + label, + labelPosition, + loading, + size, + type, + input, + transparent, + } = props - static defaultProps = { - type: 'text', - } + const classes = cx( + 'ui', + size, + useValueAndKey(actionPosition, 'action') || useKeyOnly(action, 'action'), + useKeyOnly(disabled, 'disabled'), + useKeyOnly(error, 'error'), + useKeyOnly(focus, 'focus'), + useKeyOnly(fluid, 'fluid'), + useKeyOnly(inverted, 'inverted'), + useValueAndKey(labelPosition, 'labeled') || useKeyOnly(label, 'labeled'), + useKeyOnly(loading, 'loading'), + useKeyOnly(transparent, 'transparent'), + useValueAndKey(iconPosition, 'icon') || useKeyOnly(icon, 'icon'), + className, + 'input', + ) - static _meta = { - name: 'Input', - type: META.TYPES.ELEMENT, - } + const rest = getUnhandledProps(Input, props) + const ElementType = getElementType(Input, props) + const inputProps = _.pick(props, htmlInputPropNames) - render() { - const { className, children, icon, input, type } = this.props - // Semantic supports actions and labels on either side of an input. - // The element must be on the same side as the indicated class. - // We first determine the left/right classes for each type of child, - // then we extract the children and place them on the correct side - // of the input. - const isLeftAction = _.includes(className, 'left action') - const isRightAction = !isLeftAction && _.includes(className, 'action') - const isRightLabeled = _.includes(className, 'right labeled') - const isLeftLabeled = !isRightLabeled && _.includes(className, 'labeled') - - const labelChildren = [] - const actionChildren = [] - - Children.forEach(children, child => { - const isAction = _.includes(['Button', 'Dropdown', 'Select'], child.type._meta.name) - const isLabel = child.type._meta.name === 'Label' - - if (isAction) { - actionChildren.push(child) - } else if (isLabel) { - labelChildren.push(child) - } - }) - - const classes = classNames( - 'ui', - className, - 'input' - ) - const unhandledProps = getUnhandledProps(Input, this.props) - const inputProps = _.pick(unhandledProps, inputPropNames) - const rest = _.omit(unhandledProps, inputPropNames) - const ElementType = getElementType(Input, this.props) - return ( - - {isLeftLabeled && labelChildren} - {isLeftAction && actionChildren} - - {Icon.create(icon)} - {isRightLabeled && labelChildren} - {isRightAction && actionChildren} - - ) + if (children) { + return {children} } + + const actionElement = Button.create(action, elProps => ({ + className: cx( + // all action components should have the button className + !_.includes(elProps.className, 'button') && 'button', + ), + })) + const iconElement = Icon.create(icon) + const labelElement = Label.create(label, elProps => ({ + className: cx( + // all label components should have the label className + !_.includes(elProps.className, 'label') && 'label', + // add 'left|right corner' + _.includes(labelPosition, 'corner') && labelPosition, + ), + })) + + return ( + + {actionPosition === 'left' && actionElement} + {iconPosition === 'left' && iconElement} + {labelPosition !== 'right' && labelElement} + {createHTMLInput(input || type, inputProps)} + {actionPosition !== 'left' && actionElement} + {iconPosition !== 'left' && iconElement} + {labelPosition === 'right' && labelElement} + + ) +} + +Input._meta = { + name: 'Input', + type: META.TYPES.ELEMENT, + props: { + actionPosition: ['left'], + iconPosition: ['left'], + labelPosition: ['left', 'right', 'left corner', 'right corner'], + size: SUI.SIZES, + }, +} + +Input.defaultProps = { + type: 'text', +} + +Input.propTypes = { + /** An element type to render as (string or function). */ + as: customPropTypes.as, + + /** An Input can be formatted to alert the user to an action they may perform */ + action: customPropTypes.some([ + PropTypes.bool, + customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object, + PropTypes.element, + ]), + ]), + ]), + + /** An action can appear along side an Input on the left or right */ + actionPosition: PropTypes.oneOf(Input._meta.props.actionPosition), + + /** Primary content. Used when there are multiple Labels or multiple Actions. */ + children: customPropTypes.every([ + customPropTypes.disallow(['icon', 'input', 'label']), + customPropTypes.givenProps( + { action: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element]).isRequired }, + customPropTypes.disallow(['action']), + ), + PropTypes.node, + ]), + + /** Additional classes. */ + className: PropTypes.string, + + /** An Input field can show that it is disabled */ + disabled: PropTypes.bool, + + /** An Input field can show the data contains errors */ + error: PropTypes.bool, + + /** An Input field can show a user is currently interacting with it */ + focus: PropTypes.bool, + + /** Take on the size of it's container */ + fluid: PropTypes.bool, + + /** Optional Icon to display inside the Input */ + icon: customPropTypes.some([ + PropTypes.bool, + customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element]), + ]), + ]), + + /** An Icon can appear inside an Input on the left or right */ + iconPosition: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOf(Input._meta.props.iconPosition), + ]), + + /** Format to appear on dark backgrounds */ + inverted: PropTypes.bool, + + /** Shorthand prop for creating the HTML Input */ + input: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element]), + ]), + + /** Optional Label to display along side the Input */ + label: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element]), + ]), + + /** A Label can appear outside an Input on the left or right */ + labelPosition: PropTypes.oneOf(Input._meta.props.labelPosition), + + /** An Icon Input field can show that it is currently loading data */ + loading: PropTypes.bool, + + /** An Input can vary in size */ + size: PropTypes.oneOf(Input._meta.props.size), + + /** Transparent Input has no background */ + transparent: PropTypes.bool, + + /** The HTML input type */ + type: PropTypes.string, } + +export default Input diff --git a/src/lib/factories.js b/src/lib/factories.js index 5e335a9539..959a68381b 100644 --- a/src/lib/factories.js +++ b/src/lib/factories.js @@ -30,23 +30,39 @@ const mergePropsAndClassName = (defaultProps, props) => { * @param {function|string} Component A ReactClass or string * @param {function} mapValueToProps A function that maps a primitive value to the Component props * @param {string|object|function} val The value to create a ReactElement from - * @param {object} defaultProps Default props to add to the final ReactElement + * @param {object|function} [defaultProps={}] Default props object or function (called with regular props). * @returns {function|null} */ export function createShorthand(Component, mapValueToProps, val, defaultProps = {}) { - // Clone ReactElements + // short circuit for disabling shorthand + if (val === null) return null + + let type + let usersProps = {} + if (isValidElement(val)) { - return React.cloneElement(val, mergePropsAndClassName(defaultProps, val.props)) + type = 'element' + usersProps = val.props + } else if (_.isPlainObject(val)) { + type = 'props' + usersProps = val + } else if (_.isString(val) || _.isNumber(val)) { + type = 'literal' + usersProps = mapValueToProps(val) } - // Create ReactElements from props objects - if (_.isPlainObject(val)) { - return + defaultProps = _.isFunction(defaultProps) ? defaultProps(usersProps) : defaultProps + const props = mergePropsAndClassName(defaultProps, usersProps) + + // Clone ReactElements + if (type === 'element') { + return React.cloneElement(val, props) } + // Create ReactElements from props objects // Map values to props and create a ReactElement - if (_.isString(val) || _.isNumber(val)) { - return + if (type === 'props' || type === 'literal') { + return } // Otherwise null @@ -61,3 +77,4 @@ export function createShorthandFactory(Component, mapValueToProps) { // HTML Factories // ---------------------------------------- export const createHTMLImage = createShorthandFactory('img', value => ({ src: value })) +export const createHTMLInput = createShorthandFactory('input', value => ({ type: value })) diff --git a/src/modules/Dropdown/Dropdown.js b/src/modules/Dropdown/Dropdown.js index 8cea615e21..12641b0830 100644 --- a/src/modules/Dropdown/Dropdown.js +++ b/src/modules/Dropdown/Dropdown.js @@ -164,6 +164,9 @@ export default class Dropdown extends Component { // Style // ------------------------------------ + /** A Dropdown can reduce its complexity */ + basic: PropTypes.bool, + /** Format the Dropdown to appear as a button. */ button: PropTypes.bool, @@ -184,7 +187,7 @@ export default class Dropdown extends Component { inline: PropTypes.bool, labeled: PropTypes.bool, - linkItem: PropTypes.bool, + // linkItem: PropTypes.bool, /** Allow selecting multiple options. */ multiple: PropTypes.bool, @@ -895,6 +898,7 @@ export default class Dropdown extends Component { const { open } = this.state const { + basic, button, className, compact, @@ -903,7 +907,7 @@ export default class Dropdown extends Component { icon, inline, labeled, - linkItem, + // linkItem, multiple, pointing, search, @@ -919,11 +923,12 @@ export default class Dropdown extends Component { // Classes const classes = cx( 'ui', - open && 'active visible', + useKeyOnly(open, 'active visible'), useKeyOnly(disabled, 'disabled'), useKeyOnly(error, 'error'), useKeyOnly(loading, 'loading'), + useKeyOnly(basic, 'basic'), useKeyOnly(button, 'button'), useKeyOnly(compact, 'compact'), useKeyOnly(fluid, 'fluid'), @@ -935,7 +940,7 @@ export default class Dropdown extends Component { // useKeyOnly(icon, 'icon'), useKeyOnly(labeled, 'labeled'), // TODO: linkItem is required only when Menu child, add dynamically - useKeyOnly(linkItem, 'link item'), + // useKeyOnly(linkItem, 'link item'), useKeyOnly(multiple, 'multiple'), useKeyOnly(search, 'search'), useKeyOnly(selection, 'selection'), diff --git a/src/modules/Search/Search.js b/src/modules/Search/Search.js index 70c51c4102..77e7387ac0 100644 --- a/src/modules/Search/Search.js +++ b/src/modules/Search/Search.js @@ -478,9 +478,6 @@ export default class Search extends Component { onChange={this.handleSearchChange} onFocus={this.handleFocus} onClick={this.handleInputClick} - // TODO: Input should probably add this class automatically when an icon - // is present. Gonna hold off until the V1 upgrade of the Input component. - className={icon ? 'icon' : ''} input={{ className: 'prompt', tabIndex: '0', autoComplete: 'off' }} icon={icon} /> diff --git a/test/specs/collections/Breadcrumb/BreadcrumbDivider-test.js b/test/specs/collections/Breadcrumb/BreadcrumbDivider-test.js index 6c7d52871d..5176e8f5c9 100644 --- a/test/specs/collections/Breadcrumb/BreadcrumbDivider-test.js +++ b/test/specs/collections/Breadcrumb/BreadcrumbDivider-test.js @@ -5,7 +5,7 @@ import * as common from 'test/specs/commonTests' describe('BreadcrumbDivider', () => { common.isConformant(BreadcrumbDivider) common.implementsIconProp(BreadcrumbDivider, { - requiredShorthandProps: { + shorthandDefaultProps: { className: 'divider', }, }) diff --git a/test/specs/collections/Form/FormField-test.js b/test/specs/collections/Form/FormField-test.js index 400e6a1e86..47321cc037 100644 --- a/test/specs/collections/Form/FormField-test.js +++ b/test/specs/collections/Form/FormField-test.js @@ -65,20 +65,5 @@ describe('FormField', () => { .find('Radio') .should.have.prop('label', 'Passed to the Radio') }) - it('is passed to custom control components with a "label" propType', () => { - const HandlesLabel = () => null - HandlesLabel.propTypes = { label: () => null } - - shallow() - .find('HandlesLabel') - .should.have.prop('label', 'Passed to the HandlesLabel') - }) - it('is not passed to custom control components without a "label" propType', () => { - const DoesNotHandleLabel = () => null - - shallow() - .find('DoesNotHandleLabel') - .should.not.have.prop('label', 'Passed to the DoesNotHandleLabel') - }) }) }) diff --git a/test/specs/commonTests.js b/test/specs/commonTests.js index 4cc79af365..ed62b5c190 100644 --- a/test/specs/commonTests.js +++ b/test/specs/commonTests.js @@ -8,7 +8,7 @@ import { createShorthand, META, numberToWord } from 'src/lib' import { consoleUtil, sandbox, syntheticEvent } from 'test/utils' import * as stardust from 'stardust' -import { Icon, Image, Label } from 'src/elements' +import { Button, Icon, Image, Label } from 'src/elements' const commonTestHelpers = (testName, Component) => { const throwError = msg => { @@ -571,7 +571,8 @@ export const implementsWidthProp = (Component, options = {}) => { * @param {string|function} options.ShorthandComponent The component that should be rendered from the shorthand value. * @param {function} options.mapValueToProps A function that maps a primitive value to the Component props * @param {Object} [options.requiredProps={}] Props required to render the component. - * @param {Object} [options.requiredShorthandProps={}] Props required to render the shorthand component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. + * @param {Object} [options.alwaysPresent] Whether or not the shorthand exists by default */ export const implementsShorthandProp = (Component, options = {}) => { const { assertRequired } = commonTestHelpers('implementsShorthandProp', Component) @@ -581,7 +582,8 @@ export const implementsShorthandProp = (Component, options = {}) => { ShorthandComponent, mapValueToProps, requiredProps = {}, - requiredShorthandProps = {}, + shorthandDefaultProps = {}, + alwaysPresent, } = options describe(`${propKey} shorthand prop (common)`, () => { @@ -590,33 +592,37 @@ export const implementsShorthandProp = (Component, options = {}) => { assertRequired(propKey, 'a `propKey`') assertRequired(ShorthandComponent, 'a `ShorthandComponent`') - const name = typeof ShorthandComponent === 'string' ? ShorthandComponent : ShorthandComponent.name + const name = typeof ShorthandComponent === 'string' + ? ShorthandComponent + : _.get(ShorthandComponent, '_meta.name') || ShorthandComponent.displayName || ShorthandComponent.name const assertValidShorthand = (value) => { - const renderedShorthand = createShorthand(ShorthandComponent, mapValueToProps, value, requiredShorthandProps) + const renderedShorthand = createShorthand(ShorthandComponent, mapValueToProps, value, shorthandDefaultProps) const element = createElement(Component, { ...requiredProps, [propKey]: value }) shallow(element).should.contain(renderedShorthand) } - _noDefaultClassNameFromProp(Component, propKey, { requiredProps }) - - if (Component.defaultProps && Component.defaultProps[propKey]) { + if (alwaysPresent || Component.defaultProps && Component.defaultProps[propKey]) { it(`has default ${name} when not defined`, () => { shallow() .should.have.descendants(name) }) } else { + _noDefaultClassNameFromProp(Component, propKey, { requiredProps }) + it(`has no ${name} when not defined`, () => { shallow() .should.not.have.descendants(name) }) } - it(`has no ${name} when null`, () => { - shallow(createElement(Component, { ...requiredProps, [propKey]: null })) - .should.not.have.descendants(ShorthandComponent) - }) + if (!alwaysPresent) { + it(`has no ${name} when null`, () => { + shallow(createElement(Component, { ...requiredProps, [propKey]: null })) + .should.not.have.descendants(ShorthandComponent) + }) + } it(`renders a ${name} from strings`, () => { consoleUtil.disableOnce() @@ -635,13 +641,36 @@ export const implementsShorthandProp = (Component, options = {}) => { it(`renders a ${name} from elements`, () => { consoleUtil.disableOnce() - assertValidShorthand() + assertValidShorthand() }) }) } /** - * Assert that a Component correctly implements a shorthand prop. + * Assert that a Component correctly implements a Button shorthand prop. + * + * @param {function} Component The component to test. + * @param {object} [options={}] + * @param {string} [options.propKey='button'] The name of the shorthand prop. + * @param {string|function} [options.ShorthandComponent] The component that should be rendered from the shorthand value. + * @param {function} [options.mapValueToProps] A function that maps a primitive value to the Component props + * @param {Object} [options.requiredProps={}] Props required to render the component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. + */ +export const implementsButtonProp = (Component, options = {}) => { + const opts = { + propKey: 'button', + ShorthandComponent: Button, + mapValueToProps: val => ({ content: val }), + requiredProps: {}, + shorthandDefaultProps: {}, + ...options, + } + implementsShorthandProp(Component, opts) +} + +/** + * Assert that a Component correctly implements an Icon shorthand prop. * * @param {function} Component The component to test. * @param {object} [options={}] @@ -649,22 +678,43 @@ export const implementsShorthandProp = (Component, options = {}) => { * @param {string|function} [options.ShorthandComponent] The component that should be rendered from the shorthand value. * @param {function} [options.mapValueToProps] A function that maps a primitive value to the Component props * @param {Object} [options.requiredProps={}] Props required to render the component. - * @param {Object} [options.requiredShorthandProps={}] Props required to render the shorthand component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. */ export const implementsIconProp = (Component, options = {}) => { - const opts = { + implementsShorthandProp(Component, { propKey: 'icon', ShorthandComponent: Icon, mapValueToProps: val => ({ name: val }), requiredProps: {}, - requiredShorthandProps: {}, + shorthandDefaultProps: {}, ...options, - } - implementsShorthandProp(Component, opts) + }) } /** - * Assert that a Component correctly implements a shorthand prop. + * Assert that a Component correctly implements an HTML input shorthand prop. + * + * @param {function} Component The component to test. + * @param {object} [options={}] + * @param {string} [options.propKey='icon'] The name of the shorthand prop. + * @param {string|function} [options.ShorthandComponent] The component that should be rendered from the shorthand value. + * @param {function} [options.mapValueToProps] A function that maps a primitive value to the Component props + * @param {Object} [options.requiredProps={}] Props required to render the component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. + */ +export const implementsHTMLInputProp = (Component, options = {}) => { + implementsShorthandProp(Component, { + propKey: 'input', + ShorthandComponent: 'input', + mapValueToProps: val => ({ type: val }), + requiredProps: {}, + shorthandDefaultProps: {}, + ...options, + }) +} + +/** + * Assert that a Component correctly implements a Label shorthand prop. * * @param {function} Component The component to test. * @param {object} [options={}] @@ -672,22 +722,21 @@ export const implementsIconProp = (Component, options = {}) => { * @param {string|function} [options.ShorthandComponent] The component that should be rendered from the shorthand value. * @param {function} [options.mapValueToProps] A function that maps a primitive value to the Component props * @param {Object} [options.requiredProps={}] Props required to render the component. - * @param {Object} [options.requiredShorthandProps={}] Props required to render the shorthand component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. */ export const implementsLabelProp = (Component, options = {}) => { - const opts = { + implementsShorthandProp(Component, { propKey: 'label', ShorthandComponent: Label, mapValueToProps: val => ({ content: val }), requiredProps: {}, - requiredShorthandProps: {}, + shorthandDefaultProps: {}, ...options, - } - implementsShorthandProp(Component, opts) + }) } /** - * Assert that a Component correctly implements a shorthand prop. + * Assert that a Component correctly implements an Image shorthand prop. * * @param {function} Component The component to test. * @param {object} [options={}] @@ -695,18 +744,17 @@ export const implementsLabelProp = (Component, options = {}) => { * @param {string|function} [options.ShorthandComponent] The component that should be rendered from the shorthand value. * @param {function} [options.mapValueToProps] A function that maps a primitive value to the Component props * @param {Object} [options.requiredProps={}] Props required to render the component. - * @param {Object} [options.requiredShorthandProps={}] Props required to render the shorthand component. + * @param {Object|function} [options.shorthandDefaultProps={}] Props required to render the shorthand component. */ export const implementsImageProp = (Component, options = {}) => { - const opts = { + implementsShorthandProp(Component, { propKey: 'image', ShorthandComponent: Image, mapValueToProps: val => ({ src: val }), requiredProps: {}, - requiredShorthandProps: {}, + shorthandDefaultProps: {}, ...options, - } - implementsShorthandProp(Component, opts) + }) } /** diff --git a/test/specs/elements/Button/Button-test.js b/test/specs/elements/Button/Button-test.js index 1c35c9acb5..334cda6e1b 100644 --- a/test/specs/elements/Button/Button-test.js +++ b/test/specs/elements/Button/Button-test.js @@ -13,7 +13,7 @@ describe('Button', () => { common.hasSubComponents(Button, [ButtonContent, ButtonGroup, ButtonOr]) common.implementsIconProp(Button) common.implementsLabelProp(Button, { - requiredShorthandProps: { + shorthandDefaultProps: { basic: true, pointing: 'left', }, diff --git a/test/specs/elements/Icon/Icon-test.js b/test/specs/elements/Icon/Icon-test.js index be6ff48470..6929313afb 100644 --- a/test/specs/elements/Icon/Icon-test.js +++ b/test/specs/elements/Icon/Icon-test.js @@ -6,7 +6,6 @@ import * as common from 'test/specs/commonTests' describe('Icon', () => { common.isConformant(Icon) common.hasSubComponents(Icon, [IconGroup]) - common.rendersChildren(Icon) common.propKeyOnlyToClassName(Icon, 'bordered') common.propKeyOnlyToClassName(Icon, 'circular') @@ -22,6 +21,8 @@ describe('Icon', () => { common.propKeyAndValueToClassName(Icon, 'rotated') common.propValueOnlyToClassName(Icon, 'size') + common.rendersChildren(Icon) + it('renders as an by default', () => { shallow() .should.have.tagName('i') diff --git a/test/specs/elements/Input/Input-test.js b/test/specs/elements/Input/Input-test.js index 21cf1226a3..e20f4f059d 100644 --- a/test/specs/elements/Input/Input-test.js +++ b/test/specs/elements/Input/Input-test.js @@ -1,42 +1,65 @@ +import cx from 'classnames' +import _ from 'lodash' import React from 'react' -import Input from 'src/elements/Input/Input' +import Input, { htmlInputPropNames } from 'src/elements/Input/Input' import * as common from 'test/specs/commonTests' describe('Input', () => { common.isConformant(Input) common.hasUIClassName(Input) - // TODO: inputs do not render child text, only child components in special cases - // see component and find solution - // perhaps splitting rendersChildText() and rendersChildComponents() - // common.rendersChildren(Input) - it('has the input type of text by default', () => { - shallow() - .find('input') - .should.have.prop('type', 'text') + common.implementsLabelProp(Input, { + shorthandDefaultProps: elProps => ({ + className: cx({ + label: !_.includes(elProps.className, 'label'), + }), + }), }) - - it('allows a defaultValue', () => { - shallow() - .find('input') - .should.have.value('John') + common.implementsButtonProp(Input, { + propKey: 'action', + shorthandDefaultProps: elProps => ({ + className: cx({ + button: !_.includes(elProps.className, 'button'), + }), + }), }) - it('spreads type on the input element', () => { - shallow() - .find('input') - .should.have.prop('type', 'phone') + common.implementsHTMLInputProp(Input, { + alwaysPresent: true, + shorthandDefaultProps: { type: 'text' }, }) - it('spreads name on the input element', () => { - shallow() + common.propValueOnlyToClassName(Input, 'size') + common.propKeyAndValueToClassName(Input, 'actionPosition', { className: 'action' }) + common.propKeyOnlyToClassName(Input, 'action') + common.propKeyOnlyToClassName(Input, 'disabled') + common.propKeyOnlyToClassName(Input, 'error') + common.propKeyOnlyToClassName(Input, 'focus') + common.propKeyOnlyToClassName(Input, 'fluid') + common.propKeyOnlyToClassName(Input, 'inverted') + common.propKeyAndValueToClassName(Input, 'labelPosition', { className: 'labeled' }) + common.propKeyOnlyToClassName(Input, 'label', { className: 'labeled' }) + common.propKeyOnlyToClassName(Input, 'loading') + common.propKeyOnlyToClassName(Input, 'transparent') + common.propKeyAndValueToClassName(Input, 'iconPosition', { className: 'icon' }) + common.propKeyOnlyToClassName(Input, 'icon') + + common.rendersChildren(Input) + + it('renders a text by default', () => { + shallow() .find('input') - .should.have.prop('name', 'emailAddress') + .should.have.prop('type', 'text') }) - it('adds an Icon given an icon class and prop', () => { - shallow() - .should.have.descendants('Icon') + describe('input props', () => { + htmlInputPropNames.forEach(propName => { + it(`passes \`${propName}\` to the `, () => { + shallow() + .find('input') + .should.have.prop(propName, 'foo') + }) + }) }) }) diff --git a/test/specs/modules/Dropdown/Dropdown-test.js b/test/specs/modules/Dropdown/Dropdown-test.js index e6244c5991..162c9676a4 100644 --- a/test/specs/modules/Dropdown/Dropdown-test.js +++ b/test/specs/modules/Dropdown/Dropdown-test.js @@ -76,10 +76,27 @@ describe('Dropdown Component', () => { ShorthandComponent: DropdownHeader, mapValueToProps: val => ({ content: val }), }) - + common.propKeyOnlyToClassName(Dropdown, 'disabled') + common.propKeyOnlyToClassName(Dropdown, 'error') + common.propKeyOnlyToClassName(Dropdown, 'loading') + common.propKeyOnlyToClassName(Dropdown, 'basic') + common.propKeyOnlyToClassName(Dropdown, 'button') + common.propKeyOnlyToClassName(Dropdown, 'compact') + common.propKeyOnlyToClassName(Dropdown, 'fluid') + common.propKeyOnlyToClassName(Dropdown, 'floating') + common.propKeyOnlyToClassName(Dropdown, 'inline') + // TODO: See Dropdown cx notes + // common.propKeyOnlyToClassName(Dropdown, 'icon') + common.propKeyOnlyToClassName(Dropdown, 'labeled') + // TODO: See Dropdown cx notes + // common.propKeyOnlyToClassName(Dropdown, 'link item') common.propKeyOnlyToClassName(Dropdown, 'multiple') common.propKeyOnlyToClassName(Dropdown, 'search') common.propKeyOnlyToClassName(Dropdown, 'selection') + common.propKeyOnlyToClassName(Dropdown, 'simple') + common.propKeyOnlyToClassName(Dropdown, 'scrolling') + + common.propKeyOrValueAndKeyToClassName(Dropdown, 'pointing') it('closes on blur', () => { wrapperMount()