web: components: Init AdvancedSelector
This commit is contained in:
parent
7fbbea82b4
commit
3fd0fd365e
158
web/ASC.Web.Components/src/components/advanced-selector/index.js
Normal file
158
web/ASC.Web.Components/src/components/advanced-selector/index.js
Normal 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;
|
@ -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;
|
||||
|
@ -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'
|
44
web/ASC.Web.Storybook/stories/advanced-selector/README.md
Normal file
44
web/ASC.Web.Storybook/stories/advanced-selector/README.md
Normal 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` | - | - | | |
|
@ -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>
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue
Block a user