Skip to content

Commit

Permalink
feat: dropdownMatchSelectWidth = false can disable virtual scroll (re…
Browse files Browse the repository at this point in the history
…act-component#460)

* support dropdownMatchSelectWidth is false

* add min width

* update snapshot

* add virtual prop

* add test case

* update read me

* preitter
  • Loading branch information
zombieJ authored Mar 6, 2020
1 parent bb5ec95 commit 7a95d8c
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 121 deletions.
6 changes: 4 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}
"trailingComma": "all",
"proseWrap": "never",
"printWidth": 100
}
157 changes: 75 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
# rc-select

---

React Select

[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]
[![Dependencies](https://img.shields.io/david/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select)
[![DevDependencies](https://img.shields.io/david/dev/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select?type=dev)
[![npm download][download-image]][download-url]
[![Storybook](https://gw.alipayobjects.com/mdn/ob_info/afts/img/A*CQXNTZfK1vwAAAAAAAAAAABjAQAAAQ/original)](https://github.com/react-component/select)
[![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] [![Test coverage][coveralls-image]][coveralls-url] [![Dependencies](https://img.shields.io/david/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select) [![DevDependencies](https://img.shields.io/david/dev/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select?type=dev) [![npm download][download-image]][download-url] [![Storybook](https://gw.alipayobjects.com/mdn/ob_info/afts/img/A*CQXNTZfK1vwAAAAAAAAAAABjAQAAAQ/original)](https://github.com/react-component/select)

[Storybook]: https://github.com/storybooks/press/blob/master/badges/storybook.svg
[storybook]: https://github.com/storybooks/press/blob/master/badges/storybook.svg
[npm-image]: http://img.shields.io/npm/v/rc-select.svg?style=flat-square
[npm-url]: http://npmjs.org/package/rc-select
[travis-image]: https://img.shields.io/travis/react-component/select.svg?style=flat-square
Expand All @@ -29,12 +24,12 @@ React Select

## Feature

* support ie9,ie9+,chrome,firefox,safari
- support ie9,ie9+,chrome,firefox,safari

### Keyboard

* Open select (focus input || focus and click)
* KeyDown/KeyUp/Enter to navigate menu
- Open select (focus input || focus and click)
- KeyDown/KeyUp/Enter to navigate menu

## install

Expand All @@ -45,7 +40,7 @@ React Select
### basic use

```js
import Select, {Option, OptGroup} from 'rc-select';
import Select, { Option, OptGroup } from 'rc-select';

var c = (
<Select>
Expand All @@ -61,91 +56,90 @@ React.render(c, container);

### Select props

| name | description | type | default |
|----------|----------------|----------|--------------|
|id | html id to set on the component wrapper | String | '' |
|className | additional css class of root dom node | String | '' |
|data-\* | html data attributes to set on the component wrapper | String | '' |
|prefixCls | prefix class | String | '' |
|animation | dropdown animation name. only support slide-up now | String | '' |
|transitionName | dropdown css animation name | String | '' |
|choiceTransitionName | css animation name for selected items at multiple mode | String | '' |
|dropdownMatchSelectWidth | whether dropdown's with is same with select | bool | true |
|dropdownClassName | additional className applied to dropdown | String | - |
|dropdownStyle | additional style applied to dropdown | Object | {} |
|dropdownAlign | additional align applied to dropdown | Object | {} |
|dropdownMenuStyle | additional style applied to dropdown menu | Object | {} |
|notFoundContent | specify content to show when no result matches. | String | 'Not Found' |
|tokenSeparators | separator used to tokenize on tag/multiple mode | string[]? | |
|open | control select open | bool | |
|defaultOpen | control select default open | bool | |
|placeholder | select placeholder | React Node | |
|showSearch | whether show search input in single mode | bool | true |
|showArrow | whether show arrow | bool | true (single mode), false (multiple mode) |
|allowClear | whether allowClear | bool | false |
|tags | when tagging is enabled the user can select from pre-existing options or create a new tag by picking the first choice, which is what the user has typed into the search box so far. | bool | false |
|tagRender | render custom tags. | (props: CustomTagProps) => ReactNode | - |
|maxTagTextLength | max tag text length to show | number | - |
|maxTagCount | max tag count to show | number | - |
|maxTagPlaceholder | placeholder for omitted values | ReactNode/function(omittedValues) | - |
|combobox | enable combobox mode(can not set multiple at the same time) | bool | false |
|multiple | whether multiple select | bool | false |
|disabled | whether disabled select | bool | false |
|filterOption | whether filter options by input value. default filter by option's optionFilterProp prop's value | bool | true/Function(inputValue:string, option:Option) |
|optionFilterProp | which prop value of option will be used for filter if filterOption is true | String | 'value' |
|optionLabelProp | render option value or option children as content of select | String: 'value'/'children' | 'value' |
|defaultValue | initial selected option(s) | String/Array<String> | - |
|value | current selected option(s) | String/Array<String>/{key:String, label:React.Node}/Array<{key, label}> | - |
|firstActiveValue | first active value when there is no value | String/Array<String> | - |
|labelInValue| whether to embed label in value, see above value type. Not support `combobox` mode | Bool | false |
|backfill| whether backfill select option to search input (Only works in single and combobox mode) | Bool | false |
|onChange | called when select an option or input value change(combobox) | function(value, option:Option/Array<Option>) | - |
|onSearch | called when input changed | function | - |
|onBlur | called when blur | function | - |
|onFocus | called when focus | function | - |
|onPopupScroll | called when menu is scrolled | function | - |
|onSelect | called when a option is selected. param is option's value and option instance | Function(value, option:Option) | - |
|onDeselect | called when a option is deselected. param is option's value. only called for multiple or tags | Function(value, option:Option) | - |
|onInputKeyDown | called when key down on input | Function(event) | - |
|defaultActiveFirstOption | whether active first option by default | bool | true |
|getPopupContainer | container which popup select menu rendered into | function(trigger:Node):Node | function(){return document.body;} |
|getInputElement| customize input element | function(): Element | - |
|showAction| actions trigger the dropdown to show | String[]? | - |
|autoFocus| focus select after mount | Bool | - |
| name | description | type | default |
| --- | --- | --- | --- |
| id | html id to set on the component wrapper | String | '' |
| className | additional css class of root dom node | String | '' |
| data-\* | html data attributes to set on the component wrapper | String | '' |
| prefixCls | prefix class | String | '' |
| animation | dropdown animation name. only support slide-up now | String | '' |
| transitionName | dropdown css animation name | String | '' |
| choiceTransitionName | css animation name for selected items at multiple mode | String | '' |
| dropdownMatchSelectWidth | whether dropdown's with is same with select | bool | true |
| dropdownClassName | additional className applied to dropdown | String | - |
| dropdownStyle | additional style applied to dropdown | Object | {} |
| dropdownAlign | additional align applied to dropdown | Object | {} |
| dropdownMenuStyle | additional style applied to dropdown menu | Object | {} |
| notFoundContent | specify content to show when no result matches. | String | 'Not Found' |
| tokenSeparators | separator used to tokenize on tag/multiple mode | string[]? | |
| open | control select open | bool | |
| defaultOpen | control select default open | bool | |
| placeholder | select placeholder | React Node | |
| showSearch | whether show search input in single mode | bool | true |
| showArrow | whether show arrow | bool | true (single mode), false (multiple mode) |
| allowClear | whether allowClear | bool | false |
| tags | when tagging is enabled the user can select from pre-existing options or create a new tag by picking the first choice, which is what the user has typed into the search box so far. | bool | false |
| tagRender | render custom tags. | (props: CustomTagProps) => ReactNode | - |
| maxTagTextLength | max tag text length to show | number | - |
| maxTagCount | max tag count to show | number | - |
| maxTagPlaceholder | placeholder for omitted values | ReactNode/function(omittedValues) | - |
| combobox | enable combobox mode(can not set multiple at the same time) | bool | false |
| multiple | whether multiple select | bool | false |
| disabled | whether disabled select | bool | false |
| filterOption | whether filter options by input value. default filter by option's optionFilterProp prop's value | bool | true/Function(inputValue:string, option:Option) |
| optionFilterProp | which prop value of option will be used for filter if filterOption is true | String | 'value' |
| optionLabelProp | render option value or option children as content of select | String: 'value'/'children' | 'value' |
| defaultValue | initial selected option(s) | String/Array<String> | - |
| value | current selected option(s) | String/Array<String>/{key:String, label:React.Node}/Array<{key, label}> | - |
| firstActiveValue | first active value when there is no value | String/Array<String> | - |
| labelInValue | whether to embed label in value, see above value type. Not support `combobox` mode | Bool | false |
| backfill | whether backfill select option to search input (Only works in single and combobox mode) | Bool | false |
| onChange | called when select an option or input value change(combobox) | function(value, option:Option/Array<Option>) | - |
| onSearch | called when input changed | function | - |
| onBlur | called when blur | function | - |
| onFocus | called when focus | function | - |
| onPopupScroll | called when menu is scrolled | function | - |
| onSelect | called when a option is selected. param is option's value and option instance | Function(value, option:Option) | - |
| onDeselect | called when a option is deselected. param is option's value. only called for multiple or tags | Function(value, option:Option) | - |
| onInputKeyDown | called when key down on input | Function(event) | - |
| defaultActiveFirstOption | whether active first option by default | bool | true |
| getPopupContainer | container which popup select menu rendered into | function(trigger:Node):Node | function(){return document.body;} |
| getInputElement | customize input element | function(): Element | - |
| showAction | actions trigger the dropdown to show | String[]? | - |
| autoFocus | focus select after mount | Bool | - |
| autoClearSearchValue | auto clear search input value when multiple select is selected/deselected | boolean | true |
| inputIcon | specify the select arrow icon | ReactNode | - |
| clearIcon | specify the clear icon | ReactNode | - |
| removeIcon | specify the remove icon | ReactNode | - |
| menuItemSelectedIcon | specify the remove icon | ReactNode \| (props: MenuItemProps) => ReactNode | - |
| dropdownRender | render custom dropdown menu | (menu: React.Node, props: MenuProps) => ReactNode | - |
| loading | show loading icon in arrow | Boolean | false |
| virtual | Disable virtual scroll | Boolean | true |

### Methods

| name | description | parameters | return |
|----------|----------------|----------|--------------|
|focus | focus select programmably | - | - |
|blur | blur select programmably | - | - |
| name | description | parameters | return |
| ----- | ------------------------- | ---------- | ------ |
| focus | focus select programmably | - | - |
| blur | blur select programmably | - | - |

### Option props

| name | description | type | default |
|----------|----------------|----------|--------------|
|className | additional class to option | String | '' |
|disabled | no effect for click or keydown for this item | bool | false |
|key | if react want you to set key, then key is same as value, you can omit value | String/number | - |
|value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String/number | - |
|title | if you are not satisfied with auto-generated `title` which is show while hovering on selected value, you can customize it with this property | String | - |

| name | description | type | default |
| --- | --- | --- | --- |
| className | additional class to option | String | '' |
| disabled | no effect for click or keydown for this item | bool | false |
| key | if react want you to set key, then key is same as value, you can omit value | String/number | - |
| value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String/number | - |
| title | if you are not satisfied with auto-generated `title` which is show while hovering on selected value, you can customize it with this property | String | - |

### OptGroup props

| name | description | type | default |
|----------|----------------|----------|--------------|
|label | group label | String/React.Element | - |
|key | - | String | - |
|value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String | - |

| name | description | type | default |
| --- | --- | --- | --- |
| label | group label | String/React.Element | - |
| key | - | String | - |
| value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String | - |

## Development

Expand All @@ -172,7 +166,6 @@ npm test
npm run coverage
```


## License

rc-select is released under the MIT license.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"rc-animate": "^2.10.0",
"rc-trigger": "^4.0.0",
"rc-util": "^4.20.0",
"rc-virtual-list": "^1.0.0",
"rc-virtual-list": "^1.1.0",
"warning": "^4.0.3"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions src/OptionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface OptionListProps<OptionsType extends object[]> {
menuItemSelectedIcon?: RenderNode;
childrenAsData: boolean;
searchValue: string;
virtual: boolean;

onSelect: (value: RawValueType, option: { selected: boolean }) => void;
onToggleOpen: (open?: boolean) => void;
Expand Down Expand Up @@ -62,6 +63,7 @@ const OptionList: React.RefForwardingComponent<
notFoundContent,
open,
menuItemSelectedIcon,
virtual,
onSelect,
onToggleOpen,
onActiveValue,
Expand Down Expand Up @@ -255,6 +257,7 @@ const OptionList: React.RefForwardingComponent<
fullHeight={false}
onMouseDown={onListMouseDown}
onScroll={onScroll}
virtual={virtual}
>
{({ group, groupOption, data }, itemIndex) => {
const { label, key } = data;
Expand Down
21 changes: 13 additions & 8 deletions src/SelectTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface SelectTriggerProps {
containerWidth: number;
dropdownStyle: React.CSSProperties;
dropdownClassName: string;
dropdownMatchSelectWidth?: true | number;
dropdownMatchSelectWidth?: boolean | number;
dropdownRender?: (menu: React.ReactElement) => React.ReactElement;
getPopupContainer?: RenderDOMFunc;
dropdownAlign: object;
Expand Down Expand Up @@ -90,6 +90,17 @@ const SelectTrigger: React.RefForwardingComponent<
getPopupElement: () => popupRef.current,
}));

const popupStyle: React.CSSProperties = {
minWidth: containerWidth,
...dropdownStyle,
};

if (typeof dropdownMatchSelectWidth === 'number') {
popupStyle.width = dropdownMatchSelectWidth;
} else if (dropdownMatchSelectWidth) {
popupStyle.width = containerWidth;
}

return (
<Trigger
{...restProps}
Expand All @@ -106,13 +117,7 @@ const SelectTrigger: React.RefForwardingComponent<
popupClassName={classNames(dropdownClassName, {
[`${dropdownPrefixCls}-empty`]: empty,
})}
popupStyle={{
...dropdownStyle,
width:
typeof dropdownMatchSelectWidth === 'number'
? dropdownMatchSelectWidth
: containerWidth,
}}
popupStyle={popupStyle}
getTriggerDOMNode={getTriggerDOMNode}
>
{children}
Expand Down
5 changes: 4 additions & 1 deletion src/generate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ export interface SelectProps<OptionsType extends object[], ValueType>
listItemHeight?: number;
dropdownStyle?: React.CSSProperties;
dropdownClassName?: string;
dropdownMatchSelectWidth?: true | number;
dropdownMatchSelectWidth?: boolean | number;
virtual?: boolean;
dropdownRender?: (menu: React.ReactElement) => React.ReactElement;
dropdownAlign?: any;
animation?: string;
Expand Down Expand Up @@ -301,6 +302,7 @@ export default function generateSelector<
listItemHeight = 20,
animation,
transitionName,
virtual,
dropdownStyle,
dropdownClassName,
dropdownMatchSelectWidth,
Expand Down Expand Up @@ -927,6 +929,7 @@ export default function generateSelector<
onScroll={onPopupScroll}
searchValue={mergedSearchValue}
menuItemSelectedIcon={menuItemSelectedIcon}
virtual={virtual !== false && dropdownMatchSelectWidth !== false}
/>
);

Expand Down
Loading

0 comments on commit 7a95d8c

Please sign in to comment.