1
This commit is contained in:
Generated
Vendored
+4
@@ -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;
|
||||
Generated
Vendored
+158
@@ -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
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import * as React from 'react';
|
||||
export interface PlaceholderProps {
|
||||
show?: boolean;
|
||||
}
|
||||
export default function Placeholder(props: PlaceholderProps): React.JSX.Element;
|
||||
Generated
Vendored
+28
@@ -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);
|
||||
}
|
||||
Generated
Vendored
+4
@@ -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;
|
||||
Generated
Vendored
+102
@@ -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;
|
||||
Generated
Vendored
+6
@@ -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;
|
||||
Generated
Vendored
+37
@@ -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;
|
||||
Reference in New Issue
Block a user