Skip to content

Commit

Permalink
Merge pull request #6 from MaTeMaTuK/dev
Browse files Browse the repository at this point in the history
vertical scroll fix
  • Loading branch information
MaTeMaTuK authored May 3, 2021
2 parents dcc351c + ecc502c commit 605b7fc
Show file tree
Hide file tree
Showing 12 changed files with 4,398 additions and 8,598 deletions.
7,202 changes: 2,653 additions & 4,549 deletions example/package-lock.json

Large diffs are not rendered by default.

5,609 changes: 1,623 additions & 3,986 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gantt-task-react",
"version": "0.3.0",
"version": "0.3.1",
"description": "Interactive Gantt Chart for React with TypeScript.",
"author": "MaTeMaTuK <[email protected]>",
"homepage": "https://github.com/MaTeMaTuK/gantt-task-react",
Expand Down Expand Up @@ -39,15 +39,15 @@
"react": "^16.0.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@types/jest": "^25.1.4",
"@types/node": "^12.20.4",
"@types/react": "^16.14.4",
"@types/react-dom": "^16.9.11",
"@typescript-eslint/eslint-plugin": "^4.7.0",
"@typescript-eslint/parser": "^4.7.0",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.8",
"@types/jest": "^26.0.23",
"@types/node": "^15.0.1",
"@types/react": "^17.0.4",
"@types/react-dom": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"babel-eslint": "^10.0.3",
"cross-env": "^7.0.3",
"eslint-config-prettier": "^6.15.0",
Expand All @@ -59,7 +59,7 @@
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-standard": "^4.1.0",
"gh-pages": "^2.2.0",
"gh-pages": "^3.1.0",
"microbundle-crl": "^0.13.11",
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
Expand Down
5 changes: 2 additions & 3 deletions src/components/gantt/gantt.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.ganttVerticalContainer {
overflow-x: auto;
overflow-y: hidden;
overflow: hidden;
font-size: 0;
margin: 0;
padding: 0;
Expand All @@ -9,7 +8,7 @@
.horizontalContainer {
margin: 0;
padding: 0;
overflow-y: hidden;
overflow: hidden;
}

.wrapper {
Expand Down
99 changes: 64 additions & 35 deletions src/components/gantt/gantt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { TaskGanttContentProps } from "./task-gantt-content";
import { TaskListHeaderDefault } from "../task-list/task-list-header";
import { TaskListTableDefault } from "../task-list/task-list-table";
import { StandardTooltipContent } from "../other/tooltip";
import { Scroll } from "../other/scroll";
import { VerticalScroll } from "../other/vertical-scroll";
import { TaskListProps, TaskList } from "../task-list/task-list";
import { TaskGantt } from "./task-gantt";
import { BarTask } from "../../types/bar-task";
import { convertToBarTasks } from "../../helpers/bar-helper";
import { GanttEvent } from "../../types/gantt-task-actions";
import { DateSetup } from "../../types/date-setup";
import styles from "./gantt.module.css";
import { HorizontalScroll } from "../other/horizontal-scroll";

export const Gantt: React.FunctionComponent<GanttProps> = ({
tasks,
Expand Down Expand Up @@ -54,12 +55,15 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
onSelect,
}) => {
const wrapperRef = useRef<HTMLDivElement>(null);
const taskListRef = useRef<HTMLDivElement>(null);
const verticalGanttContainerRef = useRef<HTMLDivElement>(null);
const [dateSetup, setDateSetup] = useState<DateSetup>(() => {
const [startDate, endDate] = ganttDateRange(tasks, viewMode);
return { viewMode, dates: seedDates(startDate, endDate, viewMode) };
});

const [taskHeight, setTaskHeight] = useState((rowHeight * barFill) / 100);
const [taskListWidth, setTaskListWidth] = useState(0);
const [barTasks, setBarTasks] = useState<BarTask[]>([]);
const [ganttEvent, setGanttEvent] = useState<GanttEvent>({
action: "",
Expand Down Expand Up @@ -165,27 +169,43 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
}
}, [rowHeight, barFill, taskHeight]);

useEffect(() => {
if (taskListRef.current) {
setTaskListWidth(taskListRef.current.offsetWidth);
}
}, [taskListRef]);

// scroll events
useEffect(() => {
const handleWheel = (event: WheelEvent) => {
event.preventDefault();
const newScrollY = scrollY + event.deltaY;
if (newScrollY < 0) {
setScrollY(0);
} else if (newScrollY > ganttFullHeight - ganttHeight) {
setScrollY(ganttFullHeight - ganttHeight);
if (event.shiftKey || event.deltaX) {
const scrollMove = event.deltaX ? event.deltaX : event.deltaY;
let newScrollX = scrollX + scrollMove;
if (newScrollX < 0) {
newScrollX = 0;
} else if (newScrollX > svgWidth) {
newScrollX = svgWidth;
}
setScrollX(newScrollX);
event.preventDefault();
} else {
setScrollY(newScrollY);
let newScrollY = scrollY + event.deltaY;
if (newScrollY < 0) {
newScrollY = 0;
} else if (newScrollY > ganttFullHeight - ganttHeight) {
newScrollY = ganttFullHeight - ganttHeight;
}
if (newScrollY !== scrollY) {
setScrollY(newScrollY);
event.preventDefault();
}
}

setIgnoreScrollEvent(true);
};

// subscribe if scroll is necessary
if (
wrapperRef.current &&
ganttHeight &&
ganttHeight < barTasks.length * rowHeight
) {
if (wrapperRef.current) {
wrapperRef.current.addEventListener("wheel", handleWheel, {
passive: false,
});
Expand All @@ -195,7 +215,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
wrapperRef.current.removeEventListener("wheel", handleWheel);
}
};
}, [wrapperRef.current, scrollY, ganttHeight, barTasks, rowHeight]);
}, [wrapperRef.current, scrollY, scrollX, ganttHeight, svgWidth]);

const handleScrollY = (event: SyntheticEvent<HTMLDivElement>) => {
if (scrollY !== event.currentTarget.scrollTop && !ignoreScrollEvent) {
Expand Down Expand Up @@ -330,34 +350,43 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
ganttHeight,
horizontalContainerClass: styles.horizontalContainer,
selectedTask,
taskListRef,
setSelectedTask: handleSelectedTask,
TaskListHeader,
TaskListTable,
};
return (
<div
className={styles.wrapper}
onKeyDown={handleKeyDown}
tabIndex={0}
ref={wrapperRef}
>
{listCellWidth && <TaskList {...tableProps} />}
<TaskGantt
gridProps={gridProps}
calendarProps={calendarProps}
barProps={barProps}
ganttHeight={ganttHeight}
scrollY={scrollY}
scrollX={scrollX}
<div>
<div
className={styles.wrapper}
onKeyDown={handleKeyDown}
tabIndex={0}
ref={wrapperRef}
>
{listCellWidth && <TaskList {...tableProps} />}
<TaskGantt
gridProps={gridProps}
calendarProps={calendarProps}
barProps={barProps}
ganttHeight={ganttHeight}
scrollY={scrollY}
scrollX={scrollX}
verticalGanttContainerRef={verticalGanttContainerRef}
/>
<VerticalScroll
ganttFullHeight={ganttFullHeight}
ganttHeight={ganttHeight}
headerHeight={headerHeight}
scroll={scrollY}
onScroll={handleScrollY}
/>
</div>
<HorizontalScroll
svgWidth={svgWidth}
taskListWidth={taskListWidth}
scroll={scrollX}
onScroll={handleScrollX}
/>
<Scroll
ganttFullHeight={ganttFullHeight}
ganttHeight={ganttHeight}
headerHeight={headerHeight}
scroll={scrollY}
onScroll={handleScrollY}
/>
</div>
);
};
18 changes: 8 additions & 10 deletions src/components/gantt/task-gantt.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useEffect, SyntheticEvent, useState } from "react";
import React, { useRef, useEffect, useState } from "react";
import { GridProps, Grid } from "../grid/grid";
import { CalendarProps, Calendar } from "../calendar/calendar";
import { TaskGanttContentProps, TaskGanttContent } from "./task-gantt-content";
Expand All @@ -11,7 +11,7 @@ export type TaskGanttProps = {
ganttHeight: number;
scrollY: number;
scrollX: number;
onScroll: (event: SyntheticEvent<HTMLDivElement>) => void;
verticalGanttContainerRef: React.RefObject<HTMLDivElement>;
};
export const TaskGantt: React.FC<TaskGanttProps> = ({
gridProps,
Expand All @@ -20,11 +20,10 @@ export const TaskGantt: React.FC<TaskGanttProps> = ({
ganttHeight,
scrollY,
scrollX,
onScroll,
verticalGanttContainerRef,
}) => {
const ganttSVGRef = useRef<SVGSVGElement>(null);
const horizontalContainerRef = useRef<HTMLDivElement>(null);
const verticalContainerRef = useRef<HTMLDivElement>(null);
const [displayXStartEndpoint, setDisplayXStartEndpoint] = useState({
start: 0,
end: 0,
Expand All @@ -38,21 +37,20 @@ export const TaskGantt: React.FC<TaskGanttProps> = ({
}, [scrollY]);

useEffect(() => {
if (verticalContainerRef.current) {
verticalContainerRef.current.scrollLeft = scrollX;
if (verticalGanttContainerRef.current) {
verticalGanttContainerRef.current.scrollLeft = scrollX;
setDisplayXStartEndpoint({
start: scrollX,
end: verticalContainerRef.current.clientWidth + scrollX,
end: verticalGanttContainerRef.current.clientWidth + scrollX,
});
}
// verticalContainerRef.current?.clientWidth need for resize window tracking
}, [scrollX, verticalContainerRef.current?.clientWidth]);
}, [scrollX, verticalGanttContainerRef.current?.clientWidth]);

return (
<div
className={styles.ganttVerticalContainer}
ref={verticalContainerRef}
onScroll={onScroll}
ref={verticalGanttContainerRef}
>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down
4 changes: 4 additions & 0 deletions src/components/other/horizontal-scroll.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.scroll {
overflow: auto;
max-width: 100%;
}
28 changes: 28 additions & 0 deletions src/components/other/horizontal-scroll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { SyntheticEvent, useRef, useEffect } from "react";
import styles from "./horizontal-scroll.module.css";

export const HorizontalScroll: React.FC<{
scroll: number;
svgWidth: number;
taskListWidth: number;
onScroll: (event: SyntheticEvent<HTMLDivElement>) => void;
}> = ({ scroll, svgWidth, taskListWidth, onScroll }) => {
const scrollRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollLeft = scroll;
}
}, [scroll]);

return (
<div
style={{ marginLeft: taskListWidth }}
className={styles.scroll}
onScroll={onScroll}
ref={scrollRef}
>
<div style={{ width: svgWidth, height: 1 }} />
</div>
);
};
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { SyntheticEvent, useRef, useEffect } from "react";
import styles from "./scroll.module.css";
import styles from "./vertical-scroll.module.css";

export const Scroll: React.FC<{
export const VerticalScroll: React.FC<{
scroll: number;
ganttHeight: number;
ganttFullHeight: number;
Expand Down
4 changes: 3 additions & 1 deletion src/components/task-list/task-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type TaskListProps = {
scrollY: number;
locale: string;
tasks: Task[];
taskListRef: React.RefObject<HTMLDivElement>;
horizontalContainerClass?: string;
selectedTask: BarTask | undefined;
setSelectedTask: (task: string) => void;
Expand Down Expand Up @@ -45,6 +46,7 @@ export const TaskList: React.FC<TaskListProps> = ({
setSelectedTask,
locale,
ganttHeight,
taskListRef,
horizontalContainerClass,
TaskListHeader,
TaskListTable,
Expand Down Expand Up @@ -75,7 +77,7 @@ export const TaskList: React.FC<TaskListProps> = ({
};

return (
<div>
<div ref={taskListRef}>
<TaskListHeader {...headerProps} />
<div
ref={horizontalContainerRef}
Expand Down
1 change: 0 additions & 1 deletion src/helpers/bar-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ const convertToBar = (
barBackgroundColor: string,
barBackgroundSelectedColor: string
): BarTask => {
debugger;
const x1 = taskXCoordinate(task.start, dates, dateDelta, columnWidth);
let x2 = taskXCoordinate(task.end, dates, dateDelta, columnWidth);
const y = taskYCoordinate(index, rowHeight, taskHeight);
Expand Down

0 comments on commit 605b7fc

Please sign in to comment.