Fix reorder

This commit is contained in:
Andrew Kingston 2024-06-24 13:03:33 +01:00
parent ada3367b49
commit 42538e114a
No known key found for this signature in database
5 changed files with 64 additions and 69 deletions

View File

@ -1,37 +1,33 @@
<script>
import { getContext } from "svelte"
import GridScrollWrapper from "../layout/GridScrollWrapper.svelte"
import { DefaultRowHeight, GutterWidth } from "../lib/constants"
import { DefaultRowHeight } from "../lib/constants"
const {
isReordering,
reorder,
visibleColumnLookupMap,
displayColumn,
rowHeight,
renderedRows,
scrollLeft,
bodyLeft,
} = getContext("grid")
$: targetColumn = $visibleColumnLookupMap[$reorder.targetColumn]
$: console.log(targetColumn)
$: minLeft = GutterWidth + ($displayColumn?.width || 0)
$: left = getLeft(targetColumn, $displayColumn, $scrollLeft)
$: insertAfter = $reorder.insertAfter
$: left = getLeft(targetColumn, insertAfter, $scrollLeft)
$: height = $rowHeight * $renderedRows.length + DefaultRowHeight
$: style = `left:${left}px; height:${height}px;`
$: visible = $isReordering && left >= minLeft
$: visible = $isReordering && left >= $bodyLeft
const getLeft = (targetColumn, displayColumn, scrollLeft) => {
const getLeft = (targetColumn, insertAfter, scrollLeft) => {
if (!targetColumn) {
return 0
}
let left = GutterWidth + (displayColumn?.width || 0) - scrollLeft
// If this is not the sticky column, add additional left space
if (!targetColumn.primaryDisplay) {
left += targetColumn.__left + targetColumn.width
let left = targetColumn.__left - scrollLeft
if (insertAfter) {
left += targetColumn.width
}
return left
}
</script>

View File

@ -1,41 +1,28 @@
<script>
import { getContext } from "svelte"
import { GutterWidth } from "../lib/constants"
const { resize, visibleColumns, displayColumn, isReordering, scrollLeft } =
const { resize, visibleColumns, isReordering, scrollLeft } =
getContext("grid")
$: offset = GutterWidth + ($displayColumn?.width || 0)
$: activeColumn = $resize.column
const getStyle = (column, offset, scrollLeft) => {
const left = offset + column.__left + column.width - scrollLeft
const getStyle = (column, scrollLeft) => {
let left = column.__left + column.width
if (!column.primaryDisplay) {
left -= scrollLeft
}
return `left:${left}px;`
}
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->
{#if !$isReordering}
{#if $displayColumn}
<div
class="resize-slider"
class:visible={activeColumn === $displayColumn.name}
on:mousedown={e => resize.actions.startResizing($displayColumn, e)}
on:touchstart={e => resize.actions.startResizing($displayColumn, e)}
on:dblclick={() => resize.actions.resetSize($displayColumn)}
style="left:{GutterWidth + $displayColumn.width}px;"
>
<div class="resize-indicator" />
</div>
{/if}
{#each $visibleColumns as column}
<div
class="resize-slider"
class:visible={activeColumn === column.name}
class:visible={$resize.column === column.name}
on:mousedown={e => resize.actions.startResizing(column, e)}
on:touchstart={e => resize.actions.startResizing(column, e)}
on:dblclick={() => resize.actions.resetSize(column)}
style={getStyle(column, offset, $scrollLeft)}
style={getStyle(column, $scrollLeft)}
>
<div class="resize-indicator" />
</div>

View File

@ -1,5 +1,5 @@
import { derived, get, writable } from "svelte/store"
import { DefaultColumnWidth } from "../lib/constants"
import { DefaultColumnWidth, GutterWidth } from "../lib/constants"
export const createStores = () => {
const columns = writable([])
@ -39,16 +39,16 @@ export const deriveStores = context => {
// Derived list of columns which have not been explicitly hidden, and enrich
// with an index so we can easily select nearby columns
const visibleColumns = derived(columns, $columns => {
let offset = 0
let offset = GutterWidth
return $columns
.filter(col => col.visible)
.map((column, idx) => {
.map((col, idx) => {
const enriched = {
...column,
...col,
__left: offset,
__idx: idx,
}
offset += column.width
offset += col.width
return enriched
})
})

View File

@ -4,10 +4,10 @@ import { parseEventLocation } from "../lib/utils"
const reorderInitialState = {
sourceColumn: null,
targetColumn: null,
insertAfter: false,
breakpoints: [],
gridLeft: 0,
width: 0,
latestX: 0,
increment: 0,
}
@ -35,10 +35,11 @@ export const createActions = context => {
bounds,
visibleColumns,
maxScrollLeft,
width,
datasource,
bodyLeft,
width,
} = context
let latestX = 0
let autoScrollInterval
let isAutoScrolling
@ -46,13 +47,25 @@ export const createActions = context => {
const startReordering = (column, e) => {
const $scrollableColumns = get(scrollableColumns)
const $bounds = get(bounds)
const $bodyLeft = get(bodyLeft)
// Generate new breakpoints for the current columns
const breakpoints = $scrollableColumns.map(col => ({
x: col.__left + col.width,
x: col.__left - $bodyLeft,
column: col.name,
insertAfter: false,
}))
// Add a very left breakpoint as well
const lastCol = $scrollableColumns[$scrollableColumns.length - 1]
if (lastCol) {
breakpoints.push({
x: lastCol.__left + lastCol.width - $bodyLeft,
column: lastCol.name,
insertAfter: true,
})
}
// Update state
reorder.set({
sourceColumn: column,
@ -77,10 +90,7 @@ export const createActions = context => {
const onReorderMouseMove = e => {
// Immediately handle the current position
const { x } = parseEventLocation(e)
reorder.update(state => ({
...state,
latestX: x,
}))
latestX = x
considerReorderPosition()
// Check if we need to start auto-scrolling
@ -110,20 +120,25 @@ export const createActions = context => {
const $scroll = get(scroll)
// Compute the closest breakpoint to the current position
let targetColumn
let breakpoint
let minDistance = Number.MAX_SAFE_INTEGER
const mouseX = $reorder.latestX - $reorder.gridLeft + $scroll.left
const mouseX = latestX - $reorder.gridLeft + $scroll.left
$reorder.breakpoints.forEach(point => {
const distance = Math.abs(point.x - mouseX)
if (distance < minDistance) {
minDistance = distance
targetColumn = point.column
breakpoint = point
}
})
if (targetColumn !== $reorder.targetColumn) {
if (
breakpoint &&
(breakpoint.column !== $reorder.targetColumn ||
breakpoint.insertAfter !== $reorder.insertAfter)
) {
reorder.update(state => ({
...state,
targetColumn,
targetColumn: breakpoint.column,
insertAfter: breakpoint.insertAfter,
}))
}
}

View File

@ -32,44 +32,40 @@ export const deriveStores = context => {
} = context
// Memoize store primitives
const stickyColumnWidth = derived(displayColumn, $col => $col?.width || 0, 0)
const bodyLeft = derived(displayColumn, $displayColumn => {
return ($displayColumn?.width || 0) + GutterWidth
})
// Derive vertical limits
const contentHeight = derived(
[rows, rowHeight],
([$rows, $rowHeight]) => ($rows.length + 1) * $rowHeight + Padding,
0
([$rows, $rowHeight]) => ($rows.length + 1) * $rowHeight + Padding
)
const maxScrollTop = derived(
[height, contentHeight],
([$height, $contentHeight]) => Math.max($contentHeight - $height, 0),
0
([$height, $contentHeight]) => Math.max($contentHeight - $height, 0)
)
// Derive horizontal limits
const contentWidth = derived(
[visibleColumns, stickyColumnWidth, buttonColumnWidth],
([$visibleColumns, $stickyColumnWidth, $buttonColumnWidth]) => {
[visibleColumns, buttonColumnWidth],
([$visibleColumns, $buttonColumnWidth]) => {
const space = Math.max(Padding, $buttonColumnWidth - 1)
let width = GutterWidth + space + $stickyColumnWidth
let width = GutterWidth + space
$visibleColumns.forEach(col => {
width += col.width
})
return width
},
0
)
const screenWidth = derived(
[width, stickyColumnWidth],
([$width, $stickyColumnWidth]) => $width + GutterWidth + $stickyColumnWidth,
0
}
)
const screenWidth = derived([width, bodyLeft], ([$width, $bodyLeft]) => {
return $width + $bodyLeft
})
const maxScrollLeft = derived(
[contentWidth, screenWidth],
([$contentWidth, $screenWidth]) => {
return Math.max($contentWidth - $screenWidth, 0)
},
0
}
)
// Derive whether to show scrollbars or not
@ -87,6 +83,7 @@ export const deriveStores = context => {
)
return {
bodyLeft,
contentHeight,
contentWidth,
screenWidth,