feat: update vittual-list
parent
b9f9dad4c7
commit
f6752899e2
|
@ -1 +1 @@
|
|||
Subproject commit 955716e4e9533bc628c651d6ba6c8d1eb9b21a9d
|
||||
Subproject commit 79d49c0ff31a4f505ccd5bc3ad238c08f9925212
|
|
@ -0,0 +1,69 @@
|
|||
const attributes = `accept acceptCharset accessKey action allowFullScreen allowTransparency
|
||||
alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
|
||||
charSet checked classID className colSpan cols content contentEditable contextMenu
|
||||
controls coords crossOrigin data dateTime default defer dir disabled download draggable
|
||||
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity
|
||||
is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media
|
||||
mediaGroup method min minLength multiple muted name noValidate nonce open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required
|
||||
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
|
||||
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
|
||||
summary tabIndex target title type useMap value width wmode wrap`;
|
||||
|
||||
const eventsName = `onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown
|
||||
onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick
|
||||
onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown
|
||||
onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel
|
||||
onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough
|
||||
onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata
|
||||
onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`;
|
||||
|
||||
const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/);
|
||||
|
||||
/* eslint-enable max-len */
|
||||
const ariaPrefix = 'aria-';
|
||||
const dataPrefix = 'data-';
|
||||
|
||||
function match(key, prefix) {
|
||||
return key.indexOf(prefix) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Picker props from exist props with filter
|
||||
* @param props Passed props
|
||||
* @param ariaOnly boolean | { aria?: boolean; data?: boolean; attr?: boolean; } filter config
|
||||
*/
|
||||
export default function pickAttrs(props, ariaOnly = false) {
|
||||
let mergedConfig;
|
||||
if (ariaOnly === false) {
|
||||
mergedConfig = {
|
||||
aria: true,
|
||||
data: true,
|
||||
attr: true,
|
||||
};
|
||||
} else if (ariaOnly === true) {
|
||||
mergedConfig = {
|
||||
aria: true,
|
||||
};
|
||||
} else {
|
||||
mergedConfig = {
|
||||
...ariaOnly,
|
||||
};
|
||||
}
|
||||
|
||||
const attrs = {};
|
||||
Object.keys(props).forEach(key => {
|
||||
if (
|
||||
// Aria
|
||||
(mergedConfig.aria && (key === 'role' || match(key, ariaPrefix))) ||
|
||||
// Data
|
||||
(mergedConfig.data && match(key, dataPrefix)) ||
|
||||
// Attr
|
||||
(mergedConfig.attr && propList.includes(key))
|
||||
) {
|
||||
attrs[key] = props[key];
|
||||
}
|
||||
});
|
||||
return attrs;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import PropTypes from '../_util/vue-types';
|
||||
export default {
|
||||
props: {
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
},
|
||||
isSelectOptGroup: true,
|
||||
render() {
|
||||
return null;
|
||||
},
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
import PropTypes from '../_util/vue-types';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
disabled: PropTypes.bool,
|
||||
title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
},
|
||||
isSelectOption: true,
|
||||
render() {
|
||||
return null;
|
||||
},
|
||||
};
|
|
@ -0,0 +1,348 @@
|
|||
import TransBtn from './TransBtn';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import KeyCode from '../_util/KeyCode';
|
||||
import classNames from '../_util/classNames';
|
||||
import pickAttrs from '../_util/pickAttrs';
|
||||
import { isValidElement } from '../_util/props-util';
|
||||
import createRef from '../_util/createRef';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import List from '../vc-virtual-list/List';
|
||||
|
||||
const OptionListProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
options: PropTypes.array,
|
||||
flattenOptions: PropTypes.array,
|
||||
height: PropTypes.number,
|
||||
itemHeight: PropTypes.number,
|
||||
values: PropTypes.any,
|
||||
multiple: PropTypes.bool,
|
||||
open: PropTypes.bool,
|
||||
defaultActiveFirstOption: PropTypes.bool,
|
||||
notFoundContent: PropTypes.any,
|
||||
menuItemSelectedIcon: PropTypes.any,
|
||||
childrenAsData: PropTypes.bool,
|
||||
searchValue: PropTypes.string,
|
||||
virtual: PropTypes.bool,
|
||||
|
||||
onSelect: PropTypes.func,
|
||||
onToggleOpen: PropTypes.func,
|
||||
/** Tell Select that some value is now active to make accessibility work */
|
||||
onActiveValue: PropTypes.func,
|
||||
onScroll: PropTypes.func,
|
||||
|
||||
/** Tell Select that mouse enter the popup to force re-render */
|
||||
onMouseenter: PropTypes.func,
|
||||
};
|
||||
|
||||
/**
|
||||
* Using virtual list of option display.
|
||||
* Will fallback to dom if use customize render.
|
||||
*/
|
||||
const OptionList = {
|
||||
props: OptionListProps,
|
||||
name: 'OptionList',
|
||||
inheritAttrs: false,
|
||||
setup(props) {
|
||||
const itemPrefixCls = computed(() => `${props.prefixCls}-item`);
|
||||
|
||||
// =========================== List ===========================
|
||||
const listRef = createRef();
|
||||
|
||||
const onListMouseDown = event => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const scrollIntoView = index => {
|
||||
if (listRef.current) {
|
||||
listRef.current.scrollTo({ index });
|
||||
}
|
||||
};
|
||||
|
||||
// ========================== Active ==========================
|
||||
const getEnabledActiveIndex = (index, offset = 1) => {
|
||||
const len = props.flattenOptions.length;
|
||||
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
const current = (index + i * offset + len) % len;
|
||||
|
||||
const { group, data } = props.flattenOptions[current];
|
||||
if (!group && !data.disabled) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
const state = reactive({
|
||||
activeIndex: getEnabledActiveIndex(0),
|
||||
});
|
||||
|
||||
const setActive = (index, fromKeyboard = false) => {
|
||||
state.activeIndex = index;
|
||||
const info = { source: fromKeyboard ? 'keyboard' : 'mouse' };
|
||||
|
||||
// Trigger active event
|
||||
const flattenItem = props.flattenOptions[index];
|
||||
if (!flattenItem) {
|
||||
props.onActiveValue(null, -1, info);
|
||||
return;
|
||||
}
|
||||
|
||||
props.onActiveValue(flattenItem.data.value, index, info);
|
||||
};
|
||||
|
||||
// Auto active first item when list length or searchValue changed
|
||||
|
||||
watch([props.flattenOptions.length, props.searchValue], () => {
|
||||
setActive(props.defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1);
|
||||
});
|
||||
// Auto scroll to item position in single mode
|
||||
watch(props.open, () => {
|
||||
/**
|
||||
* React will skip `onChange` when component update.
|
||||
* `setActive` function will call root accessibility state update which makes re-render.
|
||||
* So we need to delay to let Input component trigger onChange first.
|
||||
*/
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (!props.multiple && props.open && props.values.size === 1) {
|
||||
const value = Array.from(props.values)[0];
|
||||
const index = props.flattenOptions.findIndex(({ data }) => data.value === value);
|
||||
setActive(index);
|
||||
scrollIntoView(index);
|
||||
}
|
||||
});
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
});
|
||||
|
||||
// ========================== Values ==========================
|
||||
const onSelectValue = value => {
|
||||
if (value !== undefined) {
|
||||
props.onSelect(value, { selected: !props.values.has(value) });
|
||||
}
|
||||
|
||||
// Single mode should always close by select
|
||||
if (!props.multiple) {
|
||||
props.onToggleOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
function renderItem(index) {
|
||||
const item = props.flattenOptions[index];
|
||||
if (!item) return null;
|
||||
|
||||
const itemData = item.data || {};
|
||||
const { value, label, children } = itemData;
|
||||
const attrs = pickAttrs(itemData, true);
|
||||
const mergedLabel = props.childrenAsData ? children : label;
|
||||
return item ? (
|
||||
<div
|
||||
aria-label={typeof mergedLabel === 'string' ? mergedLabel : null}
|
||||
{...attrs}
|
||||
key={index}
|
||||
role="option"
|
||||
id={`${props.id}_list_${index}`}
|
||||
aria-selected={props.values.has(value)}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
return {
|
||||
renderItem,
|
||||
listRef,
|
||||
state,
|
||||
onListMouseDown,
|
||||
itemPrefixCls,
|
||||
setActive,
|
||||
onSelectValue,
|
||||
onKeydown: event => {
|
||||
const { which } = event;
|
||||
switch (which) {
|
||||
// >>> Arrow keys
|
||||
case KeyCode.UP:
|
||||
case KeyCode.DOWN: {
|
||||
let offset = 0;
|
||||
if (which === KeyCode.UP) {
|
||||
offset = -1;
|
||||
} else if (which === KeyCode.DOWN) {
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
if (offset !== 0) {
|
||||
const nextActiveIndex = getEnabledActiveIndex(state.activeIndex + offset, offset);
|
||||
scrollIntoView(nextActiveIndex);
|
||||
setActive(nextActiveIndex, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// >>> Select
|
||||
case KeyCode.ENTER: {
|
||||
// value
|
||||
const item = props.flattenOptions[state.activeIndex];
|
||||
if (item && !item.data.disabled) {
|
||||
onSelectValue(item.data.value);
|
||||
} else {
|
||||
onSelectValue(undefined);
|
||||
}
|
||||
|
||||
if (props.open) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// >>> Close
|
||||
case KeyCode.ESC: {
|
||||
props.onToggleOpen(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onKeyup: () => {},
|
||||
|
||||
scrollTo: index => {
|
||||
scrollIntoView(index);
|
||||
},
|
||||
};
|
||||
},
|
||||
render() {
|
||||
const { renderItem, listRef, onListMouseDown, itemPrefixCls, setActive, onSelectValue } = this;
|
||||
const {
|
||||
id,
|
||||
childrenAsData,
|
||||
values,
|
||||
height,
|
||||
itemHeight,
|
||||
flattenOptions,
|
||||
menuItemSelectedIcon,
|
||||
notFoundContent,
|
||||
virtual,
|
||||
onScroll,
|
||||
onMouseenter,
|
||||
} = this.$props;
|
||||
const { activeIndex } = this.state;
|
||||
// ========================== Render ==========================
|
||||
if (flattenOptions.length === 0) {
|
||||
return (
|
||||
<div
|
||||
role="listbox"
|
||||
id={`${id}_list`}
|
||||
class={`${itemPrefixCls}-empty`}
|
||||
onMousedown={onListMouseDown}
|
||||
>
|
||||
{notFoundContent}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div role="listbox" id={`${id}_list`} style={{ height: 0, width: 0, overflow: 'hidden' }}>
|
||||
{renderItem(activeIndex - 1)}
|
||||
{renderItem(activeIndex)}
|
||||
{renderItem(activeIndex + 1)}
|
||||
</div>
|
||||
<List
|
||||
itemKey="key"
|
||||
ref={listRef}
|
||||
data={flattenOptions}
|
||||
height={height}
|
||||
itemHeight={itemHeight}
|
||||
fullHeight={false}
|
||||
onMousedown={onListMouseDown}
|
||||
onScroll={onScroll}
|
||||
virtual={virtual}
|
||||
onMouseenter={onMouseenter}
|
||||
>
|
||||
{({ group, groupOption, data }, itemIndex) => {
|
||||
const { label, key } = data;
|
||||
|
||||
// Group
|
||||
if (group) {
|
||||
return (
|
||||
<div class={classNames(itemPrefixCls, `${itemPrefixCls}-group`)}>
|
||||
{label !== undefined ? label : key}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
disabled,
|
||||
value,
|
||||
title,
|
||||
children,
|
||||
style,
|
||||
class: cls,
|
||||
className,
|
||||
...otherProps
|
||||
} = data;
|
||||
|
||||
// Option
|
||||
const selected = values.has(value);
|
||||
|
||||
const optionPrefixCls = `${itemPrefixCls}-option`;
|
||||
const optionClassName = classNames(itemPrefixCls, optionPrefixCls, cls, className, {
|
||||
[`${optionPrefixCls}-grouped`]: groupOption,
|
||||
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !disabled,
|
||||
[`${optionPrefixCls}-disabled`]: disabled,
|
||||
[`${optionPrefixCls}-selected`]: selected,
|
||||
});
|
||||
|
||||
const mergedLabel = childrenAsData ? children : label;
|
||||
|
||||
const iconVisible =
|
||||
!menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected;
|
||||
|
||||
const content = mergedLabel || value;
|
||||
// https://github.com/ant-design/ant-design/issues/26717
|
||||
let optionTitle =
|
||||
typeof content === 'string' || typeof content === 'number'
|
||||
? content.toString()
|
||||
: undefined;
|
||||
if (title !== undefined) {
|
||||
optionTitle = title;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
{...otherProps}
|
||||
aria-selected={selected}
|
||||
class={optionClassName}
|
||||
title={optionTitle}
|
||||
onMousemove={() => {
|
||||
if (activeIndex === itemIndex || disabled) {
|
||||
return;
|
||||
}
|
||||
setActive(itemIndex);
|
||||
}}
|
||||
onClick={() => {
|
||||
if (!disabled) {
|
||||
onSelectValue(value);
|
||||
}
|
||||
}}
|
||||
style={style}
|
||||
>
|
||||
<div class={`${optionPrefixCls}-content`}>{content}</div>
|
||||
{isValidElement(menuItemSelectedIcon) || selected}
|
||||
{iconVisible && (
|
||||
<TransBtn
|
||||
class={`${itemPrefixCls}-option-state`}
|
||||
customizeIcon={menuItemSelectedIcon}
|
||||
customizeIconProps={{ isSelected: selected }}
|
||||
>
|
||||
{selected ? '✓' : null}
|
||||
</TransBtn>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default OptionList;
|
|
@ -0,0 +1,144 @@
|
|||
import Trigger from '../vc-trigger';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { getSlot } from '../_util/props-util';
|
||||
import classNames from '../_util/classNames';
|
||||
import createRef from '../_util/createRef';
|
||||
|
||||
const getBuiltInPlacements = dropdownMatchSelectWidth => {
|
||||
// Enable horizontal overflow auto-adjustment when a custom dropdown width is provided
|
||||
const adjustX = typeof dropdownMatchSelectWidth !== 'number' ? 0 : 1;
|
||||
|
||||
return {
|
||||
bottomLeft: {
|
||||
points: ['tl', 'bl'],
|
||||
offset: [0, 4],
|
||||
overflow: {
|
||||
adjustX,
|
||||
adjustY: 1,
|
||||
},
|
||||
},
|
||||
bottomRight: {
|
||||
points: ['tr', 'br'],
|
||||
offset: [0, 4],
|
||||
overflow: {
|
||||
adjustX,
|
||||
adjustY: 1,
|
||||
},
|
||||
},
|
||||
topLeft: {
|
||||
points: ['bl', 'tl'],
|
||||
offset: [0, -4],
|
||||
overflow: {
|
||||
adjustX,
|
||||
adjustY: 1,
|
||||
},
|
||||
},
|
||||
topRight: {
|
||||
points: ['br', 'tr'],
|
||||
offset: [0, -4],
|
||||
overflow: {
|
||||
adjustX,
|
||||
adjustY: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'SelectTrigger',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
// onPopupFocus: PropTypes.func,
|
||||
// onPopupScroll: PropTypes.func,
|
||||
dropdownAlign: PropTypes.object,
|
||||
visible: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
dropdownClassName: PropTypes.string,
|
||||
dropdownStyle: PropTypes.object,
|
||||
empty: PropTypes.bool,
|
||||
prefixCls: PropTypes.string,
|
||||
popupClassName: PropTypes.string,
|
||||
// children: PropTypes.any,
|
||||
animation: PropTypes.string,
|
||||
transitionName: PropTypes.string,
|
||||
getPopupContainer: PropTypes.func,
|
||||
dropdownRender: PropTypes.func,
|
||||
containerWidth: PropTypes.number,
|
||||
dropdownMatchSelectWidth: PropTypes.oneOfType([Number, Boolean]).def(true),
|
||||
popupElement: PropTypes.any,
|
||||
direction: PropTypes.string,
|
||||
getTriggerDOMNode: PropTypes.func,
|
||||
},
|
||||
|
||||
created() {
|
||||
this.popupRef = createRef();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getDropdownTransitionName() {
|
||||
const props = this.$props;
|
||||
let transitionName = props.transitionName;
|
||||
if (!transitionName && props.animation) {
|
||||
transitionName = `${this.getDropdownPrefixCls()}-${props.animation}`;
|
||||
}
|
||||
return transitionName;
|
||||
},
|
||||
getPopupElement() {
|
||||
return this.popupRef.current;
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const { empty, ...props } = { ...this.$props, ...this.$attrs };
|
||||
const {
|
||||
visible,
|
||||
dropdownAlign,
|
||||
prefixCls,
|
||||
popupElement,
|
||||
dropdownClassName,
|
||||
dropdownStyle,
|
||||
dropdownMatchSelectWidth,
|
||||
containerWidth,
|
||||
dropdownRender,
|
||||
} = props;
|
||||
const dropdownPrefixCls = `${prefixCls}-dropdown`;
|
||||
|
||||
let popupNode = popupElement;
|
||||
if (dropdownRender) {
|
||||
popupNode = dropdownRender({ menuNode: popupElement, props });
|
||||
}
|
||||
|
||||
const builtInPlacements = getBuiltInPlacements(dropdownMatchSelectWidth);
|
||||
const popupStyle = { minWidth: containerWidth, ...dropdownStyle };
|
||||
|
||||
if (typeof dropdownMatchSelectWidth === 'number') {
|
||||
popupStyle.width = `${dropdownMatchSelectWidth}px`;
|
||||
} else if (dropdownMatchSelectWidth) {
|
||||
popupStyle.width = `${containerWidth}px`;
|
||||
}
|
||||
return (
|
||||
<Trigger
|
||||
{...props}
|
||||
showAction={[]}
|
||||
hideAction={[]}
|
||||
popupPlacement={this.direction === 'rtl' ? 'bottomRight' : 'bottomLeft'}
|
||||
popupPlacement="bottomLeft"
|
||||
builtinPlacements={builtInPlacements}
|
||||
prefixCls={dropdownPrefixCls}
|
||||
popupTransitionName={this.getDropdownTransitionName()}
|
||||
onPopupVisibleChange={props.onDropdownVisibleChange}
|
||||
popup={<div ref={this.popupRef}>{popupNode}</div>}
|
||||
popupAlign={dropdownAlign}
|
||||
popupVisible={visible}
|
||||
getPopupContainer={props.getPopupContainer}
|
||||
popupClassName={classNames(dropdownClassName, {
|
||||
[`${dropdownPrefixCls}-empty`]: empty,
|
||||
})}
|
||||
popupStyle={popupStyle}
|
||||
getTriggerDOMNode={this.getTriggerDOMNode}
|
||||
>
|
||||
{getSlot(this)[0]}
|
||||
</Trigger>
|
||||
);
|
||||
},
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
const TransBtn = (
|
||||
_,
|
||||
{ attrs: { class: className, customizeIcon, customizeIconProps, onMousedown, onClick }, slots },
|
||||
) => {
|
||||
let icon;
|
||||
|
||||
if (typeof customizeIcon === 'function') {
|
||||
icon = customizeIcon(customizeIconProps);
|
||||
} else {
|
||||
icon = customizeIcon;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
class={className}
|
||||
onMousedown={event => {
|
||||
event.preventDefault();
|
||||
if (onMousedown) {
|
||||
onMousedown(event);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
userSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
}}
|
||||
unselectable="on"
|
||||
onClick={onClick}
|
||||
aria-hidden
|
||||
>
|
||||
{icon !== undefined ? (
|
||||
icon
|
||||
) : (
|
||||
<span class={className.split(/\s+/).map(cls => `${cls}-icon`)}>{slots?.default()}</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
TransBtn.inheritAttrs = false;
|
||||
|
||||
export default TransBtn;
|
|
@ -0,0 +1,9 @@
|
|||
// based on vc-select 9.2.2
|
||||
import Select from './Select';
|
||||
import Option from './Option';
|
||||
import { SelectPropTypes } from './PropTypes';
|
||||
import OptGroup from './OptGroup';
|
||||
Select.Option = Option;
|
||||
Select.OptGroup = OptGroup;
|
||||
export { Select, Option, OptGroup, SelectPropTypes };
|
||||
export default Select;
|
|
@ -282,7 +282,6 @@ const List = {
|
|||
};
|
||||
},
|
||||
render() {
|
||||
const { style, class: className } = this.$attrs;
|
||||
const {
|
||||
prefixCls = 'rc-virtual-list',
|
||||
height,
|
||||
|
@ -295,8 +294,10 @@ const List = {
|
|||
component: Component = 'div',
|
||||
onScroll,
|
||||
children,
|
||||
style,
|
||||
class: className,
|
||||
...restProps
|
||||
} = this.$props;
|
||||
} = { ...this.$props, ...this.$attrs };
|
||||
const mergedClassName = classNames(prefixCls, className);
|
||||
const { scrollTop, mergedData } = this.state;
|
||||
const { scrollHeight, offset, start, end } = this.calRes;
|
||||
|
|
Loading…
Reference in New Issue