Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import type { DrawerClassNames, DrawerStyles } from './inter';
export type Placement = 'left' | 'top' | 'right' | 'bottom';

export interface DrawerProps
extends Omit<DrawerPopupProps, 'prefixCls' | 'inline' | 'scrollLocker'>,
extends
Omit<DrawerPopupProps, 'prefixCls' | 'inline' | 'scrollLocker'>,
DrawerPanelEvents,
DrawerPanelAccessibility {
prefixCls?: string;
open?: boolean;
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
onClose?: (e: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

You've correctly updated the onClose type here to include KeyboardEvent. However, the onClose prop in the DrawerPopupProps interface (defined in src/DrawerPopup.tsx) was not updated to reflect this change. This creates a type inconsistency between the Drawer and DrawerPopup components, which can lead to type errors under stricter TypeScript configurations (like strictFunctionTypes). To ensure type safety, DrawerPopupProps['onClose'] should also be updated to accept a native KeyboardEvent.

destroyOnHidden?: boolean;
getContainer?: PortalProps['getContainer'];
panelRef?: React.Ref<HTMLDivElement>;
Expand Down Expand Up @@ -73,6 +74,7 @@ const Drawer: React.FC<DrawerProps> = props => {
onClick,
onKeyDown,
onKeyUp,
onClose,
resizable,
defaultSize,

Expand Down Expand Up @@ -159,13 +161,21 @@ const Drawer: React.FC<DrawerProps> = props => {
...eventHandlers,
};

const onEsc: PortalProps['onEsc'] = ({ top, event }) => {
if (top && keyboard) {
event.stopPropagation();
onClose?.(event);
}
};
Comment on lines +164 to +169
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# 查找 src/Drawer.tsx 文件并查看目标行
fd -type f "Drawer.tsx" -path "*/src/*" | head -5

Repository: react-component/drawer

Length of output: 236


🏁 Script executed:

# 检查 @rc-component/portal 包是否存在及其结构
ls -la node_modules/@rc-component/portal 2>/dev/null | head -20

Repository: react-component/drawer

Length of output: 48


🏁 Script executed:

# 正确的查找命令 - 查找 Drawer.tsx
fd "Drawer.tsx" src/

Repository: react-component/drawer

Length of output: 80


🏁 Script executed:

# 查看项目结构
ls -la src/ | head -20

Repository: react-component/drawer

Length of output: 675


🏁 Script executed:

# 查找所有 TypeScript 文件中 onEsc 的引用
rg "onEsc" --type ts --type tsx

Repository: react-component/drawer

Length of output: 93


🏁 Script executed:

# 查看 Drawer.tsx 的内容,特别关注行 164-169
cat -n src/Drawer.tsx | sed -n '150,180p'

Repository: react-component/drawer

Length of output: 1000


🏁 Script executed:

# 搜索 onEsc 的使用(不指定文件类型)
rg "onEsc" -A 5 -B 2

Repository: react-component/drawer

Length of output: 686


🏁 Script executed:

# 查看 Drawer.tsx 的导入部分
head -40 src/Drawer.tsx

Repository: react-component/drawer

Length of output: 1501


🏁 Script executed:

# 搜索 PortalProps 的定义或使用
rg "PortalProps" -B 2 -A 5

Repository: react-component/drawer

Length of output: 1158


🏁 Script executed:

# 查看 package.json 了解依赖信息
cat package.json | grep -A 2 -B 2 "portal\|Portal"

Repository: react-component/drawer

Length of output: 218


🏁 Script executed:

# 查找项目中所有的 d.ts 或 TypeScript 定义文件
find . -name "*.d.ts" -o -name "*.ts" | grep -i portal | head -10

Repository: react-component/drawer

Length of output: 48


🏁 Script executed:

# 查看是否有 node_modules,并检查 @rc-component/portal 的类型文件
find . -path "*/node_modules/@rc-component/portal*" -name "*.d.ts" 2>/dev/null | head -5

Repository: react-component/drawer

Length of output: 48


🌐 Web query:

@rc-component/portal onEsc API documentation

💡 Result:

Short answer: @rc-component/portal does not expose an onEsc prop. Its documented props are getContainer, open, and autoLock; it provides no built‑in Escape-key handler — handle Escape yourself (e.g., add a keydown listener in your portal content or use a higher-level component like rc-dialog that supports onClose). [1][2]

Sources:

  • @rc-component/portal npm README (props list: getContainer, open, autoLock). [1]
  • Package overview / API listing (no onEsc in API). [2]

🌐 Web query:

@rc-component/portal version 2.0 onEsc escape key handler support

💡 Result:

Short answer: No — @rc-component/portal v2.x does not include a built-in onEsc/escape-key prop. The published API shows only props like getContainer, open and autoLock (no onEsc/close-on-esc). See the package README/API. [1][2]

If you need ESC-to-close behavior, add a keydown listener in your component that wraps Portal (or use a higher-level rc component that provides built-in close-on-esc). [1]

Sources:

  • @rc-component/portal README / API (props list: getContainer, open, autoLock). [1]
  • jsDelivr/npm listing for @rc-component/portal (v2.x metadata). [2]

🌐 Web query:

rc-component/portal GitHub releases 2024 onEsc feature

💡 Result:

Do you mean the GitHub repo react-component/portal (or the npm package @rc-component/portal)? Do you want to know whether a 2024 release added an onEsc (escape-key) prop/feature?


🏁 Script executed:

# 查找是否有其他 Portal 使用的例子
rg "Portal" src/ -B 2 -A 5 | head -50

Repository: react-component/drawer

Length of output: 2096


🏁 Script executed:

# 查看项目的 tsconfig 或相关配置,检查是否有类型覆盖
cat tsconfig.json 2>/dev/null || echo "No tsconfig.json"

Repository: react-component/drawer

Length of output: 450


Portal 不支持 onEsc 属性,此实现将无法工作。

根据官方文档,@rc-component/portal v2.x 仅暴露以下属性:getContaineropenautoLock,不包含 onEsc 属性。当前代码将 onEsc 处理器传给 Portal(行 178),但该属性会被忽略,导致 ESC 键无法关闭 Drawer。

建议采用以下替代方案之一:

  • 在 DrawerPopup 或 DrawerPanel 组件内部添加 keydown 事件监听器
  • 检查 @rc-component/portal 是否计划添加此功能
  • 使用其他支持 escape-key 处理的高级组件


return (
<RefContext.Provider value={refContext}>
<Portal
open={mergedOpen || forceRender || animatedVisible}
autoDestroy={false}
getContainer={getContainer}
autoLock={mask && (mergedOpen || animatedVisible)}
onEsc={onEsc}
>
<DrawerPopup {...drawerPopupProps} />
</Portal>
Expand Down
13 changes: 1 addition & 12 deletions src/DrawerPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ export interface PushConfig {
}

export interface DrawerPopupProps
extends DrawerPanelEvents,
DrawerPanelAccessibility {
extends DrawerPanelEvents, DrawerPanelAccessibility {
prefixCls: string;
open?: boolean;
inline?: boolean;
Expand Down Expand Up @@ -106,7 +105,6 @@ const DrawerPopup: React.ForwardRefRenderFunction<
push,
forceRender,
autoFocus,
keyboard,

// classNames
classNames: drawerClassNames,
Expand Down Expand Up @@ -174,15 +172,6 @@ const DrawerPopup: React.ForwardRefRenderFunction<
}
break;
}

// Close
case KeyCode.ESC: {
if (onClose && keyboard) {
event.stopPropagation();
onClose(event);
}
break;
}
}
};

Expand Down
14 changes: 6 additions & 8 deletions tests/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -299,22 +299,20 @@ describe('rc-drawer-menu', () => {
describe('keyboard', () => {
it('ESC to exit', () => {
const onClose = jest.fn();
const { container } = render(
<Drawer open getContainer={false} onClose={onClose} />,
);
fireEvent.keyDown(container.querySelector('.rc-drawer-section'), {
keyCode: KeyCode.ESC,
render(<Drawer open getContainer={false} onClose={onClose} />);
fireEvent.keyDown(window, {
key: 'Escape',
});
expect(onClose).toHaveBeenCalled();
});

it('disable ESC to exit', () => {
const onClose = jest.fn();
const { container } = render(
render(
<Drawer open getContainer={false} onClose={onClose} keyboard={false} />,
);
fireEvent.keyDown(container.querySelector('.rc-drawer-section'), {
keyCode: KeyCode.ESC,
fireEvent.keyDown(window, {
key: 'Escape',
});
expect(onClose).not.toHaveBeenCalled();
});
Expand Down