wheel & arrow Up/Down key events have added
This commit is contained in:
1 parent
11ffd47294
commit
77f985dad8
8 files changed
+203
-100
No files matched your search
@@ -54,6 +54,7 @@ export const Bar: React.FC<BarProps> = ({
|
||||
break;
|
||||
}
|
||||
}
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onMouseEnter={e => {
|
||||
onEventStart(e, "mouseenter", task);
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
outline: none;
|
||||
}
|
||||
@@ -43,20 +43,66 @@ export const Gantt: React.SFC<GanttProps> = ({
|
||||
onTaskDelete,
|
||||
}) => {
|
||||
const [ganttTasks, setGanttTasks] = useState<Task[]>(tasks);
|
||||
const [scroll, setScroll] = useState(0);
|
||||
const [scrollY, setScrollY] = useState(0);
|
||||
|
||||
const [startDate, endDate] = ganttDateRange(ganttTasks, viewMode);
|
||||
const dates = seedDates(startDate, endDate, viewMode);
|
||||
|
||||
const svgHeight = rowHeight * tasks.length;
|
||||
const gridWidth = dates.length * columnWidth;
|
||||
const ganttFullHeight = ganttTasks.length * rowHeight;
|
||||
|
||||
const onTasksDateChange = (tasks: Task[]) => {
|
||||
setGanttTasks(tasks);
|
||||
};
|
||||
|
||||
const handleScroll = (event: SyntheticEvent<HTMLDivElement>) => {
|
||||
setScroll(event.currentTarget.scrollTop);
|
||||
setScrollY(event.currentTarget.scrollTop);
|
||||
};
|
||||
|
||||
const handleWheel = (event: React.WheelEvent<HTMLDivElement>) => {
|
||||
const newScrollY = scrollY + event.deltaY;
|
||||
if (newScrollY < 0) {
|
||||
setScrollY(0);
|
||||
} else if (newScrollY > ganttFullHeight - ganttHeight) {
|
||||
setScrollY(ganttFullHeight - ganttHeight);
|
||||
} else {
|
||||
setScrollY(scrollY + event.deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
let newScrollY = 0;
|
||||
let isX = true;
|
||||
switch (event.key) {
|
||||
case "Down": // IE/Edge specific value
|
||||
case "ArrowDown":
|
||||
newScrollY = scrollY + rowHeight;
|
||||
isX = false;
|
||||
break;
|
||||
case "Up": // IE/Edge specific value
|
||||
case "ArrowUp":
|
||||
newScrollY = scrollY - rowHeight;
|
||||
isX = false;
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
// Do something for "left arrow" key press.
|
||||
break;
|
||||
case "Right": // IE/Edge specific value
|
||||
case "ArrowRight":
|
||||
// Do something for "right arrow" key press.
|
||||
break;
|
||||
}
|
||||
if (isX) {
|
||||
} else {
|
||||
if (newScrollY < 0) {
|
||||
setScrollY(0);
|
||||
} else if (newScrollY > ganttFullHeight - ganttHeight) {
|
||||
setScrollY(ganttFullHeight - ganttHeight);
|
||||
} else {
|
||||
setScrollY(newScrollY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const gridProps: GridProps = {
|
||||
@@ -110,7 +156,7 @@ export const Gantt: React.SFC<GanttProps> = ({
|
||||
tasks: ganttTasks,
|
||||
locale,
|
||||
headerHeight,
|
||||
scroll,
|
||||
scrollY,
|
||||
ganttHeight,
|
||||
horizontalContainerClass: styles.horizontalContainer,
|
||||
TaskListHeader,
|
||||
@@ -118,19 +164,25 @@ export const Gantt: React.SFC<GanttProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<div
|
||||
className={styles.wrapper}
|
||||
onWheel={handleWheel}
|
||||
onKeyDown={handleKeyDown}
|
||||
tabIndex={0}
|
||||
>
|
||||
{listCellWidth && <TaskList {...tableProps} />}
|
||||
<TaskGantt
|
||||
gridProps={gridProps}
|
||||
calendarProps={calendarProps}
|
||||
barProps={barProps}
|
||||
ganttHeight={ganttHeight}
|
||||
scroll={scroll}
|
||||
scrollY={scrollY}
|
||||
/>
|
||||
<Scroll
|
||||
ganttFullHeight={ganttTasks.length * rowHeight}
|
||||
ganttFullHeight={ganttFullHeight}
|
||||
ganttHeight={ganttHeight}
|
||||
headerHeight={headerHeight}
|
||||
scroll={scrollY}
|
||||
onScroll={handleScroll}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@ export type GanttContentMoveAction =
|
||||
| BarMoveAction;
|
||||
export type BarEvent = {
|
||||
selectedTask?: BarTask;
|
||||
originalTask?: BarTask;
|
||||
action: GanttContentMoveAction;
|
||||
};
|
||||
export type TaskGanttContentProps = {
|
||||
@@ -143,7 +144,7 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
||||
}
|
||||
} else if (action === "mouseenter") {
|
||||
if (!barEvent.action) {
|
||||
setBarEvent({ action, selectedTask });
|
||||
setBarEvent({ action, selectedTask, originalTask: selectedTask });
|
||||
}
|
||||
} else if (action === "mouseleave") {
|
||||
if (barEvent.action === "mouseenter") {
|
||||
@@ -156,13 +157,14 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
||||
svg.current.getScreenCTM()?.inverse()
|
||||
);
|
||||
setInitEventX1Delta(cursor.x - selectedTask.x1);
|
||||
setBarEvent({ action, selectedTask });
|
||||
setBarEvent({ action, selectedTask, originalTask: selectedTask });
|
||||
} else if (action === "dblclick") {
|
||||
!!onDoubleClick && onDoubleClick(selectedTask);
|
||||
} else {
|
||||
setBarEvent({
|
||||
action,
|
||||
selectedTask,
|
||||
originalTask: selectedTask,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -194,8 +196,9 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
||||
};
|
||||
|
||||
const handleMouseUp = async (event: MouseEvent) => {
|
||||
const { selectedTask, action } = barEvent;
|
||||
if (!selectedTask || !point || !svg?.current) return;
|
||||
const { selectedTask, action, originalTask } = barEvent;
|
||||
|
||||
if (!selectedTask || !point || !svg?.current || !originalTask) return;
|
||||
event.preventDefault();
|
||||
|
||||
point.x = event.clientX;
|
||||
@@ -211,16 +214,23 @@ export const TaskGanttContent: React.FC<TaskGanttContentProps> = ({
|
||||
timeStep,
|
||||
initEventX1Delta
|
||||
);
|
||||
|
||||
const isNotLikeOriginal =
|
||||
originalTask.start !== changedTask.start ||
|
||||
originalTask.end !== changedTask.end ||
|
||||
originalTask.progress !== changedTask.progress;
|
||||
|
||||
if (
|
||||
(action === "move" || action === "end" || action === "start") &&
|
||||
onDateChange
|
||||
onDateChange &&
|
||||
isNotLikeOriginal
|
||||
) {
|
||||
await onDateChange(changedTask);
|
||||
const newTasks = barTasks.map(t =>
|
||||
t.id === changedTask.id ? changedTask : t
|
||||
);
|
||||
onTasksDateChange(newTasks);
|
||||
} else if (onProgressChange) {
|
||||
} else if (onProgressChange && isNotLikeOriginal) {
|
||||
await onProgressChange(changedTask);
|
||||
}
|
||||
svg.current.removeEventListener("mousemove", handleMouseMove);
|
||||
|
||||
@@ -9,14 +9,14 @@ export type TaskGanttProps = {
|
||||
calendarProps: CalendarProps;
|
||||
barProps: TaskGanttContentProps;
|
||||
ganttHeight: number;
|
||||
scroll: number;
|
||||
scrollY: number;
|
||||
};
|
||||
export const TaskGantt: React.FC<TaskGanttProps> = ({
|
||||
gridProps,
|
||||
calendarProps,
|
||||
barProps,
|
||||
ganttHeight,
|
||||
scroll,
|
||||
scrollY,
|
||||
}) => {
|
||||
const ganttSVGRef = useRef<SVGSVGElement>(null);
|
||||
const horizontalContainerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -24,9 +24,9 @@ export const TaskGantt: React.FC<TaskGanttProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (horizontalContainerRef.current) {
|
||||
horizontalContainerRef.current.scrollTop = scroll;
|
||||
horizontalContainerRef.current.scrollTop = scrollY;
|
||||
}
|
||||
}, [scroll]);
|
||||
}, [scrollY]);
|
||||
|
||||
return (
|
||||
<div className={styles.ganttVerticalContainer}>
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
import React, { SyntheticEvent } from "react";
|
||||
import React, { SyntheticEvent, useRef, useEffect } from "react";
|
||||
import styles from "./scroll.module.css";
|
||||
|
||||
export const Scroll: React.FC<{
|
||||
scroll: number;
|
||||
ganttHeight: number;
|
||||
ganttFullHeight: number;
|
||||
headerHeight: number;
|
||||
onScroll: (event: SyntheticEvent<HTMLDivElement>) => void;
|
||||
}> = ({ ganttHeight, ganttFullHeight, headerHeight, onScroll }) => {
|
||||
}> = ({ scroll, ganttHeight, ganttFullHeight, headerHeight, onScroll }) => {
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
scrollRef.current.scrollTop = scroll;
|
||||
}
|
||||
}, [scroll]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ height: ganttHeight, marginTop: headerHeight }}
|
||||
className={styles.scroll}
|
||||
onScroll={onScroll}
|
||||
ref={scrollRef}
|
||||
>
|
||||
<div style={{ height: ganttFullHeight, width: 1 }} />
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export type TaskListProps = {
|
||||
fontSize: string;
|
||||
rowHeight: number;
|
||||
ganttHeight: number;
|
||||
scroll: number;
|
||||
scrollY: number;
|
||||
locale: string;
|
||||
tasks: Task[];
|
||||
horizontalContainerClass?: string;
|
||||
@@ -34,7 +34,7 @@ export const TaskList: React.FC<TaskListProps> = ({
|
||||
fontSize,
|
||||
rowWidth,
|
||||
rowHeight,
|
||||
scroll,
|
||||
scrollY,
|
||||
tasks,
|
||||
locale,
|
||||
ganttHeight,
|
||||
@@ -45,9 +45,9 @@ export const TaskList: React.FC<TaskListProps> = ({
|
||||
const horizontalContainerRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (horizontalContainerRef.current) {
|
||||
horizontalContainerRef.current.scrollTop = scroll;
|
||||
horizontalContainerRef.current.scrollTop = scrollY;
|
||||
}
|
||||
}, [scroll]);
|
||||
}, [scrollY]);
|
||||
|
||||
const headerProps = {
|
||||
headerHeight,
|
||||
|
||||
Reference in new issue
Block a user