Skip to content

Commit

Permalink
Add DeSelect func to SelectMenu & affected components (#198)
Browse files Browse the repository at this point in the history
* Add DeSelect func to SelectMenu & affected components

Follow up from issue #196

* Add Multi-Select with Deselect Example to Storybook & Docs

Added onDeselect to index.stories.js, and attempted to put the proper docs files in place. Let me know of changes/corrections and I am happy to fix!

* Fix multi example

Linting helped me reformat this, forgot to update prior to commit..

* Fix multi deselect per linting

* Updates per comments

I also added the if statement (in lieu of switch) solution to the onSelect within these changes. This way it is always number of items + "..." for the Button presentation.

Co-Authored-By: jeroenransijn <[email protected]>

* Remove switch comments (fix local diff issue)

Something wonky happened with the disk version & VS Code version diff.. not sure, but removing commented switch stmnt
  • Loading branch information
jmfury authored and jeroenransijn committed Jun 15, 2018
1 parent 977274f commit d388f0b
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 1 deletion.
51 changes: 51 additions & 0 deletions src/select-menu/docs/examples/SelectMenu-multi.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Manager>
{({ setState, state }) => (
<SelectMenu
title="Select multiple names"
options={options}
selected={state.selected}
onSelect={item => {
let selected
if (Array.isArray(state.selected)) {
selected = [...state.selected, item.value]
} else {
selected = arrify(item.value)
}
const selectedItems = selected
const selectedItemsLength = selectedItems.length
let selectedNames = ''
if (selectedItemsLength === 0) {
selectedNames = ''
}
else if (selectedItemsLength === 1) {
selectedNames = selectedItems.toString()
} else if (selectedItemsLength > 1 ) {
selectedNames = selectedItemsLength.toString() + " selected..."
}
setState({
selected,
selectedNames
})
}}
onDeselect={item => {
const deselectedItemIndex = state.selected.indexOf(item.value)
const selectedItems = state.selected.filter(
(_item, i) => i !== deselectedItemIndex
)
const selectedItemsLength = selectedItems.length
let selectedNames = ''
if (selectedItemsLength === 0) {
selectedNames = ''
}
else if (selectedItemsLength === 1) {
selectedNames = selectedItems.toString()
} else if (selectedItemsLength > 1 ) {
selectedNames = selectedItemsLength.toString() + " selected..."
}
setState({ selected: selectedItems, selectedNames })
}}
>
<Button>{state.selectedNames || 'Select multiple...'}</Button>
</SelectMenu>
)}
</Manager>
21 changes: 21 additions & 0 deletions src/select-menu/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import sourceSelectMenu from '!raw-loader!../src/SelectMenu'
* Code examples
*/
import exampleSelectMenuBasic from './examples/SelectMenu-basic.example'
import exampleSelectMenuMulti from './examples/SelectMenu-multi.example'

const title = 'Select Menu'
const subTitle = 'Select one or multiple items from a dropdown list.'
Expand Down Expand Up @@ -90,6 +91,26 @@ const components = [
),
codeText: exampleSelectMenuBasic,
scope
},
{
title: 'Multi SelectMenu Example',
description: (
<div>
<p>This example shows basic usage with multiple selected items.</p>
<p>
This pattern is only an example. Selected values and the
formatting of their names should be managed wherever you choose to
manage state. The onDeselect method is provided to assist with
this.
</p>
<p>
As users click on selected values to remove them, you can update
state.
</p>
</div>
),
codeText: exampleSelectMenuMulti,
scope
}
]
}
Expand Down
3 changes: 3 additions & 0 deletions src/select-menu/src/Option.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default class Option extends PureComponent {
style: PropTypes.any,
height: PropTypes.number,
onSelect: PropTypes.func,
onDeselect: PropTypes.func,
isHighlighted: PropTypes.bool,
isSelected: PropTypes.bool
}
Expand All @@ -31,6 +32,7 @@ export default class Option extends PureComponent {
const {
label,
onSelect,
onDeselect,
isHighlighted,
isSelected,
style,
Expand All @@ -43,6 +45,7 @@ export default class Option extends PureComponent {
isSelectable
isHighlighted={isHighlighted}
onSelect={onSelect}
onDeselect={onDeselect}
isSelected={isSelected}
style={style}
display="flex"
Expand Down
7 changes: 7 additions & 0 deletions src/select-menu/src/OptionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default class OptionsList extends PureComponent {
*/
selected: PropTypes.arrayOf(PropTypes.string),
onSelect: PropTypes.func,
onDeselect: PropTypes.func,
hasFilter: PropTypes.bool,
optionSize: PropTypes.number,
renderItem: PropTypes.func,
Expand All @@ -50,6 +51,7 @@ export default class OptionsList extends PureComponent {
*/
optionSize: 33,
onSelect: () => {},
onDeselect: () => {},
selected: [],
renderItem: itemRenderer,
optionsFilter: fuzzyFilter,
Expand Down Expand Up @@ -115,6 +117,9 @@ export default class OptionsList extends PureComponent {
handleSelect = item => {
this.props.onSelect(item)
}
handleDeselect = item => {
this.props.onDeselect(item)
}

assignSearchRef = ref => {
this.searchRef = ref
Expand All @@ -127,6 +132,7 @@ export default class OptionsList extends PureComponent {
width,
height,
onSelect,
onDeselect,
selected,
hasFilter,
optionSize,
Expand Down Expand Up @@ -173,6 +179,7 @@ export default class OptionsList extends PureComponent {
style,
height: optionSize,
onSelect: () => this.handleSelect(item),
onDeselect: () => this.handleDeselect(item),
isSelected: this.isSelected(item)
})
}}
Expand Down
8 changes: 8 additions & 0 deletions src/select-menu/src/SelectMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export default class SelectMenu extends PureComponent {
* Function that is called when an option is selected.
*/
onSelect: PropTypes.func,
/**
* Function that is called when an option is Deselected.
*/
onDeselect: PropTypes.func,

/**
*
Expand Down Expand Up @@ -65,6 +69,7 @@ export default class SelectMenu extends PureComponent {

static defaultProps = {
onSelect: () => {},
onDeselect: () => {},
width: 240,
height: 248,
position: Position.BOTTOM_LEFT
Expand Down Expand Up @@ -115,6 +120,9 @@ export default class SelectMenu extends PureComponent {
onSelect: item => {
this.props.onSelect(item)
},
onDeselect: item => {
this.props.onDeselect(item)
},
selected: arrify(selected)
}}
close={close}
Expand Down
50 changes: 50 additions & 0 deletions src/select-menu/stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { storiesOf } from '@storybook/react'
import arrify from 'arrify'
import React from 'react'
import Box from 'ui-box'
import options from '../docs/starwars-options'
Expand All @@ -24,5 +25,54 @@ storiesOf('select-menu', module).add('SelectMenu', () => (
</SelectMenu>
)}
</Manager>
<Manager>
{({ setState, state }) => (
<SelectMenu
title="Select multiple names"
options={options}
selected={state.selected}
onSelect={item => {
let selected
if (Array.isArray(state.selected)) {
selected = [...state.selected, item.value]
} else {
selected = arrify(item.value)
}
const selectedItems = selected
const selectedItemsLength = selectedItems.length
let selectedNames = ''
if (selectedItemsLength === 0) {
selectedNames = ''
} else if (selectedItemsLength === 1) {
selectedNames = selectedItems.toString()
} else if (selectedItemsLength > 1) {
selectedNames = selectedItemsLength.toString() + ' selected...'
}
setState({
selected,
selectedNames
})
}}
onDeselect={item => {
const deselectedItemIndex = state.selected.indexOf(item.value)
const selectedItems = state.selected.filter(
(_item, i) => i !== deselectedItemIndex
)
const selectedItemsLength = selectedItems.length
let selectedNames = ''
if (selectedItemsLength === 0) {
selectedNames = ''
} else if (selectedItemsLength === 1) {
selectedNames = selectedItems.toString()
} else if (selectedItemsLength > 1) {
selectedNames = selectedItemsLength.toString() + ' selected...'
}
setState({ selected: selectedItems, selectedNames })
}}
>
<Button>{state.selectedNames || 'Select multiple...'}</Button>
</SelectMenu>
)}
</Manager>
</Box>
))
11 changes: 10 additions & 1 deletion src/table/src/TableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default class TableRow extends PureComponent {
* Function that is called on click and enter/space keypress.
*/
onSelect: PropTypes.func,
/**
* Function that is called on click and enter/space keypress.
*/
onDeselect: PropTypes.func,

/**
* Makes the TableRow selectable.
Expand All @@ -34,13 +38,18 @@ export default class TableRow extends PureComponent {
static defaultProps = {
onClick: () => {},
onSelect: () => {},
onDeselect: () => {},
onKeyPress: () => {}
}

handleClick = e => {
this.props.onClick(e)
if (this.props.isSelectable) {
this.props.onSelect()
if (this.props.isSelected) {
this.props.onDeselect()
} else {
this.props.onSelect()
}
}
}

Expand Down

0 comments on commit d388f0b

Please sign in to comment.