- ESLint flat config + Prettier + EditorConfig - Markdown处理器LRU缓存 - Zustand选择器优化减少重渲染 - CodeMirror Compartment主题热切换 - Preview防抖(150ms) + IndexedDB去抖(500ms) - 组件拆分: App.tsx 310→104行, Sidebar.tsx 244→90行 - 统一错误处理 errorHandler.ts - ConfirmDialog替代原生confirm - LoadingSpinner加载状态 - Toast多条堆叠+类型区分 - 可访问性增强(ARIA属性、键盘导航) - Vitest测试框架(78个测试用例) - Git hooks(husky + lint-staged) - 项目文档(README.md, CONTRIBUTING.md)
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
import { useState, useCallback, useRef } from 'react'
|
|
|
|
interface ConfirmOptions {
|
|
title: string
|
|
message: string
|
|
confirmLabel?: string
|
|
cancelLabel?: string
|
|
variant?: 'danger' | 'warning' | 'info'
|
|
}
|
|
|
|
interface ConfirmState extends ConfirmOptions {
|
|
open: boolean
|
|
resolve: ((value: boolean) => void) | null
|
|
}
|
|
|
|
/**
|
|
* UX-01: Promise-based 确认对话框 hook
|
|
* 替代原生 confirm(),返回 Promise<boolean>
|
|
*/
|
|
export function useConfirm() {
|
|
const [state, setState] = useState<ConfirmState>({
|
|
open: false,
|
|
title: '',
|
|
message: '',
|
|
resolve: null
|
|
})
|
|
|
|
// 使用 ref 确保回调中能拿到最新的 resolve
|
|
const resolveRef = useRef<((value: boolean) => void) | null>(null)
|
|
|
|
const confirm = useCallback((options: ConfirmOptions): Promise<boolean> => {
|
|
return new Promise<boolean>((resolve) => {
|
|
resolveRef.current = resolve
|
|
setState({
|
|
open: true,
|
|
title: options.title,
|
|
message: options.message,
|
|
confirmLabel: options.confirmLabel,
|
|
cancelLabel: options.cancelLabel,
|
|
variant: options.variant,
|
|
resolve
|
|
})
|
|
})
|
|
}, [])
|
|
|
|
const handleConfirm = useCallback(() => {
|
|
resolveRef.current?.(true)
|
|
setState(prev => ({ ...prev, open: false, resolve: null }))
|
|
resolveRef.current = null
|
|
}, [])
|
|
|
|
const handleCancel = useCallback(() => {
|
|
resolveRef.current?.(false)
|
|
setState(prev => ({ ...prev, open: false, resolve: null }))
|
|
resolveRef.current = null
|
|
}, [])
|
|
|
|
return {
|
|
confirm,
|
|
confirmDialogProps: {
|
|
open: state.open,
|
|
title: state.title,
|
|
message: state.message,
|
|
confirmLabel: state.confirmLabel,
|
|
cancelLabel: state.cancelLabel,
|
|
variant: state.variant,
|
|
onConfirm: handleConfirm,
|
|
onCancel: handleCancel
|
|
}
|
|
}
|
|
}
|