be89296492
拆分 App 认证、壳层、运行配置与项目摘要模块 拆分 Tauri 项目能力与 Rust 测试领域模块 拆分界面测试与 Agent Runtime 真实 E2E 套件 补充源码扫描和客户端模块化文档约定
56 lines
1.3 KiB
TypeScript
56 lines
1.3 KiB
TypeScript
import {
|
|
type KeyboardEvent as ReactKeyboardEvent,
|
|
type MouseEvent as ReactMouseEvent,
|
|
useLayoutEffect,
|
|
} from 'react';
|
|
|
|
function isEscapeKey(event: { key: string }) {
|
|
return event.key === 'Escape';
|
|
}
|
|
|
|
function isEditableEscapeTarget(target: EventTarget | null) {
|
|
return (
|
|
target instanceof HTMLInputElement ||
|
|
target instanceof HTMLTextAreaElement ||
|
|
target instanceof HTMLSelectElement ||
|
|
(target instanceof HTMLElement && target.isContentEditable)
|
|
);
|
|
}
|
|
|
|
export function closeDialogOnEscape(
|
|
event: ReactKeyboardEvent,
|
|
onClose: () => void,
|
|
) {
|
|
if (isEscapeKey(event) && !isEditableEscapeTarget(event.target)) {
|
|
event.preventDefault();
|
|
onClose();
|
|
}
|
|
}
|
|
|
|
export function useEscapeToClose(onClose: () => void, enabled = true) {
|
|
useLayoutEffect(() => {
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
|
|
const handleKeyDown = (event: globalThis.KeyboardEvent) => {
|
|
if (isEscapeKey(event) && !isEditableEscapeTarget(event.target)) {
|
|
event.preventDefault();
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [enabled, onClose]);
|
|
}
|
|
|
|
export function closeDialogOnBackdropMouseDown(
|
|
event: ReactMouseEvent,
|
|
onClose: () => void,
|
|
) {
|
|
if (event.target === event.currentTarget) {
|
|
onClose();
|
|
}
|
|
}
|