Skip to content

Commit

Permalink
feat: support classnames and styles
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkasany committed Feb 25, 2025
1 parent e8096c0 commit 1ded65d
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 4 deletions.
11 changes: 10 additions & 1 deletion src/BaseSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { getSeparatedContent, isValidCount } from '../utils/valueUtil';
import SelectContext from '../SelectContext';
import type { SelectContextProps } from '../SelectContext';
import Polite from './Polite';
import { SemanticName } from '../Select';

export type {
DisplayInfoType,
Expand Down Expand Up @@ -131,6 +132,8 @@ export type BaseSelectPropsWithoutPrivate = Omit<BaseSelectProps, keyof BaseSele
export interface BaseSelectProps extends BaseSelectPrivateProps, React.AriaAttributes {
className?: string;
style?: React.CSSProperties;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
title?: string;
showSearch?: boolean;
tagRender?: (props: CustomTagProps) => React.ReactElement;
Expand Down Expand Up @@ -291,6 +294,9 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
onKeyDown,
onMouseDown,

classNames: selectClassNames,
styles,

// Rest Props
...restProps
} = props;
Expand Down Expand Up @@ -720,9 +726,10 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
if (showSuffixIcon) {
arrowNode = (
<TransBtn
className={classNames(`${prefixCls}-arrow`, {
className={classNames(`${prefixCls}-arrow`, selectClassNames?.suffix, {
[`${prefixCls}-arrow-loading`]: loading,
})}
style={styles?.suffix}
customizeIcon={suffixIcon}
customizeIconProps={{
loading,
Expand Down Expand Up @@ -812,6 +819,8 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
) : (
<Selector
{...props}
prefixClassName={selectClassNames?.prefix}
prefixStyle={styles?.prefix}
domRef={selectorDomRef}
prefixCls={prefixCls}
inputElement={customizeInputElement}
Expand Down
3 changes: 3 additions & 0 deletions src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export type SelectHandler<ValueType, OptionType extends BaseOptionType = Default

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

export type SemanticName = 'prefix' | 'suffix';
export interface SelectProps<ValueType = any, OptionType extends BaseOptionType = DefaultOptionType>
extends BaseSelectPropsWithoutPrivate {
prefixCls?: string;
Expand Down Expand Up @@ -157,6 +158,8 @@ export interface SelectProps<ValueType = any, OptionType extends BaseOptionType
defaultValue?: ValueType | null;
maxCount?: number;
onChange?: (value: ValueType, option?: OptionType | OptionType[]) => void;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
}

function isRawValue(value: DraftValueType): value is RawValueType {
Expand Down
11 changes: 10 additions & 1 deletion src/Selector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import useLock from '../hooks/useLock';
import { isValidateOpenKey } from '../utils/keyUtil';
import MultipleSelector from './MultipleSelector';
import SingleSelector from './SingleSelector';
import classNames from 'classnames';

export interface InnerSelectorProps {
prefixCls: string;
Expand Down Expand Up @@ -54,6 +55,8 @@ export interface RefSelectorProps {
}

export interface SelectorProps {
prefixClassName: string;
prefixStyle: React.CSSProperties;
id: string;
prefixCls: string;
showSearch?: boolean;
Expand Down Expand Up @@ -107,6 +110,8 @@ const Selector: React.ForwardRefRenderFunction<RefSelectorProps, SelectorProps>
const compositionStatusRef = useRef<boolean>(false);

const {
prefixClassName,
prefixStyle,
prefixCls,
open,
mode,
Expand Down Expand Up @@ -290,7 +295,11 @@ const Selector: React.ForwardRefRenderFunction<RefSelectorProps, SelectorProps>
onClick={onClick}
onMouseDown={onMouseDown}
>
{prefix && <div className={`${prefixCls}-prefix`}>{prefix}</div>}
{prefix && (
<div className={classNames(`${prefixCls}-prefix`, prefixClassName)} style={prefixStyle}>
{prefix}
</div>
)}
{selectNode}
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/TransBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { RenderNode } from './BaseSelect';

export interface TransBtnProps {
className: string;
style?: React.CSSProperties;
customizeIcon: RenderNode;
customizeIconProps?: any;
onMouseDown?: React.MouseEventHandler<HTMLSpanElement>;
Expand All @@ -12,7 +13,8 @@ export interface TransBtnProps {
}

const TransBtn: React.FC<TransBtnProps> = (props) => {
const { className, customizeIcon, customizeIconProps, children, onMouseDown, onClick } = props;
const { className, style, customizeIcon, customizeIconProps, children, onMouseDown, onClick } =
props;

const icon =
typeof customizeIcon === 'function' ? customizeIcon(customizeIconProps) : customizeIcon;
Expand All @@ -24,7 +26,7 @@ const TransBtn: React.FC<TransBtnProps> = (props) => {
event.preventDefault();
onMouseDown?.(event);
}}
style={{ userSelect: 'none', WebkitUserSelect: 'none' }}
style={{ userSelect: 'none', WebkitUserSelect: 'none', ...style }}
unselectable="on"
onClick={onClick}
aria-hidden
Expand Down
31 changes: 31 additions & 0 deletions tests/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2417,4 +2417,35 @@ describe('Select.Basic', () => {
expect(onBlur).toHaveBeenCalledTimes(2);
expect(inputElem.value).toEqual('bb');
});
it('support classnames and styles', () => {
const customClassNames = {
prefix: 'cutsom-prefix',
suffix: 'custom-suffix',
};
const customStyle = {
prefix: { color: 'red' },
suffix: { color: 'green' },
};
const { container } = render(
<Select
open
classNames={customClassNames}
styles={customStyle}
suffixIcon={<div>arrow</div>}
prefix="Foobar"
value={['bamboo']}
mode="multiple"
options={[
{ value: 'jack', label: 'Jack' },
{ value: 'lucy', label: 'Lucy' },
]}
/>,
);
const prefix = container.querySelector('.rc-select-prefix');
const suffix = container.querySelector('.rc-select-arrow');
expect(prefix).toHaveClass('cutsom-prefix');
expect(prefix).toHaveStyle('color: red');
expect(suffix).toHaveClass('custom-suffix');
expect(suffix).toHaveStyle('color: green');
});
});

0 comments on commit 1ded65d

Please sign in to comment.