diff --git a/examples/src/app.js b/examples/src/app.js index ba23d8954b..d48ff7fabb 100644 --- a/examples/src/app.js +++ b/examples/src/app.js @@ -11,6 +11,7 @@ import GithubUsers from './components/GithubUsers'; import CustomComponents from './components/CustomComponents'; import CustomRender from './components/CustomRender'; import Multiselect from './components/Multiselect'; +import MultiselectSortable from './components/MultiselectSortable'; import NumericSelect from './components/NumericSelect'; import BooleanSelect from './components/BooleanSelect'; import Virtualized from './components/Virtualized'; @@ -20,6 +21,7 @@ ReactDOM.render(
+ diff --git a/examples/src/components/MultiselectSortable.js b/examples/src/components/MultiselectSortable.js new file mode 100644 index 0000000000..1566800ca2 --- /dev/null +++ b/examples/src/components/MultiselectSortable.js @@ -0,0 +1,57 @@ +import React from 'react'; +import Select, { Value } from 'react-select'; +import { SortableContainer, SortableElement, SortableHandle, arrayMove } from 'react-sortable-hoc'; + +const FLAVOURS = [ + { label: 'Chocolate', value: 'chocolate' }, + { label: 'Vanilla', value: 'vanilla' }, + { label: 'Strawberry', value: 'strawberry' }, + { label: 'Caramel', value: 'caramel' }, + { label: 'Cookies and Cream', value: 'cookiescream' }, + { label: 'Peppermint', value: 'peppermint' }, +]; + +const SortableLabel = SortableHandle(({ label }) => {label}); +const SortableValue = SortableElement(Value); +const SortableSelect = SortableContainer(Select); + +class MultiSelectSortableField extends React.Component{ + constructor(){ + super(); + this.state = { + value: ['chocolate', 'vanilla', 'caramel'] + }; + } + handleSelectChange(value){ + this.setState({ value }); + } + onSortEnd({ oldIndex, newIndex }) { + this.setState({ + value: arrayMove(this.state.value, oldIndex, newIndex), + }); + } + render(){ + const { value } = this.state; + return ( +
+

{this.props.label}

+ this.handleSelectChange(value)} + options={FLAVOURS} + placeholder="Select your favourite(s)" + value={value} + valueRenderer={(option) => } + valueComponent={SortableValue} + axis="xy" + helperClass="draggable-dragging" + onSortEnd={(sortState) => this.onSortEnd(sortState)} + useDragHandle={true} + /> +
+ ); + } +} +MultiSelectSortableField.displayName = 'MultiSelectSortableField'; + +module.exports = MultiSelectSortableField; diff --git a/examples/src/example.less b/examples/src/example.less index 801c1fc5d1..a93083e9c6 100644 --- a/examples/src/example.less +++ b/examples/src/example.less @@ -254,3 +254,94 @@ h6, .h6 { .virtual-scroll { z-index: 1; } + + +// Draggable item +// ------------------------------ + +// Replicate styles for the dragging state +// @TODO need a better way to copy over style + +@select-item-border-radius: 2px; +@select-item-gutter: 5px; +@select-item-padding-vertical: 2px; +@select-item-padding-horizontal: 5px; +@select-item-font-size: .9em; +@select-item-color: #08c; // pale blue +@select-item-bg: #f2f9fc; +@select-item-border-color: darken(@select-item-bg, 10%); +@select-item-hover-color: darken(@select-item-color, 5%); // pale blue +@select-item-hover-bg: darken(@select-item-bg, 5%); +@select-item-disabled-color: #333; +@select-item-disabled-bg: #fcfcfc; +@select-item-disabled-border-color: darken(@select-item-disabled-bg, 10%); + + +.Select-value { + &.draggable-dragging { + background-color: @select-item-bg; + border-radius: @select-item-border-radius; + border: 1px solid @select-item-border-color; + color: @select-item-color; + display: inline-block; + font-size: @select-item-font-size; + line-height: 1.4; + margin-left: @select-item-gutter; + margin-top: @select-item-gutter; + vertical-align: top; + + // common + .Select-value-icon, + .Select-value-label { + display: inline-block; + vertical-align: middle; + box-sizing: border-box; + float: left; + } + + // label + .Select-value-label { + border-bottom-right-radius: @select-item-border-radius; + border-top-right-radius: @select-item-border-radius; + cursor: default; + padding: @select-item-padding-vertical 0 @select-item-padding-vertical @select-item-padding-horizontal; + } + + // icon + .Select-value-icon { + cursor: pointer; + border-bottom-left-radius: @select-item-border-radius; + border-top-left-radius: @select-item-border-radius; + border-right: 1px solid @select-item-border-color; + + // move the baseline up by 1px + padding: (@select-item-padding-vertical - 1) @select-item-padding-horizontal (@select-item-padding-vertical + 1); + + &:hover, + &:focus { + background-color: @select-item-hover-bg; + color: @select-item-hover-color; + } + &:active { + background-color: @select-item-border-color; + } + } + } +} + +.draggable-dragging { + box-shadow: 0 2px 6px 0 rgba(0,0,0,.1); + background-color: rgba(255, 255, 255, 0.8); + cursor: row-resize; + z-index: 10; + border-radius: 5px; + + * { + -webkit-touch-callout: none; + user-select: none; + } + + label, p { + text-align: left; + } +} diff --git a/package.json b/package.json index b689a04d98..007c9e1d62 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "react-dom": "^15.5.0", "react-gravatar": "^2.4.5", "react-highlight-words": "^0.8.1", + "react-sortable-hoc": "^0.6.8", "react-test-renderer": "^15.6.1", "react-virtualized": "^9.9.0", "react-virtualized-select": "^3.1.0", @@ -88,7 +89,12 @@ "test": "cross-env NODE_ENV=test mocha --compilers js:babel-core/register", "precommit": "lint-staged && yarn run test" }, - "files": ["dist", "less", "lib", "scss"], + "files": [ + "dist", + "less", + "lib", + "scss" + ], "keywords": [ "combobox", "form", diff --git a/src/Select.js b/src/Select.js index 75d25a7a66..c7852b508b 100644 --- a/src/Select.js +++ b/src/Select.js @@ -827,6 +827,7 @@ class Select extends React.Component { onRemove={this.removeValue} placeholder={this.props.placeholder} value={value} + index={i} > {renderLabel(value, i)}