Skip to content

Commit

Permalink
Merge pull request #44 from kenshoo/render_custom_components
Browse files Browse the repository at this point in the history
render custom components
  • Loading branch information
liorheber authored Mar 22, 2018
2 parents 3cfd466 + d932aac commit e466d7b
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 63 deletions.
56 changes: 20 additions & 36 deletions src/components/multi_selection_list/multiselection_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import styles from "./multiselection_list.scss";
import { LinearProgress } from "material-ui/Progress";
import { isAllSelected } from "./multiselection_list_utils";
import VirtualizedListItems from "./virtualized_items/multiselection_virtualized_items";
import { FormControl } from "material-ui/Form";
import Input, { InputAdornment } from "material-ui/Input";
import Icon from "material-ui/Icon";
import Search from "./search/search";

class MultiSelectionList extends PureComponent {
constructor(props) {
Expand Down Expand Up @@ -203,33 +201,6 @@ class MultiSelectionList extends PureComponent {
this.handleFilter(newValue);
}

listFilter() {
const { searchPlaceholder, searchIcon } = this.props;

return (
<FormControl
className={classNames(
styles.list_filter_container,
styles.search_wrapper
)}
fullWidth
>
<Input
id="search"
value={this.state.searchTerm}
placeholder={searchPlaceholder}
onChange={this.onSearchTermChange}
className={styles.input}
endAdornment={
<InputAdornment position="end">
<Icon>{searchIcon}</Icon>
</InputAdornment>
}
/>
</FormControl>
);
}

render() {
const {
loading,
Expand All @@ -239,12 +210,22 @@ class MultiSelectionList extends PureComponent {
filterResultsText,
emptyText,
listHeight,
listRowHeight
listRowHeight,
searchRenderer
} = this.props;

const SearchRenderer = searchRenderer;

return (
<div className={styles.multi_selection_list}>
{withSearch && this.listFilter()}
{withSearch && (
<div className={styles.search_wrapper}>
<SearchRenderer
searchTerm={this.state.searchTerm}
onSearchTermChange={this.onSearchTermChange}
/>
</div>
)}

<div className={styles.list_box}>
{withSelectAll && (
Expand Down Expand Up @@ -281,21 +262,22 @@ class MultiSelectionList extends PureComponent {
MultiSelectionList.propTypes = {
items: PropTypes.array,
selectedIds: PropTypes.array,
searchPlaceholder: PropTypes.string,
emptyText: PropTypes.string,
filterResultsText: PropTypes.string,
displayFn: PropTypes.func,
displaySelectAllFn: PropTypes.func,
filterFn: PropTypes.func,
withSearch: PropTypes.bool,
filterSelected: PropTypes.bool,
onSelect: PropTypes.func
onSelect: PropTypes.func,
onFilterChange: PropTypes.func,
msDelayOnChangeFilter: PropTypes.number,
searchRenderer: PropTypes.func
};

MultiSelectionList.defaultProps = {
items: [],
selectedIds: [],
searchPlaceholder: "Search...",
emptyText: "No items...",
filterResultsText: "No available items...",
displayFn: item => item.id,
Expand All @@ -308,7 +290,9 @@ MultiSelectionList.defaultProps = {
.includes(value.toLowerCase()),
withSearch: true,
filterSelected: true,
onSelect: () => {}
onSelect: () => {},
onFilterChange: () => {},
searchRenderer: Search
};

export default MultiSelectionList;
27 changes: 8 additions & 19 deletions src/components/multi_selection_list/multiselection_list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ $list_font_size: $font-default;
}
}

.list_filter_container {
margin-bottom: 10px;
position: relative;
}

.search_icon {
padding: 15px;
padding-bottom: 0;
Expand Down Expand Up @@ -74,20 +69,6 @@ $list_font_size: $font-default;
z-index: 99;
}

.search_wrapper {
display: flex;
justify-content: flex-end;
margin-bottom: 0;
height: $space-50 + 1;
}

.input {
height: $space-50;
padding: 0 $space-12;
display: flex;
align-items: center;
}

.select_all {
border: $border-1 solid $grey-350;
border-left: 0;
Expand All @@ -99,4 +80,12 @@ $list_font_size: $font-default;
&:hover {
background-color: $grey-200;
}
}

.search_wrapper {
display: flex;
margin-bottom: 0;
height: $space-50 + 1;
border-right: $border-1 solid $grey-350;
width: 100%;
}
49 changes: 49 additions & 0 deletions src/components/multi_selection_list/search/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, {Component} from 'react';
import classNames from "classnames/bind";
import { FormControl } from "material-ui/Form";
import Input, { InputAdornment } from "material-ui/Input";
import Icon from "material-ui/Icon";
import PropTypes from "prop-types";

import styles from './search.scss';

export class Search extends Component {
render() {
const { searchPlaceholder, searchIcon, searchTerm, onSearchTermChange } = this.props;
return (
<FormControl
className={classNames(
styles.list_filter_container
)}
fullWidth
>
<Input
id="search"
value={searchTerm}
placeholder={searchPlaceholder}
onChange={onSearchTermChange}
className={styles.input}
endAdornment={
<InputAdornment position="end">
<Icon>{searchIcon}</Icon>
</InputAdornment>
}
/>
</FormControl>
);
}
}

Search.propTypes = {
searchPlaceholder: PropTypes.string,
searchIcon: PropTypes.string,
searchTerm: PropTypes.string,
onSearchTermChange: PropTypes.func
};

Search.defaultProps = {
searchPlaceholder: "Search...",
searchIcon: "search"
};

export default Search;
13 changes: 13 additions & 0 deletions src/components/multi_selection_list/search/search.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import "../../../resources/globals";

.input {
height: $space-50;
padding: 0 $space-12;
display: flex;
align-items: center;
}

.list_filter_container {
margin-bottom: 10px;
position: relative;
}
15 changes: 10 additions & 5 deletions src/components/react_multi_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const displayItem = ({ isItemSelected }) => item => {
className={styles.checkbox_control}
control={
<Checkbox
value={item.label}
value={item.value}
checked={isItemSelected(item)}
color="primary"
/>
Expand Down Expand Up @@ -157,7 +157,8 @@ export default class ReactMultiSelect extends PureComponent {
messages,
listRowHeight,
selectedListHeight,
dstItemsWrapperClassName
dstItemsWrapperClassName,
selectedItemRenderer
} = this.props;
const { selectedItems } = this.state;

Expand All @@ -171,7 +172,7 @@ export default class ReactMultiSelect extends PureComponent {
listHeight={selectedListHeight}
listRowHeight={listRowHeight}
emptyText={messages[DESTINATION_NO_ITEMS]}
displayFn={displayFn => displaySelectedItem(displayFn, this.props)}
displayFn={selectedItemRenderer ? item => selectedItemRenderer(item) : displayFn => displaySelectedItem(displayFn, this.props)}
className={classnames(
styles.destination_items_wrapper,
dstItemsWrapperClassName
Expand All @@ -188,7 +189,8 @@ export default class ReactMultiSelect extends PureComponent {
listRowHeight,
showSearch,
showSelectAll,
searchIcon
searchIcon,
searchRenderer
} = this.props;
const { filteredItems } = this.state;

Expand All @@ -199,6 +201,7 @@ export default class ReactMultiSelect extends PureComponent {
items={filteredItems}
onSelect={this.select}
withSearch={showSearch}
searchRenderer={searchRenderer}
withSelectAll={showSelectAll}
displayFn={displayItem({ isItemSelected: this.isItemSelected })}
filterFn={filterItems}
Expand Down Expand Up @@ -257,7 +260,9 @@ ReactMultiSelect.propTypes = {
showSearch: PropTypes.bool,
showSelectAll: PropTypes.bool,
searchIcon: PropTypes.string,
deleteIcon: PropTypes.string
deleteIcon: PropTypes.string,
searchRenderer: PropTypes.func,
selectedItemRenderer: PropTypes.func
};

ReactMultiSelect.defaultProps = {
Expand Down
43 changes: 40 additions & 3 deletions stories/multi-select.stories.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { Component } from "react";
import { action, storiesOf } from "@storybook/react";
import {
DESTINATION_HEADER_CLEAR_ALL,
Expand All @@ -11,6 +11,8 @@ import {
} from "../src/components/react_multi_select_messages";
import ReactMultiSelect from "../src/components/react_multi_select";
import { boolean, withKnobs } from "@storybook/addon-knobs";
import Icon from "material-ui/Icon";
import Input from "material-ui/Input";
import customStyle from "./custom_style.scss";

const custom_messages = {
Expand Down Expand Up @@ -74,8 +76,6 @@ storiesOf("React Multi Select", module)
wrapperClassName={customStyle.wrapper}
listHeight={500}
selectedListHeight={540}
deleteIcon={"delete"}
searchIcon={"star"}
loading={boolean("Loading", false)}
onChange={action("onChange")}
showSearch={boolean("Show search", true)}
Expand Down Expand Up @@ -120,4 +120,41 @@ storiesOf("React Multi Select", module)
showSelectAll={boolean("Show select all", true)}
/>
);
})
.add("With custom components", () => {
const items = Array.apply(null, { length: 10 }).map((i, index) => ({
id: index,
value: `item ${index}`,
label: (
<div>
<Icon>star</Icon>
{`Item ${index}`}
</div>
)
}));

const displaySelectedItemFunc = item => (
<div>{`selected: ${item.value}`}</div>
);

const searchRenderer = ({ searchTerm, onSearchTermChange }) => {
return (
<div>
custom search{" "}
<input value={searchTerm} onChange={onSearchTermChange} />
</div>
);
};

return (
<ReactMultiSelect
displaySelectedItemFunc={displaySelectedItemFunc}
items={items}
loading={boolean("Loading", false)}
onChange={action("onChange")}
showSearch={boolean("Show search", true)}
showSelectAll={boolean("Show select all", true)}
searchRenderer={searchRenderer}
/>
);
});

0 comments on commit e466d7b

Please sign in to comment.