fix(git): convert to auto-resizing commit input
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Input } from '@/components/ui/input';
|
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
@@ -10,65 +9,41 @@ interface CommitInputProps {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MIN_HEIGHT = 38; // Single line height
|
||||||
|
const MAX_HEIGHT = 200;
|
||||||
|
|
||||||
export const CommitInput: React.FC<CommitInputProps> = ({
|
export const CommitInput: React.FC<CommitInputProps> = ({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
placeholder = 'Commit message',
|
placeholder = 'Commit message',
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
||||||
const hasMultipleLines = value.includes('\n');
|
|
||||||
const textareaRef = React.useRef<HTMLTextAreaElement>(null);
|
const textareaRef = React.useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const shouldShowTextarea = isExpanded || hasMultipleLines;
|
// Auto-resize based on content
|
||||||
|
|
||||||
const handleInputFocus = () => {
|
|
||||||
setIsExpanded(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTextareaBlur = () => {
|
|
||||||
if (!hasMultipleLines && !value.trim()) {
|
|
||||||
setIsExpanded(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (shouldShowTextarea && textareaRef.current) {
|
const textarea = textareaRef.current;
|
||||||
textareaRef.current.focus();
|
if (!textarea) return;
|
||||||
const len = textareaRef.current.value.length;
|
|
||||||
textareaRef.current.setSelectionRange(len, len);
|
|
||||||
}
|
|
||||||
}, [shouldShowTextarea]);
|
|
||||||
|
|
||||||
if (shouldShowTextarea) {
|
// Reset height to measure scrollHeight accurately
|
||||||
return (
|
textarea.style.height = `${MIN_HEIGHT}px`;
|
||||||
<Textarea
|
const newHeight = Math.min(Math.max(textarea.scrollHeight, MIN_HEIGHT), MAX_HEIGHT);
|
||||||
ref={textareaRef}
|
textarea.style.height = `${newHeight}px`;
|
||||||
value={value}
|
}, [value]);
|
||||||
onChange={(e) => onChange(e.target.value)}
|
|
||||||
onBlur={handleTextareaBlur}
|
|
||||||
placeholder={placeholder}
|
|
||||||
rows={4}
|
|
||||||
disabled={disabled}
|
|
||||||
className={cn(
|
|
||||||
'rounded-lg bg-background/80 resize-none min-h-[100px]',
|
|
||||||
disabled && 'opacity-50'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Textarea
|
||||||
|
ref={textareaRef}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange(e.target.value)}
|
onChange={(e) => onChange(e.target.value)}
|
||||||
onFocus={handleInputFocus}
|
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
rows={1}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-lg bg-background/80',
|
'rounded-lg bg-background/80 resize-none overflow-y-auto',
|
||||||
disabled && 'opacity-50'
|
disabled && 'opacity-50'
|
||||||
)}
|
)}
|
||||||
|
style={{ minHeight: MIN_HEIGHT, maxHeight: MAX_HEIGHT }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user