From e05c46435f256310cb0df8f1d1de55297f3fb128 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Jun 2024 13:45:37 +0100 Subject: [PATCH] Improve and simplify scrolling --- .../grid/overlays/ReorderOverlay.svelte | 5 +- .../src/components/grid/stores/clipboard.js | 6 +-- .../src/components/grid/stores/columns.js | 53 +++++++------------ .../src/components/grid/stores/reorder.js | 46 ++++++++++------ 4 files changed, 56 insertions(+), 54 deletions(-) diff --git a/packages/frontend-core/src/components/grid/overlays/ReorderOverlay.svelte b/packages/frontend-core/src/components/grid/overlays/ReorderOverlay.svelte index b14db312bf..31a2739bb4 100644 --- a/packages/frontend-core/src/components/grid/overlays/ReorderOverlay.svelte +++ b/packages/frontend-core/src/components/grid/overlays/ReorderOverlay.svelte @@ -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 } diff --git a/packages/frontend-core/src/components/grid/stores/clipboard.js b/packages/frontend-core/src/components/grid/stores/clipboard.js index 4aaf2429f4..7cce2b27c8 100644 --- a/packages/frontend-core/src/components/grid/stores/clipboard.js +++ b/packages/frontend-core/src/components/grid/stores/clipboard.js @@ -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) diff --git a/packages/frontend-core/src/components/grid/stores/columns.js b/packages/frontend-core/src/components/grid/stores/columns.js index d575ca7910..d3ec66e94a 100644 --- a/packages/frontend-core/src/components/grid/stores/columns.js +++ b/packages/frontend-core/src/components/grid/stores/columns.js @@ -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, } diff --git a/packages/frontend-core/src/components/grid/stores/reorder.js b/packages/frontend-core/src/components/grid/stores/reorder.js index 3d41b2227e..48b054b862 100644 --- a/packages/frontend-core/src/components/grid/stores/reorder.js +++ b/packages/frontend-core/src/components/grid/stores/reorder.js @@ -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 {