Skip to content

Commit

Permalink
feat(structure): starting support for left and right arrows
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanl17 committed May 17, 2024
1 parent abd9685 commit 0e36e41
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function DocumentSheetListPaneInner({
</Flex>
<TableContainer>
<ColumnsControl table={table} />
<SheetListProvider>
<SheetListProvider table={table}>
<Table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
Expand Down
104 changes: 65 additions & 39 deletions packages/sanity/src/structure/panes/documentList/SheetListContext.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import {type SanityDocument} from '@sanity/types'
import {type Table} from '@tanstack/react-table'
import {type ReactNode, useCallback, useContext, useMemo, useState} from 'react'

import {SheetListContext} from '../../../_singletons/structure/panes/document/DocumentSheetListContext'

interface SheetListProviderProps {
children?: ReactNode
table: Table<SanityDocument>
}

type SelectionDirection = 'down' | 'up'
type SelectionDirection = 'down' | 'up' | 'left' | 'right'

export interface SheetListContextValue {
setFocusedCellId: (colId: string, rowIndex: number) => void
Expand All @@ -29,50 +32,13 @@ export const useSheetListContext = (): SheetListContextValue => {
return context
}

export function SheetListProvider({children}: SheetListProviderProps): ReactNode {
export function SheetListProvider({children, table}: SheetListProviderProps): ReactNode {
const [focusedCellDetails, setFocusedCellDetails] = useState<{
colId: string
rowIndex: number
} | null>(null)
const [selectedCellIndexes, setSelectedCellIndexes] = useState<number[]>([])

const onSelectedCellChange = useCallback(
(direction: SelectionDirection) => {
if (!focusedCellDetails) return

setSelectedCellIndexes((previousSelection) => {
const selectionDirectionalChange = direction === 'down' ? 1 : -1
// if no cells are selected, select the cell in the direction
if (!previousSelection.length) {
const firstSelectedIndex = focusedCellDetails.rowIndex + selectionDirectionalChange
if (firstSelectedIndex < 0) return []
return [firstSelectedIndex]
}
const lastIndexSelected = previousSelection[previousSelection.length - 1]
const indexInDirectionFromLast = lastIndexSelected + selectionDirectionalChange

// if the cell in the direction is out of bounds, return the previous selection
if (indexInDirectionFromLast < 0) return previousSelection

// if the cell in the direction is the same as the focused cell, deselect all cells
if (indexInDirectionFromLast === focusedCellDetails?.rowIndex) {
return []
}

// if the cell in the direction is already selected, deselect the last selected cell
if (previousSelection.includes(indexInDirectionFromLast)) {
const nextSelection = [...previousSelection]
nextSelection.pop()

return nextSelection
}

return [...previousSelection, indexInDirectionFromLast]
})
},
[focusedCellDetails],
)

const handleSetFocusedCellId = useCallback((colId: string, rowIndex: number) => {
setFocusedCellDetails({colId, rowIndex})
}, [])
Expand All @@ -86,6 +52,66 @@ export function SheetListProvider({children}: SheetListProviderProps): ReactNode
setSelectedCellIndexes([])
}, [])

const moveHorizontal = useCallback(
(direction: 'left' | 'right') => {
const visibleColumns = table.getVisibleLeafColumns()
const horizontallyMovedNextIndex =
visibleColumns.findIndex((col) => col.id === focusedCellDetails?.colId) +
(direction === 'left' ? -1 : 1)

if (horizontallyMovedNextIndex < 0 || horizontallyMovedNextIndex >= visibleColumns.length)
return

handleSetFocusedCellId(
visibleColumns[horizontallyMovedNextIndex].id,
focusedCellDetails!.rowIndex,
)
resetSelection()
},
[focusedCellDetails, handleSetFocusedCellId, resetSelection, table],
)

const onSelectedCellChange = useCallback(
(direction: SelectionDirection) => {
if (!focusedCellDetails) return

if (direction === 'left' || direction === 'right') {
moveHorizontal(direction)
} else {
setSelectedCellIndexes((previousSelection) => {
const selectionDirectionalChange = direction === 'down' ? 1 : -1
// if no cells are selected, select the cell in the direction
if (!previousSelection.length) {
const firstSelectedIndex = focusedCellDetails.rowIndex + selectionDirectionalChange
if (firstSelectedIndex < 0) return []
return [firstSelectedIndex]
}
const lastIndexSelected = previousSelection[previousSelection.length - 1]
const indexInDirectionFromLast = lastIndexSelected + selectionDirectionalChange

// if the cell in the direction is out of bounds, return the previous selection
if (indexInDirectionFromLast < 0) return previousSelection

// if the cell in the direction is the same as the focused cell, deselect all cells
if (indexInDirectionFromLast === focusedCellDetails?.rowIndex) {
return []
}

// if the cell in the direction is already selected, deselect the last selected cell
if (previousSelection.includes(indexInDirectionFromLast)) {
const nextSelection = [...previousSelection]
nextSelection.pop()

return nextSelection
}

return [...previousSelection, indexInDirectionFromLast]
})
}
},
[focusedCellDetails, moveHorizontal],
)

const value = useMemo(
() => ({
focusedCellDetails,
Expand Down

0 comments on commit 0e36e41

Please sign in to comment.