Browse Source

chore: code style optimization (#43478)

* chore: code style optimization

* add type
pull/43496/head
lijianan 1 year ago
committed by GitHub
parent
commit
2d9f7de524
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 62
      components/alert/Alert.tsx
  2. 174
      components/carousel/index.tsx
  3. 74
      components/checkbox/Group.tsx
  4. 2
      components/dropdown/dropdown.tsx
  5. 295
      components/layout/Sider.tsx
  6. 7
      components/popconfirm/PurePanel.tsx
  7. 7
      components/transfer/ListItem.tsx

62
components/alert/Alert.tsx

@ -96,25 +96,27 @@ const CloseIcon: React.FC<CloseIconProps> = (props) => {
) : null;
};
const Alert: React.FC<AlertProps> = ({
description,
prefixCls: customizePrefixCls,
message,
banner,
className,
rootClassName,
style,
onMouseEnter,
onMouseLeave,
onClick,
afterClose,
showIcon,
closable,
closeText,
closeIcon,
action,
...props
}) => {
const Alert: React.FC<AlertProps> = (props) => {
const {
description,
prefixCls: customizePrefixCls,
message,
banner,
className,
rootClassName,
style,
onMouseEnter,
onMouseLeave,
onClick,
afterClose,
showIcon,
closable,
closeText,
closeIcon,
action,
...otherProps
} = props;
const [closed, setClosed] = React.useState(false);
if (process.env.NODE_ENV !== 'production') {
warning(!closeText, 'Alert', '`closeText` is deprecated. Please use `closeIcon` instead.');
@ -129,14 +131,13 @@ const Alert: React.FC<AlertProps> = ({
props.onClose?.(e);
};
const getType = () => {
const { type } = props;
if (type !== undefined) {
return type;
const type = React.useMemo<AlertProps['type']>(() => {
if (props.type !== undefined) {
return props.type;
}
// banner mode defaults to 'warning'
return banner ? 'warning' : 'info';
};
}, [props.type, banner]);
// closeable when closeText or closeIcon is assigned
const isClosable = React.useMemo(() => {
@ -150,8 +151,6 @@ const Alert: React.FC<AlertProps> = ({
return closeIcon !== false && closeIcon !== null && closeIcon !== undefined;
}, [closeText, closeIcon, closable]);
const type = getType();
// banner mode defaults to Icon
const isShowIcon = banner && showIcon === undefined ? true : showIcon;
@ -170,10 +169,7 @@ const Alert: React.FC<AlertProps> = ({
hashId,
);
const dataOrAriaProps = pickAttrs(props, {
aria: true,
data: true,
});
const restProps = pickAttrs(otherProps, { aria: true, data: true });
return wrapSSR(
<CSSMotion
@ -181,9 +177,7 @@ const Alert: React.FC<AlertProps> = ({
motionName={`${prefixCls}-motion`}
motionAppear={false}
motionEnter={false}
onLeaveStart={(node) => ({
maxHeight: node.offsetHeight,
})}
onLeaveStart={(node) => ({ maxHeight: node.offsetHeight })}
onLeaveEnd={afterClose}
>
{({ className: motionClassName, style: motionStyle }) => (
@ -196,7 +190,7 @@ const Alert: React.FC<AlertProps> = ({
onMouseLeave={onMouseLeave}
onClick={onClick}
role="alert"
{...dataOrAriaProps}
{...restProps}
>
{isShowIcon ? (
<IconNode

174
components/carousel/index.tsx

@ -29,98 +29,94 @@ export interface CarouselRef {
innerSlider: any;
}
const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
(
{
dots = true,
arrows = false,
draggable = false,
waitForAnimate = false,
dotPosition = 'bottom',
vertical = dotPosition === 'left' || dotPosition === 'right',
rootClassName,
className: customClassName,
style,
...props
},
const Carousel = React.forwardRef<CarouselRef, CarouselProps>((props, ref) => {
const {
dots = true,
arrows = false,
draggable = false,
waitForAnimate = false,
dotPosition = 'bottom',
vertical = dotPosition === 'left' || dotPosition === 'right',
rootClassName,
className: customClassName,
style,
...otherProps
} = props;
const { getPrefixCls, direction, carousel } = React.useContext(ConfigContext);
const slickRef = React.useRef<any>();
const goTo = (slide: number, dontAnimate = false) => {
slickRef.current.slickGoTo(slide, dontAnimate);
};
React.useImperativeHandle(
ref,
) => {
const { getPrefixCls, direction, carousel } = React.useContext(ConfigContext);
const slickRef = React.useRef<any>();
const goTo = (slide: number, dontAnimate = false) => {
slickRef.current.slickGoTo(slide, dontAnimate);
};
React.useImperativeHandle(
ref,
() => ({
goTo,
autoPlay: slickRef.current.innerSlider.autoPlay,
innerSlider: slickRef.current.innerSlider,
prev: slickRef.current.slickPrev,
next: slickRef.current.slickNext,
}),
[slickRef.current],
);
const prevCount = React.useRef(React.Children.count(props.children));
React.useEffect(() => {
if (prevCount.current !== React.Children.count(props.children)) {
goTo(props.initialSlide || 0, false);
prevCount.current = React.Children.count(props.children);
}
}, [props.children]);
const newProps = {
vertical,
className: classNames(customClassName, carousel?.className),
style: { ...carousel?.style, ...style },
...props,
};
if (newProps.effect === 'fade') {
newProps.fade = true;
() => ({
goTo,
autoPlay: slickRef.current.innerSlider.autoPlay,
innerSlider: slickRef.current.innerSlider,
prev: slickRef.current.slickPrev,
next: slickRef.current.slickNext,
}),
[slickRef.current],
);
const prevCount = React.useRef(React.Children.count(props.children));
React.useEffect(() => {
if (prevCount.current !== React.Children.count(props.children)) {
goTo(props.initialSlide || 0, false);
prevCount.current = React.Children.count(props.children);
}
}, [props.children]);
const newProps = {
vertical,
className: classNames(customClassName, carousel?.className),
style: { ...carousel?.style, ...style },
...otherProps,
};
if (newProps.effect === 'fade') {
newProps.fade = true;
}
const prefixCls = getPrefixCls('carousel', newProps.prefixCls);
const dotsClass = 'slick-dots';
const prefixCls = getPrefixCls('carousel', newProps.prefixCls);
const dotsClass = 'slick-dots';
const enableDots = !!dots;
const dsClass = classNames(
dotsClass,
`${dotsClass}-${dotPosition}`,
typeof dots === 'boolean' ? false : dots?.className,
);
const [wrapSSR, hashId] = useStyle(prefixCls);
const className = classNames(
prefixCls,
{
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-vertical`]: newProps.vertical,
},
hashId,
rootClassName,
);
return wrapSSR(
<div className={className}>
<SlickCarousel
ref={slickRef}
{...newProps}
dots={enableDots}
dotsClass={dsClass}
arrows={arrows}
draggable={draggable}
waitForAnimate={waitForAnimate}
/>
</div>,
);
},
);
const enableDots = !!dots;
const dsClass = classNames(
dotsClass,
`${dotsClass}-${dotPosition}`,
typeof dots === 'boolean' ? false : dots?.className,
);
const [wrapSSR, hashId] = useStyle(prefixCls);
const className = classNames(
prefixCls,
{
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-vertical`]: newProps.vertical,
},
hashId,
rootClassName,
);
return wrapSSR(
<div className={className}>
<SlickCarousel
ref={slickRef}
{...newProps}
dots={enableDots}
dotsClass={dsClass}
arrows={arrows}
draggable={draggable}
waitForAnimate={waitForAnimate}
/>
</div>,
);
});
if (process.env.NODE_ENV !== 'production') {
Carousel.displayName = 'Carousel';

74
components/checkbox/Group.tsx

@ -36,8 +36,11 @@ export interface CheckboxGroupProps extends AbstractCheckboxGroupProps {
children?: React.ReactNode;
}
const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGroupProps> = (
{
const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGroupProps> = (
props,
ref,
) => {
const {
defaultValue,
children,
options = [],
@ -47,9 +50,7 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
style,
onChange,
...restProps
},
ref,
) => {
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const [value, setValue] = React.useState<CheckboxValueType[]>(
@ -63,16 +64,16 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
}
}, [restProps.value]);
const getOptions = () =>
options.map((option) => {
if (typeof option === 'string' || typeof option === 'number') {
return {
label: option,
value: option,
};
}
return option;
});
const memoOptions = React.useMemo(
() =>
options.map<CheckboxOptionType>((option) => {
if (typeof option === 'string' || typeof option === 'number') {
return { label: option, value: option };
}
return option;
}),
[options],
);
const cancelValue = (val: string) => {
setRegisteredValues((prevValues) => prevValues.filter((v) => v !== val));
@ -93,13 +94,12 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
if (!('value' in restProps)) {
setValue(newValue);
}
const opts = getOptions();
onChange?.(
newValue
.filter((val) => registeredValues.includes(val))
.sort((a, b) => {
const indexA = opts.findIndex((opt) => opt.value === a);
const indexB = opts.findIndex((opt) => opt.value === b);
const indexA = memoOptions.findIndex((opt) => opt.value === a);
const indexB = memoOptions.findIndex((opt) => opt.value === b);
return indexA - indexB;
}),
);
@ -112,23 +112,23 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
const domProps = omit(restProps, ['value', 'disabled']);
if (options && options.length > 0) {
children = getOptions().map((option) => (
<Checkbox
prefixCls={prefixCls}
key={option.value.toString()}
disabled={'disabled' in option ? option.disabled : restProps.disabled}
value={option.value}
checked={value.includes(option.value)}
onChange={option.onChange}
className={`${groupPrefixCls}-item`}
style={option.style}
title={option.title}
>
{option.label}
</Checkbox>
));
}
const childrenNode = options.length
? memoOptions.map<React.ReactNode>((option) => (
<Checkbox
prefixCls={prefixCls}
key={option.value.toString()}
disabled={'disabled' in option ? option.disabled : restProps.disabled}
value={option.value}
checked={value.includes(option.value)}
onChange={option.onChange}
className={`${groupPrefixCls}-item`}
style={option.style}
title={option.title}
>
{option.label}
</Checkbox>
))
: children;
// eslint-disable-next-line react/jsx-no-constructed-context-values
const context = {
@ -151,7 +151,7 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
);
return wrapSSR(
<div className={classString} style={style} {...domProps} ref={ref}>
<GroupContext.Provider value={context}>{children}</GroupContext.Provider>
<GroupContext.Provider value={context}>{childrenNode}</GroupContext.Provider>
</div>,
);
};
@ -159,6 +159,6 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction<HTMLDivElement, Chec
export type { CheckboxGroupContext } from './GroupContext';
export { GroupContext };
const CheckboxGroup = React.forwardRef<HTMLDivElement, CheckboxGroupProps>(InternalCheckboxGroup);
const CheckboxGroup = React.forwardRef<HTMLDivElement, CheckboxGroupProps>(InternalGroup);
export default React.memo(CheckboxGroup);

2
components/dropdown/dropdown.tsx

@ -318,7 +318,7 @@ function postPureProps(props: DropdownProps) {
const PurePanel = genPurePanel(Dropdown, 'dropdown', (prefixCls) => prefixCls, postPureProps);
/* istanbul ignore next */
const WrapPurePanel = (props: DropdownProps) => (
const WrapPurePanel: React.FC<DropdownProps> = (props) => (
<PurePanel {...props}>
<span />
</PurePanel>

295
components/layout/Sider.tsx

@ -6,8 +6,8 @@ import omit from 'rc-util/lib/omit';
import * as React from 'react';
import { useContext, useEffect, useRef, useState } from 'react';
import { ConfigContext } from '../config-provider';
import isNumeric from '../_util/isNumeric';
import { ConfigContext } from '../config-provider';
import { LayoutContext } from './layout';
const dimensionMaxMap = {
@ -58,172 +58,161 @@ const generateId = (() => {
};
})();
const Sider = React.forwardRef<HTMLDivElement, SiderProps>(
(
{
prefixCls: customizePrefixCls,
className,
trigger,
children,
defaultCollapsed = false,
theme = 'dark',
style = {},
collapsible = false,
reverseArrow = false,
width = 200,
collapsedWidth = 80,
zeroWidthTriggerStyle,
breakpoint,
onCollapse,
onBreakpoint,
...props
},
ref,
) => {
const { siderHook } = useContext(LayoutContext);
const [collapsed, setCollapsed] = useState(
'collapsed' in props ? props.collapsed : defaultCollapsed,
);
const [below, setBelow] = useState(false);
useEffect(() => {
if ('collapsed' in props) {
setCollapsed(props.collapsed);
}
}, [props.collapsed]);
const handleSetCollapsed = (value: boolean, type: CollapseType) => {
if (!('collapsed' in props)) {
setCollapsed(value);
}
onCollapse?.(value, type);
};
const Sider = React.forwardRef<HTMLDivElement, SiderProps>((props, ref) => {
const {
prefixCls: customizePrefixCls,
className,
trigger,
children,
defaultCollapsed = false,
theme = 'dark',
style = {},
collapsible = false,
reverseArrow = false,
width = 200,
collapsedWidth = 80,
zeroWidthTriggerStyle,
breakpoint,
onCollapse,
onBreakpoint,
...otherProps
} = props;
const { siderHook } = useContext(LayoutContext);
const [collapsed, setCollapsed] = useState(
'collapsed' in props ? props.collapsed : defaultCollapsed,
);
const [below, setBelow] = useState(false);
useEffect(() => {
if ('collapsed' in props) {
setCollapsed(props.collapsed);
}
}, [props.collapsed]);
const handleSetCollapsed = (value: boolean, type: CollapseType) => {
if (!('collapsed' in props)) {
setCollapsed(value);
}
onCollapse?.(value, type);
};
// ========================= Responsive =========================
const responsiveHandlerRef = useRef<(mql: MediaQueryListEvent | MediaQueryList) => void>();
responsiveHandlerRef.current = (mql: MediaQueryListEvent | MediaQueryList) => {
setBelow(mql.matches);
onBreakpoint?.(mql.matches);
// ========================= Responsive =========================
const responsiveHandlerRef = useRef<(mql: MediaQueryListEvent | MediaQueryList) => void>();
responsiveHandlerRef.current = (mql: MediaQueryListEvent | MediaQueryList) => {
setBelow(mql.matches);
onBreakpoint?.(mql.matches);
if (collapsed !== mql.matches) {
handleSetCollapsed(mql.matches, 'responsive');
}
};
if (collapsed !== mql.matches) {
handleSetCollapsed(mql.matches, 'responsive');
}
};
useEffect(() => {
function responsiveHandler(mql: MediaQueryListEvent | MediaQueryList) {
return responsiveHandlerRef.current!(mql);
}
useEffect(() => {
function responsiveHandler(mql: MediaQueryListEvent | MediaQueryList) {
return responsiveHandlerRef.current!(mql);
}
let mql: MediaQueryList;
if (typeof window !== 'undefined') {
const { matchMedia } = window;
if (matchMedia! && breakpoint && breakpoint in dimensionMaxMap) {
mql = matchMedia(`(max-width: ${dimensionMaxMap[breakpoint]})`);
try {
mql.addEventListener('change', responsiveHandler);
} catch (error) {
mql.addListener(responsiveHandler);
}
responsiveHandler(mql);
}
}
return () => {
let mql: MediaQueryList;
if (typeof window !== 'undefined') {
const { matchMedia } = window;
if (matchMedia! && breakpoint && breakpoint in dimensionMaxMap) {
mql = matchMedia(`(max-width: ${dimensionMaxMap[breakpoint]})`);
try {
mql?.removeEventListener('change', responsiveHandler);
mql.addEventListener('change', responsiveHandler);
} catch (error) {
mql?.removeListener(responsiveHandler);
mql.addListener(responsiveHandler);
}
};
}, [breakpoint]); // in order to accept dynamic 'breakpoint' property, we need to add 'breakpoint' into dependency array.
responsiveHandler(mql);
}
}
return () => {
try {
mql?.removeEventListener('change', responsiveHandler);
} catch (error) {
mql?.removeListener(responsiveHandler);
}
};
}, [breakpoint]); // in order to accept dynamic 'breakpoint' property, we need to add 'breakpoint' into dependency array.
useEffect(() => {
const uniqueId = generateId('ant-sider-');
siderHook.addSider(uniqueId);
return () => siderHook.removeSider(uniqueId);
}, []);
useEffect(() => {
const uniqueId = generateId('ant-sider-');
siderHook.addSider(uniqueId);
return () => siderHook.removeSider(uniqueId);
}, []);
const toggle = () => {
handleSetCollapsed(!collapsed, 'clickTrigger');
};
const toggle = () => {
handleSetCollapsed(!collapsed, 'clickTrigger');
};
const { getPrefixCls } = useContext(ConfigContext);
const renderSider = () => {
const prefixCls = getPrefixCls('layout-sider', customizePrefixCls);
const divProps = omit(props, ['collapsed']);
const rawWidth = collapsed ? collapsedWidth : width;
// use "px" as fallback unit for width
const siderWidth = isNumeric(rawWidth) ? `${rawWidth}px` : String(rawWidth);
// special trigger when collapsedWidth == 0
const zeroWidthTrigger =
parseFloat(String(collapsedWidth || 0)) === 0 ? (
<span
onClick={toggle}
className={classNames(
`${prefixCls}-zero-width-trigger`,
`${prefixCls}-zero-width-trigger-${reverseArrow ? 'right' : 'left'}`,
)}
style={zeroWidthTriggerStyle}
>
{trigger || <BarsOutlined />}
</span>
) : null;
const iconObj = {
expanded: reverseArrow ? <RightOutlined /> : <LeftOutlined />,
collapsed: reverseArrow ? <LeftOutlined /> : <RightOutlined />,
};
const status = collapsed ? 'collapsed' : 'expanded';
const defaultTrigger = iconObj[status];
const triggerDom =
trigger !== null
? zeroWidthTrigger || (
<div
className={`${prefixCls}-trigger`}
onClick={toggle}
style={{ width: siderWidth }}
>
{trigger || defaultTrigger}
</div>
)
: null;
const divStyle = {
...style,
flex: `0 0 ${siderWidth}`,
maxWidth: siderWidth, // Fix width transition bug in IE11
minWidth: siderWidth, // https://github.com/ant-design/ant-design/issues/6349
width: siderWidth,
};
const siderCls = classNames(
prefixCls,
`${prefixCls}-${theme}`,
{
[`${prefixCls}-collapsed`]: !!collapsed,
[`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger,
[`${prefixCls}-below`]: !!below,
[`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0,
},
className,
);
return (
<aside className={siderCls} {...divProps} style={divStyle} ref={ref}>
<div className={`${prefixCls}-children`}>{children}</div>
{collapsible || (below && zeroWidthTrigger) ? triggerDom : null}
</aside>
);
const { getPrefixCls } = useContext(ConfigContext);
const renderSider = () => {
const prefixCls = getPrefixCls('layout-sider', customizePrefixCls);
const divProps = omit(otherProps, ['collapsed']);
const rawWidth = collapsed ? collapsedWidth : width;
// use "px" as fallback unit for width
const siderWidth = isNumeric(rawWidth) ? `${rawWidth}px` : String(rawWidth);
// special trigger when collapsedWidth == 0
const zeroWidthTrigger =
parseFloat(String(collapsedWidth || 0)) === 0 ? (
<span
onClick={toggle}
className={classNames(
`${prefixCls}-zero-width-trigger`,
`${prefixCls}-zero-width-trigger-${reverseArrow ? 'right' : 'left'}`,
)}
style={zeroWidthTriggerStyle}
>
{trigger || <BarsOutlined />}
</span>
) : null;
const iconObj = {
expanded: reverseArrow ? <RightOutlined /> : <LeftOutlined />,
collapsed: reverseArrow ? <LeftOutlined /> : <RightOutlined />,
};
const status = collapsed ? 'collapsed' : 'expanded';
const defaultTrigger = iconObj[status];
const triggerDom =
trigger !== null
? zeroWidthTrigger || (
<div className={`${prefixCls}-trigger`} onClick={toggle} style={{ width: siderWidth }}>
{trigger || defaultTrigger}
</div>
)
: null;
const divStyle: React.CSSProperties = {
...style,
flex: `0 0 ${siderWidth}`,
maxWidth: siderWidth, // Fix width transition bug in IE11
minWidth: siderWidth, // https://github.com/ant-design/ant-design/issues/6349
width: siderWidth,
};
const contextValue = React.useMemo(
() => ({
siderCollapsed: collapsed,
}),
[collapsed],
const siderCls = classNames(
prefixCls,
`${prefixCls}-${theme}`,
{
[`${prefixCls}-collapsed`]: !!collapsed,
[`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger,
[`${prefixCls}-below`]: !!below,
[`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0,
},
className,
);
return (
<aside className={siderCls} {...divProps} style={divStyle} ref={ref}>
<div className={`${prefixCls}-children`}>{children}</div>
{collapsible || (below && zeroWidthTrigger) ? triggerDom : null}
</aside>
);
};
const contextValue = React.useMemo(() => ({ siderCollapsed: collapsed }), [collapsed]);
return <SiderContext.Provider value={contextValue}>{renderSider()}</SiderContext.Provider>;
},
);
return <SiderContext.Provider value={contextValue}>{renderSider()}</SiderContext.Provider>;
});
if (process.env.NODE_ENV !== 'production') {
Sider.displayName = 'Sider';

7
components/popconfirm/PurePanel.tsx

@ -10,7 +10,6 @@ import { ConfigContext } from '../config-provider';
import { useLocale } from '../locale';
import defaultLocale from '../locale/en_US';
import PopoverPurePanel from '../popover/PurePanel';
import useStyle from './style';
export interface PopconfirmLocale {
@ -100,7 +99,7 @@ export interface PurePanelProps
prefixCls?: string;
}
export default function PurePanel(props: PurePanelProps) {
const PurePanel: React.FC<PurePanelProps> = (props) => {
const { prefixCls: customizePrefixCls, placement, className, style, ...restProps } = props;
const { getPrefixCls } = React.useContext(ConfigContext);
@ -115,4 +114,6 @@ export default function PurePanel(props: PurePanelProps) {
content={<Overlay prefixCls={prefixCls} {...restProps} />}
/>,
);
}
};
export default PurePanel;

7
components/transfer/ListItem.tsx

@ -2,10 +2,10 @@ import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
import classNames from 'classnames';
import * as React from 'react';
import type { KeyWiseTransferItem } from '.';
import TransButton from '../_util/transButton';
import Checkbox from '../checkbox';
import defaultLocale from '../locale/en_US';
import { useLocale } from '../locale';
import TransButton from '../_util/transButton';
import defaultLocale from '../locale/en_US';
type ListItemProps<RecordType> = {
renderedText?: string | number;
@ -32,8 +32,7 @@ const ListItem = <RecordType extends KeyWiseTransferItem>(props: ListItemProps<R
showRemove,
} = props;
const className = classNames({
[`${prefixCls}-content-item`]: true,
const className = classNames(`${prefixCls}-content-item`, {
[`${prefixCls}-content-item-disabled`]: disabled || item.disabled,
[`${prefixCls}-content-item-checked`]: checked,
});

Loading…
Cancel
Save