import DeleteIcon from '@mui/icons-material/Delete'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import type { ComponentPropsWithRef, ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { IconButton } from '../Button'; import { Tooltip } from '../Tooltip'; import type { RenderRowParams, RowParams, SortableRowAction } from './models'; import { labelDelete, labelDragToReorder } from './translatedLabels'; type RowButtonProps = ComponentPropsWithRef & { label: string; }; // 30px buttons at a 32px pitch. The icon size is set here because the Tooltip // overrides IconButton's own small-size class, and consumer icons may be any size. const RowButton = ({ className = '', label, ...buttonProps }: RowButtonProps): JSX.Element => ( ); interface Props { actions: Array; className?: string; draggable: boolean; id: string; onDelete: (id: string) => void; onUpdate: (id: string, update: (value: T) => T) => void; renderRow: (params: RenderRowParams) => ReactNode; rowParams: RowParams; } export const Row = ({ actions, className = '', draggable, id, onDelete, onUpdate, renderRow, rowParams }: Props): JSX.Element => { const { t } = useTranslation(); const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition } = useSortable({ disabled: !draggable, id }); const setValue = (value: T): void => onUpdate(id, () => value); const setField = (field: K, fieldValue: T[K]): void => onUpdate( id, (value) => ({ ...(value as object), [field]: fieldValue }) as T ); return (
  • {renderRow({ ...rowParams, setField, setValue })}
    {actions.map(({ icon, id: actionId, isDisabled, label, onClick }) => ( ))} } label={t(labelDelete)} onClick={(): void => onDelete(id)} /> {draggable && ( } label={t(labelDragToReorder)} ref={setActivatorNodeRef} /> )}
  • ); };