import { FormControl, MenuItem, Select } from '@mui/material';
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useRealtimeActions, useVspOptions } from '../../contexts/RealtimeContext';
const EDITOR_STYLES = {
position: 'absolute',
zIndex: 12,
top: 0,
};
const VspDropdownEditCell = memo(({ refCell, onChange, disabled, value, table, cell }) => {
const { endEditing: contextEndEditing } = useRealtimeActions();
const vspOptions = useVspOptions();
const [selectedValue, setSelectedValue] = useState(() => value ?? '');
const [position, setPosition] = useState();
const [open, setOpen] = useState(false);
const refFinished = useRef(false);
// AURORA-1891: см. тот же приём в EditCell.jsx — фокус после закрытия
// редактора возвращается в
, чтобы клавиатурная навигация не отваливалась.
const tdRef = useRef(null);
useEffect(() => {
const timer = setTimeout(() => {
setOpen(true);
}, 80);
return () => clearTimeout(timer);
}, []);
useLayoutEffect(() => {
if (!refCell?.current) return;
const td = refCell.current.offsetParent;
const tr = td?.offsetParent;
if (td && tr) {
tdRef.current = td;
setPosition({
left: td.offsetLeft,
width: td.offsetWidth,
translateY: tr.style.transform || '',
});
}
}, [refCell]);
useEffect(() => {
return () => {
tdRef.current?.focus?.();
};
}, []);
const finishEditing = useCallback(() => {
if (refFinished.current) return;
refFinished.current = true;
table.setEditingCell(null);
const editingCell = table.getState().editingCell;
if (editingCell) {
contextEndEditing?.(editingCell.row, editingCell.column);
}
}, [table, contextEndEditing]);
// AURORA-1891: та же клавиатурная логика, что в EditCell.jsx — Esc уже
// работает через onClose MUI Select (reason !== 'selectOption' вызывает
// finishEditing без onChange, т.е. без cell_updated — отмена). Здесь
// добираем Tab/Shift+Tab и Enter: сохранить (для dropdown «сохранить» —
// это просто закрыть без выбора, onChange уже случился в handleSelectChange,
// если пользователь кликнул опцию) и перейти к следующей редактируемой ячейке.
const handleKeyDown = useCallback(
(event) => {
if (refFinished.current) return;
if (event.key === 'Tab') {
event.preventDefault();
table.options.meta?.openNextEditableCell?.(cell.row, cell.column, event.shiftKey ? 'left' : 'right');
finishEditing();
return;
}
if (event.key === 'Enter') {
event.preventDefault();
table.options.meta?.openNextEditableCell?.(cell.row, cell.column, 'down');
finishEditing();
}
},
[cell, finishEditing, table],
);
const handleSelectChange = useCallback(
(e) => {
const val = e.target.value;
if (val == null || val === '') return;
refFinished.current = true;
setSelectedValue(val);
onChange?.(val);
const editingCell = table.getState().editingCell;
if (editingCell) {
contextEndEditing?.(editingCell.row, editingCell.column);
}
},
[onChange, table, contextEndEditing],
);
const handleSelectClose = useCallback(
(_event, reason) => {
if (reason === 'selectOption') return;
finishEditing();
},
[finishEditing],
);
const editorStyles = useMemo(
() => ({
...EDITOR_STYLES,
left: position?.left || 0,
width: position?.width || 0,
transform: position?.translateY || 0,
}),
[position],
);
return (
|
|
{position && (
)}
|
);
});
VspDropdownEditCell.displayName = 'VspDropdownEditCell';
export default VspDropdownEditCell;