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 +39 -0
- package/apexgantt.es.min.js +220 -86
- package/apexgantt.min.js +2 -2
- package/demo/basic-gantt-large-range.html +1 -1
- package/demo/basic-gantt.html +1 -1
- package/demo/data-parsing.html +1 -1
- package/demo/gantt-with-annotations.html +1 -1
- package/demo/gantt-with-interactions.html +2 -1
- package/lib/gantt.d.ts +11 -0
- package/lib/models/Options.d.ts +6 -1
- package/lib/models/Tasks.d.ts +9 -0
- package/lib/styles/Tasks.style.d.ts +1 -1
- package/lib/util/gantt-export.d.ts +1 -0
- package/lib/util/task.util.d.ts +7 -1
- package/package.json +1 -1
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.
|
package/apexgantt.es.min.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
16402
|
-
const maxWidth = containerRect.width -
|
|
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(
|
|
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 = "
|
|
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 -
|
|
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
|
|
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: (
|
|
16504
|
-
timelineVertical: (
|
|
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
|
|
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 (
|
|
16524
|
-
|
|
16585
|
+
if (splitViewContainer) {
|
|
16586
|
+
splitViewContainer.scrollTop = this.state.scrollPosition.tasksVertical;
|
|
16525
16587
|
}
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
|
|
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
|
-
|
|
17014
|
+
this.hasExplicitDimensions();
|
|
16952
17015
|
const normalizedHeight = this.normalizeDimension(height2);
|
|
16953
17016
|
const normalizedWidth = this.normalizeDimension(width2);
|
|
16954
|
-
|
|
16955
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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(
|