|
@@ -293,6 +293,8 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
inputRef: React.RefObject<HTMLInputElement>;
|
|
inputRef: React.RefObject<HTMLInputElement>;
|
|
|
triggerRef: React.RefObject<HTMLDivElement>;
|
|
triggerRef: React.RefObject<HTMLDivElement>;
|
|
|
optionsRef: React.RefObject<any>;
|
|
optionsRef: React.RefObject<any>;
|
|
|
|
|
+ virtualizeListRef: React.RefObject<any>;
|
|
|
|
|
+ selectOptionListID: string;
|
|
|
clickOutsideHandler: (e: MouseEvent) => void;
|
|
clickOutsideHandler: (e: MouseEvent) => void;
|
|
|
foundation: SelectFoundation;
|
|
foundation: SelectFoundation;
|
|
|
|
|
|
|
@@ -312,6 +314,9 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
optionGroups: [],
|
|
optionGroups: [],
|
|
|
isHovering: false,
|
|
isHovering: false,
|
|
|
};
|
|
};
|
|
|
|
|
+ /* Generate random string */
|
|
|
|
|
+ this.selectOptionListID = Math.random().toString(36).slice(2);
|
|
|
|
|
+ this.virtualizeListRef = React.createRef();
|
|
|
this.inputRef = React.createRef();
|
|
this.inputRef = React.createRef();
|
|
|
this.triggerRef = React.createRef();
|
|
this.triggerRef = React.createRef();
|
|
|
this.optionsRef = React.createRef();
|
|
this.optionsRef = React.createRef();
|
|
@@ -493,7 +498,26 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ updateScrollTop: () => {
|
|
|
|
|
+ // eslint-disable-next-line max-len
|
|
|
|
|
+ let destNode = document.querySelector(`#${prefixcls}-${this.selectOptionListID} .${prefixcls}-option-selected`) as HTMLDivElement;
|
|
|
|
|
+ if (Array.isArray(destNode)) {
|
|
|
|
|
+ // eslint-disable-next-line prefer-destructuring
|
|
|
|
|
+ destNode = destNode[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (destNode) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Scroll the first selected item into view.
|
|
|
|
|
+ * The reason why ScrollIntoView is not used here is that it may cause page to move.
|
|
|
|
|
+ */
|
|
|
|
|
+ const destParent = destNode.parentNode as HTMLDivElement;
|
|
|
|
|
+ destParent.scrollTop = destNode.offsetTop -
|
|
|
|
|
+ destParent.offsetTop -
|
|
|
|
|
+ (destParent.clientHeight / 2) +
|
|
|
|
|
+ (destNode.clientHeight / 2);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -718,6 +742,7 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<List
|
|
<List
|
|
|
|
|
+ ref={this.virtualizeListRef}
|
|
|
height={height || numbers.LIST_HEIGHT}
|
|
height={height || numbers.LIST_HEIGHT}
|
|
|
itemCount={visibileOptions.length}
|
|
itemCount={visibileOptions.length}
|
|
|
itemSize={itemSize}
|
|
itemSize={itemSize}
|
|
@@ -761,7 +786,7 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
|
|
|
|
|
const isEmpty = !options.length || !options.some(item => item._show);
|
|
const isEmpty = !options.length || !options.some(item => item._show);
|
|
|
return (
|
|
return (
|
|
|
- <div className={dropdownClassName} style={style}>
|
|
|
|
|
|
|
+ <div id={`${prefixcls}-${this.selectOptionListID}`} className={dropdownClassName} style={style}>
|
|
|
{outerTopSlot}
|
|
{outerTopSlot}
|
|
|
<div
|
|
<div
|
|
|
style={{ maxHeight: `${maxHeight}px` }}
|
|
style={{ maxHeight: `${maxHeight}px` }}
|
|
@@ -894,6 +919,27 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
this.foundation.handleMouseLeave(e as any);
|
|
this.foundation.handleMouseLeave(e as any);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /* Processing logic when popover visible changes */
|
|
|
|
|
+ handlePopoverVisibleChange(status) {
|
|
|
|
|
+ const { virtualize } = this.props;
|
|
|
|
|
+ const { selections } = this.state;
|
|
|
|
|
+ if (!status) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (virtualize) {
|
|
|
|
|
+ let minKey;
|
|
|
|
|
+ selections.forEach((v, k) => {
|
|
|
|
|
+ const tempKey = Number(String(k).match(/option-(.*)/)[1]);
|
|
|
|
|
+ minKey = (typeof minKey === 'number' && minKey < tempKey) ? minKey : tempKey;
|
|
|
|
|
+ });
|
|
|
|
|
+ if (minKey) {
|
|
|
|
|
+ this.virtualizeListRef.current.scrollToItem(minKey, 'center');
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.foundation.updateScrollTop();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
renderSuffix() {
|
|
renderSuffix() {
|
|
|
const { suffix } = this.props;
|
|
const { suffix } = this.props;
|
|
|
const suffixWrapperCls = cls({
|
|
const suffixWrapperCls = cls({
|
|
@@ -1053,6 +1099,7 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
position={position}
|
|
position={position}
|
|
|
spacing={spacing}
|
|
spacing={spacing}
|
|
|
stopPropagation={stopPropagation}
|
|
stopPropagation={stopPropagation}
|
|
|
|
|
+ onVisibleChange={status => this.handlePopoverVisibleChange(status)}
|
|
|
>
|
|
>
|
|
|
{selection}
|
|
{selection}
|
|
|
</Popover>
|
|
</Popover>
|