mirror of
https://github.com/docmost/docmost.git
synced 2026-07-25 19:04:45 +10: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 { Badge } from "@mantine/core";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
NO_VALUE_CHOICE_ID,
|
NO_VALUE_CHOICE_ID,
|
||||||
} from "@/features/base/types/base.types";
|
} from "@/features/base/types/base.types";
|
||||||
import { useKanbanGroups } from "@/features/base/hooks/use-kanban-groups";
|
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 { useUpdateViewMutation } from "@/features/base/queries/base-view-query";
|
||||||
import {
|
import {
|
||||||
useCreateRowMutation,
|
useCreateRowMutation,
|
||||||
@@ -56,6 +57,14 @@ export function BaseKanban({
|
|||||||
const updateRowMutation = useUpdateRowMutation();
|
const updateRowMutation = useUpdateRowMutation();
|
||||||
const reorderRowMutation = useReorderRowMutation();
|
const reorderRowMutation = useReorderRowMutation();
|
||||||
const sortsActive = (effectiveView?.config?.sorts?.length ?? 0) > 0;
|
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`
|
// Rules of Hooks: call useKanbanGroups unconditionally with `undefined`
|
||||||
// when not groupable; switch the render path on isGroupable below.
|
// 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.")}
|
{t("Sorted — cards within a column can't be reordered.")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={classes.board}>
|
<div ref={boardRef} className={classes.board}>
|
||||||
{columns.map((column) => (
|
{columns.map((column) => (
|
||||||
<KanbanColumn
|
<KanbanColumn
|
||||||
key={column.key}
|
key={column.key}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
import { KanbanColumnData } from "@/features/base/hooks/use-kanban-groups";
|
import { KanbanColumnData } from "@/features/base/hooks/use-kanban-groups";
|
||||||
import { IBaseProperty } from "@/features/base/types/base.types";
|
import { IBaseProperty } from "@/features/base/types/base.types";
|
||||||
import { KanbanCard } from "./kanban-card";
|
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 { CardDropPayload } from "@/features/base/hooks/use-kanban-card-drag";
|
||||||
import type { ColumnReorderPayload } from "@/features/base/hooks/use-kanban-column-reorder";
|
import type { ColumnReorderPayload } from "@/features/base/hooks/use-kanban-column-reorder";
|
||||||
import { useKanbanColumnDrop } from "@/features/base/hooks/use-kanban-column-drop";
|
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";
|
import classes from "@/features/base/styles/kanban.module.css";
|
||||||
|
|
||||||
type KanbanColumnProps = {
|
type KanbanColumnProps = {
|
||||||
@@ -33,6 +35,12 @@ export function KanbanColumn({
|
|||||||
columnKey: column.key,
|
columnKey: column.key,
|
||||||
onDrop: onCardDrop,
|
onDrop: onCardDrop,
|
||||||
});
|
});
|
||||||
|
const canScrollColumn = useCallback(
|
||||||
|
({ source }: { source: { data: Record<string, unknown> } }) =>
|
||||||
|
source.data.type === "base-kanban-card",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
useKanbanAutoScroll(bodyRef, canScrollColumn);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.column} data-column-key={column.key}>
|
<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