73 lines
2.7 KiB
TypeScript
73 lines
2.7 KiB
TypeScript
|
|
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}`}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
};
|