Update grid to support dragging to scroll via touch events
This commit is contained in:
parent
647becd52c
commit
0a1070a4f2
|
@ -35,7 +35,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={body} class="grid-body">
|
<div bind:this={body} class="grid-body">
|
||||||
<GridScrollWrapper scrollHorizontally scrollVertically wheelInteractive>
|
<GridScrollWrapper scrollHorizontally scrollVertically attachHandlers>
|
||||||
{#each $renderedRows as row, idx}
|
{#each $renderedRows as row, idx}
|
||||||
<GridRow
|
<GridRow
|
||||||
{row}
|
{row}
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
|
|
||||||
export let scrollVertically = false
|
export let scrollVertically = false
|
||||||
export let scrollHorizontally = false
|
export let scrollHorizontally = false
|
||||||
export let wheelInteractive = false
|
export let attachHandlers = false
|
||||||
|
|
||||||
|
// Used for tracking touch events
|
||||||
|
let initialTouchX
|
||||||
|
let initialTouchY
|
||||||
|
|
||||||
$: style = generateStyle($scroll, $rowHeight, $hiddenColumnsWidth)
|
$: style = generateStyle($scroll, $rowHeight, $hiddenColumnsWidth)
|
||||||
|
|
||||||
|
@ -27,17 +31,47 @@
|
||||||
return `transform: translate3d(${offsetX}px, ${offsetY}px, 0);`
|
return `transform: translate3d(${offsetX}px, ${offsetY}px, 0);`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles a wheel even and updates the scroll offsets
|
// Handles a mouse wheel event and updates scroll state
|
||||||
const handleWheel = e => {
|
const handleWheel = e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
debouncedHandleWheel(e.deltaX, e.deltaY, e.clientY)
|
updateScroll(e.deltaX, e.deltaY, e.clientY)
|
||||||
|
|
||||||
// If a context menu was visible, hide it
|
// If a context menu was visible, hide it
|
||||||
if ($menu.visible) {
|
if ($menu.visible) {
|
||||||
menu.actions.close()
|
menu.actions.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const debouncedHandleWheel = domDebounce((deltaX, deltaY, clientY) => {
|
|
||||||
|
// Handles touch start events
|
||||||
|
const handleTouchStart = e => {
|
||||||
|
if (!e.touches?.[0]) return
|
||||||
|
initialTouchX = e.touches[0].clientX
|
||||||
|
initialTouchY = e.touches[0].clientY
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles touch move events and updates scroll state
|
||||||
|
const handleTouchMove = e => {
|
||||||
|
if (!e.touches?.[0]) return
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
// Compute delta from previous event, and update scroll
|
||||||
|
const deltaX = initialTouchX - e.touches[0].clientX
|
||||||
|
const deltaY = initialTouchY - e.touches[0].clientY
|
||||||
|
updateScroll(deltaX, deltaY)
|
||||||
|
|
||||||
|
// Store position to reference in next event
|
||||||
|
initialTouchX = e.touches[0].clientX
|
||||||
|
initialTouchY = e.touches[0].clientY
|
||||||
|
|
||||||
|
// If a context menu was visible, hide it
|
||||||
|
if ($menu.visible) {
|
||||||
|
menu.actions.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the scroll offset by a certain delta, and ensure scrolling
|
||||||
|
// stays within sensible bounds. Debounced for performance.
|
||||||
|
const updateScroll = domDebounce((deltaX, deltaY, clientY) => {
|
||||||
const { top, left } = $scroll
|
const { top, left } = $scroll
|
||||||
|
|
||||||
// Calculate new scroll top
|
// Calculate new scroll top
|
||||||
|
@ -55,15 +89,19 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
// Hover row under cursor
|
// Hover row under cursor
|
||||||
|
if (clientY != null) {
|
||||||
const y = clientY - $bounds.top + (newScrollTop % $rowHeight)
|
const y = clientY - $bounds.top + (newScrollTop % $rowHeight)
|
||||||
const hoveredRow = $renderedRows[Math.floor(y / $rowHeight)]
|
const hoveredRow = $renderedRows[Math.floor(y / $rowHeight)]
|
||||||
hoveredRowId.set(hoveredRow?._id)
|
hoveredRowId.set(hoveredRow?._id)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="outer"
|
class="outer"
|
||||||
on:wheel={wheelInteractive ? handleWheel : null}
|
on:wheel={attachHandlers ? handleWheel : null}
|
||||||
|
on:touchstart={attachHandlers ? handleTouchStart : null}
|
||||||
|
on:touchmove={attachHandlers ? handleTouchMove : null}
|
||||||
on:click|self={() => ($focusedCellId = null)}
|
on:click|self={() => ($focusedCellId = null)}
|
||||||
>
|
>
|
||||||
<div {style} class="inner">
|
<div {style} class="inner">
|
||||||
|
|
|
@ -205,7 +205,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="normal-columns" transition:fade|local={{ duration: 130 }}>
|
<div class="normal-columns" transition:fade|local={{ duration: 130 }}>
|
||||||
<GridScrollWrapper scrollHorizontally wheelInteractive>
|
<GridScrollWrapper scrollHorizontally attachHandlers>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{#each $renderedColumns as column, columnIdx}
|
{#each $renderedColumns as column, columnIdx}
|
||||||
{@const cellId = `new-${column.name}`}
|
{@const cellId = `new-${column.name}`}
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
|
<div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
|
||||||
<GridScrollWrapper scrollVertically wheelInteractive>
|
<GridScrollWrapper scrollVertically attachHandlers>
|
||||||
{#each $renderedRows as row, idx}
|
{#each $renderedRows as row, idx}
|
||||||
{@const rowSelected = !!$selectedRows[row._id]}
|
{@const rowSelected = !!$selectedRows[row._id]}
|
||||||
{@const rowHovered = $hoveredRowId === row._id}
|
{@const rowHovered = $hoveredRowId === row._id}
|
||||||
|
|
Loading…
Reference in New Issue