gantt-canvas-chart 1.5.4 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.5.4
2
+ * gantt-canvas-chart v1.6.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -9,24 +9,35 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
9
9
  class DateUtils {
10
10
  static ONE_DAY_MS = 24 * 60 * 60 * 1e3;
11
11
  static format(date, format = "yyyy-MM-dd") {
12
- const o = {
13
- "M+": date.getMonth() + 1,
14
- "d+": date.getDate(),
15
- "h+": date.getHours(),
16
- "m+": date.getMinutes(),
17
- "s+": date.getSeconds(),
12
+ let fmt = format;
13
+ let ret;
14
+ const opt = {
15
+ "Y+": `${date.getFullYear()}`,
16
+ //
17
+ "y+": `${date.getFullYear()}`,
18
+ // 年
19
+ "M+": `${date.getMonth() + 1}`,
20
+ // 月
21
+ "D+": `${date.getDate()}`,
22
+ // 日
23
+ "d+": `${date.getDate()}`,
24
+ // 日
25
+ "h+": `${date.getHours()}`,
26
+ // 时
27
+ "m+": `${date.getMinutes()}`,
28
+ // 分
29
+ "s+": `${date.getSeconds()}`,
30
+ // 秒
18
31
  "q+": Math.floor((date.getMonth() + 3) / 3),
19
32
  W: ["日", "一", "二", "三", "四", "五", "六"][date.getDay()]
20
33
  };
21
- if (/(y+)/.test(format))
22
- format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
23
- for (let k in o)
24
- if (new RegExp("(" + k + ")").test(format))
25
- format = format.replace(
26
- RegExp.$1,
27
- RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
28
- );
29
- return format;
34
+ for (const k in opt) {
35
+ ret = new RegExp("(" + k + ")").exec(fmt);
36
+ if (ret) {
37
+ fmt = fmt.replace(ret[1], ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, "0"));
38
+ }
39
+ }
40
+ return fmt;
30
41
  }
31
42
  static addDays(date, days) {
32
43
  const r = new Date(date);
@@ -146,6 +157,7 @@ class GanttChart {
146
157
  resizeObserver;
147
158
  taskPositions;
148
159
  taskMap;
160
+ holidaysMap;
149
161
  isLoadingData = false;
150
162
  hasMoreDataLeft = true;
151
163
  hasMoreDataRight = true;
@@ -194,6 +206,9 @@ class GanttChart {
194
206
  tooltipFormat: null,
195
207
  tooltipColor: "black",
196
208
  todayColor: "#ff4d4f",
209
+ weekendBgColor: "#f7f7f7",
210
+ holidays: [],
211
+ dateSeparator: "/",
197
212
  offsetTop: 0,
198
213
  offsetLeft: 0,
199
214
  scrollEdgeThresholds: 10,
@@ -232,6 +247,7 @@ class GanttChart {
232
247
  this.totalHeight = 0;
233
248
  this.taskPositions = /* @__PURE__ */ new Map();
234
249
  this.taskMap = /* @__PURE__ */ new Map();
250
+ this.holidaysMap = /* @__PURE__ */ new Map();
235
251
  this.handleMouseMove = this.handleMouseMove.bind(this);
236
252
  this.handleMouseLeave = this.handleMouseLeave.bind(this);
237
253
  this.handleScroll = this.handleScroll.bind(this);
@@ -241,6 +257,9 @@ class GanttChart {
241
257
  this.init();
242
258
  }
243
259
  init() {
260
+ if (this.config.holidays.length > 0) {
261
+ this.buildHolidaysMap();
262
+ }
244
263
  this.buildTaskMap();
245
264
  this.updatePixelsPerDay();
246
265
  this.calculateFullTimeline();
@@ -289,10 +308,26 @@ class GanttChart {
289
308
  this.updatePixelsPerDay();
290
309
  this.calculateFullTimeline();
291
310
  }
311
+ if (this.config.holidays.length !== this.holidaysMap.size) {
312
+ this.buildHolidaysMap();
313
+ }
292
314
  this.updateLoadMoreConf();
293
315
  this.updateDimensions();
294
316
  this.render();
295
317
  }
318
+ buildHolidaysMap() {
319
+ this.holidaysMap.clear();
320
+ const separator = this.config.dateSeparator;
321
+ if (this.config.holidays && this.config.holidays.length > 0 && this.config.holidays[0].includes(separator)) {
322
+ this.config.holidays.forEach((holiday) => {
323
+ this.holidaysMap.set(holiday, true);
324
+ });
325
+ } else {
326
+ this.config.holidays.forEach((holiday) => {
327
+ this.holidaysMap.set(DateUtils.format(new Date(holiday), `yyyy${separator}MM${separator}dd`), true);
328
+ });
329
+ }
330
+ }
296
331
  setData(newData, newConfig) {
297
332
  this.data = newData;
298
333
  this.buildTaskMap();
@@ -307,6 +342,7 @@ class GanttChart {
307
342
  destroy() {
308
343
  if (this.resizeObserver) {
309
344
  this.resizeObserver.disconnect();
345
+ this.resizeObserver = null;
310
346
  }
311
347
  this.container.removeEventListener("scroll", this.handleScroll);
312
348
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
@@ -314,6 +350,8 @@ class GanttChart {
314
350
  this.data = [];
315
351
  this.taskMap.clear();
316
352
  this.taskPositions.clear();
353
+ this.holidaysMap.clear();
354
+ this.config.holidays = [];
317
355
  this.container.remove();
318
356
  }
319
357
  calculateFullTimeline() {
@@ -730,7 +768,7 @@ class GanttChart {
730
768
  }
731
769
  const groupedBlocks = this.groupConsecutiveBlocks(visibleBlocks);
732
770
  ctx.fillStyle = "#333";
733
- ctx.font = "bold 14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
771
+ ctx.font = "bold 12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
734
772
  ctx.textAlign = "left";
735
773
  groupedBlocks.forEach((group) => {
736
774
  const visibleStart = Math.max(group.startX, this.scrollLeft);
@@ -739,7 +777,7 @@ class GanttChart {
739
777
  ctx.fillStyle = this.config.headerBgColor;
740
778
  ctx.fillRect(Math.round(visibleStart), 0, Math.round(visibleEnd - visibleStart), Math.round(h * 0.5));
741
779
  ctx.fillStyle = "#333";
742
- ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos));
780
+ ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos - 3));
743
781
  }
744
782
  });
745
783
  while (currentDateForLower <= this.visibleDateRange.end) {
@@ -778,7 +816,7 @@ class GanttChart {
778
816
  }
779
817
  const unitWidth = this.dateToX(nextDate) - x;
780
818
  ctx.fillStyle = "#000412";
781
- ctx.font = "14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
819
+ ctx.font = "12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
782
820
  ctx.textAlign = "center";
783
821
  ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
784
822
  ctx.beginPath();
@@ -930,6 +968,7 @@ class GanttChart {
930
968
  }
931
969
  // In the drawGrid method
932
970
  drawGrid(ctx, startDate, endDate) {
971
+ const separator = this.config.dateSeparator;
933
972
  ctx.strokeStyle = "#e6e6e6";
934
973
  ctx.lineWidth = 1;
935
974
  ctx.beginPath();
@@ -989,6 +1028,12 @@ class GanttChart {
989
1028
  const x = this.snap(this.dateToX(currentDate));
990
1029
  ctx.moveTo(x, this.scrollTop);
991
1030
  ctx.lineTo(x, this.scrollTop + this.viewportHeight);
1031
+ if (this.config.viewMode === "Day") {
1032
+ if ([0, 6].includes(currentDate.getDay()) || this.holidaysMap.has(DateUtils.format(currentDate, `yyyy${separator}MM${separator}dd`))) {
1033
+ ctx.fillStyle = this.config.weekendBgColor;
1034
+ ctx.fillRect(x + 1, this.scrollTop, Math.round(this.pixelsPerDay - 1), Math.round(this.scrollTop + this.viewportHeight));
1035
+ }
1036
+ }
992
1037
  switch (this.config.viewMode) {
993
1038
  case "Day":
994
1039
  nextDate = DateUtils.addDays(currentDate, 1);
package/dist/index.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.5.4
2
+ * gantt-canvas-chart v1.6.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
package/dist/index.d.ts CHANGED
@@ -85,6 +85,7 @@ export declare class GanttChart {
85
85
  row: number;
86
86
  task: Task;
87
87
  }>;
88
+ holidaysMap: Map<string, boolean>;
88
89
  private isLoadingData;
89
90
  private hasMoreDataLeft;
90
91
  private hasMoreDataRight;
@@ -99,6 +100,7 @@ export declare class GanttChart {
99
100
  private buildTaskMap;
100
101
  private setupEvents;
101
102
  updateConfig(newConfig: GanttConfig): void;
103
+ private buildHolidaysMap;
102
104
  setData(newData: GanttData, newConfig?: GanttConfig): void;
103
105
  destroy(): void;
104
106
  private calculateFullTimeline;
@@ -180,6 +182,9 @@ export declare interface GanttConfig {
180
182
  showTooltip?: boolean;
181
183
  tooltipColor?: 'black' | 'white';
182
184
  todayColor?: string;
185
+ weekendBgColor?: string;
186
+ holidays?: string[];
187
+ dateSeparator?: string;
183
188
  offsetTop?: number;
184
189
  offsetLeft?: number;
185
190
  scrollEdgeThresholds?: number;
package/dist/index.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.5.4
2
+ * gantt-canvas-chart v1.6.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -7,24 +7,35 @@
7
7
  class DateUtils {
8
8
  static ONE_DAY_MS = 24 * 60 * 60 * 1e3;
9
9
  static format(date, format = "yyyy-MM-dd") {
10
- const o = {
11
- "M+": date.getMonth() + 1,
12
- "d+": date.getDate(),
13
- "h+": date.getHours(),
14
- "m+": date.getMinutes(),
15
- "s+": date.getSeconds(),
10
+ let fmt = format;
11
+ let ret;
12
+ const opt = {
13
+ "Y+": `${date.getFullYear()}`,
14
+ //
15
+ "y+": `${date.getFullYear()}`,
16
+ // 年
17
+ "M+": `${date.getMonth() + 1}`,
18
+ // 月
19
+ "D+": `${date.getDate()}`,
20
+ // 日
21
+ "d+": `${date.getDate()}`,
22
+ // 日
23
+ "h+": `${date.getHours()}`,
24
+ // 时
25
+ "m+": `${date.getMinutes()}`,
26
+ // 分
27
+ "s+": `${date.getSeconds()}`,
28
+ // 秒
16
29
  "q+": Math.floor((date.getMonth() + 3) / 3),
17
30
  W: ["日", "一", "二", "三", "四", "五", "六"][date.getDay()]
18
31
  };
19
- if (/(y+)/.test(format))
20
- format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
21
- for (let k in o)
22
- if (new RegExp("(" + k + ")").test(format))
23
- format = format.replace(
24
- RegExp.$1,
25
- RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
26
- );
27
- return format;
32
+ for (const k in opt) {
33
+ ret = new RegExp("(" + k + ")").exec(fmt);
34
+ if (ret) {
35
+ fmt = fmt.replace(ret[1], ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, "0"));
36
+ }
37
+ }
38
+ return fmt;
28
39
  }
29
40
  static addDays(date, days) {
30
41
  const r = new Date(date);
@@ -144,6 +155,7 @@ class GanttChart {
144
155
  resizeObserver;
145
156
  taskPositions;
146
157
  taskMap;
158
+ holidaysMap;
147
159
  isLoadingData = false;
148
160
  hasMoreDataLeft = true;
149
161
  hasMoreDataRight = true;
@@ -192,6 +204,9 @@ class GanttChart {
192
204
  tooltipFormat: null,
193
205
  tooltipColor: "black",
194
206
  todayColor: "#ff4d4f",
207
+ weekendBgColor: "#f7f7f7",
208
+ holidays: [],
209
+ dateSeparator: "/",
195
210
  offsetTop: 0,
196
211
  offsetLeft: 0,
197
212
  scrollEdgeThresholds: 10,
@@ -230,6 +245,7 @@ class GanttChart {
230
245
  this.totalHeight = 0;
231
246
  this.taskPositions = /* @__PURE__ */ new Map();
232
247
  this.taskMap = /* @__PURE__ */ new Map();
248
+ this.holidaysMap = /* @__PURE__ */ new Map();
233
249
  this.handleMouseMove = this.handleMouseMove.bind(this);
234
250
  this.handleMouseLeave = this.handleMouseLeave.bind(this);
235
251
  this.handleScroll = this.handleScroll.bind(this);
@@ -239,6 +255,9 @@ class GanttChart {
239
255
  this.init();
240
256
  }
241
257
  init() {
258
+ if (this.config.holidays.length > 0) {
259
+ this.buildHolidaysMap();
260
+ }
242
261
  this.buildTaskMap();
243
262
  this.updatePixelsPerDay();
244
263
  this.calculateFullTimeline();
@@ -287,10 +306,26 @@ class GanttChart {
287
306
  this.updatePixelsPerDay();
288
307
  this.calculateFullTimeline();
289
308
  }
309
+ if (this.config.holidays.length !== this.holidaysMap.size) {
310
+ this.buildHolidaysMap();
311
+ }
290
312
  this.updateLoadMoreConf();
291
313
  this.updateDimensions();
292
314
  this.render();
293
315
  }
316
+ buildHolidaysMap() {
317
+ this.holidaysMap.clear();
318
+ const separator = this.config.dateSeparator;
319
+ if (this.config.holidays && this.config.holidays.length > 0 && this.config.holidays[0].includes(separator)) {
320
+ this.config.holidays.forEach((holiday) => {
321
+ this.holidaysMap.set(holiday, true);
322
+ });
323
+ } else {
324
+ this.config.holidays.forEach((holiday) => {
325
+ this.holidaysMap.set(DateUtils.format(new Date(holiday), `yyyy${separator}MM${separator}dd`), true);
326
+ });
327
+ }
328
+ }
294
329
  setData(newData, newConfig) {
295
330
  this.data = newData;
296
331
  this.buildTaskMap();
@@ -305,6 +340,7 @@ class GanttChart {
305
340
  destroy() {
306
341
  if (this.resizeObserver) {
307
342
  this.resizeObserver.disconnect();
343
+ this.resizeObserver = null;
308
344
  }
309
345
  this.container.removeEventListener("scroll", this.handleScroll);
310
346
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
@@ -312,6 +348,8 @@ class GanttChart {
312
348
  this.data = [];
313
349
  this.taskMap.clear();
314
350
  this.taskPositions.clear();
351
+ this.holidaysMap.clear();
352
+ this.config.holidays = [];
315
353
  this.container.remove();
316
354
  }
317
355
  calculateFullTimeline() {
@@ -728,7 +766,7 @@ class GanttChart {
728
766
  }
729
767
  const groupedBlocks = this.groupConsecutiveBlocks(visibleBlocks);
730
768
  ctx.fillStyle = "#333";
731
- ctx.font = "bold 14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
769
+ ctx.font = "bold 12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
732
770
  ctx.textAlign = "left";
733
771
  groupedBlocks.forEach((group) => {
734
772
  const visibleStart = Math.max(group.startX, this.scrollLeft);
@@ -737,7 +775,7 @@ class GanttChart {
737
775
  ctx.fillStyle = this.config.headerBgColor;
738
776
  ctx.fillRect(Math.round(visibleStart), 0, Math.round(visibleEnd - visibleStart), Math.round(h * 0.5));
739
777
  ctx.fillStyle = "#333";
740
- ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos));
778
+ ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos - 3));
741
779
  }
742
780
  });
743
781
  while (currentDateForLower <= this.visibleDateRange.end) {
@@ -776,7 +814,7 @@ class GanttChart {
776
814
  }
777
815
  const unitWidth = this.dateToX(nextDate) - x;
778
816
  ctx.fillStyle = "#000412";
779
- ctx.font = "14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
817
+ ctx.font = "12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
780
818
  ctx.textAlign = "center";
781
819
  ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
782
820
  ctx.beginPath();
@@ -928,6 +966,7 @@ class GanttChart {
928
966
  }
929
967
  // In the drawGrid method
930
968
  drawGrid(ctx, startDate, endDate) {
969
+ const separator = this.config.dateSeparator;
931
970
  ctx.strokeStyle = "#e6e6e6";
932
971
  ctx.lineWidth = 1;
933
972
  ctx.beginPath();
@@ -987,6 +1026,12 @@ class GanttChart {
987
1026
  const x = this.snap(this.dateToX(currentDate));
988
1027
  ctx.moveTo(x, this.scrollTop);
989
1028
  ctx.lineTo(x, this.scrollTop + this.viewportHeight);
1029
+ if (this.config.viewMode === "Day") {
1030
+ if ([0, 6].includes(currentDate.getDay()) || this.holidaysMap.has(DateUtils.format(currentDate, `yyyy${separator}MM${separator}dd`))) {
1031
+ ctx.fillStyle = this.config.weekendBgColor;
1032
+ ctx.fillRect(x + 1, this.scrollTop, Math.round(this.pixelsPerDay - 1), Math.round(this.scrollTop + this.viewportHeight));
1033
+ }
1034
+ }
990
1035
  switch (this.config.viewMode) {
991
1036
  case "Day":
992
1037
  nextDate = DateUtils.addDays(currentDate, 1);
package/dist/index.umd.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * gantt-canvas-chart v1.5.4
2
+ * gantt-canvas-chart v1.6.1
3
3
  * (c) 2025-present chandq
4
4
  * Released under the MIT License.
5
5
  */
@@ -11,24 +11,35 @@
11
11
  class DateUtils {
12
12
  static ONE_DAY_MS = 24 * 60 * 60 * 1e3;
13
13
  static format(date, format = "yyyy-MM-dd") {
14
- const o = {
15
- "M+": date.getMonth() + 1,
16
- "d+": date.getDate(),
17
- "h+": date.getHours(),
18
- "m+": date.getMinutes(),
19
- "s+": date.getSeconds(),
14
+ let fmt = format;
15
+ let ret;
16
+ const opt = {
17
+ "Y+": `${date.getFullYear()}`,
18
+ //
19
+ "y+": `${date.getFullYear()}`,
20
+ // 年
21
+ "M+": `${date.getMonth() + 1}`,
22
+ // 月
23
+ "D+": `${date.getDate()}`,
24
+ // 日
25
+ "d+": `${date.getDate()}`,
26
+ // 日
27
+ "h+": `${date.getHours()}`,
28
+ // 时
29
+ "m+": `${date.getMinutes()}`,
30
+ // 分
31
+ "s+": `${date.getSeconds()}`,
32
+ // 秒
20
33
  "q+": Math.floor((date.getMonth() + 3) / 3),
21
34
  W: ["日", "一", "二", "三", "四", "五", "六"][date.getDay()]
22
35
  };
23
- if (/(y+)/.test(format))
24
- format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
25
- for (let k in o)
26
- if (new RegExp("(" + k + ")").test(format))
27
- format = format.replace(
28
- RegExp.$1,
29
- RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
30
- );
31
- return format;
36
+ for (const k in opt) {
37
+ ret = new RegExp("(" + k + ")").exec(fmt);
38
+ if (ret) {
39
+ fmt = fmt.replace(ret[1], ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, "0"));
40
+ }
41
+ }
42
+ return fmt;
32
43
  }
33
44
  static addDays(date, days) {
34
45
  const r = new Date(date);
@@ -148,6 +159,7 @@
148
159
  resizeObserver;
149
160
  taskPositions;
150
161
  taskMap;
162
+ holidaysMap;
151
163
  isLoadingData = false;
152
164
  hasMoreDataLeft = true;
153
165
  hasMoreDataRight = true;
@@ -196,6 +208,9 @@
196
208
  tooltipFormat: null,
197
209
  tooltipColor: "black",
198
210
  todayColor: "#ff4d4f",
211
+ weekendBgColor: "#f7f7f7",
212
+ holidays: [],
213
+ dateSeparator: "/",
199
214
  offsetTop: 0,
200
215
  offsetLeft: 0,
201
216
  scrollEdgeThresholds: 10,
@@ -234,6 +249,7 @@
234
249
  this.totalHeight = 0;
235
250
  this.taskPositions = /* @__PURE__ */ new Map();
236
251
  this.taskMap = /* @__PURE__ */ new Map();
252
+ this.holidaysMap = /* @__PURE__ */ new Map();
237
253
  this.handleMouseMove = this.handleMouseMove.bind(this);
238
254
  this.handleMouseLeave = this.handleMouseLeave.bind(this);
239
255
  this.handleScroll = this.handleScroll.bind(this);
@@ -243,6 +259,9 @@
243
259
  this.init();
244
260
  }
245
261
  init() {
262
+ if (this.config.holidays.length > 0) {
263
+ this.buildHolidaysMap();
264
+ }
246
265
  this.buildTaskMap();
247
266
  this.updatePixelsPerDay();
248
267
  this.calculateFullTimeline();
@@ -291,10 +310,26 @@
291
310
  this.updatePixelsPerDay();
292
311
  this.calculateFullTimeline();
293
312
  }
313
+ if (this.config.holidays.length !== this.holidaysMap.size) {
314
+ this.buildHolidaysMap();
315
+ }
294
316
  this.updateLoadMoreConf();
295
317
  this.updateDimensions();
296
318
  this.render();
297
319
  }
320
+ buildHolidaysMap() {
321
+ this.holidaysMap.clear();
322
+ const separator = this.config.dateSeparator;
323
+ if (this.config.holidays && this.config.holidays.length > 0 && this.config.holidays[0].includes(separator)) {
324
+ this.config.holidays.forEach((holiday) => {
325
+ this.holidaysMap.set(holiday, true);
326
+ });
327
+ } else {
328
+ this.config.holidays.forEach((holiday) => {
329
+ this.holidaysMap.set(DateUtils.format(new Date(holiday), `yyyy${separator}MM${separator}dd`), true);
330
+ });
331
+ }
332
+ }
298
333
  setData(newData, newConfig) {
299
334
  this.data = newData;
300
335
  this.buildTaskMap();
@@ -309,6 +344,7 @@
309
344
  destroy() {
310
345
  if (this.resizeObserver) {
311
346
  this.resizeObserver.disconnect();
347
+ this.resizeObserver = null;
312
348
  }
313
349
  this.container.removeEventListener("scroll", this.handleScroll);
314
350
  this.mainCanvas.removeEventListener("mousemove", this.handleMouseMove);
@@ -316,6 +352,8 @@
316
352
  this.data = [];
317
353
  this.taskMap.clear();
318
354
  this.taskPositions.clear();
355
+ this.holidaysMap.clear();
356
+ this.config.holidays = [];
319
357
  this.container.remove();
320
358
  }
321
359
  calculateFullTimeline() {
@@ -732,7 +770,7 @@
732
770
  }
733
771
  const groupedBlocks = this.groupConsecutiveBlocks(visibleBlocks);
734
772
  ctx.fillStyle = "#333";
735
- ctx.font = "bold 14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
773
+ ctx.font = "bold 12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
736
774
  ctx.textAlign = "left";
737
775
  groupedBlocks.forEach((group) => {
738
776
  const visibleStart = Math.max(group.startX, this.scrollLeft);
@@ -741,7 +779,7 @@
741
779
  ctx.fillStyle = this.config.headerBgColor;
742
780
  ctx.fillRect(Math.round(visibleStart), 0, Math.round(visibleEnd - visibleStart), Math.round(h * 0.5));
743
781
  ctx.fillStyle = "#333";
744
- ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos));
782
+ ctx.fillText(group.text, Math.round(visibleStart + 5), Math.round(group.yPos - 3));
745
783
  }
746
784
  });
747
785
  while (currentDateForLower <= this.visibleDateRange.end) {
@@ -780,7 +818,7 @@
780
818
  }
781
819
  const unitWidth = this.dateToX(nextDate) - x;
782
820
  ctx.fillStyle = "#000412";
783
- ctx.font = "14px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
821
+ ctx.font = "12px Roboto,PingFang SC,Noto Sans SC,Microsoft YaHei UI,Microsoft YaHei,Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif";
784
822
  ctx.textAlign = "center";
785
823
  ctx.fillText(lowerText, Math.round(x + unitWidth / 2), Math.round(h * 0.7));
786
824
  ctx.beginPath();
@@ -932,6 +970,7 @@
932
970
  }
933
971
  // In the drawGrid method
934
972
  drawGrid(ctx, startDate, endDate) {
973
+ const separator = this.config.dateSeparator;
935
974
  ctx.strokeStyle = "#e6e6e6";
936
975
  ctx.lineWidth = 1;
937
976
  ctx.beginPath();
@@ -991,6 +1030,12 @@
991
1030
  const x = this.snap(this.dateToX(currentDate));
992
1031
  ctx.moveTo(x, this.scrollTop);
993
1032
  ctx.lineTo(x, this.scrollTop + this.viewportHeight);
1033
+ if (this.config.viewMode === "Day") {
1034
+ if ([0, 6].includes(currentDate.getDay()) || this.holidaysMap.has(DateUtils.format(currentDate, `yyyy${separator}MM${separator}dd`))) {
1035
+ ctx.fillStyle = this.config.weekendBgColor;
1036
+ ctx.fillRect(x + 1, this.scrollTop, Math.round(this.pixelsPerDay - 1), Math.round(this.scrollTop + this.viewportHeight));
1037
+ }
1038
+ }
994
1039
  switch (this.config.viewMode) {
995
1040
  case "Day":
996
1041
  nextDate = DateUtils.addDays(currentDate, 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gantt-canvas-chart",
3
- "version": "1.5.4",
3
+ "version": "1.6.1",
4
4
  "description": "High performance Gantt chart component based on Canvas, can be applied to any framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.es.js",