Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/components/select/base/Option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface SelectOptionProps
optionLength?: number;
isVirtual?: boolean;
onRowMounted?: (rowData: { ref: HTMLElement; data: SelectOption }) => void;
isKeyboardHovered?: boolean;
}

const componentType = 'select';
Expand All @@ -57,6 +58,7 @@ const Option: React.FC<SelectOptionProps> = (props) => {
style,
className,
isVirtual,
isKeyboardHovered,
} = props;

const label = propLabel || value;
Expand Down Expand Up @@ -164,6 +166,7 @@ const Option: React.FC<SelectOptionProps> = (props) => {
[`${classPrefix}-is-selected`]: selected,
[`${classPrefix}-size-s`]: size === 'small',
[`${classPrefix}-size-l`]: size === 'large',
[`${classPrefix}-${componentType}-option__hover`]: isKeyboardHovered,
})}
key={value}
onClick={handleSelect}
Expand Down
68 changes: 34 additions & 34 deletions packages/components/select/base/PopupContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { isEqual } from 'lodash-es';
import useConfig from '../../hooks/useConfig';
import { useLocaleReceiver } from '../../locale/LocalReceiver';
import usePanelVirtualScroll from '../hooks/usePanelVirtualScroll';
import { getSelectValueArr } from '../util/helper';
import { getKeyMapping, getSelectValueArr } from '../util/helper';
import Option, { type SelectOptionProps } from './Option';
import OptionGroup from './OptionGroup';

Expand Down Expand Up @@ -46,6 +46,8 @@ interface SelectPopupProps
trigger: SelectValueChangeTrigger;
},
) => void;
hoverIndex: number;
children?: React.ReactNode;
/**
* 是否展示popup
*/
Expand All @@ -54,7 +56,6 @@ interface SelectPopupProps
* 控制popup展示的函数
*/
setShowPopup: (show: boolean) => void;
children?: React.ReactNode;
onCheckAllChange?: (checkAll: boolean, e: React.MouseEvent<HTMLLIElement>) => void;
getPopupInstance?: () => HTMLDivElement;
}
Expand All @@ -80,13 +81,14 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
getPopupInstance,
options: propsOptions,
scroll: propsScroll,
hoverIndex,
} = props;
const { classPrefix } = useConfig();

// 国际化文本初始化
const [local, t] = useLocaleReceiver('select');
const emptyText = t(local.empty);
const popupContentRef = useRef<HTMLDivElement>(null);

const popupContentRef = useRef<HTMLDivElement>(null);
popupContentRef.current = getPopupInstance();

const { visibleData, handleRowMounted, isVirtual, panelStyle, cursorStyle } = usePanelVirtualScroll({
Expand All @@ -96,6 +98,9 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
size,
});

const isObjectType = useMemo(() => valueType === 'object', [valueType]);
const { valueKey, labelKey } = useMemo(() => getKeyMapping(keys), [keys]);

const optionsExcludedCheckAll = useMemo(() => {
const uniqueOptions = {};
propsOptions?.forEach((option: SelectOption) => {
Expand All @@ -112,36 +117,18 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
return Object.values(uniqueOptions);
}, [propsOptions]);

const { classPrefix } = useConfig();
if (!children && !propsOptions) {
return null;
}

const onSelect: SelectOptionProps['onSelect'] = (selectedValue, { label, selected, event, restData }) => {
const isValObj = valueType === 'object';
let objVal = {};
if (isValObj) {
objVal = { ...restData };
if (!keys?.label) {
Object.assign(objVal, { label });
}
if (!keys?.value) {
Object.assign(objVal, { value: selectedValue });
}
}

if (!Object.keys(objVal).length) {
Object.assign(objVal, { [keys?.label || 'label']: label, [keys?.value || 'value']: selectedValue });
}
const objVal = {
...(isObjectType ? { ...restData } : {}),
[labelKey]: label,
[valueKey]: selectedValue,
};

if (multiple) {
// calc multiple select values
const values = getSelectValueArr(value, selectedValue, selected, valueType, keys, objVal);
onChange(values, { label, value: selectedValue, e: event, trigger: selected ? 'uncheck' : 'check' });
} else {
// calc single select value
const selectVal = valueType === 'object' ? objVal : selectedValue;

if (!isEqual(value, selectVal)) {
onChange(selectVal, { label, value: selectVal, e: event, trigger: 'check' });
}
Expand All @@ -157,27 +144,38 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
return child;
});

const isEmpty =
(Array.isArray(childrenWithProps) && !childrenWithProps.length) || (propsOptions && propsOptions.length === 0);

// 渲染 options
const renderOptions = (options: SelectOption[]) => {
const renderOptions = (options: SelectOption[], startIndex = 0) => {
if (options) {
let currentIndex = startIndex;
// 通过 options API配置的
return (
<ul className={`${classPrefix}-select__list`}>
{options.map((item, index) => {
const { group, divider, ...rest } = item as SelectOptionGroup;
if (group) {
return (
const groupElement = (
<OptionGroup label={group} divider={divider} key={index} {...rest}>
{renderOptions(rest.children)}
{renderOptions(rest.children, currentIndex)}
</OptionGroup>
);
// group 的 children 数量需要累加
currentIndex += rest.children.length;
return groupElement;
}

const { value: optionValue, label, disabled, children, ...restData } = item as TdOptionProps;
// 当 keys 属性配置 content 作为 value 或 label 时,确保 restData 中也包含它, 不参与渲染计算
const { content } = item as TdOptionProps;
const shouldOmitContent = Object.values(keys || {}).includes('content');
return (

const isKeyboardHovered = hoverIndex === currentIndex;
currentIndex += 1;

const optionElement = (
<Option
key={index}
max={max}
Expand All @@ -191,6 +189,7 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
disabled={disabled}
restData={restData}
keys={keys}
isKeyboardHovered={isKeyboardHovered}
onCheckAllChange={onCheckAllChange}
onRowMounted={handleRowMounted}
{...(isVirtual
Expand All @@ -206,16 +205,14 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
{children}
</Option>
);
return optionElement;
})}
</ul>
);
}
return <ul className={`${classPrefix}-select__list`}>{childrenWithProps}</ul>;
};

const isEmpty =
(Array.isArray(childrenWithProps) && !childrenWithProps.length) || (propsOptions && propsOptions.length === 0);

const renderPanel = (renderedOptions: SelectOption[], extraStyle?: React.CSSProperties) => (
<div
ref={ref}
Expand All @@ -233,6 +230,7 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
{!loading && !isEmpty && renderOptions(renderedOptions)}
</div>
);

if (isVirtual) {
return (
<>
Expand All @@ -246,6 +244,8 @@ const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props,
);
}

if (!children && !propsOptions) return null;

return (
<>
{panelTopContent}
Expand Down
Loading
Loading