Skip to content

Commit 1ded65d

Browse files
committed
feat: support classnames and styles
1 parent e8096c0 commit 1ded65d

File tree

5 files changed

+58
-4
lines changed

5 files changed

+58
-4
lines changed

src/BaseSelect/index.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { getSeparatedContent, isValidCount } from '../utils/valueUtil';
3030
import SelectContext from '../SelectContext';
3131
import type { SelectContextProps } from '../SelectContext';
3232
import Polite from './Polite';
33+
import { SemanticName } from '../Select';
3334

3435
export type {
3536
DisplayInfoType,
@@ -131,6 +132,8 @@ export type BaseSelectPropsWithoutPrivate = Omit<BaseSelectProps, keyof BaseSele
131132
export interface BaseSelectProps extends BaseSelectPrivateProps, React.AriaAttributes {
132133
className?: string;
133134
style?: React.CSSProperties;
135+
classNames?: Partial<Record<SemanticName, string>>;
136+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
134137
title?: string;
135138
showSearch?: boolean;
136139
tagRender?: (props: CustomTagProps) => React.ReactElement;
@@ -291,6 +294,9 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
291294
onKeyDown,
292295
onMouseDown,
293296

297+
classNames: selectClassNames,
298+
styles,
299+
294300
// Rest Props
295301
...restProps
296302
} = props;
@@ -720,9 +726,10 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
720726
if (showSuffixIcon) {
721727
arrowNode = (
722728
<TransBtn
723-
className={classNames(`${prefixCls}-arrow`, {
729+
className={classNames(`${prefixCls}-arrow`, selectClassNames?.suffix, {
724730
[`${prefixCls}-arrow-loading`]: loading,
725731
})}
732+
style={styles?.suffix}
726733
customizeIcon={suffixIcon}
727734
customizeIconProps={{
728735
loading,
@@ -812,6 +819,8 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
812819
) : (
813820
<Selector
814821
{...props}
822+
prefixClassName={selectClassNames?.prefix}
823+
prefixStyle={styles?.prefix}
815824
domRef={selectorDomRef}
816825
prefixCls={prefixCls}
817826
inputElement={customizeInputElement}

src/Select.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export type SelectHandler<ValueType, OptionType extends BaseOptionType = Default
107107

108108
type ArrayElementType<T> = T extends (infer E)[] ? E : T;
109109

110+
export type SemanticName = 'prefix' | 'suffix';
110111
export interface SelectProps<ValueType = any, OptionType extends BaseOptionType = DefaultOptionType>
111112
extends BaseSelectPropsWithoutPrivate {
112113
prefixCls?: string;
@@ -157,6 +158,8 @@ export interface SelectProps<ValueType = any, OptionType extends BaseOptionType
157158
defaultValue?: ValueType | null;
158159
maxCount?: number;
159160
onChange?: (value: ValueType, option?: OptionType | OptionType[]) => void;
161+
classNames?: Partial<Record<SemanticName, string>>;
162+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
160163
}
161164

162165
function isRawValue(value: DraftValueType): value is RawValueType {

src/Selector/index.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import useLock from '../hooks/useLock';
1717
import { isValidateOpenKey } from '../utils/keyUtil';
1818
import MultipleSelector from './MultipleSelector';
1919
import SingleSelector from './SingleSelector';
20+
import classNames from 'classnames';
2021

2122
export interface InnerSelectorProps {
2223
prefixCls: string;
@@ -54,6 +55,8 @@ export interface RefSelectorProps {
5455
}
5556

5657
export interface SelectorProps {
58+
prefixClassName: string;
59+
prefixStyle: React.CSSProperties;
5760
id: string;
5861
prefixCls: string;
5962
showSearch?: boolean;
@@ -107,6 +110,8 @@ const Selector: React.ForwardRefRenderFunction<RefSelectorProps, SelectorProps>
107110
const compositionStatusRef = useRef<boolean>(false);
108111

109112
const {
113+
prefixClassName,
114+
prefixStyle,
110115
prefixCls,
111116
open,
112117
mode,
@@ -290,7 +295,11 @@ const Selector: React.ForwardRefRenderFunction<RefSelectorProps, SelectorProps>
290295
onClick={onClick}
291296
onMouseDown={onMouseDown}
292297
>
293-
{prefix && <div className={`${prefixCls}-prefix`}>{prefix}</div>}
298+
{prefix && (
299+
<div className={classNames(`${prefixCls}-prefix`, prefixClassName)} style={prefixStyle}>
300+
{prefix}
301+
</div>
302+
)}
294303
{selectNode}
295304
</div>
296305
);

src/TransBtn.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { RenderNode } from './BaseSelect';
44

55
export interface TransBtnProps {
66
className: string;
7+
style?: React.CSSProperties;
78
customizeIcon: RenderNode;
89
customizeIconProps?: any;
910
onMouseDown?: React.MouseEventHandler<HTMLSpanElement>;
@@ -12,7 +13,8 @@ export interface TransBtnProps {
1213
}
1314

1415
const TransBtn: React.FC<TransBtnProps> = (props) => {
15-
const { className, customizeIcon, customizeIconProps, children, onMouseDown, onClick } = props;
16+
const { className, style, customizeIcon, customizeIconProps, children, onMouseDown, onClick } =
17+
props;
1618

1719
const icon =
1820
typeof customizeIcon === 'function' ? customizeIcon(customizeIconProps) : customizeIcon;
@@ -24,7 +26,7 @@ const TransBtn: React.FC<TransBtnProps> = (props) => {
2426
event.preventDefault();
2527
onMouseDown?.(event);
2628
}}
27-
style={{ userSelect: 'none', WebkitUserSelect: 'none' }}
29+
style={{ userSelect: 'none', WebkitUserSelect: 'none', ...style }}
2830
unselectable="on"
2931
onClick={onClick}
3032
aria-hidden

tests/Select.test.tsx

+31
Original file line numberDiff line numberDiff line change
@@ -2417,4 +2417,35 @@ describe('Select.Basic', () => {
24172417
expect(onBlur).toHaveBeenCalledTimes(2);
24182418
expect(inputElem.value).toEqual('bb');
24192419
});
2420+
it('support classnames and styles', () => {
2421+
const customClassNames = {
2422+
prefix: 'cutsom-prefix',
2423+
suffix: 'custom-suffix',
2424+
};
2425+
const customStyle = {
2426+
prefix: { color: 'red' },
2427+
suffix: { color: 'green' },
2428+
};
2429+
const { container } = render(
2430+
<Select
2431+
open
2432+
classNames={customClassNames}
2433+
styles={customStyle}
2434+
suffixIcon={<div>arrow</div>}
2435+
prefix="Foobar"
2436+
value={['bamboo']}
2437+
mode="multiple"
2438+
options={[
2439+
{ value: 'jack', label: 'Jack' },
2440+
{ value: 'lucy', label: 'Lucy' },
2441+
]}
2442+
/>,
2443+
);
2444+
const prefix = container.querySelector('.rc-select-prefix');
2445+
const suffix = container.querySelector('.rc-select-arrow');
2446+
expect(prefix).toHaveClass('cutsom-prefix');
2447+
expect(prefix).toHaveStyle('color: red');
2448+
expect(suffix).toHaveClass('custom-suffix');
2449+
expect(suffix).toHaveStyle('color: green');
2450+
});
24202451
});

0 commit comments

Comments
 (0)