Fix columnn reordering
This commit is contained in:
parent
0eadca9acb
commit
e9b801e205
|
@ -37,6 +37,16 @@
|
||||||
const newRows = writable([])
|
const newRows = writable([])
|
||||||
const visibleRows = writable([0, 0])
|
const visibleRows = writable([0, 0])
|
||||||
const visibleColumns = writable([0, 0])
|
const visibleColumns = writable([0, 0])
|
||||||
|
const scroll = writable({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
})
|
||||||
|
const bounds = writable({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
})
|
||||||
|
|
||||||
// Build up spreadsheet context and additional stores
|
// Build up spreadsheet context and additional stores
|
||||||
const context = {
|
const context = {
|
||||||
|
@ -52,6 +62,8 @@
|
||||||
cellHeight,
|
cellHeight,
|
||||||
visibleRows,
|
visibleRows,
|
||||||
visibleColumns,
|
visibleColumns,
|
||||||
|
bounds,
|
||||||
|
scroll,
|
||||||
}
|
}
|
||||||
const { reorder, reorderPlaceholder } = createReorderStores(context)
|
const { reorder, reorderPlaceholder } = createReorderStores(context)
|
||||||
const resize = createResizeStore(context)
|
const resize = createResizeStore(context)
|
||||||
|
|
|
@ -10,18 +10,18 @@
|
||||||
visibleColumns,
|
visibleColumns,
|
||||||
cellHeight,
|
cellHeight,
|
||||||
rows,
|
rows,
|
||||||
|
bounds,
|
||||||
|
scroll,
|
||||||
} = getContext("spreadsheet")
|
} = getContext("spreadsheet")
|
||||||
|
|
||||||
const padding = 180
|
const padding = 180
|
||||||
|
|
||||||
let ref
|
let ref
|
||||||
let width
|
|
||||||
let height
|
|
||||||
let scrollLeft = 0
|
let scrollLeft = 0
|
||||||
let scrollTop = 0
|
let scrollTop = 0
|
||||||
|
|
||||||
$: updateVisibleRows($columns, scrollTop, height)
|
$: updateVisibleRows($columns, scrollTop, $bounds.height)
|
||||||
$: updateVisibleColumns($columns, scrollLeft, width)
|
$: updateVisibleColumns($columns, scrollLeft, $bounds.width)
|
||||||
$: contentHeight = ($rows.length + 2) * cellHeight + padding
|
$: contentHeight = ($rows.length + 2) * cellHeight + padding
|
||||||
$: contentWidth = computeContentWidth($columns)
|
$: contentWidth = computeContentWidth($columns)
|
||||||
$: horizontallyScrolled = scrollLeft > 0
|
$: horizontallyScrolled = scrollLeft > 0
|
||||||
|
@ -57,12 +57,16 @@
|
||||||
|
|
||||||
const handleScroll = domDebounce(
|
const handleScroll = domDebounce(
|
||||||
({ left, top }) => {
|
({ left, top }) => {
|
||||||
|
// Only update local state when big changes occur
|
||||||
if (Math.abs(top - scrollTop) > 100) {
|
if (Math.abs(top - scrollTop) > 100) {
|
||||||
scrollTop = top
|
scrollTop = top
|
||||||
}
|
}
|
||||||
if (left === 0 || Math.abs(left - scrollLeft) > 100) {
|
if (left === 0 || Math.abs(left - scrollLeft) > 100) {
|
||||||
scrollLeft = left
|
scrollLeft = left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always update store
|
||||||
|
scroll.set({ left, top })
|
||||||
},
|
},
|
||||||
e => ({ left: e.target.scrollLeft, top: e.target.scrollTop })
|
e => ({ left: e.target.scrollLeft, top: e.target.scrollTop })
|
||||||
)
|
)
|
||||||
|
@ -81,6 +85,7 @@
|
||||||
if (!columns.length) {
|
if (!columns.length) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute column visibility
|
// Compute column visibility
|
||||||
let startColIdx = 1
|
let startColIdx = 1
|
||||||
let rightEdge = columns[1].width
|
let rightEdge = columns[1].width
|
||||||
|
@ -99,9 +104,8 @@
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Observe and record the height of the body
|
// Observe and record the height of the body
|
||||||
const observer = new ResizeObserver(entries => {
|
const observer = new ResizeObserver(() => {
|
||||||
width = entries[0].contentRect.width
|
bounds.set(ref.getBoundingClientRect())
|
||||||
height = entries[0].contentRect.height
|
|
||||||
})
|
})
|
||||||
observer.observe(ref)
|
observer.observe(ref)
|
||||||
return () => {
|
return () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { get, writable } from "svelte/store"
|
import { get, writable } from "svelte/store"
|
||||||
|
|
||||||
export const createReorderStores = context => {
|
export const createReorderStores = context => {
|
||||||
const { columns, rand, rows } = context
|
const { columns, bounds, rows, scroll } = context
|
||||||
const reorderInitialState = {
|
const reorderInitialState = {
|
||||||
columnIdx: null,
|
columnIdx: null,
|
||||||
swapColumnIdx: null,
|
swapColumnIdx: null,
|
||||||
|
@ -23,22 +23,20 @@ export const createReorderStores = context => {
|
||||||
|
|
||||||
// Callback when dragging on a colum header and starting reordering
|
// Callback when dragging on a colum header and starting reordering
|
||||||
const startReordering = (columnIdx, e) => {
|
const startReordering = (columnIdx, e) => {
|
||||||
|
const $columns = get(columns)
|
||||||
|
const $bounds = get(bounds)
|
||||||
|
const $rows = get(rows)
|
||||||
|
const $scroll = get(scroll)
|
||||||
|
|
||||||
// Generate new breakpoints for the current columns
|
// Generate new breakpoints for the current columns
|
||||||
let breakpoints = []
|
let breakpoints = []
|
||||||
const cols = get(columns)
|
$columns.forEach((col, idx) => {
|
||||||
cols.forEach((col, idx) => {
|
|
||||||
breakpoints.push(col.left)
|
breakpoints.push(col.left)
|
||||||
if (idx === cols.length - 1) {
|
if (idx === $columns.length - 1) {
|
||||||
breakpoints.push(col.left + col.width)
|
breakpoints.push(col.left + col.width)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(breakpoints, e.clientX)
|
const self = $columns[columnIdx]
|
||||||
|
|
||||||
// Get bounds of the selected header and sheet body
|
|
||||||
|
|
||||||
const self = cols[columnIdx]
|
|
||||||
const body = document.getElementById(`sheet-${rand}-body`)
|
|
||||||
const bodyBounds = body.getBoundingClientRect()
|
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
reorder.set({
|
reorder.set({
|
||||||
|
@ -48,10 +46,13 @@ export const createReorderStores = context => {
|
||||||
initialMouseX: e.clientX,
|
initialMouseX: e.clientX,
|
||||||
})
|
})
|
||||||
placeholder.set({
|
placeholder.set({
|
||||||
initialX: self.left - bodyBounds.x,
|
initialX: self.left,
|
||||||
x: self.left - bodyBounds.x,
|
x: self.left,
|
||||||
width: self.width,
|
width: self.width,
|
||||||
height: (get(rows).length + 2) * 32,
|
height: ($rows.length + 2) * 32,
|
||||||
|
sheetLeft: $bounds.left,
|
||||||
|
maxX: $bounds.width - self.width,
|
||||||
|
scrollLeft: $scroll.left,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add listeners to handle mouse movement
|
// Add listeners to handle mouse movement
|
||||||
|
@ -71,14 +72,21 @@ export const createReorderStores = context => {
|
||||||
|
|
||||||
// Compute new placeholder position
|
// Compute new placeholder position
|
||||||
const $placeholder = get(placeholder)
|
const $placeholder = get(placeholder)
|
||||||
let newX = e.clientX - $reorder.initialMouseX + $placeholder.initialX
|
let newX =
|
||||||
|
e.clientX -
|
||||||
|
$reorder.initialMouseX +
|
||||||
|
$placeholder.initialX -
|
||||||
|
$placeholder.scrollLeft
|
||||||
newX = Math.max(0, newX)
|
newX = Math.max(0, newX)
|
||||||
|
newX = Math.min($placeholder.maxX, newX)
|
||||||
|
|
||||||
// Compute the closest breakpoint to the current position
|
// Compute the closest breakpoint to the current position
|
||||||
let swapColumnIdx
|
let swapColumnIdx
|
||||||
let minDistance = Number.MAX_SAFE_INTEGER
|
let minDistance = Number.MAX_SAFE_INTEGER
|
||||||
$reorder.breakpoints.forEach((point, idx) => {
|
$reorder.breakpoints.forEach((point, idx) => {
|
||||||
const distance = Math.abs(point - e.clientX)
|
const distance = Math.abs(
|
||||||
|
point - e.clientX + $placeholder.sheetLeft - $placeholder.scrollLeft
|
||||||
|
)
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
minDistance = distance
|
minDistance = distance
|
||||||
swapColumnIdx = idx
|
swapColumnIdx = idx
|
||||||
|
@ -108,8 +116,16 @@ export const createReorderStores = context => {
|
||||||
swapColumnIdx++
|
swapColumnIdx++
|
||||||
}
|
}
|
||||||
state.splice(swapColumnIdx, 0, removed[0])
|
state.splice(swapColumnIdx, 0, removed[0])
|
||||||
state = state.map((col, idx) => ({ ...col, idx }))
|
let offset = 40
|
||||||
return state
|
return state.map((col, idx) => {
|
||||||
|
const newCol = {
|
||||||
|
...col,
|
||||||
|
idx,
|
||||||
|
left: offset,
|
||||||
|
}
|
||||||
|
offset += col.width
|
||||||
|
return newCol
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reset state
|
// Reset state
|
||||||
|
|
Loading…
Reference in New Issue