This commit is contained in:
2026-05-25 17:08:18 +08:00
parent df501f6151
commit f1259b71b5
9178 changed files with 1626125 additions and 0 deletions
@@ -0,0 +1,4 @@
import * as React from 'react';
import type { SharedContentProps } from '.';
declare const _default: React.ForwardRefExoticComponent<SharedContentProps & React.RefAttributes<HTMLInputElement>>;
export default _default;
@@ -0,0 +1,158 @@
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import * as React from 'react';
import { clsx } from 'clsx';
import Overflow from '@rc-component/overflow';
import Input from "../Input";
import { useSelectInputContext } from "../context";
import TransBtn from "../../TransBtn";
import { getTitle } from "../../utils/commonUtil";
import useBaseProps from "../../hooks/useBaseProps";
import Placeholder from "./Placeholder";
function itemKey(value) {
return value.key ?? value.value;
}
const onPreventMouseDown = event => {
event.preventDefault();
event.stopPropagation();
};
export default /*#__PURE__*/React.forwardRef(function MultipleContent({
inputProps
}, ref) {
const {
prefixCls,
displayValues,
searchValue,
mode,
onSelectorRemove,
removeIcon: removeIconFromContext
} = useSelectInputContext();
const {
disabled,
showSearch,
triggerOpen,
rawOpen,
toggleOpen,
autoClearSearchValue,
tagRender: tagRenderFromContext,
maxTagPlaceholder: maxTagPlaceholderFromContext,
maxTagTextLength,
maxTagCount,
classNames,
styles
} = useBaseProps();
const selectionItemPrefixCls = `${prefixCls}-selection-item`;
// ===================== Search ======================
// Apply autoClearSearchValue logic: when dropdown is closed and autoClearSearchValue is not false (default true), clear search value
// Use rawOpen to avoid clearing search when emptyListContent blocks open
let computedSearchValue = searchValue;
if (!rawOpen && mode === 'multiple' && autoClearSearchValue !== false) {
computedSearchValue = '';
}
const inputValue = showSearch ? computedSearchValue || '' : '';
const inputEditable = showSearch && !disabled;
// Props from context with safe defaults
const removeIcon = removeIconFromContext ?? '×';
const maxTagPlaceholder = maxTagPlaceholderFromContext ?? (omittedValues => `+ ${omittedValues.length} ...`);
const tagRender = tagRenderFromContext;
const onToggleOpen = newOpen => {
toggleOpen(newOpen);
};
const onRemove = value => {
onSelectorRemove?.(value);
};
// ======================== Item ========================
// >>> Render Selector Node. Includes Item & Rest
const defaultRenderSelector = (item, content, itemDisabled, closable, onClose) => /*#__PURE__*/React.createElement("span", {
title: getTitle(item),
className: clsx(selectionItemPrefixCls, {
[`${selectionItemPrefixCls}-disabled`]: itemDisabled
}, classNames?.item),
style: styles?.item
}, /*#__PURE__*/React.createElement("span", {
className: clsx(`${selectionItemPrefixCls}-content`, classNames?.itemContent),
style: styles?.itemContent
}, content), closable && /*#__PURE__*/React.createElement(TransBtn, {
className: clsx(`${selectionItemPrefixCls}-remove`, classNames?.itemRemove),
style: styles?.itemRemove,
onMouseDown: onPreventMouseDown,
onClick: onClose,
customizeIcon: removeIcon
}, "\xD7"));
const customizeRenderSelector = (value, content, itemDisabled, closable, onClose, isMaxTag, info) => {
const onMouseDown = e => {
onPreventMouseDown(e);
onToggleOpen(!triggerOpen);
};
return /*#__PURE__*/React.createElement("span", {
onMouseDown: onMouseDown
}, tagRender({
label: content,
value,
index: info?.index,
disabled: itemDisabled,
closable,
onClose,
isMaxTag: !!isMaxTag
}));
};
// ====================== Overflow ======================
const renderItem = (valueItem, info) => {
const {
disabled: itemDisabled,
label,
value
} = valueItem;
const closable = !disabled && !itemDisabled;
let displayLabel = label;
if (typeof maxTagTextLength === 'number') {
if (typeof label === 'string' || typeof label === 'number') {
const strLabel = String(displayLabel);
if (strLabel.length > maxTagTextLength) {
displayLabel = `${strLabel.slice(0, maxTagTextLength)}...`;
}
}
}
const onClose = event => {
if (event) {
event.stopPropagation();
}
onRemove(valueItem);
};
return typeof tagRender === 'function' ? customizeRenderSelector(value, displayLabel, itemDisabled, closable, onClose, undefined, info) : defaultRenderSelector(valueItem, displayLabel, itemDisabled, closable, onClose);
};
const renderRest = omittedValues => {
// https://github.com/ant-design/ant-design/issues/48930
if (!displayValues.length) {
return null;
}
const content = typeof maxTagPlaceholder === 'function' ? maxTagPlaceholder(omittedValues) : maxTagPlaceholder;
return typeof tagRender === 'function' ? customizeRenderSelector(undefined, content, false, false, undefined, true) : defaultRenderSelector({
title: content
}, content, false);
};
// ======================= Render =======================
return /*#__PURE__*/React.createElement(Overflow, {
prefixCls: `${prefixCls}-content`,
className: classNames?.content,
style: styles?.content,
prefix: !displayValues.length && !inputValue && /*#__PURE__*/React.createElement(Placeholder, null),
data: displayValues,
renderItem: renderItem,
renderRest: renderRest,
suffix: /*#__PURE__*/React.createElement(Input, _extends({
ref: ref,
disabled: disabled,
readOnly: !inputEditable
}, inputProps, {
value: inputValue || '',
syncWidth: true
})),
itemKey: itemKey,
maxCount: maxTagCount
});
});
@@ -0,0 +1,5 @@
import * as React from 'react';
export interface PlaceholderProps {
show?: boolean;
}
export default function Placeholder(props: PlaceholderProps): React.JSX.Element;
@@ -0,0 +1,28 @@
import * as React from 'react';
import { clsx } from 'clsx';
import { useSelectInputContext } from "../context";
import useBaseProps from "../../hooks/useBaseProps";
export default function Placeholder(props) {
const {
prefixCls,
placeholder,
displayValues
} = useSelectInputContext();
const {
classNames,
styles
} = useBaseProps();
const {
show = true
} = props;
if (displayValues.length) {
return null;
}
return /*#__PURE__*/React.createElement("div", {
className: clsx(`${prefixCls}-placeholder`, classNames?.placeholder),
style: {
visibility: show ? 'visible' : 'hidden',
...styles?.placeholder
}
}, placeholder);
}
@@ -0,0 +1,4 @@
import * as React from 'react';
import type { SharedContentProps } from '.';
declare const SingleContent: React.ForwardRefExoticComponent<SharedContentProps & React.RefAttributes<HTMLInputElement>>;
export default SingleContent;
@@ -0,0 +1,102 @@
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import * as React from 'react';
import { clsx } from 'clsx';
import Input from "../Input";
import { useSelectInputContext } from "../context";
import useBaseProps from "../../hooks/useBaseProps";
import Placeholder from "./Placeholder";
import SelectContext from "../../SelectContext";
import { getTitle } from "../../utils/commonUtil";
const SingleContent = /*#__PURE__*/React.forwardRef(({
inputProps
}, ref) => {
const {
prefixCls,
searchValue,
activeValue,
displayValues,
maxLength,
mode,
components
} = useSelectInputContext();
const {
triggerOpen,
title: rootTitle,
showSearch,
classNames,
styles
} = useBaseProps();
const selectContext = React.useContext(SelectContext);
const [inputChanged, setInputChanged] = React.useState(false);
const combobox = mode === 'combobox';
const displayValue = displayValues[0];
// Implement the same logic as the old SingleSelector
const mergedSearchValue = React.useMemo(() => {
if (combobox && activeValue && !inputChanged && triggerOpen) {
return activeValue;
}
return showSearch ? searchValue : '';
}, [combobox, activeValue, inputChanged, triggerOpen, searchValue, showSearch]);
const [optionClassName, optionStyle, optionTitle, hasOptionStyle] = React.useMemo(() => {
let className;
let style;
let titleValue;
if (displayValue && selectContext?.flattenOptions) {
const option = selectContext.flattenOptions.find(opt => opt.value === displayValue.value);
if (option?.data) {
className = option.data.className;
style = option.data.style;
titleValue = getTitle(option.data);
}
}
if (displayValue && !titleValue) {
titleValue = getTitle(displayValue);
}
if (rootTitle !== undefined) {
titleValue = rootTitle;
}
const nextHasStyle = !!className || !!style;
return [className, style, titleValue, nextHasStyle];
}, [displayValue, selectContext?.flattenOptions, rootTitle]);
React.useEffect(() => {
if (combobox) {
setInputChanged(false);
}
}, [combobox, activeValue]);
// ========================== Render ==========================
const showHasValueCls = displayValue && displayValue.label !== null && displayValue.label !== undefined && String(displayValue.label).trim() !== '';
// Render value
// Only render value when not using custom input in combobox mode
const shouldRenderValue = !(combobox && components?.input);
const renderValue = shouldRenderValue ? displayValue ? hasOptionStyle ? /*#__PURE__*/React.createElement("div", {
className: clsx(`${prefixCls}-content-value`, optionClassName),
style: {
...(mergedSearchValue ? {
visibility: 'hidden'
} : {}),
...optionStyle
},
title: optionTitle
}, displayValue.label) : displayValue.label : /*#__PURE__*/React.createElement(Placeholder, {
show: !mergedSearchValue
}) : null;
// Render
return /*#__PURE__*/React.createElement("div", {
className: clsx(`${prefixCls}-content`, showHasValueCls && `${prefixCls}-content-has-value`, mergedSearchValue && `${prefixCls}-content-has-search-value`, hasOptionStyle && `${prefixCls}-content-has-option-style`, classNames?.content),
style: styles?.content,
title: hasOptionStyle ? undefined : optionTitle
}, renderValue, /*#__PURE__*/React.createElement(Input, _extends({
ref: ref
}, inputProps, {
value: mergedSearchValue,
maxLength: mode === 'combobox' ? maxLength : undefined,
onChange: e => {
setInputChanged(true);
inputProps.onChange?.(e);
}
})));
});
export default SingleContent;
@@ -0,0 +1,6 @@
import * as React from 'react';
export interface SharedContentProps {
inputProps: React.InputHTMLAttributes<HTMLInputElement>;
}
declare const SelectContent: React.ForwardRefExoticComponent<React.RefAttributes<HTMLInputElement>>;
export default SelectContent;
@@ -0,0 +1,37 @@
import * as React from 'react';
import pickAttrs from "@rc-component/util/es/pickAttrs";
import SingleContent from "./SingleContent";
import MultipleContent from "./MultipleContent";
import { useSelectInputContext } from "../context";
import useBaseProps from "../../hooks/useBaseProps";
const SelectContent = /*#__PURE__*/React.forwardRef(function SelectContent(_, ref) {
const {
multiple,
onInputKeyDown,
tabIndex
} = useSelectInputContext();
const baseProps = useBaseProps();
const {
showSearch
} = baseProps;
const ariaProps = pickAttrs(baseProps, {
aria: true
});
const sharedInputProps = {
...ariaProps,
onKeyDown: onInputKeyDown,
readOnly: !showSearch,
tabIndex
};
if (multiple) {
return /*#__PURE__*/React.createElement(MultipleContent, {
ref: ref,
inputProps: sharedInputProps
});
}
return /*#__PURE__*/React.createElement(SingleContent, {
ref: ref,
inputProps: sharedInputProps
});
});
export default SelectContent;