diff --git a/src/components/EditableCell.tsx b/src/components/EditableCell.tsx new file mode 100644 index 0000000..7c166a4 --- /dev/null +++ b/src/components/EditableCell.tsx @@ -0,0 +1,125 @@ +import React, { useState, useEffect, useRef, useCallback } from 'react'; + +interface EditableCellProps { + value: string; + onInput: (value: string) => void; + focusedCell: string | null; + setFocusedCell: (cellKey: string | null) => void; + cellKey: string; + inputType?: 'text' | 'textarea'; + onFocus?: () => void; + onBlur?: () => void; + placeholder?: string; + className?: string; +} + +export function EditableCell({ + value, + onInput, + focusedCell, + setFocusedCell, + cellKey, + inputType = 'text', + onFocus, + onBlur, + placeholder = '', + className = '' +}: EditableCellProps) { + const [localValue, setLocalValue] = useState(value); + const inputRef = useRef(null); + const textareaRef = useRef(null); + + // Update local value when prop changes + useEffect(() => { + setLocalValue(value); + }, [value]); + + // Handle focus when this cell becomes focused + useEffect(() => { + if (focusedCell === cellKey) { + const element = inputType === 'textarea' ? textareaRef.current : inputRef.current; + if (element) { + element.focus(); + // Select all text when focusing + element.select(); + } + } + }, [focusedCell, cellKey, inputType]); + + const handleInput = useCallback((e: React.ChangeEvent) => { + const newValue = e.target.value; + console.log('Input event:', newValue); + setLocalValue(newValue); + }, []); + + const commitInput = useCallback(() => { + console.log('Committing input:', localValue); + onInput(localValue); + }, [localValue, onInput]); + + const handleFocus = useCallback(() => { + console.log('Focus gained for key:', cellKey); + setFocusedCell(cellKey); + onFocus?.(); + }, [cellKey, setFocusedCell, onFocus]); + + const handleBlur = useCallback(() => { + console.log('Focus lost'); + setFocusedCell(null); + commitInput(); + onBlur?.(); + }, [setFocusedCell, commitInput, onBlur]); + + const handleKeyDown = useCallback((e: React.KeyboardEvent) => { + if (e.key === 'Enter' && inputType === 'text') { + // For text inputs, commit on Enter + e.preventDefault(); + commitInput(); + setFocusedCell(null); + } else if (e.key === 'Escape') { + // Reset to original value on Escape + setLocalValue(value); + setFocusedCell(null); + } + }, [inputType, commitInput, setFocusedCell, value]); + + const baseClassName = ` + w-full px-2 py-1 border-none outline-none resize-none + focus:ring-2 focus:ring-blue-500 focus:ring-inset + ${className} + `.trim(); + + if (inputType === 'textarea') { + return ( +
+