mirror of
https://github.com/docmost/docmost.git
synced 2026-06-10 10:13:01 +08:00
feat(bases): auto-scroll the kanban board and columns during drag
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import { Badge } from "@mantine/core";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
NO_VALUE_CHOICE_ID,
|
||||
} from "@/features/base/types/base.types";
|
||||
import { useKanbanGroups } from "@/features/base/hooks/use-kanban-groups";
|
||||
import { useKanbanAutoScroll } from "@/features/base/hooks/use-kanban-auto-scroll";
|
||||
import { useUpdateViewMutation } from "@/features/base/queries/base-view-query";
|
||||
import {
|
||||
useCreateRowMutation,
|
||||
@@ -56,6 +57,14 @@ export function BaseKanban({
|
||||
const updateRowMutation = useUpdateRowMutation();
|
||||
const reorderRowMutation = useReorderRowMutation();
|
||||
const sortsActive = (effectiveView?.config?.sorts?.length ?? 0) > 0;
|
||||
const boardRef = useRef<HTMLDivElement>(null);
|
||||
const canScrollBoard = useCallback(
|
||||
({ source }: { source: { data: Record<string, unknown> } }) =>
|
||||
source.data.type === "base-kanban-card" ||
|
||||
source.data.type === "base-kanban-column",
|
||||
[],
|
||||
);
|
||||
useKanbanAutoScroll(boardRef, canScrollBoard);
|
||||
|
||||
// Rules of Hooks: call useKanbanGroups unconditionally with `undefined`
|
||||
// when not groupable; switch the render path on isGroupable below.
|
||||
@@ -253,7 +262,7 @@ export function BaseKanban({
|
||||
{t("Sorted — cards within a column can't be reordered.")}
|
||||
</div>
|
||||
)}
|
||||
<div className={classes.board}>
|
||||
<div ref={boardRef} className={classes.board}>
|
||||
{columns.map((column) => (
|
||||
<KanbanColumn
|
||||
key={column.key}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { KanbanColumnData } from "@/features/base/hooks/use-kanban-groups";
|
||||
import { IBaseProperty } from "@/features/base/types/base.types";
|
||||
import { KanbanCard } from "./kanban-card";
|
||||
@@ -6,6 +7,7 @@ import { KanbanAddCardButton } from "./kanban-add-card-button";
|
||||
import type { CardDropPayload } from "@/features/base/hooks/use-kanban-card-drag";
|
||||
import type { ColumnReorderPayload } from "@/features/base/hooks/use-kanban-column-reorder";
|
||||
import { useKanbanColumnDrop } from "@/features/base/hooks/use-kanban-column-drop";
|
||||
import { useKanbanAutoScroll } from "@/features/base/hooks/use-kanban-auto-scroll";
|
||||
import classes from "@/features/base/styles/kanban.module.css";
|
||||
|
||||
type KanbanColumnProps = {
|
||||
@@ -33,6 +35,12 @@ export function KanbanColumn({
|
||||
columnKey: column.key,
|
||||
onDrop: onCardDrop,
|
||||
});
|
||||
const canScrollColumn = useCallback(
|
||||
({ source }: { source: { data: Record<string, unknown> } }) =>
|
||||
source.data.type === "base-kanban-card",
|
||||
[],
|
||||
);
|
||||
useKanbanAutoScroll(bodyRef, canScrollColumn);
|
||||
|
||||
return (
|
||||
<div className={classes.column} data-column-key={column.key}>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { useEffect, RefObject } from "react";
|
||||
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
|
||||
|
||||
export function useKanbanAutoScroll(
|
||||
ref: RefObject<HTMLElement | null>,
|
||||
canScroll: ({
|
||||
source,
|
||||
}: {
|
||||
source: { data: Record<string, unknown> };
|
||||
}) => boolean = () => true,
|
||||
) {
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
return autoScrollForElements({ element: el, canScroll });
|
||||
}, [ref, canScroll]);
|
||||
}
|
||||
Reference in New Issue
Block a user