1ad25e30f8
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
|
import { copyTextToClipboard } from '../../services/clipboard';
|
|
|
|
export type CopyFeedbackState = 'idle' | 'copied' | 'failed';
|
|
|
|
type UseCopyFeedbackOptions = {
|
|
resetDelayMs?: number;
|
|
};
|
|
|
|
/**
|
|
* 统一剪贴板复制反馈。
|
|
* 复制实现、成功/失败状态和定时复位集中在这里,调用方只负责渲染按钮文案。
|
|
*/
|
|
export function useCopyFeedback({
|
|
resetDelayMs = 1400,
|
|
}: UseCopyFeedbackOptions = {}) {
|
|
const [copyState, setCopyState] = useState<CopyFeedbackState>('idle');
|
|
const resetTimerRef = useRef<number | null>(null);
|
|
|
|
const clearResetTimer = useCallback(() => {
|
|
if (resetTimerRef.current !== null) {
|
|
window.clearTimeout(resetTimerRef.current);
|
|
resetTimerRef.current = null;
|
|
}
|
|
}, []);
|
|
|
|
const resetCopyState = useCallback(() => {
|
|
clearResetTimer();
|
|
setCopyState('idle');
|
|
}, [clearResetTimer]);
|
|
|
|
const copyText = useCallback(
|
|
async (value: string) => {
|
|
const copied = await copyTextToClipboard(value);
|
|
setCopyState(copied ? 'copied' : 'failed');
|
|
clearResetTimer();
|
|
resetTimerRef.current = window.setTimeout(() => {
|
|
resetTimerRef.current = null;
|
|
setCopyState('idle');
|
|
}, resetDelayMs);
|
|
return copied;
|
|
},
|
|
[clearResetTimer, resetDelayMs],
|
|
);
|
|
|
|
useEffect(() => resetCopyState, [resetCopyState]);
|
|
|
|
return {
|
|
copyState,
|
|
copyText,
|
|
resetCopyState,
|
|
};
|
|
}
|