2023-09-11 17:28:04 +08:00
|
|
|
|
import * as React from 'react';
|
2018-08-05 07:08:34 +08:00
|
|
|
|
import classNames from 'classnames';
|
2022-07-25 21:04:43 +08:00
|
|
|
|
import type { DrawerProps as RcDrawerProps } from 'rc-drawer';
|
2023-07-06 10:42:13 +08:00
|
|
|
|
import RcDrawer from 'rc-drawer';
|
2023-07-22 12:18:17 +08:00
|
|
|
|
import type { Placement } from 'rc-drawer/lib/Drawer';
|
2022-07-25 21:04:43 +08:00
|
|
|
|
import type { CSSMotionProps } from 'rc-motion';
|
2023-09-11 17:28:04 +08:00
|
|
|
|
|
2023-10-20 19:22:55 +08:00
|
|
|
|
import { useZIndex } from '../_util/hooks/useZIndex';
|
2022-07-25 21:04:43 +08:00
|
|
|
|
import { getTransitionName } from '../_util/motion';
|
2023-09-11 17:28:04 +08:00
|
|
|
|
import { devUseWarning } from '../_util/warning';
|
2023-11-16 15:07:32 +08:00
|
|
|
|
import zIndexContext from '../_util/zindexContext';
|
2023-07-06 10:42:13 +08:00
|
|
|
|
import { ConfigContext } from '../config-provider';
|
|
|
|
|
import { NoFormStyle } from '../form/context';
|
2022-11-22 22:52:40 +08:00
|
|
|
|
import { NoCompactStyle } from '../space/Compact';
|
2023-08-08 16:48:26 +08:00
|
|
|
|
import { usePanelRef } from '../watermark/context';
|
2023-09-25 20:37:37 +08:00
|
|
|
|
import type { DrawerClassNames, DrawerPanelProps, DrawerStyles } from './DrawerPanel';
|
2023-09-11 17:28:04 +08:00
|
|
|
|
import DrawerPanel from './DrawerPanel';
|
|
|
|
|
import useStyle from './style';
|
2022-03-24 23:33:51 +08:00
|
|
|
|
|
2022-12-13 14:57:40 +08:00
|
|
|
|
const SizeTypes = ['default', 'large'] as const;
|
2023-11-29 17:23:45 +08:00
|
|
|
|
type sizeType = (typeof SizeTypes)[number];
|
2021-06-11 08:39:17 +08:00
|
|
|
|
|
2020-07-12 18:47:14 +08:00
|
|
|
|
export interface PushState {
|
|
|
|
|
distance: string | number;
|
|
|
|
|
}
|
2022-08-01 17:06:19 +08:00
|
|
|
|
|
|
|
|
|
// Drawer diff props: 'open' | 'motion' | 'maskMotion' | 'wrapperClassName'
|
2022-09-21 16:35:01 +08:00
|
|
|
|
export interface DrawerProps extends RcDrawerProps, Omit<DrawerPanelProps, 'prefixCls'> {
|
2022-08-01 17:06:19 +08:00
|
|
|
|
size?: sizeType;
|
|
|
|
|
|
2022-08-23 16:22:00 +08:00
|
|
|
|
open?: boolean;
|
2022-08-01 17:06:19 +08:00
|
|
|
|
|
2022-08-23 16:22:00 +08:00
|
|
|
|
afterOpenChange?: (open: boolean) => void;
|
2022-09-06 21:46:49 +08:00
|
|
|
|
|
|
|
|
|
// Deprecated
|
|
|
|
|
/** @deprecated Please use `open` instead */
|
|
|
|
|
visible?: boolean;
|
|
|
|
|
/** @deprecated Please use `afterOpenChange` instead */
|
|
|
|
|
afterVisibleChange?: (open: boolean) => void;
|
2023-09-25 20:37:37 +08:00
|
|
|
|
classNames?: DrawerClassNames;
|
|
|
|
|
styles?: DrawerStyles;
|
2020-10-24 14:47:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-12 18:47:14 +08:00
|
|
|
|
const defaultPushState: PushState = { distance: 180 };
|
2019-07-17 19:55:59 +08:00
|
|
|
|
|
2023-07-22 12:18:17 +08:00
|
|
|
|
const Drawer: React.FC<DrawerProps> & {
|
|
|
|
|
_InternalPanelDoNotUseOrYouWillBeFired: typeof PurePanel;
|
|
|
|
|
} = (props) => {
|
2022-08-23 16:22:00 +08:00
|
|
|
|
const {
|
|
|
|
|
rootClassName,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
size = 'default',
|
|
|
|
|
mask = true,
|
|
|
|
|
push = defaultPushState,
|
|
|
|
|
open,
|
2022-09-06 21:46:49 +08:00
|
|
|
|
afterOpenChange,
|
2022-08-23 16:22:00 +08:00
|
|
|
|
onClose,
|
|
|
|
|
prefixCls: customizePrefixCls,
|
|
|
|
|
getContainer: customizeGetContainer,
|
2023-07-06 10:42:13 +08:00
|
|
|
|
style,
|
|
|
|
|
className,
|
2022-09-06 21:46:49 +08:00
|
|
|
|
|
|
|
|
|
// Deprecated
|
|
|
|
|
visible,
|
|
|
|
|
afterVisibleChange,
|
|
|
|
|
|
2022-08-23 16:22:00 +08:00
|
|
|
|
...rest
|
|
|
|
|
} = props;
|
|
|
|
|
|
2023-07-06 10:42:13 +08:00
|
|
|
|
const { getPopupContainer, getPrefixCls, direction, drawer } = React.useContext(ConfigContext);
|
2023-11-16 15:07:32 +08:00
|
|
|
|
|
2022-07-25 21:04:43 +08:00
|
|
|
|
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
|
|
|
|
|
|
2023-12-14 14:58:53 +08:00
|
|
|
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
2022-07-29 15:56:11 +08:00
|
|
|
|
|
2022-07-25 21:04:43 +08:00
|
|
|
|
const getContainer =
|
|
|
|
|
// 有可能为 false,所以不能直接判断
|
|
|
|
|
customizeGetContainer === undefined && getPopupContainer
|
|
|
|
|
? () => getPopupContainer(document.body)
|
|
|
|
|
: customizeGetContainer;
|
|
|
|
|
|
|
|
|
|
const drawerClassName = classNames(
|
|
|
|
|
{
|
|
|
|
|
'no-mask': !mask,
|
|
|
|
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
|
|
|
|
},
|
2022-08-01 23:20:04 +08:00
|
|
|
|
rootClassName,
|
2022-07-29 15:56:11 +08:00
|
|
|
|
hashId,
|
2023-12-14 14:58:53 +08:00
|
|
|
|
cssVarCls,
|
2022-07-25 21:04:43 +08:00
|
|
|
|
);
|
|
|
|
|
|
2022-08-23 16:22:00 +08:00
|
|
|
|
// ========================== Warning ===========================
|
|
|
|
|
if (process.env.NODE_ENV !== 'production') {
|
2023-09-13 22:07:33 +08:00
|
|
|
|
const warning = devUseWarning('Drawer');
|
2023-09-11 17:28:04 +08:00
|
|
|
|
|
2022-08-23 16:22:00 +08:00
|
|
|
|
[
|
|
|
|
|
['visible', 'open'],
|
|
|
|
|
['afterVisibleChange', 'afterOpenChange'],
|
2023-09-25 20:37:37 +08:00
|
|
|
|
['headerStyle', 'styles.header'],
|
|
|
|
|
['bodyStyle', 'styles.body'],
|
|
|
|
|
['footerStyle', 'styles.footer'],
|
2022-08-23 16:22:00 +08:00
|
|
|
|
].forEach(([deprecatedName, newName]) => {
|
2023-09-13 22:07:33 +08:00
|
|
|
|
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
|
2022-08-23 16:22:00 +08:00
|
|
|
|
});
|
2022-12-02 22:44:16 +08:00
|
|
|
|
|
|
|
|
|
if (getContainer !== undefined && props.style?.position === 'absolute') {
|
|
|
|
|
warning(
|
|
|
|
|
false,
|
2023-09-11 17:28:04 +08:00
|
|
|
|
'breaking',
|
2022-12-03 19:36:03 +08:00
|
|
|
|
'`style` is replaced by `rootStyle` in v5. Please check that `position: absolute` is necessary.',
|
2022-12-02 22:44:16 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
2022-08-23 16:22:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-25 21:04:43 +08:00
|
|
|
|
// ============================ Size ============================
|
2023-07-22 12:18:17 +08:00
|
|
|
|
const mergedWidth = React.useMemo<string | number>(
|
|
|
|
|
() => width ?? (size === 'large' ? 736 : 378),
|
|
|
|
|
[width, size],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const mergedHeight = React.useMemo<string | number>(
|
2022-07-25 21:04:43 +08:00
|
|
|
|
() => height ?? (size === 'large' ? 736 : 378),
|
|
|
|
|
[height, size],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// =========================== Motion ===========================
|
|
|
|
|
const maskMotion: CSSMotionProps = {
|
|
|
|
|
motionName: getTransitionName(prefixCls, 'mask-motion'),
|
|
|
|
|
motionAppear: true,
|
|
|
|
|
motionEnter: true,
|
|
|
|
|
motionLeave: true,
|
2022-08-17 11:16:01 +08:00
|
|
|
|
motionDeadline: 500,
|
2022-07-25 21:04:43 +08:00
|
|
|
|
};
|
|
|
|
|
|
2022-11-19 13:47:33 +08:00
|
|
|
|
const panelMotion: RcDrawerProps['motion'] = (motionPlacement) => ({
|
2022-07-25 21:04:43 +08:00
|
|
|
|
motionName: getTransitionName(prefixCls, `panel-motion-${motionPlacement}`),
|
|
|
|
|
motionAppear: true,
|
|
|
|
|
motionEnter: true,
|
|
|
|
|
motionLeave: true,
|
2022-08-17 11:16:01 +08:00
|
|
|
|
motionDeadline: 500,
|
2022-07-25 21:04:43 +08:00
|
|
|
|
});
|
|
|
|
|
|
2023-08-08 16:48:26 +08:00
|
|
|
|
// ============================ Refs ============================
|
|
|
|
|
// Select `ant-modal-content` by `panelRef`
|
|
|
|
|
const panelRef = usePanelRef();
|
|
|
|
|
|
2023-10-20 19:22:55 +08:00
|
|
|
|
// ============================ zIndex ============================
|
|
|
|
|
const [zIndex, contextZIndex] = useZIndex('Drawer', rest.zIndex);
|
|
|
|
|
|
2022-07-25 21:04:43 +08:00
|
|
|
|
// =========================== Render ===========================
|
2023-11-16 15:07:32 +08:00
|
|
|
|
return wrapCSSVar(
|
2022-11-22 22:52:40 +08:00
|
|
|
|
<NoCompactStyle>
|
|
|
|
|
<NoFormStyle status override>
|
2023-10-20 19:22:55 +08:00
|
|
|
|
<zIndexContext.Provider value={contextZIndex}>
|
|
|
|
|
<RcDrawer
|
|
|
|
|
prefixCls={prefixCls}
|
|
|
|
|
onClose={onClose}
|
|
|
|
|
maskMotion={maskMotion}
|
|
|
|
|
motion={panelMotion}
|
|
|
|
|
{...rest}
|
|
|
|
|
classNames={{
|
|
|
|
|
mask: classNames(rest.classNames?.mask, drawer?.classNames?.mask),
|
|
|
|
|
content: classNames(rest.classNames?.content, drawer?.classNames?.content),
|
|
|
|
|
}}
|
|
|
|
|
styles={{
|
|
|
|
|
mask: {
|
|
|
|
|
...rest.styles?.mask,
|
|
|
|
|
...drawer?.styles?.mask,
|
|
|
|
|
},
|
|
|
|
|
content: {
|
|
|
|
|
...rest.styles?.content,
|
|
|
|
|
...drawer?.styles?.content,
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
open={open ?? visible}
|
|
|
|
|
mask={mask}
|
|
|
|
|
push={push}
|
|
|
|
|
width={mergedWidth}
|
|
|
|
|
height={mergedHeight}
|
|
|
|
|
style={{ ...drawer?.style, ...style }}
|
|
|
|
|
className={classNames(drawer?.className, className)}
|
|
|
|
|
rootClassName={drawerClassName}
|
|
|
|
|
getContainer={getContainer}
|
|
|
|
|
afterOpenChange={afterOpenChange ?? afterVisibleChange}
|
|
|
|
|
panelRef={panelRef}
|
|
|
|
|
zIndex={zIndex}
|
|
|
|
|
>
|
|
|
|
|
<DrawerPanel prefixCls={prefixCls} {...rest} onClose={onClose} />
|
|
|
|
|
</RcDrawer>
|
|
|
|
|
</zIndexContext.Provider>
|
2022-11-22 22:52:40 +08:00
|
|
|
|
</NoFormStyle>
|
|
|
|
|
</NoCompactStyle>,
|
2022-07-25 21:04:43 +08:00
|
|
|
|
);
|
2023-07-22 12:18:17 +08:00
|
|
|
|
};
|
2019-01-03 17:10:04 +08:00
|
|
|
|
|
2023-07-22 12:18:17 +08:00
|
|
|
|
interface PurePanelInterface {
|
2022-09-21 16:35:01 +08:00
|
|
|
|
prefixCls?: string;
|
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
|
className?: string;
|
2023-07-22 12:18:17 +08:00
|
|
|
|
placement?: Placement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @private Internal Component. Do not use in your production. */
|
|
|
|
|
const PurePanel: React.FC<Omit<DrawerPanelProps, 'prefixCls'> & PurePanelInterface> = (props) => {
|
|
|
|
|
const {
|
|
|
|
|
prefixCls: customizePrefixCls,
|
|
|
|
|
style,
|
|
|
|
|
className,
|
|
|
|
|
placement = 'right',
|
|
|
|
|
...restProps
|
|
|
|
|
} = props;
|
2022-09-21 16:35:01 +08:00
|
|
|
|
const { getPrefixCls } = React.useContext(ConfigContext);
|
|
|
|
|
|
|
|
|
|
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
|
|
|
|
|
|
2023-12-14 14:58:53 +08:00
|
|
|
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
2022-09-21 16:35:01 +08:00
|
|
|
|
|
2023-07-22 12:18:17 +08:00
|
|
|
|
const cls = classNames(
|
|
|
|
|
prefixCls,
|
|
|
|
|
`${prefixCls}-pure`,
|
|
|
|
|
`${prefixCls}-${placement}`,
|
|
|
|
|
hashId,
|
2023-12-14 14:58:53 +08:00
|
|
|
|
cssVarCls,
|
2023-07-22 12:18:17 +08:00
|
|
|
|
className,
|
|
|
|
|
);
|
|
|
|
|
|
2023-11-16 15:07:32 +08:00
|
|
|
|
return wrapCSSVar(
|
2023-07-22 12:18:17 +08:00
|
|
|
|
<div className={cls} style={style}>
|
2022-09-21 16:35:01 +08:00
|
|
|
|
<DrawerPanel prefixCls={prefixCls} {...restProps} />
|
|
|
|
|
</div>,
|
2022-08-01 23:20:04 +08:00
|
|
|
|
);
|
2023-07-22 12:18:17 +08:00
|
|
|
|
};
|
2022-08-01 23:20:04 +08:00
|
|
|
|
|
|
|
|
|
Drawer._InternalPanelDoNotUseOrYouWillBeFired = PurePanel;
|
|
|
|
|
|
2023-07-22 12:18:17 +08:00
|
|
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
|
|
|
Drawer.displayName = 'Drawer';
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-23 22:46:15 +08:00
|
|
|
|
export default Drawer;
|