apexgantt 3.1.1 → 3.3.0

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/README.md CHANGED
@@ -67,6 +67,7 @@ The layout can be configured by either setting the properties in the table below
67
67
  | barTextColor | `#FFFFFF` | Text color for timeline bar |
68
68
  | cellBorderColor | `#eff0f0` | Border color for all table cells and timeline cells |
69
69
  | cellBorderWidth | `1px` | Border width for all table cells and timeline cells |
70
+ | columnConfig | `undefined` | Custom column widths |
70
71
  | enableToolbar | `false` | Enable/disable graph toolbar |
71
72
  | enableResize | `true` | Enable/disable gantt sidebar resize |
72
73
  | enableExport | `true` | Enable/disable gantt export options |
@@ -185,6 +186,44 @@ Each tasks should be in below format
185
186
  ];
186
187
  ```
187
188
 
189
+ ## Column Configuration
190
+
191
+ Customize task table column widths:
192
+
193
+ ```js
194
+ import {ColumnKey} from 'apexgantt';
195
+
196
+ const gantt = new ApexGantt(element, {
197
+ series: tasks,
198
+ columnConfig: [
199
+ {
200
+ key: ColumnKey.Name,
201
+ title: 'Task Name',
202
+ minWidth: '100px',
203
+ flexGrow: 3,
204
+ },
205
+ {
206
+ key: ColumnKey.StartTime,
207
+ title: 'Start',
208
+ minWidth: '100px',
209
+ flexGrow: 1.5,
210
+ },
211
+ {
212
+ key: ColumnKey.Duration,
213
+ title: 'Duration',
214
+ minWidth: '80px',
215
+ flexGrow: 1,
216
+ },
217
+ {
218
+ key: ColumnKey.Progress,
219
+ title: 'Progress',
220
+ minWidth: '80px',
221
+ flexGrow: 1,
222
+ },
223
+ ],
224
+ });
225
+ ```
226
+
188
227
  ## Data Parsing
189
228
 
190
229
  Map your existing data structure to ApexGantt format without manual transformation.
@@ -5965,6 +5965,13 @@ const _Watermark = class _Watermark {
5965
5965
  _Watermark.WATERMARK_CLASS = "apexgantt-watermark";
5966
5966
  _Watermark.WATERMARK_TEXT = "Powered by apexcharts.com";
5967
5967
  let Watermark = _Watermark;
5968
+ function getParentElement(element) {
5969
+ const rootNode = element.getRootNode();
5970
+ if (rootNode instanceof ShadowRoot) {
5971
+ return rootNode.host;
5972
+ }
5973
+ return element.parentElement;
5974
+ }
5968
5975
  function getCumulativeTransform(element) {
5969
5976
  let scaleX = 1;
5970
5977
  let scaleY = 1;
@@ -5996,7 +6003,7 @@ function getCumulativeTransform(element) {
5996
6003
  console.warn("Failed to parse transform matrix:", transform2, e);
5997
6004
  }
5998
6005
  }
5999
- currentElement = currentElement.parentElement;
6006
+ currentElement = getParentElement(currentElement);
6000
6007
  }
6001
6008
  return { scaleX, scaleY, translateX, translateY };
6002
6009
  }
@@ -13903,7 +13910,8 @@ const ColumnList = [
13903
13910
  "name"
13904
13911
  /* Name */
13905
13912
  ],
13906
- width: "160px"
13913
+ minWidth: "120px",
13914
+ flexGrow: 3
13907
13915
  },
13908
13916
  {
13909
13917
  key: "startTime",
@@ -13911,7 +13919,8 @@ const ColumnList = [
13911
13919
  "startTime"
13912
13920
  /* StartTime */
13913
13921
  ],
13914
- width: "100px"
13922
+ minWidth: "70px",
13923
+ flexGrow: 1.5
13915
13924
  },
13916
13925
  {
13917
13926
  key: "duration",
@@ -13919,7 +13928,8 @@ const ColumnList = [
13919
13928
  "duration"
13920
13929
  /* Duration */
13921
13930
  ],
13922
- width: "80px"
13931
+ minWidth: "50px",
13932
+ flexGrow: 1
13923
13933
  },
13924
13934
  {
13925
13935
  key: "progress",
@@ -13927,9 +13937,17 @@ const ColumnList = [
13927
13937
  "progress"
13928
13938
  /* Progress */
13929
13939
  ],
13930
- width: "80px"
13940
+ minWidth: "50px",
13941
+ flexGrow: 1
13931
13942
  }
13932
13943
  ];
13944
+ function generateGridTemplateColumns(columns) {
13945
+ return columns.map((col) => {
13946
+ const minWidth = col.minWidth || "30px";
13947
+ const flexGrow = col.flexGrow || 1;
13948
+ return `minmax(${minWidth}, ${flexGrow}fr)`;
13949
+ }).join(" ");
13950
+ }
13933
13951
  function getTaskTextByColumn(task, columnKey, inputDateFormat) {
13934
13952
  const taskColumnValue = task[columnKey];
13935
13953
  if (columnKey === "startTime") {
@@ -14057,6 +14075,40 @@ class Tasks {
14057
14075
  this.options = options;
14058
14076
  this.chartContext = chartContext;
14059
14077
  this.dataManager = dataManager;
14078
+ this.effectiveColumnList = this.mergeColumnConfig();
14079
+ this.injectDynamicColumnStyles();
14080
+ }
14081
+ /**
14082
+ * Merges user column config with defaults
14083
+ */
14084
+ mergeColumnConfig() {
14085
+ if (!this.options.columnConfig || this.options.columnConfig.length === 0) {
14086
+ return ColumnList;
14087
+ }
14088
+ return ColumnList.map((defaultCol) => {
14089
+ var _a;
14090
+ const userCol = (_a = this.options.columnConfig) == null ? void 0 : _a.find((col) => col.key === defaultCol.key);
14091
+ return userCol ? { ...defaultCol, ...userCol } : defaultCol;
14092
+ });
14093
+ }
14094
+ /**
14095
+ * Dynamic CSS for column widths based on configuration
14096
+ */
14097
+ injectDynamicColumnStyles() {
14098
+ const gridTemplate = generateGridTemplateColumns(this.effectiveColumnList);
14099
+ const chartInstanceId = this.chartContext.getInstanceId();
14100
+ const dynamicStyles = `
14101
+ .tasks-container .tasks-header[data-chart-instance="${chartInstanceId}"] .tasks-header-row {
14102
+ grid-template-columns: ${gridTemplate};
14103
+ }
14104
+
14105
+ .tasks-container .tasks-data-row[data-chart-instance="${chartInstanceId}"] {
14106
+ grid-template-columns: ${gridTemplate};
14107
+ }
14108
+ `;
14109
+ this.chartContext.injectStyles(dynamicStyles, `tasks-dynamic-columns-${chartInstanceId}`, {
14110
+ priority: "high"
14111
+ });
14060
14112
  }
14061
14113
  generateBody(tasks, reRender) {
14062
14114
  const bodyContainer = createBox(this.chartContext, { className: "tasks-data-container" });
@@ -14069,19 +14121,13 @@ class Tasks {
14069
14121
  const { headerBackground, rowHeight, fontColor } = this.options;
14070
14122
  const chartInstanceId = this.chartContext.getInstanceId();
14071
14123
  headerContainer.setAttribute("data-chart-instance", chartInstanceId);
14072
- forEach(headerList, (header, index) => {
14073
- const columnDef = ColumnList[index];
14124
+ forEach(headerList, (header) => {
14074
14125
  const headerCell = createBox(this.chartContext, {
14075
14126
  className: "tasks-header-cell",
14076
14127
  content: header
14077
14128
  });
14078
14129
  headerCell.style.height = `${rowHeight * 2}px`;
14079
14130
  headerCell.style.color = fontColor;
14080
- if (columnDef == null ? void 0 : columnDef.width) {
14081
- headerCell.style.width = columnDef.width;
14082
- headerCell.style.minWidth = columnDef.width;
14083
- headerCell.style.flexBasis = columnDef.width;
14084
- }
14085
14131
  headerRow.append(headerCell);
14086
14132
  });
14087
14133
  headerContainer.append(headerRow);
@@ -14095,7 +14141,7 @@ class Tasks {
14095
14141
  row.setAttribute("data-taskid", task.id);
14096
14142
  row.setAttribute("data-chart-instance", chartInstanceId);
14097
14143
  row.style.height = `${rowHeight}px`;
14098
- forEach(ColumnList, ({ key, width: width2 }) => {
14144
+ forEach(this.effectiveColumnList, ({ key }) => {
14099
14145
  const cell = createBox(this.chartContext, {
14100
14146
  className: "tasks-data-cell",
14101
14147
  content: getTaskTextByColumn(task, key, this.options.inputDateFormat)
@@ -14104,11 +14150,6 @@ class Tasks {
14104
14150
  cell.setAttribute("data-chart-instance", chartInstanceId);
14105
14151
  cell.style.height = `${rowHeight}px`;
14106
14152
  cell.style.color = fontColor;
14107
- if (width2) {
14108
- cell.style.width = width2;
14109
- cell.style.minWidth = width2;
14110
- cell.style.flexBasis = width2;
14111
- }
14112
14153
  if (key === ColumnKey.Name) {
14113
14154
  cell.style.paddingLeft = `${task.level * 15}px`;
14114
14155
  cell.style.textAlign = "left";
@@ -14167,7 +14208,7 @@ class Tasks {
14167
14208
  row.setAttribute("data-taskid", `empty-${index}`);
14168
14209
  row.setAttribute("data-chart-instance", chartInstanceId);
14169
14210
  row.style.height = `${rowHeight}px`;
14170
- forEach(ColumnList, ({ key, width: width2 }) => {
14211
+ forEach(this.effectiveColumnList, ({ key }) => {
14171
14212
  const cell = createBox(this.chartContext, {
14172
14213
  className: "tasks-data-cell",
14173
14214
  content: ""
@@ -14176,17 +14217,12 @@ class Tasks {
14176
14217
  cell.setAttribute("data-chart-instance", chartInstanceId);
14177
14218
  cell.style.height = `${rowHeight}px`;
14178
14219
  cell.style.color = fontColor;
14179
- if (width2) {
14180
- cell.style.width = width2;
14181
- cell.style.minWidth = width2;
14182
- cell.style.flexBasis = width2;
14183
- }
14184
14220
  row.append(cell);
14185
14221
  });
14186
14222
  return row;
14187
14223
  }
14188
14224
  render(reRender) {
14189
- const headerRow = this.generateHeader(ColumnList.map((col) => col.title));
14225
+ const headerRow = this.generateHeader(this.effectiveColumnList.map((col) => col.title));
14190
14226
  const dataRows = this.generateBody(this.dataManager.getFlatVisibleTasks(), reRender);
14191
14227
  return [headerRow, dataRows];
14192
14228
  }
@@ -14294,6 +14330,32 @@ class DataManager {
14294
14330
  }
14295
14331
  getDateRange(add = 0, viewMode) {
14296
14332
  const tasks = this.getTasks();
14333
+ if (tasks.length === 0) {
14334
+ const today = dayjs();
14335
+ const startDate = today.startOf(viewMode);
14336
+ let defaultRange = 1;
14337
+ switch (viewMode) {
14338
+ case "day":
14339
+ defaultRange = 30;
14340
+ break;
14341
+ case "week":
14342
+ defaultRange = 12;
14343
+ break;
14344
+ case "month":
14345
+ defaultRange = 12;
14346
+ break;
14347
+ case "quarter":
14348
+ defaultRange = 4;
14349
+ break;
14350
+ case "year":
14351
+ defaultRange = 5;
14352
+ break;
14353
+ default:
14354
+ defaultRange = 12;
14355
+ }
14356
+ const endDate = startDate.add(defaultRange + add, viewMode);
14357
+ return [startDate, endDate];
14358
+ }
14297
14359
  const startDates = tasks.map((task) => dayjs(task.startTime));
14298
14360
  const endDates = tasks.filter((task) => !!task.endTime).map((task) => dayjs(task.endTime));
14299
14361
  return [dayjs.min(startDates), dayjs.max(endDates).add(add, viewMode)];
@@ -15293,7 +15355,7 @@ const TableStyle = `
15293
15355
  }
15294
15356
 
15295
15357
  .tasks-header-row {
15296
- display: flex;
15358
+ display: grid;
15297
15359
  width: 100%;
15298
15360
  }
15299
15361
 
@@ -15308,7 +15370,6 @@ const TableStyle = `
15308
15370
  border: var(--cell-border-width, 1px) solid var(--cell-border-color, #eff0f0);
15309
15371
  color: var(--text-color, #000);
15310
15372
  box-sizing: border-box;
15311
- flex-shrink: 0;
15312
15373
  font-weight: 600;
15313
15374
  }
15314
15375
 
@@ -15325,7 +15386,7 @@ const TableStyle = `
15325
15386
  }
15326
15387
 
15327
15388
  .tasks-data-row {
15328
- display: flex;
15389
+ display: grid;
15329
15390
  width: 100%;
15330
15391
  border-bottom: var(--cell-border-width, 1px) solid var(--cell-border-color, #eff0f0);
15331
15392
  box-sizing: border-box;
@@ -15343,7 +15404,6 @@ const TableStyle = `
15343
15404
  border-right: var(--cell-border-width, 1px) solid var(--cell-border-color, #eff0f0);
15344
15405
  color: var(--text-color, #000);
15345
15406
  box-sizing: border-box;
15346
- flex-shrink: 0;
15347
15407
  }
15348
15408
 
15349
15409
  .tasks-data-row .tasks-data-cell:first-child {
@@ -16240,7 +16300,7 @@ class SplitView {
16240
16300
 
16241
16301
  .split-view-container .split-left-container {
16242
16302
  flex-grow: 0 !important;
16243
- flex-shrink: 0 !important;
16303
+ flex-shrink: 1 !important;
16244
16304
  overflow: visible;
16245
16305
  display: flex !important;
16246
16306
  flex-direction: column;
@@ -16398,8 +16458,8 @@ class SplitView {
16398
16458
  if (!containerRect)
16399
16459
  return;
16400
16460
  const newWidth = moveEvent.clientX - containerRect.left;
16401
- const minWidth = 50;
16402
- const maxWidth = containerRect.width - 100;
16461
+ const minWidth = 0;
16462
+ const maxWidth = containerRect.width - 50;
16403
16463
  const clampedWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));
16404
16464
  this.leftContainer.style.flexBasis = `${clampedWidth}px`;
16405
16465
  this.dispatchResizeEvent();
@@ -16428,25 +16488,29 @@ class SplitView {
16428
16488
  switch (e.key) {
16429
16489
  case "ArrowLeft":
16430
16490
  e.preventDefault();
16431
- newWidth = Math.max(50, currentWidth - step);
16491
+ newWidth = Math.max(0, currentWidth - step);
16432
16492
  this.leftContainer.style.flexBasis = `${newWidth}px`;
16493
+ this.dispatchResizeEvent();
16433
16494
  break;
16434
16495
  case "ArrowRight":
16435
16496
  e.preventDefault();
16436
16497
  newWidth = currentWidth + step;
16437
16498
  this.leftContainer.style.flexBasis = `${newWidth}px`;
16499
+ this.dispatchResizeEvent();
16438
16500
  break;
16439
16501
  case "Home":
16440
16502
  e.preventDefault();
16441
- this.leftContainer.style.flexBasis = "50px";
16503
+ this.leftContainer.style.flexBasis = "0px";
16504
+ this.dispatchResizeEvent();
16442
16505
  break;
16443
16506
  case "End": {
16444
16507
  e.preventDefault();
16445
16508
  const container = this.splitBarContainer.parentElement;
16446
16509
  if (container) {
16447
- const maxWidth = container.clientWidth - 100;
16510
+ const maxWidth = container.clientWidth - 50;
16448
16511
  this.leftContainer.style.flexBasis = `${maxWidth}px`;
16449
16512
  }
16513
+ this.dispatchResizeEvent();
16450
16514
  break;
16451
16515
  }
16452
16516
  }
@@ -16496,12 +16560,11 @@ class GanttStateManager {
16496
16560
  */
16497
16561
  captureState(element, dataManager, viewMode) {
16498
16562
  const horizontalScroll = element.querySelector(".timeline-horizontal-scroll");
16499
- const tasksBodyWrapper = element.querySelector(".tasks-body-wrapper");
16500
- const timelineBodyWrapper = element.querySelector(".timeline-body-wrapper");
16563
+ const splitViewContainer = element.querySelector(".split-view-container");
16501
16564
  this.state.scrollPosition = {
16502
16565
  horizontal: (horizontalScroll == null ? void 0 : horizontalScroll.scrollLeft) || 0,
16503
- tasksVertical: (tasksBodyWrapper == null ? void 0 : tasksBodyWrapper.scrollTop) || 0,
16504
- timelineVertical: (timelineBodyWrapper == null ? void 0 : timelineBodyWrapper.scrollTop) || 0
16566
+ tasksVertical: (splitViewContainer == null ? void 0 : splitViewContainer.scrollTop) || 0,
16567
+ timelineVertical: (splitViewContainer == null ? void 0 : splitViewContainer.scrollTop) || 0
16505
16568
  };
16506
16569
  this.state.viewMode = viewMode;
16507
16570
  this.state.collapsedTasks = new Set(
@@ -16515,20 +16578,16 @@ class GanttStateManager {
16515
16578
  if (!skipScroll) {
16516
16579
  requestAnimationFrame(() => {
16517
16580
  const horizontalScroll = element.querySelector(".timeline-horizontal-scroll");
16518
- const tasksBodyWrapper = element.querySelector(".tasks-body-wrapper");
16519
- const timelineBodyWrapper = element.querySelector(".timeline-body-wrapper");
16581
+ const splitViewContainer = element.querySelector(".split-view-container");
16520
16582
  if (horizontalScroll) {
16521
16583
  horizontalScroll.scrollLeft = this.state.scrollPosition.horizontal;
16522
16584
  }
16523
- if (tasksBodyWrapper) {
16524
- tasksBodyWrapper.scrollTop = this.state.scrollPosition.tasksVertical;
16585
+ if (splitViewContainer) {
16586
+ splitViewContainer.scrollTop = this.state.scrollPosition.tasksVertical;
16525
16587
  }
16526
- if (timelineBodyWrapper) {
16527
- timelineBodyWrapper.scrollTop = this.state.scrollPosition.timelineVertical;
16528
- const timelineHeader = element.querySelector(".timeline-header");
16529
- if (timelineHeader) {
16530
- timelineHeader.scrollLeft = this.state.scrollPosition.horizontal;
16531
- }
16588
+ const timelineHeader = element.querySelector(".timeline-header");
16589
+ if (timelineHeader) {
16590
+ timelineHeader.scrollLeft = this.state.scrollPosition.horizontal;
16532
16591
  }
16533
16592
  });
16534
16593
  }
@@ -16714,6 +16773,10 @@ class ApexGantt extends BaseChart {
16714
16773
  this.isSyncingScroll = false;
16715
16774
  this.scrollbarResizeObserver = null;
16716
16775
  this.splitBarResizeHandler = null;
16776
+ this.containerResizeObserver = null;
16777
+ this.lastKnownWidth = 0;
16778
+ this.lastKnownHeight = 0;
16779
+ this.resizeDebounceTimer = null;
16717
16780
  const themeDefaults = getDefaultOptions(options == null ? void 0 : options.theme);
16718
16781
  let processedSeries;
16719
16782
  if (options == null ? void 0 : options.parsing) {
@@ -16948,21 +17011,11 @@ class ApexGantt extends BaseChart {
16948
17011
  this.setCSSVariables();
16949
17012
  this.initializeTooltip();
16950
17013
  this.element.innerHTML = "";
16951
- const existingDimensions = this.hasExplicitDimensions();
17014
+ this.hasExplicitDimensions();
16952
17015
  const normalizedHeight = this.normalizeDimension(height2);
16953
17016
  const normalizedWidth = this.normalizeDimension(width2);
16954
- if (normalizedHeight === "100%" && existingDimensions.height) {
16955
- const computedHeight = window.getComputedStyle(this.element).height;
16956
- this.element.style.height = computedHeight;
16957
- } else {
16958
- this.element.style.height = normalizedHeight;
16959
- }
16960
- if (normalizedWidth === "100%" && existingDimensions.width) {
16961
- const computedWidth = window.getComputedStyle(this.element).width;
16962
- this.element.style.width = computedWidth;
16963
- } else {
16964
- this.element.style.width = normalizedWidth;
16965
- }
17017
+ this.element.style.width = normalizedWidth;
17018
+ this.element.style.height = normalizedHeight;
16966
17019
  this.element.style.display = "flex";
16967
17020
  this.element.style.flexDirection = "column";
16968
17021
  this.element.style.boxSizing = "border-box";
@@ -16996,14 +17049,7 @@ class ApexGantt extends BaseChart {
16996
17049
  this.setupDependencyArrowEvents();
16997
17050
  this.renderDependencyArrows();
16998
17051
  requestAnimationFrame(() => {
16999
- this.syncTasksColumnWidths();
17000
- this.compensateForScrollbar();
17001
- this.updateHorizontalScrollbarContent();
17002
- this.setupTimelineHorizontalScroll();
17003
- this.positionHorizontalScrollbar();
17004
- this.setupScrollbarResizeObserver();
17005
- this.disableHeaderMousewheelScroll();
17006
- this.fillEmptyRowsAfterRender();
17052
+ this.performAfterActions();
17007
17053
  });
17008
17054
  if (isReRender) {
17009
17055
  requestAnimationFrame(() => {
@@ -17012,6 +17058,18 @@ class ApexGantt extends BaseChart {
17012
17058
  }
17013
17059
  return this.element;
17014
17060
  }
17061
+ performAfterActions() {
17062
+ this.syncTasksColumnWidths();
17063
+ this.compensateForScrollbar();
17064
+ this.updateHorizontalScrollbarContent();
17065
+ this.setupTimelineHorizontalScroll();
17066
+ this.positionHorizontalScrollbar();
17067
+ this.setupContainerResizeObserver();
17068
+ this.setupScrollbarResizeObserver();
17069
+ this.setupRowBackgroundColors();
17070
+ this.disableHeaderMousewheelScroll();
17071
+ this.fillEmptyRowsAfterRender();
17072
+ }
17015
17073
  /**
17016
17074
  * Setup proper positioning for chart container to support dialogs
17017
17075
  */
@@ -17350,15 +17408,7 @@ class ApexGantt extends BaseChart {
17350
17408
  }
17351
17409
  }
17352
17410
  requestAnimationFrame(() => {
17353
- this.syncTasksColumnWidths();
17354
- this.compensateForScrollbar();
17355
- this.updateHorizontalScrollbarContent();
17356
- this.setupTimelineHorizontalScroll();
17357
- this.positionHorizontalScrollbar();
17358
- this.setupScrollbarResizeObserver();
17359
- this.setupRowBackgroundColors();
17360
- this.disableHeaderMousewheelScroll();
17361
- this.fillEmptyRowsAfterRender();
17411
+ this.performAfterActions();
17362
17412
  });
17363
17413
  }
17364
17414
  updateToolbarAfterZoom() {
@@ -17587,6 +17637,10 @@ class ApexGantt extends BaseChart {
17587
17637
  if (!ganttContainer || !timelineBody || !tasksBody) {
17588
17638
  return;
17589
17639
  }
17640
+ const oldEmptyTimelineRows = timelineBody.querySelectorAll(".timeline-empty-row");
17641
+ oldEmptyTimelineRows.forEach((row) => row.remove());
17642
+ const oldEmptyTaskRows = tasksBody.querySelectorAll(".tasks-empty-row");
17643
+ oldEmptyTaskRows.forEach((row) => row.remove());
17590
17644
  const containerHeight = ganttContainer.clientHeight;
17591
17645
  const existingRows = timelineBody.querySelectorAll(".timeline-data-row:not(.timeline-empty-row)");
17592
17646
  const existingRowCount = existingRows.length;
@@ -17595,8 +17649,17 @@ class ApexGantt extends BaseChart {
17595
17649
  const emptyRowsNeeded = Math.max(0, totalRowsNeeded - existingRowCount);
17596
17650
  if (emptyRowsNeeded === 0)
17597
17651
  return;
17652
+ let cellCount = 0;
17598
17653
  const firstRow = timelineBody.querySelector(".timeline-data-row");
17599
- const cellCount = firstRow ? firstRow.querySelectorAll(".timeline-data-cell").length : 0;
17654
+ if (firstRow) {
17655
+ cellCount = firstRow.querySelectorAll(".timeline-data-cell").length;
17656
+ } else {
17657
+ const timelineHeader = ganttContainer.querySelector(".timeline-header");
17658
+ if (timelineHeader) {
17659
+ const headerCells = timelineHeader.querySelectorAll(".timeline-header-cell");
17660
+ cellCount = headerCells.length;
17661
+ }
17662
+ }
17600
17663
  if (cellCount === 0)
17601
17664
  return;
17602
17665
  for (let i = 0; i < emptyRowsNeeded; i++) {
@@ -17635,7 +17698,7 @@ class ApexGantt extends BaseChart {
17635
17698
  row.setAttribute("data-taskid", `empty-${index}`);
17636
17699
  row.setAttribute("data-chart-instance", chartInstanceId);
17637
17700
  row.style.height = `${rowHeight}px`;
17638
- ColumnList.forEach(({ key, width: width2 }) => {
17701
+ ColumnList.forEach(({ key }) => {
17639
17702
  const cell = createBox(this.chartContext, {
17640
17703
  className: "tasks-data-cell",
17641
17704
  content: ""
@@ -17644,11 +17707,6 @@ class ApexGantt extends BaseChart {
17644
17707
  cell.setAttribute("data-chart-instance", chartInstanceId);
17645
17708
  cell.style.height = `${rowHeight}px`;
17646
17709
  cell.style.color = fontColor;
17647
- if (width2) {
17648
- cell.style.width = width2;
17649
- cell.style.minWidth = width2;
17650
- cell.style.flexBasis = width2;
17651
- }
17652
17710
  row.appendChild(cell);
17653
17711
  });
17654
17712
  return row;
@@ -17756,8 +17814,84 @@ class ApexGantt extends BaseChart {
17756
17814
  }
17757
17815
  return value;
17758
17816
  }
17817
+ /**
17818
+ * resize observer for container to handle responsive width and height changes
17819
+ */
17820
+ setupContainerResizeObserver() {
17821
+ if (!this.element) {
17822
+ return;
17823
+ }
17824
+ if (this.containerResizeObserver) {
17825
+ this.containerResizeObserver.disconnect();
17826
+ }
17827
+ const normalizedWidth = this.normalizeDimension(this.options.width);
17828
+ const normalizedHeight = this.normalizeDimension(this.options.height);
17829
+ const isPercentageWidth = typeof normalizedWidth === "string" && normalizedWidth.includes("%");
17830
+ const isPercentageHeight = typeof normalizedHeight === "string" && normalizedHeight.includes("%");
17831
+ if (!isPercentageWidth && !isPercentageHeight) {
17832
+ return;
17833
+ }
17834
+ this.lastKnownWidth = this.element.offsetWidth;
17835
+ this.lastKnownHeight = this.element.offsetHeight;
17836
+ this.containerResizeObserver = new ResizeObserver((entries) => {
17837
+ for (const entry of entries) {
17838
+ const newWidth = entry.contentRect.width;
17839
+ const newHeight = entry.contentRect.height;
17840
+ const widthChanged = Math.abs(newWidth - this.lastKnownWidth) > 1;
17841
+ const heightChanged = Math.abs(newHeight - this.lastKnownHeight) > 1;
17842
+ if (widthChanged || heightChanged) {
17843
+ this.lastKnownWidth = newWidth;
17844
+ this.lastKnownHeight = newHeight;
17845
+ this.handleContainerResize();
17846
+ }
17847
+ }
17848
+ });
17849
+ this.containerResizeObserver.observe(this.element);
17850
+ }
17851
+ handleContainerResize() {
17852
+ if (this.resizeDebounceTimer !== null) {
17853
+ window.clearTimeout(this.resizeDebounceTimer);
17854
+ }
17855
+ this.resizeDebounceTimer = window.setTimeout(() => {
17856
+ this.performResize();
17857
+ this.resizeDebounceTimer = null;
17858
+ }, 150);
17859
+ }
17860
+ performResize() {
17861
+ if (!this.element || this.isDestroyed()) {
17862
+ return;
17863
+ }
17864
+ const normalizedWidth = this.normalizeDimension(this.options.width);
17865
+ const normalizedHeight = this.normalizeDimension(this.options.height);
17866
+ const isPercentageWidth = typeof normalizedWidth === "string" && normalizedWidth.includes("%");
17867
+ const isPercentageHeight = typeof normalizedHeight === "string" && normalizedHeight.includes("%");
17868
+ if (isPercentageWidth) {
17869
+ const computedWidth = window.getComputedStyle(this.element.parentElement || this.element).width;
17870
+ const currentElementWidth = window.getComputedStyle(this.element).width;
17871
+ if (computedWidth !== currentElementWidth) {
17872
+ requestAnimationFrame(() => {
17873
+ this.positionHorizontalScrollbar();
17874
+ this.updateHorizontalScrollbarContent();
17875
+ this.syncTasksColumnWidths();
17876
+ });
17877
+ }
17878
+ }
17879
+ if (isPercentageHeight) {
17880
+ requestAnimationFrame(() => {
17881
+ this.fillEmptyRowsAfterRender();
17882
+ });
17883
+ }
17884
+ }
17759
17885
  destroy() {
17760
17886
  try {
17887
+ if (this.containerResizeObserver) {
17888
+ this.containerResizeObserver.disconnect();
17889
+ this.containerResizeObserver = null;
17890
+ }
17891
+ if (this.resizeDebounceTimer !== null) {
17892
+ window.clearTimeout(this.resizeDebounceTimer);
17893
+ this.resizeDebounceTimer = null;
17894
+ }
17761
17895
  if (this.zoomHandler) {
17762
17896
  const chartInstanceId = this.getInstanceId();
17763
17897
  const timelineElement = this.chartContext.querySelector(