ge-tool/components/TruncatedPath.tsx

73 lines
2.7 KiB
TypeScript
Raw Permalink Normal View History

2025-12-10 06:41:43 +00:00
import React, { useState } from 'react';
interface TruncatedPathProps {
path: string;
variant?: 'blue' | 'yellow';
maxChars?: number;
label?: string; // Optional label for display context
}
/**
* Component hiển thị đưng dẫn với overflow che khuất phần đu (bên trái)
* Sử dụng useEffect đ scroll input về cuối, hiển thị phần filename
*/
export const TruncatedPath: React.FC<TruncatedPathProps> = ({
path,
variant = 'yellow',
maxChars = 50,
label
}) => {
const [isCopied, setIsCopied] = useState(false);
const inputRef = React.useRef<HTMLInputElement>(null);
// Scroll to end on mount to show filename
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.scrollLeft = inputRef.current.scrollWidth;
}
}, [path]);
const handleCopy = async () => {
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(path);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 1000);
} else {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = path;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 1000);
}
} catch (err) {
console.error('Failed to copy:', err);
}
};
const inputClasses = variant === 'blue'
? `border-blue-700/30 ${isCopied ? 'text-green-400 bg-green-900/20 border-green-600/50' : 'text-blue-400/80 bg-slate-900/50'}`
: `border-yellow-700/30 ${isCopied ? 'text-green-400 bg-green-900/20 border-green-600/50' : 'text-yellow-400/80 bg-slate-900/50'}`;
const titleText = label ? `${label}: Click để copy` : `Click để copy: ${path}`;
return (
<input
ref={inputRef}
type="text"
value={path}
readOnly
onClick={handleCopy}
title={titleText}
className={`w-full px-3 py-2 text-xs border rounded-lg focus:outline-none focus:ring-2 transition-all duration-300 cursor-pointer ${variant === 'blue' ? 'focus:ring-blue-500/30 hover:border-blue-600/50' : 'focus:ring-yellow-500/30 hover:border-yellow-600/50'
} ${inputClasses}`}
/>
);
};