web: components: Styling AdvancedSelector for People groups selector
This commit is contained in:
parent
aade91af35
commit
30027112f9
@ -12,6 +12,8 @@ import { isArrayEqual } from "../../utils/array";
|
|||||||
import findIndex from "lodash/findIndex";
|
import findIndex from "lodash/findIndex";
|
||||||
import filter from "lodash/filter";
|
import filter from "lodash/filter";
|
||||||
import DropDown from "../drop-down";
|
import DropDown from "../drop-down";
|
||||||
|
import { handleAnyClick } from "../../utils/event";
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
@ -32,16 +34,27 @@ const Container = ({
|
|||||||
groups,
|
groups,
|
||||||
selectedGroups,
|
selectedGroups,
|
||||||
onChangeGroup,
|
onChangeGroup,
|
||||||
|
isOpen,
|
||||||
|
isDropDown,
|
||||||
|
containerWidth,
|
||||||
|
containerHeight,
|
||||||
...props
|
...props
|
||||||
}) => <div {...props} />;
|
}) => <div {...props} />;
|
||||||
/* eslint-enable react/prop-types */
|
/* eslint-enable react/prop-types */
|
||||||
/* eslint-enable no-unused-vars */
|
/* eslint-enable no-unused-vars */
|
||||||
|
|
||||||
const StyledContainer = styled(Container)`
|
const StyledContainer = styled(Container)`
|
||||||
${props => (props.width ? `width: ${props.width}px;` : "")}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
${props => (props.containerWidth ? `width: ${props.containerWidth}px;` : "")}
|
||||||
|
${props =>
|
||||||
|
props.containerHeight
|
||||||
|
? `height: ${props.containerHeight}px;`
|
||||||
|
: ""}
|
||||||
|
|
||||||
.data_container {
|
.data_container {
|
||||||
margin: 16px;
|
margin: 16px 16px 0 16px;
|
||||||
|
|
||||||
.options_searcher {
|
.options_searcher {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@ -53,7 +66,7 @@ const StyledContainer = styled(Container)`
|
|||||||
|
|
||||||
.option_select_all_checkbox {
|
.option_select_all_checkbox {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
margin-left: 8px;
|
/*margin-left: 8px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.options_list {
|
.options_list {
|
||||||
@ -62,25 +75,26 @@ const StyledContainer = styled(Container)`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.option_checkbox {
|
.option_checkbox {
|
||||||
margin-left: 8px;
|
/*margin-left: 8px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.option_link {
|
.option_link {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
/*&:hover {
|
||||||
background-color: #eceef1;
|
background-color: #eceef1;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button_container {
|
.button_container {
|
||||||
border-top: 1px solid #eceef1;
|
border-top: 1px solid #eceef1;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
.add_members_btn {
|
.add_members_btn {
|
||||||
margin: 16px;
|
margin: 16px;
|
||||||
width: 293px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -89,6 +103,8 @@ class AdvancedSelector extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.ref = React.createRef();
|
||||||
|
|
||||||
const groups = this.convertGroups(this.props.groups);
|
const groups = this.convertGroups(this.props.groups);
|
||||||
const currentGroup = this.getCurrentGroup(groups);
|
const currentGroup = this.getCurrentGroup(groups);
|
||||||
|
|
||||||
@ -98,25 +114,53 @@ class AdvancedSelector extends React.Component {
|
|||||||
groups: groups,
|
groups: groups,
|
||||||
currentGroup: currentGroup
|
currentGroup: currentGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (props.isOpen) handleAnyClick(true, this.handleClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = e => {
|
||||||
|
if (this.props.isOpen && !this.ref.current.contains(e.target)) {
|
||||||
|
this.props.onSelect && this.props.onSelect(this.state.selectedOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
handleAnyClick(false, this.handleClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
let newState = {};
|
||||||
|
|
||||||
if (!isArrayEqual(this.props.selectedOptions, prevProps.selectedOptions)) {
|
if (!isArrayEqual(this.props.selectedOptions, prevProps.selectedOptions)) {
|
||||||
this.setState({ selectedOptions: this.props.selectedOptions });
|
newState = { selectedOptions: this.props.selectedOptions };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.isMultiSelect !== prevProps.isMultiSelect) {
|
if (this.props.isMultiSelect !== prevProps.isMultiSelect) {
|
||||||
this.setState({ selectedOptions: [] });
|
newState = Object.assign({}, newState, {
|
||||||
|
selectedOptions: []
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.selectedAll !== prevProps.selectedAll) {
|
if (this.props.selectedAll !== prevProps.selectedAll) {
|
||||||
this.setState({ selectedAll: this.props.selectedAll });
|
newState = Object.assign({}, newState, {
|
||||||
|
selectedAll: this.props.selectedAll
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isArrayEqual(this.props.groups, prevProps.groups)) {
|
if (!isArrayEqual(this.props.groups, prevProps.groups)) {
|
||||||
const groups = this.convertGroups(this.props.groups);
|
const groups = this.convertGroups(this.props.groups);
|
||||||
const currentGroup = this.getCurrentGroup(groups);
|
const currentGroup = this.getCurrentGroup(groups);
|
||||||
this.setState({ groups, currentGroup });
|
newState = Object.assign({}, newState, {
|
||||||
|
groups, currentGroup
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isEmpty(newState)) {
|
||||||
|
this.setState({ ...this.state, ...newState });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.isOpen !== prevProps.isOpen) {
|
||||||
|
handleAnyClick(this.props.isOpen, this.handleClick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +259,6 @@ class AdvancedSelector extends React.Component {
|
|||||||
const {
|
const {
|
||||||
value,
|
value,
|
||||||
placeholder,
|
placeholder,
|
||||||
maxHeight,
|
|
||||||
isDisabled,
|
isDisabled,
|
||||||
onSearchChanged,
|
onSearchChanged,
|
||||||
options,
|
options,
|
||||||
@ -225,9 +268,19 @@ class AdvancedSelector extends React.Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { selectedOptions, selectedAll, currentGroup, groups } = this.state;
|
const { selectedOptions, selectedAll, currentGroup, groups } = this.state;
|
||||||
|
|
||||||
|
const containerHeight = !groups || !groups.length ? 336 : 545;
|
||||||
|
const containerWidth = !groups || !groups.length ? 325 : 690;
|
||||||
|
const listHeight = 176;
|
||||||
|
const itemHeight = 32;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer {...this.props}>
|
<StyledContainer
|
||||||
<div className="data_container">
|
containerHeight={containerHeight}
|
||||||
|
containerWidth={containerWidth}
|
||||||
|
{...this.props}
|
||||||
|
>
|
||||||
|
<div className="data_container" ref={this.ref}>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
className="options_searcher"
|
className="options_searcher"
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
@ -264,10 +317,10 @@ class AdvancedSelector extends React.Component {
|
|||||||
)}
|
)}
|
||||||
<FixedSizeList
|
<FixedSizeList
|
||||||
className="options_list"
|
className="options_list"
|
||||||
height={maxHeight}
|
height={listHeight}
|
||||||
itemSize={32}
|
itemSize={itemHeight}
|
||||||
itemCount={options.length}
|
itemCount={this.props.options.length}
|
||||||
itemData={options}
|
itemData={this.props.options}
|
||||||
outerElementType={CustomScrollbarsVirtualList}
|
outerElementType={CustomScrollbarsVirtualList}
|
||||||
>
|
>
|
||||||
{this.renderRow.bind(this)}
|
{this.renderRow.bind(this)}
|
||||||
@ -310,8 +363,7 @@ AdvancedSelector.propTypes = {
|
|||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
isMultiSelect: PropTypes.bool,
|
isMultiSelect: PropTypes.bool,
|
||||||
mode: PropTypes.oneOf(["base", "compact"]),
|
mode: PropTypes.oneOf(["compact", "full"]),
|
||||||
width: PropTypes.number,
|
|
||||||
maxHeight: PropTypes.number,
|
maxHeight: PropTypes.number,
|
||||||
isDisabled: PropTypes.bool,
|
isDisabled: PropTypes.bool,
|
||||||
onSearchChanged: PropTypes.func,
|
onSearchChanged: PropTypes.func,
|
||||||
@ -330,9 +382,7 @@ AdvancedSelector.propTypes = {
|
|||||||
|
|
||||||
AdvancedSelector.defaultProps = {
|
AdvancedSelector.defaultProps = {
|
||||||
isMultiSelect: false,
|
isMultiSelect: false,
|
||||||
width: 325,
|
mode: "compact",
|
||||||
maxHeight: 545,
|
|
||||||
mode: "base",
|
|
||||||
buttonLabel: "Add members",
|
buttonLabel: "Add members",
|
||||||
selectAllLabel: "Select all"
|
selectAllLabel: "Select all"
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import { action } from "@storybook/addon-actions";
|
||||||
|
import { withKnobs, text } from "@storybook/addon-knobs/react";
|
||||||
|
import AdvancedSelector from "../advanced-selector";
|
||||||
|
import Section from "../../../.storybook/decorators/section";
|
||||||
|
import { boolean } from "@storybook/addon-knobs/dist/deprecated";
|
||||||
|
import { ArrayValue, BooleanValue } from "react-values";
|
||||||
|
import Button from "../button";
|
||||||
|
|
||||||
|
storiesOf("EXAMPLES|AdvancedSelector", module)
|
||||||
|
.addDecorator(withKnobs)
|
||||||
|
// To set a default viewport for all the stories for this component
|
||||||
|
.addParameters({ viewport: { defaultViewport: "responsive" } })
|
||||||
|
.add("people group selector", () => {
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
key: "group-all",
|
||||||
|
label: "All groups",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-dev",
|
||||||
|
label: "Development",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-management",
|
||||||
|
label: "Management",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-marketing",
|
||||||
|
label: "Marketing",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-mobile",
|
||||||
|
label: "Mobile",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-support",
|
||||||
|
label: "Support",
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "group-web",
|
||||||
|
label: "Web",
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section>
|
||||||
|
<BooleanValue
|
||||||
|
defaultValue={true}
|
||||||
|
onChange={() => action("isOpen changed")}
|
||||||
|
>
|
||||||
|
{({ value: isOpen, toggle }) => (
|
||||||
|
<div style={{ position: "relative" }}>
|
||||||
|
<Button label="Toggle dropdown" onClick={toggle} />
|
||||||
|
<ArrayValue
|
||||||
|
defaultValue={options}
|
||||||
|
onChange={() => action("options onChange")}
|
||||||
|
>
|
||||||
|
{({ value, set }) => (
|
||||||
|
<AdvancedSelector
|
||||||
|
isDropDown={true}
|
||||||
|
isOpen={isOpen}
|
||||||
|
maxHeight={336}
|
||||||
|
width={379}
|
||||||
|
placeholder={text("placeholder", "Search")}
|
||||||
|
onSearchChanged={value => {
|
||||||
|
action("onSearchChanged")(value);
|
||||||
|
set(
|
||||||
|
options.filter(option => {
|
||||||
|
return option.label.indexOf(value) > -1;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={value}
|
||||||
|
isMultiSelect={boolean("isMultiSelect", true)}
|
||||||
|
buttonLabel={text("buttonLabel", "Add departments")}
|
||||||
|
selectAllLabel={text("selectAllLabel", "Select all")}
|
||||||
|
onSelect={selectedOptions => {
|
||||||
|
action("onSelect")(selectedOptions);
|
||||||
|
toggle();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ArrayValue>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</BooleanValue>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user