From 5ae90e909e6dc993dc9fe8d1b48d213345a17466 Mon Sep 17 00:00:00 2001 From: Renaud Dumont Date: Tue, 17 Jun 2025 23:26:51 +0200 Subject: [PATCH 1/4] updated react and ts --- example/tsconfig.json | 1 - package-lock.json | 151 ++++++++++++++++++++++++++---------------- package.json | 13 ++-- tsconfig.json | 1 - 4 files changed, 101 insertions(+), 65 deletions(-) diff --git a/example/tsconfig.json b/example/tsconfig.json index f87431a99..cc4e6ae94 100644 --- a/example/tsconfig.json +++ b/example/tsconfig.json @@ -15,7 +15,6 @@ "noImplicitThis": true, "noImplicitAny": true, "strictNullChecks": true, - "suppressImplicitAnyIndexErrors": true, "noUnusedLocals": true, "noUnusedParameters": true, "allowSyntheticDefaultImports": true, diff --git a/package-lock.json b/package-lock.json index aeca7dc81..f08d9b90f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,24 @@ { "name": "gantt-task-react", - "version": "0.3.8", + "version": "0.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gantt-task-react", - "version": "0.3.8", + "version": "0.4.0", "license": "MIT", + "dependencies": { + "@uidotdev/usehooks": "^2.4.1" + }, "devDependencies": { "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^14.2.1", "@types/jest": "^27.5.1", "@types/node": "^15.0.1", - "@types/react": "^18.0.5", - "@types/react-dom": "^18.0.5", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", "cross-env": "^7.0.3", "gh-pages": "^3.1.0", "microbundle-crl": "^0.13.11", @@ -34,7 +37,7 @@ "node": ">=10" }, "peerDependencies": { - "react": "^18.0.0" + "react": "^19.0.0" } }, "node_modules/@ampproject/remapping": { @@ -3535,6 +3538,26 @@ "react-dom": "^18.0.0" } }, + "node_modules/@testing-library/react/node_modules/@types/react": { + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@testing-library/react/node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@testing-library/user-event": { "version": "14.2.1", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.2.1.tgz", @@ -3795,10 +3818,11 @@ "dev": true }, "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "peer": true }, "node_modules/@types/q": { "version": "1.5.5", @@ -3819,23 +3843,21 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.0.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.9.tgz", - "integrity": "sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "dev": true, "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.5.tgz", - "integrity": "sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "dev": true, - "dependencies": { - "@types/react": "*" + "peerDependencies": { + "@types/react": "^19.0.0" } }, "node_modules/@types/resolve": { @@ -3853,12 +3875,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -4198,6 +4214,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@uidotdev/usehooks": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz", + "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -12498,8 +12526,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -12872,7 +12899,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -16748,7 +16774,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16953,7 +16978,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -18110,7 +18134,6 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -23225,6 +23248,26 @@ "@babel/runtime": "^7.12.5", "@testing-library/dom": "^8.5.0", "@types/react-dom": "^18.0.0" + }, + "dependencies": { + "@types/react": { + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", + "dev": true, + "peer": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "requires": {} + } } }, "@testing-library/user-event": { @@ -23475,10 +23518,11 @@ "dev": true }, "@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "peer": true }, "@types/q": { "version": "1.5.5", @@ -23499,24 +23543,20 @@ "dev": true }, "@types/react": { - "version": "18.0.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.9.tgz", - "integrity": "sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "dev": true, "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "@types/react-dom": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.5.tgz", - "integrity": "sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "dev": true, - "requires": { - "@types/react": "*" - } + "requires": {} }, "@types/resolve": { "version": "0.0.8", @@ -23533,12 +23573,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -23761,6 +23795,12 @@ "eslint-visitor-keys": "^3.0.0" } }, + "@uidotdev/usehooks": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz", + "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==", + "requires": {} + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -30168,8 +30208,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -30471,7 +30510,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -33405,7 +33443,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -33552,7 +33589,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dev": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -34425,7 +34461,6 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dev": true, "requires": { "loose-envify": "^1.1.0" } diff --git a/package.json b/package.json index a0097baa7..10b363246 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gantt-task-react", - "version": "0.3.9", + "version": "0.4.0", "description": "Interactive Gantt Chart for React with TypeScript.", "author": "MaTeMaTuK ", "homepage": "https://github.com/MaTeMaTuK/gantt-task-react", @@ -36,7 +36,7 @@ "deploy": "gh-pages -d example/build" }, "peerDependencies": { - "react": "^18.0.0" + "react": "^19.0.0" }, "devDependencies": { "@testing-library/jest-dom": "^5.16.4", @@ -44,8 +44,8 @@ "@testing-library/user-event": "^14.2.1", "@types/jest": "^27.5.1", "@types/node": "^15.0.1", - "@types/react": "^18.0.5", - "@types/react-dom": "^18.0.5", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", "cross-env": "^7.0.3", "gh-pages": "^3.1.0", "microbundle-crl": "^0.13.11", @@ -62,5 +62,8 @@ }, "files": [ "dist" - ] + ], + "dependencies": { + "@uidotdev/usehooks": "^2.4.1" + } } diff --git a/tsconfig.json b/tsconfig.json index 66e34d8eb..00ae3632b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,6 @@ "noImplicitThis": true, "noImplicitAny": true, "strictNullChecks": true, - "suppressImplicitAnyIndexErrors": true, "noUnusedLocals": true, "noUnusedParameters": true, "allowSyntheticDefaultImports": true, From 7ecf219c9ec6ffb566b847a8f43f0e3b55f540f2 Mon Sep 17 00:00:00 2001 From: Renaud Dumont Date: Tue, 17 Jun 2025 23:27:56 +0200 Subject: [PATCH 2/4] added helpers method and wrapper components to calculate component width and calculate min number of columns --- src/components/gantt/gantt.tsx | 28 ++++- src/components/gantt/task-gantt-content.tsx | 2 +- src/components/task-list/task-list-table.tsx | 2 +- src/components/task-list/task-list.tsx | 2 +- src/helpers/date-helper.ts | 118 +++++++++---------- src/index.tsx | 2 +- src/types/public-types.ts | 1 + 7 files changed, 88 insertions(+), 67 deletions(-) diff --git a/src/components/gantt/gantt.tsx b/src/components/gantt/gantt.tsx index b90483f3d..43f7ae5a7 100644 --- a/src/components/gantt/gantt.tsx +++ b/src/components/gantt/gantt.tsx @@ -4,6 +4,7 @@ import React, { useRef, useEffect, useMemo, + JSX, } from "react"; import { ViewMode, GanttProps, Task } from "../../types/public-types"; import { GridProps } from "../grid/grid"; @@ -23,9 +24,11 @@ import { DateSetup } from "../../types/date-setup"; import { HorizontalScroll } from "../other/horizontal-scroll"; import { removeHiddenTasks, sortTasks } from "../../helpers/other-helper"; import styles from "./gantt.module.css"; +import { useMeasure } from "@uidotdev/usehooks"; -export const Gantt: React.FunctionComponent = ({ +export const Gantt = ({ tasks, + componentWidth, headerHeight = 50, columnWidth = 60, listCellWidth = "155px", @@ -65,11 +68,16 @@ export const Gantt: React.FunctionComponent = ({ onDelete, onSelect, onExpanderClick, -}) => { +}: GanttProps): JSX.Element => { const wrapperRef = useRef(null); const taskListRef = useRef(null); const [dateSetup, setDateSetup] = useState(() => { - const [startDate, endDate] = ganttDateRange(tasks, viewMode, preStepsCount); + const [startDate, endDate] = ganttDateRange( + tasks, + viewMode, + preStepsCount, + componentWidth ? componentWidth / columnWidth : 0 + ); return { viewMode, dates: seedDates(startDate, endDate, viewMode) }; }); const [currentViewDate, setCurrentViewDate] = useState( @@ -110,7 +118,8 @@ export const Gantt: React.FunctionComponent = ({ const [startDate, endDate] = ganttDateRange( filteredTasks, viewMode, - preStepsCount + preStepsCount, + componentWidth ? componentWidth / columnWidth : 0 ); let newDates = seedDates(startDate, endDate, viewMode); if (rtl) { @@ -164,6 +173,7 @@ export const Gantt: React.FunctionComponent = ({ rtl, scrollX, onExpanderClick, + componentWidth, ]); useEffect(() => { @@ -387,6 +397,7 @@ export const Gantt: React.FunctionComponent = ({ onExpanderClick({ ...task, hideChildren: !task.hideChildren }); } }; + const gridProps: GridProps = { columnWidth, svgWidth, @@ -503,3 +514,12 @@ export const Gantt: React.FunctionComponent = ({ ); }; + +export const FullWidthGantt = (props: GanttProps): JSX.Element => { + const [wrapperRef, { width }] = useMeasure(); + return ( +
+ {width && } +
+ ); +}; diff --git a/src/components/gantt/task-gantt-content.tsx b/src/components/gantt/task-gantt-content.tsx index 33326df92..585a4f7f3 100644 --- a/src/components/gantt/task-gantt-content.tsx +++ b/src/components/gantt/task-gantt-content.tsx @@ -19,7 +19,7 @@ export type TaskGanttContentProps = { rowHeight: number; columnWidth: number; timeStep: number; - svg?: React.RefObject; + svg?: React.RefObject; svgWidth: number; taskHeight: number; arrowColor: string; diff --git a/src/components/task-list/task-list-table.tsx b/src/components/task-list/task-list-table.tsx index b165f6002..09e375b7e 100644 --- a/src/components/task-list/task-list-table.tsx +++ b/src/components/task-list/task-list-table.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from "react"; import styles from "./task-list-table.module.css"; import { Task } from "../../types/public-types"; -const localeDateStringCache = {}; +const localeDateStringCache: Record = {}; const toLocaleDateStringFactory = (locale: string) => (date: Date, dateTimeOptions: Intl.DateTimeFormatOptions) => { diff --git a/src/components/task-list/task-list.tsx b/src/components/task-list/task-list.tsx index bbfed4365..facce54c5 100644 --- a/src/components/task-list/task-list.tsx +++ b/src/components/task-list/task-list.tsx @@ -12,7 +12,7 @@ export type TaskListProps = { scrollY: number; locale: string; tasks: Task[]; - taskListRef: React.RefObject; + taskListRef: React.RefObject; horizontalContainerClass?: string; selectedTask: BarTask | undefined; setSelectedTask: (task: string) => void; diff --git a/src/helpers/date-helper.ts b/src/helpers/date-helper.ts index 1b2a0f5c4..163fa6bbc 100644 --- a/src/helpers/date-helper.ts +++ b/src/helpers/date-helper.ts @@ -11,7 +11,7 @@ type DateHelperScales = | "second" | "millisecond"; -const intlDTCache = {}; +const intlDTCache: Record = {}; export const getCachedDateTimeFormat = ( locString: string | string[], opts: DateTimeFormatOptions = {} @@ -69,11 +69,49 @@ export const startOfDate = (date: Date, scale: DateHelperScales) => { return newDate; }; +export const countSteps = ( + startDate: Date, + endDate: Date, + viewMode: ViewMode +) => { + let count = 0; + const { scale, count: stepCount } = getScaleAndCount(viewMode); + while (startDate < endDate) { + startDate = addToDate(startDate, stepCount, scale); + count++; + } + return count; +}; + +const getScaleAndCount = ( + viewMode: ViewMode +): { scale: DateHelperScales; count: number } => { + switch (viewMode) { + case ViewMode.Year: + return { scale: "year", count: 1 }; + case ViewMode.QuarterYear: + return { scale: "month", count: 3 }; + case ViewMode.Month: + return { scale: "month", count: 1 }; + case ViewMode.Week: + return { scale: "day", count: 7 }; + case ViewMode.Day: + return { scale: "day", count: 1 }; + case ViewMode.HalfDay: + return { scale: "hour", count: 12 }; + case ViewMode.QuarterDay: + return { scale: "hour", count: 6 }; + case ViewMode.Hour: + return { scale: "hour", count: 1 }; + } +}; + export const ganttDateRange = ( tasks: Task[], viewMode: ViewMode, - preStepsCount: number -) => { + preStepsCount: number, + minStepsCount: number +): [Date, Date, number, number] => { let newStartDate: Date = tasks[0].start; let newEndDate: Date = tasks[0].start; for (const task of tasks) { @@ -84,61 +122,23 @@ export const ganttDateRange = ( newEndDate = task.end; } } - switch (viewMode) { - case ViewMode.Year: - newStartDate = addToDate(newStartDate, -1, "year"); - newStartDate = startOfDate(newStartDate, "year"); - newEndDate = addToDate(newEndDate, 1, "year"); - newEndDate = startOfDate(newEndDate, "year"); - break; - case ViewMode.QuarterYear: - newStartDate = addToDate(newStartDate, -3, "month"); - newStartDate = startOfDate(newStartDate, "month"); - newEndDate = addToDate(newEndDate, 3, "year"); - newEndDate = startOfDate(newEndDate, "year"); - break; - case ViewMode.Month: - newStartDate = addToDate(newStartDate, -1 * preStepsCount, "month"); - newStartDate = startOfDate(newStartDate, "month"); - newEndDate = addToDate(newEndDate, 1, "year"); - newEndDate = startOfDate(newEndDate, "year"); - break; - case ViewMode.Week: - newStartDate = startOfDate(newStartDate, "day"); - newStartDate = addToDate( - getMonday(newStartDate), - -7 * preStepsCount, - "day" - ); - newEndDate = startOfDate(newEndDate, "day"); - newEndDate = addToDate(newEndDate, 1.5, "month"); - break; - case ViewMode.Day: - newStartDate = startOfDate(newStartDate, "day"); - newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day"); - newEndDate = startOfDate(newEndDate, "day"); - newEndDate = addToDate(newEndDate, 19, "day"); - break; - case ViewMode.QuarterDay: - newStartDate = startOfDate(newStartDate, "day"); - newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day"); - newEndDate = startOfDate(newEndDate, "day"); - newEndDate = addToDate(newEndDate, 66, "hour"); // 24(1 day)*3 - 6 - break; - case ViewMode.HalfDay: - newStartDate = startOfDate(newStartDate, "day"); - newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day"); - newEndDate = startOfDate(newEndDate, "day"); - newEndDate = addToDate(newEndDate, 108, "hour"); // 24(1 day)*5 - 12 - break; - case ViewMode.Hour: - newStartDate = startOfDate(newStartDate, "hour"); - newStartDate = addToDate(newStartDate, -1 * preStepsCount, "hour"); - newEndDate = startOfDate(newEndDate, "day"); - newEndDate = addToDate(newEndDate, 1, "day"); - break; - } - return [newStartDate, newEndDate]; + + const { scale, count: stepCount } = getScaleAndCount(viewMode); + + newStartDate = addToDate(newStartDate, -1 * preStepsCount * stepCount, scale); + newStartDate = startOfDate(newStartDate, scale); + + const stepsBetweenDates = countSteps(newStartDate, newEndDate, viewMode); + const maxStepsCount = Math.max(stepsBetweenDates, minStepsCount); + + newEndDate = addToDate( + newStartDate, + maxStepsCount * stepCount, + scale + ); + newEndDate = startOfDate(newEndDate, scale); + + return [newStartDate, newEndDate, minStepsCount, preStepsCount]; }; export const seedDates = ( @@ -210,7 +210,7 @@ export const getLocalDayOfWeek = ( * Returns monday of current week * @param date date for modify */ -const getMonday = (date: Date) => { +export const getMonday = (date: Date) => { const day = date.getDay(); const diff = date.getDate() - day + (day === 0 ? -6 : 1); // adjust when day is sunday return new Date(date.setDate(diff)); diff --git a/src/index.tsx b/src/index.tsx index 47e8b63a4..88425546e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ -export { Gantt } from "./components/gantt/gantt"; +export { Gantt, FullWidthGantt } from "./components/gantt/gantt"; export { ViewMode } from "./types/public-types"; export type { GanttProps, diff --git a/src/types/public-types.ts b/src/types/public-types.ts index cc44ff17c..081a87009 100644 --- a/src/types/public-types.ts +++ b/src/types/public-types.ts @@ -78,6 +78,7 @@ export interface DisplayOption { viewMode?: ViewMode; viewDate?: Date; preStepsCount?: number; + componentWidth?: number; /** * Specifies the month name language. Able formats: ISO 639-2, Java Locale */ From f10bd213ee5a18fcdfc2bcf50fff105e50731ede Mon Sep 17 00:00:00 2001 From: Renaud Dumont Date: Tue, 17 Jun 2025 23:36:16 +0200 Subject: [PATCH 3/4] use short format for month display --- src/helpers/date-helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/date-helper.ts b/src/helpers/date-helper.ts index 163fa6bbc..7d17a8fbb 100644 --- a/src/helpers/date-helper.ts +++ b/src/helpers/date-helper.ts @@ -182,7 +182,7 @@ export const seedDates = ( export const getLocaleMonth = (date: Date, locale: string) => { let bottomValue = getCachedDateTimeFormat(locale, { - month: "long", + month: "short", }).format(date); bottomValue = bottomValue.replace( bottomValue[0], From 7fb53ea0fed60916a40deaa6f6a4d00c00f612a4 Mon Sep 17 00:00:00 2001 From: Renaud Dumont Date: Wed, 18 Jun 2025 16:47:31 +0200 Subject: [PATCH 4/4] updated package config --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a0097baa7..d128c41e6 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,10 @@ "name": "gantt-task-react", "version": "0.3.9", "description": "Interactive Gantt Chart for React with TypeScript.", - "author": "MaTeMaTuK ", - "homepage": "https://github.com/MaTeMaTuK/gantt-task-react", + "author": "Sparkle ", + "homepage": "https://github.com/sprkl/gantt-task-react", "license": "MIT", - "repository": "MaTeMaTuK/gantt-task-react", + "repository": "@sparkle_tech/gantt-task-react", "main": "dist/index.js", "module": "dist/index.modern.js", "source": "src/index.tsx",