Improve and simplify scrolling

This commit is contained in:
Andrew Kingston 2024-06-24 13:45:37 +01:00
parent 42538e114a
commit e05c46435f
No known key found for this signature in database
4 changed files with 56 additions and 54 deletions

View File

@ -6,14 +6,14 @@
const {
isReordering,
reorder,
visibleColumnLookupMap,
columnLookupMap,
rowHeight,
renderedRows,
scrollLeft,
bodyLeft,
} = getContext("grid")
$: targetColumn = $visibleColumnLookupMap[$reorder.targetColumn]
$: targetColumn = $columnLookupMap[$reorder.targetColumn]
$: insertAfter = $reorder.insertAfter
$: left = getLeft(targetColumn, insertAfter, $scrollLeft)
$: height = $rowHeight * $renderedRows.length + DefaultRowHeight
@ -21,6 +21,7 @@
$: visible = $isReordering && left >= $bodyLeft
const getLeft = (targetColumn, insertAfter, scrollLeft) => {
console.log(targetColumn)
if (!targetColumn) {
return 0
}

View File

@ -63,7 +63,7 @@ export const createActions = context => {
rowChangeCache,
rows,
focusedCellId,
visibleColumnLookupMap,
columnLookupMap,
allVisibleColumns,
} = context
@ -156,9 +156,9 @@ export const createActions = context => {
const $focusedCellId = get(focusedCellId)
const { rowId, field } = parseCellID($focusedCellId)
const $rowLookupMap = get(rowLookupMap)
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
const $columnLookupMap = get(columnLookupMap)
const rowIdx = $rowLookupMap[rowId].__idx
const colIdx = $visibleColumnLookupMap[field].__idx
const colIdx = $columnLookupMap[field].__idx
// Get limits of how many rows and columns we're able to paste into
const $rows = get(rows)

View File

@ -5,10 +5,21 @@ export const createStores = () => {
const columns = writable([])
const enrichedColumns = derived(columns, $columns => {
return $columns.map((col, idx) => ({
...col,
__idx: idx,
}))
let offset = GutterWidth
let visibleIdx = 0
return $columns.map((col, idx) => {
const enriched = {
...col,
__idx: idx, // Overall column index
__visibleIdx: visibleIdx, // Index within the visible columns
__left: offset, // Left offset relative to all visible columns
}
if (col.visible) {
visibleIdx++
offset += col.width
}
return enriched
})
})
return {
@ -22,11 +33,6 @@ export const createStores = () => {
export const deriveStores = context => {
const { columns } = context
// Derive the primary display column
const displayColumn = derived(columns, $columns => {
return $columns.find(col => col.primaryDisplay)
})
// Derive a lookup map for all columns by name
const columnLookupMap = derived(columns, $columns => {
let map = {}
@ -36,33 +42,15 @@ export const deriveStores = context => {
return map
})
// Derived list of columns which have not been explicitly hidden, and enrich
// with an index so we can easily select nearby columns
// Derived list of columns which have not been explicitly hidden
const visibleColumns = derived(columns, $columns => {
let offset = GutterWidth
return $columns
.filter(col => col.visible)
.map((col, idx) => {
const enriched = {
...col,
__left: offset,
__idx: idx,
}
offset += col.width
return enriched
})
return $columns.filter(col => col.visible)
})
// Derive a lookup map for visible columns by name
const visibleColumnLookupMap = derived(visibleColumns, $visibleColumns => {
let map = {}
$visibleColumns.forEach(column => {
map[column.name] = column
})
return map
// Split visible columns into their discrete types
const displayColumn = derived(visibleColumns, $visibleColumns => {
return $visibleColumns.find(col => col.primaryDisplay)
})
// Derive scrollable columns
const scrollableColumns = derived(visibleColumns, $visibleColumns => {
return $visibleColumns.filter(col => !col.primaryDisplay)
})
@ -79,7 +67,6 @@ export const deriveStores = context => {
displayColumn,
columnLookupMap,
visibleColumns,
visibleColumnLookupMap,
scrollableColumns,
hasNonAutoColumn,
}

View File

@ -30,14 +30,14 @@ export const createActions = context => {
columns,
columnLookupMap,
scrollableColumns,
visibleColumnLookupMap,
scroll,
bounds,
visibleColumns,
maxScrollLeft,
datasource,
bodyLeft,
width,
scrollLeft,
maxScrollLeft,
} = context
let latestX = 0
let autoScrollInterval
@ -94,17 +94,19 @@ export const createActions = context => {
considerReorderPosition()
// Check if we need to start auto-scrolling
const $scrollLeft = get(scrollLeft)
const $maxScrollLeft = get(maxScrollLeft)
const $reorder = get(reorder)
const proximityCutoff = Math.min(140, get(width) / 6)
const speedFactor = 16
const rightProximity = Math.max(0, $reorder.gridLeft + $reorder.width - x)
const leftProximity = Math.max(0, x - $reorder.gridLeft)
if (rightProximity < proximityCutoff) {
if (rightProximity < proximityCutoff && $scrollLeft < $maxScrollLeft) {
const weight = proximityCutoff - rightProximity
const increment = (weight / proximityCutoff) * speedFactor
reorder.update(state => ({ ...state, increment }))
startAutoScroll()
} else if (leftProximity < proximityCutoff) {
} else if (leftProximity < proximityCutoff && $scrollLeft > 0) {
const weight = -1 * (proximityCutoff - leftProximity)
const increment = (weight / proximityCutoff) * speedFactor
reorder.update(state => ({ ...state, increment }))
@ -180,20 +182,26 @@ export const createActions = context => {
document.removeEventListener("touchcancel", stopReordering)
// Ensure there's actually a change before saving
const { sourceColumn, targetColumn } = get(reorder)
const { sourceColumn, targetColumn, insertAfter } = get(reorder)
reorder.set(reorderInitialState)
if (sourceColumn !== targetColumn) {
await moveColumn(sourceColumn, targetColumn)
await moveColumn({ sourceColumn, targetColumn, insertAfter })
}
}
// Moves a column after another columns.
// An undefined target column will move the source to index 0.
const moveColumn = async (sourceColumn, targetColumn) => {
const moveColumn = async ({
sourceColumn,
targetColumn,
insertAfter = false,
}) => {
const $columnLookupMap = get(columnLookupMap)
let sourceIdx = $columnLookupMap[sourceColumn]
let targetIdx = $columnLookupMap[targetColumn]
targetIdx++
let sourceIdx = $columnLookupMap[sourceColumn].__idx
let targetIdx = $columnLookupMap[targetColumn].__idx
if (insertAfter) {
targetIdx++
}
columns.update(state => {
const removed = state.splice(sourceIdx, 1)
if (--targetIdx < sourceIdx) {
@ -214,20 +222,26 @@ export const createActions = context => {
// Moves a column one place left (as appears visually)
const moveColumnLeft = async column => {
const $visibleColumns = get(visibleColumns)
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
const sourceIdx = $visibleColumnLookupMap[column]
await moveColumn(column, $visibleColumns[sourceIdx - 2]?.name)
const $columnLookupMap = get(columnLookupMap)
const sourceIdx = $columnLookupMap[column]
await moveColumn({
sourceColumn: column,
targetColumn: $visibleColumns[sourceIdx - 2]?.name,
})
}
// Moves a column one place right (as appears visually)
const moveColumnRight = async column => {
const $visibleColumns = get(visibleColumns)
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
const sourceIdx = $visibleColumnLookupMap[column]
const $columnLookupMap = get(columnLookupMap)
const sourceIdx = $columnLookupMap[column]
if (sourceIdx === $visibleColumns.length - 1) {
return
}
await moveColumn(column, $visibleColumns[sourceIdx + 1]?.name)
await moveColumn({
sourceColumn: column,
targetColumn: $visibleColumns[sourceIdx + 1]?.name,
})
}
return {