Skip to content

Commit 7a95d8c

Browse files
authored
feat: dropdownMatchSelectWidth = false can disable virtual scroll (#460)
* support dropdownMatchSelectWidth is false * add min width * update snapshot * add virtual prop * add test case * update read me * preitter
1 parent bb5ec95 commit 7a95d8c

File tree

9 files changed

+178
-121
lines changed

9 files changed

+178
-121
lines changed

.prettierrc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
"semi": true,
44
"singleQuote": true,
55
"tabWidth": 2,
6-
"trailingComma": "all"
7-
}
6+
"trailingComma": "all",
7+
"proseWrap": "never",
8+
"printWidth": 100
9+
}

README.md

Lines changed: 75 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
# rc-select
2+
23
---
34

45
React Select
56

6-
[![NPM version][npm-image]][npm-url]
7-
[![build status][travis-image]][travis-url]
8-
[![Test coverage][coveralls-image]][coveralls-url]
9-
[![Dependencies](https://img.shields.io/david/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select)
10-
[![DevDependencies](https://img.shields.io/david/dev/react-component/select.svg?style=flat-square)](https://david-dm.org/react-component/select?type=dev)
11-
[![npm download][download-image]][download-url]
12-
[![Storybook](https://gw.alipayobjects.com/mdn/ob_info/afts/img/A*CQXNTZfK1vwAAAAAAAAAAABjAQAAAQ/original)](https://github.com/react-component/select)
7+
[![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)
138

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

3025
## Feature
3126

32-
* support ie9,ie9+,chrome,firefox,safari
27+
- support ie9,ie9+,chrome,firefox,safari
3328

3429
### Keyboard
3530

36-
* Open select (focus input || focus and click)
37-
* KeyDown/KeyUp/Enter to navigate menu
31+
- Open select (focus input || focus and click)
32+
- KeyDown/KeyUp/Enter to navigate menu
3833

3934
## install
4035

@@ -45,7 +40,7 @@ React Select
4540
### basic use
4641

4742
```js
48-
import Select, {Option, OptGroup} from 'rc-select';
43+
import Select, { Option, OptGroup } from 'rc-select';
4944

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

6257
### Select props
6358

64-
| name | description | type | default |
65-
|----------|----------------|----------|--------------|
66-
|id | html id to set on the component wrapper | String | '' |
67-
|className | additional css class of root dom node | String | '' |
68-
|data-\* | html data attributes to set on the component wrapper | String | '' |
69-
|prefixCls | prefix class | String | '' |
70-
|animation | dropdown animation name. only support slide-up now | String | '' |
71-
|transitionName | dropdown css animation name | String | '' |
72-
|choiceTransitionName | css animation name for selected items at multiple mode | String | '' |
73-
|dropdownMatchSelectWidth | whether dropdown's with is same with select | bool | true |
74-
|dropdownClassName | additional className applied to dropdown | String | - |
75-
|dropdownStyle | additional style applied to dropdown | Object | {} |
76-
|dropdownAlign | additional align applied to dropdown | Object | {} |
77-
|dropdownMenuStyle | additional style applied to dropdown menu | Object | {} |
78-
|notFoundContent | specify content to show when no result matches. | String | 'Not Found' |
79-
|tokenSeparators | separator used to tokenize on tag/multiple mode | string[]? | |
80-
|open | control select open | bool | |
81-
|defaultOpen | control select default open | bool | |
82-
|placeholder | select placeholder | React Node | |
83-
|showSearch | whether show search input in single mode | bool | true |
84-
|showArrow | whether show arrow | bool | true (single mode), false (multiple mode) |
85-
|allowClear | whether allowClear | bool | false |
86-
|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 |
87-
|tagRender | render custom tags. | (props: CustomTagProps) => ReactNode | - |
88-
|maxTagTextLength | max tag text length to show | number | - |
89-
|maxTagCount | max tag count to show | number | - |
90-
|maxTagPlaceholder | placeholder for omitted values | ReactNode/function(omittedValues) | - |
91-
|combobox | enable combobox mode(can not set multiple at the same time) | bool | false |
92-
|multiple | whether multiple select | bool | false |
93-
|disabled | whether disabled select | bool | false |
94-
|filterOption | whether filter options by input value. default filter by option's optionFilterProp prop's value | bool | true/Function(inputValue:string, option:Option) |
95-
|optionFilterProp | which prop value of option will be used for filter if filterOption is true | String | 'value' |
96-
|optionLabelProp | render option value or option children as content of select | String: 'value'/'children' | 'value' |
97-
|defaultValue | initial selected option(s) | String/Array<String> | - |
98-
|value | current selected option(s) | String/Array<String>/{key:String, label:React.Node}/Array<{key, label}> | - |
99-
|firstActiveValue | first active value when there is no value | String/Array<String> | - |
100-
|labelInValue| whether to embed label in value, see above value type. Not support `combobox` mode | Bool | false |
101-
|backfill| whether backfill select option to search input (Only works in single and combobox mode) | Bool | false |
102-
|onChange | called when select an option or input value change(combobox) | function(value, option:Option/Array<Option>) | - |
103-
|onSearch | called when input changed | function | - |
104-
|onBlur | called when blur | function | - |
105-
|onFocus | called when focus | function | - |
106-
|onPopupScroll | called when menu is scrolled | function | - |
107-
|onSelect | called when a option is selected. param is option's value and option instance | Function(value, option:Option) | - |
108-
|onDeselect | called when a option is deselected. param is option's value. only called for multiple or tags | Function(value, option:Option) | - |
109-
|onInputKeyDown | called when key down on input | Function(event) | - |
110-
|defaultActiveFirstOption | whether active first option by default | bool | true |
111-
|getPopupContainer | container which popup select menu rendered into | function(trigger:Node):Node | function(){return document.body;} |
112-
|getInputElement| customize input element | function(): Element | - |
113-
|showAction| actions trigger the dropdown to show | String[]? | - |
114-
|autoFocus| focus select after mount | Bool | - |
59+
| name | description | type | default |
60+
| --- | --- | --- | --- |
61+
| id | html id to set on the component wrapper | String | '' |
62+
| className | additional css class of root dom node | String | '' |
63+
| data-\* | html data attributes to set on the component wrapper | String | '' |
64+
| prefixCls | prefix class | String | '' |
65+
| animation | dropdown animation name. only support slide-up now | String | '' |
66+
| transitionName | dropdown css animation name | String | '' |
67+
| choiceTransitionName | css animation name for selected items at multiple mode | String | '' |
68+
| dropdownMatchSelectWidth | whether dropdown's with is same with select | bool | true |
69+
| dropdownClassName | additional className applied to dropdown | String | - |
70+
| dropdownStyle | additional style applied to dropdown | Object | {} |
71+
| dropdownAlign | additional align applied to dropdown | Object | {} |
72+
| dropdownMenuStyle | additional style applied to dropdown menu | Object | {} |
73+
| notFoundContent | specify content to show when no result matches. | String | 'Not Found' |
74+
| tokenSeparators | separator used to tokenize on tag/multiple mode | string[]? | |
75+
| open | control select open | bool | |
76+
| defaultOpen | control select default open | bool | |
77+
| placeholder | select placeholder | React Node | |
78+
| showSearch | whether show search input in single mode | bool | true |
79+
| showArrow | whether show arrow | bool | true (single mode), false (multiple mode) |
80+
| allowClear | whether allowClear | bool | false |
81+
| 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 |
82+
| tagRender | render custom tags. | (props: CustomTagProps) => ReactNode | - |
83+
| maxTagTextLength | max tag text length to show | number | - |
84+
| maxTagCount | max tag count to show | number | - |
85+
| maxTagPlaceholder | placeholder for omitted values | ReactNode/function(omittedValues) | - |
86+
| combobox | enable combobox mode(can not set multiple at the same time) | bool | false |
87+
| multiple | whether multiple select | bool | false |
88+
| disabled | whether disabled select | bool | false |
89+
| filterOption | whether filter options by input value. default filter by option's optionFilterProp prop's value | bool | true/Function(inputValue:string, option:Option) |
90+
| optionFilterProp | which prop value of option will be used for filter if filterOption is true | String | 'value' |
91+
| optionLabelProp | render option value or option children as content of select | String: 'value'/'children' | 'value' |
92+
| defaultValue | initial selected option(s) | String/Array<String> | - |
93+
| value | current selected option(s) | String/Array<String>/{key:String, label:React.Node}/Array<{key, label}> | - |
94+
| firstActiveValue | first active value when there is no value | String/Array<String> | - |
95+
| labelInValue | whether to embed label in value, see above value type. Not support `combobox` mode | Bool | false |
96+
| backfill | whether backfill select option to search input (Only works in single and combobox mode) | Bool | false |
97+
| onChange | called when select an option or input value change(combobox) | function(value, option:Option/Array<Option>) | - |
98+
| onSearch | called when input changed | function | - |
99+
| onBlur | called when blur | function | - |
100+
| onFocus | called when focus | function | - |
101+
| onPopupScroll | called when menu is scrolled | function | - |
102+
| onSelect | called when a option is selected. param is option's value and option instance | Function(value, option:Option) | - |
103+
| onDeselect | called when a option is deselected. param is option's value. only called for multiple or tags | Function(value, option:Option) | - |
104+
| onInputKeyDown | called when key down on input | Function(event) | - |
105+
| defaultActiveFirstOption | whether active first option by default | bool | true |
106+
| getPopupContainer | container which popup select menu rendered into | function(trigger:Node):Node | function(){return document.body;} |
107+
| getInputElement | customize input element | function(): Element | - |
108+
| showAction | actions trigger the dropdown to show | String[]? | - |
109+
| autoFocus | focus select after mount | Bool | - |
115110
| autoClearSearchValue | auto clear search input value when multiple select is selected/deselected | boolean | true |
116111
| inputIcon | specify the select arrow icon | ReactNode | - |
117112
| clearIcon | specify the clear icon | ReactNode | - |
118113
| removeIcon | specify the remove icon | ReactNode | - |
119114
| menuItemSelectedIcon | specify the remove icon | ReactNode \| (props: MenuItemProps) => ReactNode | - |
120115
| dropdownRender | render custom dropdown menu | (menu: React.Node, props: MenuProps) => ReactNode | - |
121116
| loading | show loading icon in arrow | Boolean | false |
117+
| virtual | Disable virtual scroll | Boolean | true |
122118

123119
### Methods
124120

125-
| name | description | parameters | return |
126-
|----------|----------------|----------|--------------|
127-
|focus | focus select programmably | - | - |
128-
|blur | blur select programmably | - | - |
121+
| name | description | parameters | return |
122+
| ----- | ------------------------- | ---------- | ------ |
123+
| focus | focus select programmably | - | - |
124+
| blur | blur select programmably | - | - |
129125

130126
### Option props
131127

132-
| name | description | type | default |
133-
|----------|----------------|----------|--------------|
134-
|className | additional class to option | String | '' |
135-
|disabled | no effect for click or keydown for this item | bool | false |
136-
|key | if react want you to set key, then key is same as value, you can omit value | String/number | - |
137-
|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 | - |
138-
|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 | - |
139-
128+
| name | description | type | default |
129+
| --- | --- | --- | --- |
130+
| className | additional class to option | String | '' |
131+
| disabled | no effect for click or keydown for this item | bool | false |
132+
| key | if react want you to set key, then key is same as value, you can omit value | String/number | - |
133+
| 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 | - |
134+
| 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 | - |
140135

141136
### OptGroup props
142137

143-
| name | description | type | default |
144-
|----------|----------------|----------|--------------|
145-
|label | group label | String/React.Element | - |
146-
|key | - | String | - |
147-
|value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String | - |
148-
138+
| name | description | type | default |
139+
| --- | --- | --- | --- |
140+
| label | group label | String/React.Element | - |
141+
| key | - | String | - |
142+
| value | default filter by this attribute. if react want you to set key, then key is same as value, you can omit value | String | - |
149143

150144
## Development
151145

@@ -172,7 +166,6 @@ npm test
172166
npm run coverage
173167
```
174168

175-
176169
## License
177170

178171
rc-select is released under the MIT license.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"rc-animate": "^2.10.0",
4747
"rc-trigger": "^4.0.0",
4848
"rc-util": "^4.20.0",
49-
"rc-virtual-list": "^1.0.0",
49+
"rc-virtual-list": "^1.1.0",
5050
"warning": "^4.0.3"
5151
},
5252
"devDependencies": {

src/OptionList.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface OptionListProps<OptionsType extends object[]> {
2727
menuItemSelectedIcon?: RenderNode;
2828
childrenAsData: boolean;
2929
searchValue: string;
30+
virtual: boolean;
3031

3132
onSelect: (value: RawValueType, option: { selected: boolean }) => void;
3233
onToggleOpen: (open?: boolean) => void;
@@ -62,6 +63,7 @@ const OptionList: React.RefForwardingComponent<
6263
notFoundContent,
6364
open,
6465
menuItemSelectedIcon,
66+
virtual,
6567
onSelect,
6668
onToggleOpen,
6769
onActiveValue,
@@ -255,6 +257,7 @@ const OptionList: React.RefForwardingComponent<
255257
fullHeight={false}
256258
onMouseDown={onListMouseDown}
257259
onScroll={onScroll}
260+
virtual={virtual}
258261
>
259262
{({ group, groupOption, data }, itemIndex) => {
260263
const { label, key } = data;

src/SelectTrigger.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface SelectTriggerProps {
3838
containerWidth: number;
3939
dropdownStyle: React.CSSProperties;
4040
dropdownClassName: string;
41-
dropdownMatchSelectWidth?: true | number;
41+
dropdownMatchSelectWidth?: boolean | number;
4242
dropdownRender?: (menu: React.ReactElement) => React.ReactElement;
4343
getPopupContainer?: RenderDOMFunc;
4444
dropdownAlign: object;
@@ -90,6 +90,17 @@ const SelectTrigger: React.RefForwardingComponent<
9090
getPopupElement: () => popupRef.current,
9191
}));
9292

93+
const popupStyle: React.CSSProperties = {
94+
minWidth: containerWidth,
95+
...dropdownStyle,
96+
};
97+
98+
if (typeof dropdownMatchSelectWidth === 'number') {
99+
popupStyle.width = dropdownMatchSelectWidth;
100+
} else if (dropdownMatchSelectWidth) {
101+
popupStyle.width = containerWidth;
102+
}
103+
93104
return (
94105
<Trigger
95106
{...restProps}
@@ -106,13 +117,7 @@ const SelectTrigger: React.RefForwardingComponent<
106117
popupClassName={classNames(dropdownClassName, {
107118
[`${dropdownPrefixCls}-empty`]: empty,
108119
})}
109-
popupStyle={{
110-
...dropdownStyle,
111-
width:
112-
typeof dropdownMatchSelectWidth === 'number'
113-
? dropdownMatchSelectWidth
114-
: containerWidth,
115-
}}
120+
popupStyle={popupStyle}
116121
getTriggerDOMNode={getTriggerDOMNode}
117122
>
118123
{children}

src/generate.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ export interface SelectProps<OptionsType extends object[], ValueType>
107107
listItemHeight?: number;
108108
dropdownStyle?: React.CSSProperties;
109109
dropdownClassName?: string;
110-
dropdownMatchSelectWidth?: true | number;
110+
dropdownMatchSelectWidth?: boolean | number;
111+
virtual?: boolean;
111112
dropdownRender?: (menu: React.ReactElement) => React.ReactElement;
112113
dropdownAlign?: any;
113114
animation?: string;
@@ -301,6 +302,7 @@ export default function generateSelector<
301302
listItemHeight = 20,
302303
animation,
303304
transitionName,
305+
virtual,
304306
dropdownStyle,
305307
dropdownClassName,
306308
dropdownMatchSelectWidth,
@@ -927,6 +929,7 @@ export default function generateSelector<
927929
onScroll={onPopupScroll}
928930
searchValue={mergedSearchValue}
929931
menuItemSelectedIcon={menuItemSelectedIcon}
932+
virtual={virtual !== false && dropdownMatchSelectWidth !== false}
930933
/>
931934
);
932935

0 commit comments

Comments
 (0)