web: components: Init AdvancedSelector

This commit is contained in:
Alexey Safronov 2019-08-26 11:51:36 +03:00
parent 7fbbea82b4
commit 3fd0fd365e
5 changed files with 277 additions and 23 deletions

View File

@ -0,0 +1,158 @@
import React, { memo } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
import SearchInput from "../search-input";
import CustomScrollbarsVirtualList from "../scrollbar/custom-scrollbars-virtual-list";
import { FixedSizeList } from "react-window";
import Link from "../link";
import Button from "../button";
const Container = ({
value,
placeholder,
isMultiSelect,
mode,
width,
maxHeight,
isDisabled,
onSearchChanged,
options,
selectedOptions,
...props
}) => <div {...props} />;
const StyledContainer = styled(Container)`
${props => (props.width ? `width: ${props.width}px;` : "")}
.options_searcher {
margin-bottom: 12px;
}
.options_list {
.option {
line-height: 32px;
cursor: pointer;
&:hover {
background-color: #eceef1;
}
}
}
.add_members_btn {
margin: 16px 0;
}
`;
/*const Row = memo(({ data, index, style }) => {
const option = data[index];
return (
<div class="option" style={style}>
<Link as="span" truncate={true}>
{option.label}
</Link>
</div>
);
});*/
class AdvancedSelector extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
onButtonClick = () => {};
onSelect = option => {
if (!this.props.isMultiSelect) this.props.onSelect(option);
};
renderRow = ({ data, index, style }) => {
const option = data[index];
return (
<div class="option" style={style}>
<Link as="span" truncate={true} onClick={this.onSelect.bind(this, option)}>
{option.label}
</Link>
</div>
);
};
render() {
const {
value,
placeholder,
maxHeight,
isDisabled,
onSearchChanged,
options,
selectedOptions,
isMultiSelect,
buttonLabel
} = this.props;
return (
<StyledContainer {...this.props}>
<SearchInput
className="options_searcher"
isDisabled={isDisabled}
size="base"
scale={true}
isNeedFilter={false}
placeholder={placeholder}
value={value}
onChange={onSearchChanged}
/>
<FixedSizeList
className="options_list"
stype="smallBlack"
height={maxHeight}
itemSize={32}
itemCount={options.length}
itemData={options}
outerElementType={CustomScrollbarsVirtualList}
>
{this.renderRow}
</FixedSizeList>
{isMultiSelect && (
<Button
className="add_members_btn"
primary={true}
size="big"
label={buttonLabel}
scale={true}
onClick={this.onButtonClick}
/>
)}
</StyledContainer>
);
}
}
AdvancedSelector.propTypes = {
value: PropTypes.string,
placeholder: PropTypes.string,
isMultiSelect: PropTypes.bool,
mode: PropTypes.oneOf(["base", "compact"]),
width: PropTypes.number,
maxHeight: PropTypes.number,
isDisabled: PropTypes.bool,
onSearchChanged: PropTypes.func,
options: PropTypes.array.isRequired,
selectedOptions: PropTypes.array,
buttonLabel: PropTypes.string,
onSelect: PropTypes.func
};
AdvancedSelector.defaultProps = {
isMultiSelect: false,
width: 325,
maxHeight: 545,
mode: "base",
buttonLabel: "Add members"
};
export default AdvancedSelector;

View File

@ -1,32 +1,47 @@
import React from 'react';
import Scrollbar from '../scrollbar';
import React from "react";
import Scrollbar from "../scrollbar";
class CustomScrollbars extends React.Component {
refSetter = (scrollbarsRef, forwardedRef) => {
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
} else {
forwardedRef(null);
}
};
render() {
const { onScroll, forwardedRef, style, children } = this.props;
class CustomScrollbars extends React.Component {
refSetter = (scrollbarsRef, forwardedRef) => {
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
} else {
forwardedRef(null);
}
};
render() {
const {
onScroll,
forwardedRef,
style,
children,
className,
stype
} = this.props;
//console.log("CustomScrollbars", this.props);
return (
<Scrollbar
ref={scrollbarsRef => this.refSetter.bind(this, scrollbarsRef, forwardedRef)}
ref={scrollbarsRef =>
this.refSetter.bind(this, scrollbarsRef, forwardedRef)
}
style={{ ...style, overflow: "hidden" }}
onScroll={onScroll}
stype="mediumBlack"
stype={stype}
className={className}
>
{children}
</Scrollbar>
);
};
};
const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
<CustomScrollbars {...props} forwardedRef={ref} />
));
}
}
export default CustomScrollbarsVirtualList;
CustomScrollbars.defaultProps = {
stype: "mediumBlack"
};
const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
<CustomScrollbars {...props} forwardedRef={ref} />
));
export default CustomScrollbarsVirtualList;

View File

@ -48,4 +48,5 @@ export { default as Calendar } from './components/calendar'
export { default as Label} from './components/label'
export { default as EmptyScreenContainer} from './components/empty-screen-container'
export { default as CustomScrollbarsVirtualList } from './components/scrollbar/custom-scrollbars-virtual-list'
export { default as RowContent } from './components/row-content'
export { default as RowContent } from './components/row-content'
export { default as AdvancedSelector } from './components/advanced-selector'

View File

@ -0,0 +1,44 @@
# AdvancedSelector
## Usage
```js
import { AdvancedSelector } from 'asc-web-components';
```
#### Description
Required to select some advanced data.
#### Usage
```js
let options = [{key: "self", label: "Me"}];
options = [...options, ...[...Array(100).keys()].map(
index => {
return { key: `user${index}`, label: `User ${index+1} of ${optionsCount}` };
}
)];
<AdvancedSelector
placeholder="Search users"
onSearchChanged={(e) => console.log(e.target.value)}
options={options}
isMultiSelect={false}
buttonLabel="Add members"
onSelect={(selectedOptions) => console.log("onSelect", selectedOptions)}
/>
```
#### Properties
| Props | Type | Required | Values | Default | Description |
| ------------------ | -------- | :------: | ----------------------------------------- | --------- | ----------------------------------------------------- |
| `placeholder` | `string` | - | | | |
| `options` | `array of objects` | - | | | |
| `isMultiSelect` | `bool` | - | - | | |
| `buttonLabel` | `string` | - | - | | |
| `onSearchChanged` | `func` | - | - | | |
| `onSelect` | `func` | - | - | | |

View File

@ -0,0 +1,36 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs, text, number } from '@storybook/addon-knobs/react';
import withReadme from 'storybook-readme/with-readme';
import Readme from './README.md';
import { AdvancedSelector } from 'asc-web-components';
import Section from '../../.storybook/decorators/section';
import { boolean } from '@storybook/addon-knobs/dist/deprecated';
storiesOf('Components|AdvancedSelector', module)
.addDecorator(withKnobs)
.addDecorator(withReadme(Readme))
.add('base', () => {
const optionsCount = number("Users count", 100);
let options = [{key: "self", label: "Me"}];
options = [...options, ...[...Array(optionsCount).keys()].map(
index => {
return { key: `user${index}`, label: `User ${index+1} of ${optionsCount}` };
}
)];
return (
<Section>
<AdvancedSelector
placeholder={text("placeholder", "Search users")}
onSearchChanged={(e) => console.log(e.target.value)}
options={options}
isMultiSelect={boolean("isMultiSelect", true)}
buttonLabel={text("buttonLabel", "Add members")}
onSelect={(selectedOptions) => console.log("onSelect", selectedOptions)}
/>
</Section>
);
});