added autoscroll on drag + style fixes

This commit is contained in:
Pavel Laptev 2024-03-28 15:55:47 +01:00 committed by Mattias Granlund
parent 585bd463b8
commit a49ccc3eee
2 changed files with 37 additions and 5 deletions

View File

@ -90,6 +90,7 @@
use:draggable={{
data: new DraggableFile($branch?.id || '', file, selectedFiles),
disabled: readonly || isUnapplied,
viewportId: 'board-viewport',
selector: '.selected-draggable'
}}
role="button"
@ -137,7 +138,7 @@
user-select: none;
outline: none;
background: var(--clr-theme-container-light);
border: 1px solid var(--clr-theme-container-light);
border: 1px solid transparent;
&:not(.selected-draggable):hover {
background-color: color-mix(
@ -187,7 +188,8 @@
}
.selected-draggable {
background-color: var(--clr-scale-pop-80);
background-color: var(--clr-theme-scale-pop-80);
border: 1px solid var(--clr-theme-container-light);
&:hover {
background-color: color-mix(

View File

@ -5,6 +5,7 @@ export interface DraggableConfig {
readonly selector?: string;
readonly disabled?: boolean;
readonly data?: DraggableFile | DraggableHunk | DraggableCommit;
readonly viewportId?: string;
}
export function applyContainerStyle(element: HTMLElement) {
@ -14,11 +15,19 @@ export function applyContainerStyle(element: HTMLElement) {
element.style.padding = '30px'; // To prevent clipping of rotated element
}
export function createContainerForMultiDrag(children: Element[]): HTMLDivElement {
export function createContainerForMultiDrag(
children: Element[],
containerWidth: number
): HTMLDivElement {
const inner = document.createElement('div');
inner.style.display = 'flex';
inner.style.flexDirection = 'column';
inner.style.gap = 'var(--size-2)';
// need to set the width in order to make all the children have the same width
// this is necessary for the tree view where the children are nested and have different widths
inner.style.width = containerWidth + 'px';
children.forEach((child) => {
inner.appendChild(cloneWithPreservedDimensions(child));
});
@ -34,7 +43,7 @@ export function createContainerForMultiDrag(children: Element[]): HTMLDivElement
export function cloneWithPreservedDimensions(node: any) {
const clone = node.cloneNode(true) as HTMLElement;
clone.style.height = node.clientHeight + 'px';
clone.style.width = node.clientWidth + 'px';
clone.classList.remove('selected-draggable');
return clone;
}
@ -96,7 +105,8 @@ export function draggable(node: HTMLElement, opts: DraggableConfig) {
);
if (selectedElements.length > 0) {
clone = createContainerForMultiDrag(selectedElements);
const firstChildWidth = selectedElements[0].clientWidth;
clone = createContainerForMultiDrag(selectedElements, firstChildWidth);
// Dim the original element while dragging
selectedElements.forEach((element) => {
@ -212,10 +222,29 @@ export function draggable(node: HTMLElement, opts: DraggableConfig) {
e.stopPropagation();
}
const viewport = opts.viewportId ? document.getElementById(opts.viewportId) : null;
const triggerRange = 100;
const scrollSpeed = 5;
function handleDrag(e: DragEvent) {
if (!viewport) return;
const viewportWidth = viewport.clientWidth;
const relativeX = e.clientX - viewport.getBoundingClientRect().left;
// Scroll horizontally if the draggable is near the edge of the viewport
if (relativeX < triggerRange) {
viewport.scrollBy(-scrollSpeed, 0);
} else if (relativeX > viewportWidth - triggerRange) {
viewport.scrollBy(scrollSpeed, 0);
}
}
function setup(opts: DraggableConfig) {
if (opts.disabled) return;
node.draggable = true;
node.addEventListener('dragstart', handleDragStart);
node.addEventListener('drag', handleDrag);
node.addEventListener('dragend', handleDragEnd);
node.addEventListener('mousedown', handleMouseDown, { capture: false });
}
@ -223,6 +252,7 @@ export function draggable(node: HTMLElement, opts: DraggableConfig) {
function clean() {
node.draggable = false;
node.removeEventListener('dragstart', handleDragStart);
node.removeEventListener('drag', handleDrag);
node.removeEventListener('dragend', handleDragEnd);
}