Выдение ячеек по клику
This commit is contained in:
@@ -19,6 +19,8 @@ import {
|
||||
} from './types'
|
||||
import {
|
||||
convertReferencesToHighlights,
|
||||
createCellAddress,
|
||||
createQualifiedCellReference,
|
||||
extractCellReferences,
|
||||
getColumnLabel,
|
||||
} from './utils'
|
||||
@@ -67,6 +69,8 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
} | null>(null)
|
||||
const [isEditing, setIsEditing] = useState(false)
|
||||
const [editingValue, setEditingValue] = useState<string>('') // Локальное значение во время редактирования
|
||||
// Источник ввода: 'cell' (редактирование внутри ячейки) или 'formula'
|
||||
const [editingSource, setEditingSource] = useState<'cell' | 'formula'>('cell')
|
||||
const [isInitialized, setIsInitialized] = useState(false)
|
||||
const [baseFileData, setBaseFileData] = useState<
|
||||
Record<string, Record<string, any>>
|
||||
@@ -427,6 +431,7 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
}
|
||||
setIsEditing(false)
|
||||
setEditingValue('')
|
||||
setEditingSource('cell')
|
||||
containerRefs.current[activeSheet]?.focus({ preventScroll: true })
|
||||
},
|
||||
[activeSheet, selectedCell, editingValue, multiSheetEngine, updateRevision]
|
||||
@@ -497,8 +502,14 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
ArrowDown: () => moveSelection(1, 0),
|
||||
ArrowLeft: () => moveSelection(0, -1),
|
||||
ArrowRight: () => moveSelection(0, 1),
|
||||
Enter: () => startEditing(),
|
||||
F2: () => startEditing(),
|
||||
Enter: () => {
|
||||
setEditingSource('cell')
|
||||
startEditing()
|
||||
},
|
||||
F2: () => {
|
||||
setEditingSource('cell')
|
||||
startEditing()
|
||||
},
|
||||
Delete: handleClearCell,
|
||||
Backspace: handleClearCell,
|
||||
}
|
||||
@@ -508,6 +519,7 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
keyHandlers[e.key]()
|
||||
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
|
||||
e.preventDefault()
|
||||
setEditingSource('cell')
|
||||
setEditingValue(e.key)
|
||||
setIsEditing(true)
|
||||
}
|
||||
@@ -517,6 +529,13 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
|
||||
const handleCellClick = useCallback(
|
||||
(row: number, col: number) => {
|
||||
console.log('🖱️ Обычный клик по ячейке:', {
|
||||
row,
|
||||
col,
|
||||
isEditing,
|
||||
activeSheet,
|
||||
})
|
||||
|
||||
if (isEditing) {
|
||||
stopEditing(true)
|
||||
}
|
||||
@@ -526,9 +545,71 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
[isEditing, stopEditing, activeSheet]
|
||||
)
|
||||
|
||||
// Новый обработчик для кликов в режиме редактирования - вставляет ссылку
|
||||
const handleCellReferenceClick = useCallback(
|
||||
(targetSheetType: SheetType, row: number, col: number) => {
|
||||
console.log('🔗 Клик для вставки ссылки:', {
|
||||
targetSheetType,
|
||||
row,
|
||||
col,
|
||||
isEditing,
|
||||
selectedCell,
|
||||
editingValue,
|
||||
})
|
||||
|
||||
// Проверяем, что мы в режиме редактирования
|
||||
if (!isEditing || !selectedCell) {
|
||||
console.log(
|
||||
'⚠️ Игнорируем клик ссылки: не в режиме редактирования или нет выбранной ячейки'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем ссылку на ячейку
|
||||
let cellReference: string
|
||||
|
||||
// Если это другой лист, делаем квалифицированную ссылку
|
||||
if (targetSheetType !== activeSheet) {
|
||||
cellReference = createQualifiedCellReference(targetSheetType, row, col)
|
||||
console.log('📋 Создана межлистовая ссылка:', cellReference)
|
||||
} else {
|
||||
// Если это тот же лист, делаем локальную ссылку
|
||||
cellReference = createCellAddress(row, col)
|
||||
console.log('📋 Создана локальная ссылка:', cellReference)
|
||||
}
|
||||
|
||||
// Добавляем ссылку к текущему значению редактирования
|
||||
const newValue = editingValue + cellReference
|
||||
console.log('✏️ Новое значение формулы:', {
|
||||
oldValue: editingValue,
|
||||
newValue,
|
||||
})
|
||||
|
||||
setEditingValue(newValue)
|
||||
|
||||
if (editingSource === 'formula') {
|
||||
if (formulaBarRef.current) {
|
||||
formulaBarRef.current.value = newValue
|
||||
formulaBarRef.current.focus()
|
||||
const length = newValue.length
|
||||
formulaBarRef.current.setSelectionRange(length, length)
|
||||
}
|
||||
} else {
|
||||
if (activeCellInputRef.current) {
|
||||
activeCellInputRef.current.value = newValue
|
||||
activeCellInputRef.current.focus({ preventScroll: true })
|
||||
const length = newValue.length
|
||||
activeCellInputRef.current.setSelectionRange(length, length)
|
||||
}
|
||||
}
|
||||
},
|
||||
[isEditing, selectedCell, editingValue, activeSheet, editingSource]
|
||||
)
|
||||
|
||||
const handleCellDoubleClick = useCallback(
|
||||
(row: number, col: number) => {
|
||||
setSelectedCell({ row, col })
|
||||
setEditingSource('cell')
|
||||
startEditing()
|
||||
},
|
||||
[startEditing]
|
||||
@@ -563,6 +644,7 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
|
||||
const handleFormulaBarFocus = useCallback(() => {
|
||||
if (selectedCell && !isEditing) {
|
||||
setEditingSource('formula')
|
||||
startEditing()
|
||||
}
|
||||
}, [selectedCell, isEditing, startEditing])
|
||||
@@ -864,6 +946,8 @@ const DualSpreadsheet: FC<DualSpreadsheetProps> = ({
|
||||
handleCellClick={handleCellClick}
|
||||
handleCellDoubleClick={handleCellDoubleClick}
|
||||
handleCellChange={handleCellChange}
|
||||
handleCellReferenceClick={handleCellReferenceClick}
|
||||
isInEditMode={isEditing}
|
||||
stopEditing={stopEditing}
|
||||
setActiveSheet={setActiveSheet}
|
||||
activeCellInputRef={activeCellInputRef}
|
||||
|
||||
@@ -18,6 +18,8 @@ export const Cell = memo(
|
||||
onCellClick,
|
||||
onCellDoubleClick,
|
||||
onCellValueChange,
|
||||
onCellReferenceClick,
|
||||
isInEditMode,
|
||||
stopEditing,
|
||||
setActiveSheet,
|
||||
activeCellRef,
|
||||
@@ -105,20 +107,89 @@ export const Cell = memo(
|
||||
// Используем обычное значение displayValue для всех ячеек, включая объединенные
|
||||
const cellDisplayValue = displayValue
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
setActiveSheet(sheetType)
|
||||
onCellClick(rowIndex, colIndex)
|
||||
}, [setActiveSheet, sheetType, onCellClick, rowIndex, colIndex])
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
console.log('🖱️ Cell клик:', {
|
||||
rowIndex,
|
||||
colIndex,
|
||||
sheetType,
|
||||
isInEditMode,
|
||||
isSelected,
|
||||
hasReferenceHandler: !!onCellReferenceClick,
|
||||
})
|
||||
|
||||
// Если мы в режиме редактирования, вставка была обработана на mousedown.
|
||||
// Останавливаем всплытие, чтобы родительский Spreadsheet не сменил активный лист.
|
||||
if (isInEditMode) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// Обычная логика клика (выделение ячейки)
|
||||
console.log('📍 Обычный клик - выбираем ячейку:', {
|
||||
rowIndex,
|
||||
colIndex,
|
||||
sheetType,
|
||||
})
|
||||
|
||||
// Подсказка для пользователя
|
||||
if (!isInEditMode) {
|
||||
console.log(
|
||||
'💡 Чтобы вставить ссылку на ячейку: 1) Выберите ячейку 2) Нажмите F2 или Enter для редактирования 3) Кликните на нужную ячейку'
|
||||
)
|
||||
}
|
||||
|
||||
setActiveSheet(sheetType)
|
||||
onCellClick(rowIndex, colIndex)
|
||||
},
|
||||
[
|
||||
setActiveSheet,
|
||||
sheetType,
|
||||
onCellClick,
|
||||
onCellReferenceClick,
|
||||
rowIndex,
|
||||
colIndex,
|
||||
isInEditMode,
|
||||
isSelected,
|
||||
]
|
||||
)
|
||||
|
||||
const handleDoubleClick = useCallback(
|
||||
() => onCellDoubleClick(rowIndex, colIndex),
|
||||
[onCellDoubleClick, rowIndex, colIndex]
|
||||
)
|
||||
|
||||
const handleMouseDown = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
// Используем mousedown, чтобы сработать раньше blur FormulaBar
|
||||
if (isInEditMode && onCellReferenceClick && !isSelected) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
console.log('🖱️ mousedown – вставка ссылки до blur:', {
|
||||
rowIndex,
|
||||
colIndex,
|
||||
sheetType,
|
||||
})
|
||||
onCellReferenceClick(sheetType, rowIndex, colIndex)
|
||||
return
|
||||
}
|
||||
},
|
||||
[
|
||||
isInEditMode,
|
||||
onCellReferenceClick,
|
||||
isSelected,
|
||||
sheetType,
|
||||
rowIndex,
|
||||
colIndex,
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={cellStyle}
|
||||
onMouseDown={handleMouseDown}
|
||||
onClick={handleClick}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
>
|
||||
|
||||
@@ -22,6 +22,8 @@ export const CellRenderer = ({
|
||||
handleCellClick,
|
||||
handleCellDoubleClick,
|
||||
handleCellChange,
|
||||
handleCellReferenceClick,
|
||||
isInEditMode,
|
||||
stopEditing,
|
||||
setActiveSheet,
|
||||
activeCellInputRef,
|
||||
@@ -99,6 +101,8 @@ export const CellRenderer = ({
|
||||
onCellClick={handleCellClick}
|
||||
onCellDoubleClick={handleCellDoubleClick}
|
||||
onCellValueChange={handleCellChange}
|
||||
onCellReferenceClick={handleCellReferenceClick}
|
||||
isInEditMode={isEditing}
|
||||
stopEditing={stopEditing}
|
||||
setActiveSheet={setActiveSheet}
|
||||
activeCellRef={activeCellInputRef}
|
||||
|
||||
@@ -18,6 +18,8 @@ export const Spreadsheet = ({
|
||||
handleCellClick,
|
||||
handleCellDoubleClick,
|
||||
handleCellChange,
|
||||
handleCellReferenceClick,
|
||||
isInEditMode,
|
||||
stopEditing,
|
||||
setActiveSheet,
|
||||
activeCellInputRef,
|
||||
@@ -46,11 +48,22 @@ export const Spreadsheet = ({
|
||||
handleCellClick,
|
||||
handleCellDoubleClick,
|
||||
handleCellChange,
|
||||
handleCellReferenceClick,
|
||||
isInEditMode,
|
||||
stopEditing,
|
||||
setActiveSheet,
|
||||
activeCellInputRef,
|
||||
}
|
||||
|
||||
// Отладочное логирование для проверки состояния
|
||||
console.log(`📊 Spreadsheet ${sheetType} состояние:`, {
|
||||
isEditing,
|
||||
isInEditMode,
|
||||
selectedCell,
|
||||
activeSheet,
|
||||
isActiveSheet: activeSheet === sheetType,
|
||||
})
|
||||
|
||||
const parentRef = useRef<HTMLDivElement>(null)
|
||||
const [gridSize, setGridSize] = useState({ width: 0, height: 0 })
|
||||
|
||||
|
||||
@@ -56,9 +56,15 @@ export interface CellProps {
|
||||
onCellClick: (row: number, col: number) => void
|
||||
onCellDoubleClick: (row: number, col: number) => void
|
||||
onCellValueChange: (newValue: string) => void // Изменение значения во время редактирования
|
||||
onCellReferenceClick?: (
|
||||
sheetType: SheetType,
|
||||
row: number,
|
||||
col: number
|
||||
) => void // Клик для вставки ссылки
|
||||
isInEditMode: boolean // Глобальный режим редактирования
|
||||
stopEditing: (save: boolean) => void
|
||||
setActiveSheet: (type: SheetType) => void
|
||||
activeCellRef: React.RefObject<HTMLInputElement>
|
||||
activeCellRef: React.RefObject<HTMLInputElement | null>
|
||||
style: CSSProperties // Добавляем style для react-window
|
||||
mergedCellInfo?: {
|
||||
// Информация об объединенных ячейках
|
||||
@@ -104,9 +110,15 @@ export interface CellRendererData {
|
||||
handleCellClick: (row: number, col: number) => void
|
||||
handleCellDoubleClick: (row: number, col: number) => void
|
||||
handleCellChange: (newValue: string) => void
|
||||
handleCellReferenceClick?: (
|
||||
sheetType: SheetType,
|
||||
row: number,
|
||||
col: number
|
||||
) => void // Клик для вставки ссылки
|
||||
isInEditMode: boolean // Глобальный режим редактирования
|
||||
stopEditing: (save: boolean) => void
|
||||
setActiveSheet: (type: SheetType) => void
|
||||
activeCellInputRef: React.RefObject<HTMLInputElement>
|
||||
activeCellInputRef: React.RefObject<HTMLInputElement | null>
|
||||
}
|
||||
|
||||
export interface CellRendererProps {
|
||||
@@ -129,9 +141,15 @@ export interface SpreadsheetProps {
|
||||
handleCellClick: (row: number, col: number) => void
|
||||
handleCellDoubleClick: (row: number, col: number) => void
|
||||
handleCellChange: (newValue: string) => void
|
||||
handleCellReferenceClick?: (
|
||||
sheetType: SheetType,
|
||||
row: number,
|
||||
col: number
|
||||
) => void // Клик для вставки ссылки
|
||||
isInEditMode: boolean // Глобальный режим редактирования
|
||||
stopEditing: (save: boolean) => void
|
||||
setActiveSheet: (type: SheetType) => void
|
||||
activeCellInputRef: React.RefObject<HTMLInputElement>
|
||||
activeCellInputRef: React.RefObject<HTMLInputElement | null>
|
||||
containerRefs: React.MutableRefObject<
|
||||
Record<SheetType, HTMLDivElement | null>
|
||||
>
|
||||
|
||||
@@ -11,6 +11,22 @@ export function getColumnLabel(index: number): string {
|
||||
return label
|
||||
}
|
||||
|
||||
// Создает адрес ячейки из координат (например, A1, B2)
|
||||
export function createCellAddress(row: number, col: number): string {
|
||||
return getColumnLabel(col) + (row + 1)
|
||||
}
|
||||
|
||||
// Создает квалифицированную ссылку на ячейку с указанием листа
|
||||
export function createQualifiedCellReference(
|
||||
sheetType: 'report' | 'calculations',
|
||||
row: number,
|
||||
col: number
|
||||
): string {
|
||||
const sheetName = sheetType === 'report' ? 'L' : 'R'
|
||||
const cellAddress = createCellAddress(row, col)
|
||||
return `${sheetName}!${cellAddress}`
|
||||
}
|
||||
|
||||
export function findMergedCellInfo(
|
||||
row: number,
|
||||
col: number,
|
||||
|
||||
Reference in New Issue
Block a user