@progress/kendo-angular-gantt 17.2.1-develop.2 → 17.3.0-develop.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.
Files changed (45) hide show
  1. package/directives.d.ts +3 -1
  2. package/dragging/task-drag.directive.d.ts +29 -0
  3. package/dragging/task-drag.service.d.ts +49 -0
  4. package/esm2022/directives.mjs +5 -1
  5. package/esm2022/dragging/task-drag.directive.mjs +81 -0
  6. package/esm2022/dragging/task-drag.service.mjs +231 -0
  7. package/esm2022/gantt.component.mjs +49 -9
  8. package/esm2022/gantt.module.mjs +3 -1
  9. package/esm2022/index.mjs +2 -0
  10. package/esm2022/localization/messages.mjs +13 -1
  11. package/esm2022/models/events/{task-move-start-event.interface.mjs → index.mjs} +1 -1
  12. package/esm2022/models/models.mjs +2 -1
  13. package/esm2022/package-metadata.mjs +2 -2
  14. package/esm2022/rendering/gantt-task-base.mjs +9 -1
  15. package/esm2022/rendering/gantt-task.component.mjs +20 -7
  16. package/esm2022/rendering/gantt-tasks-table-body.component.mjs +35 -12
  17. package/esm2022/template-directives/task-tooltip-template.directive.mjs +49 -0
  18. package/esm2022/timeline/gantt-timeline.component.mjs +205 -13
  19. package/fesm2022/progress-kendo-angular-gantt.mjs +681 -66
  20. package/gantt.component.d.ts +18 -2
  21. package/gantt.module.d.ts +3 -1
  22. package/index.d.ts +2 -0
  23. package/localization/messages.d.ts +9 -1
  24. package/models/events/index.d.ts +21 -0
  25. package/models/events/task-drag-event.interface.d.ts +67 -0
  26. package/models/models.d.ts +4 -24
  27. package/models/tooltip-options.interface.d.ts +28 -0
  28. package/package.json +16 -15
  29. package/rendering/gantt-task-base.d.ts +7 -1
  30. package/rendering/gantt-task.component.d.ts +1 -0
  31. package/rendering/gantt-tasks-table-body.component.d.ts +7 -2
  32. package/schematics/ngAdd/index.js +7 -7
  33. package/template-directives/task-tooltip-template.directive.d.ts +38 -0
  34. package/timeline/gantt-timeline.component.d.ts +31 -6
  35. package/esm2022/models/events/task-resize-end-event.interface.mjs +0 -5
  36. package/esm2022/models/events/task-resize-event.interface.mjs +0 -5
  37. package/esm2022/models/events/task-resize-start-event.interface.mjs +0 -5
  38. package/models/events/task-move-end-event.interface.d.ts +0 -12
  39. package/models/events/task-move-event.interface.d.ts +0 -23
  40. package/models/events/task-move-start-event.interface.d.ts +0 -15
  41. package/models/events/task-resize-end-event.interface.d.ts +0 -12
  42. package/models/events/task-resize-event.interface.d.ts +0 -23
  43. package/models/events/task-resize-start-event.interface.d.ts +0 -15
  44. /package/esm2022/models/events/{task-move-end-event.interface.mjs → task-drag-event.interface.mjs} +0 -0
  45. /package/esm2022/models/{events/task-move-event.interface.mjs → tooltip-options.interface.mjs} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { Component, ElementRef, EventEmitter, Input, NgZone, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
5
+ import { Component, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
6
6
  import { Subscription } from 'rxjs';
7
7
  import { filter, map, switchMap, take } from 'rxjs/operators';
8
8
  import { DraggableDirective, isDocumentAvailable } from '@progress/kendo-angular-common';
@@ -12,13 +12,21 @@ import { isPresent } from '../utils';
12
12
  import { CurrentTimeMarkerService } from './current-time-marker.service';
13
13
  import { GanttDependencyDirective } from '../dependencies/gantt-dependency.directive';
14
14
  import { GanttTasksTableBodyComponent } from '../rendering/gantt-tasks-table-body.component';
15
- import { NgFor } from '@angular/common';
15
+ import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
16
16
  import { TimelineScrollableDirective } from '../scrolling/timeline-scroll.directive';
17
17
  import { GanttHeaderTableBodyComponent } from '../rendering/gantt-header-table-body.component';
18
+ import { TaskDragService } from '../dragging/task-drag.service';
19
+ import { KENDO_TOOLTIP, TooltipDirective } from '@progress/kendo-angular-tooltip';
20
+ import { DatePipe, NumberPipe } from '@progress/kendo-angular-intl';
21
+ import { GanttTaskTooltipTemplateDirective } from '../template-directives/task-tooltip-template.directive';
22
+ import { GanttLocalizationService } from '../localization/gantt-localization.service';
18
23
  import * as i0 from "@angular/core";
19
24
  import * as i1 from "../scrolling/scroll-sync.service";
20
25
  import * as i2 from "../dependencies/dependency-dom.service";
21
26
  import * as i3 from "./current-time-marker.service";
27
+ import * as i4 from "../localization/gantt-localization.service";
28
+ import * as i5 from "../dragging/task-drag.service";
29
+ import * as i6 from "@progress/kendo-angular-tooltip";
22
30
  /**
23
31
  * @hidden
24
32
  */
@@ -28,6 +36,8 @@ export class GanttTimelineComponent {
28
36
  renderer;
29
37
  zone;
30
38
  currentTimeMarkerService;
39
+ localization;
40
+ taskDragService;
31
41
  /**
32
42
  * Represents the scrollable container of the timeline content.
33
43
  * Used externally by the DependencyDragCreateDirective.
@@ -36,6 +46,7 @@ export class GanttTimelineComponent {
36
46
  timelineColumns;
37
47
  timelineHeaderWrap;
38
48
  tasksContainer;
49
+ tooltip;
39
50
  /**
40
51
  * Represents the view container ref used for rendering the dependency drag popop.
41
52
  * Used externally by the DependencyDragCreateDirective.
@@ -58,6 +69,8 @@ export class GanttTimelineComponent {
58
69
  renderDependencyDragClues;
59
70
  dragScrollSettings;
60
71
  currentTimeMarker;
72
+ customTooltipTemplate;
73
+ tooltipOptions;
61
74
  selectable;
62
75
  isTaskSelected;
63
76
  isExpanded;
@@ -72,13 +85,26 @@ export class GanttTimelineComponent {
72
85
  get draggableEnabled() {
73
86
  return this.renderDependencyDragClues;
74
87
  }
88
+ task;
89
+ dragResult;
90
+ dragging = false;
91
+ completion = false;
92
+ marquee = {
93
+ show: false,
94
+ left: 0,
95
+ width: 0
96
+ };
97
+ dragOffset;
75
98
  subscriptions = new Subscription();
76
- constructor(scrollSyncService, dependencyDomService, renderer, zone, currentTimeMarkerService) {
99
+ popupRef;
100
+ constructor(scrollSyncService, dependencyDomService, renderer, zone, currentTimeMarkerService, localization, taskDragService) {
77
101
  this.scrollSyncService = scrollSyncService;
78
102
  this.dependencyDomService = dependencyDomService;
79
103
  this.renderer = renderer;
80
104
  this.zone = zone;
81
105
  this.currentTimeMarkerService = currentTimeMarkerService;
106
+ this.localization = localization;
107
+ this.taskDragService = taskDragService;
82
108
  this.subscriptions.add(
83
109
  // task changes indicates change in row content, number, height, etc.
84
110
  this.dependencyDomService.taskChanges
@@ -94,6 +120,73 @@ export class GanttTimelineComponent {
94
120
  this.createTimeMarker();
95
121
  this.renderer.setStyle(this.timelineColumns.nativeElement, 'height', `${(this.rows || []).length * timelineRowHeight}px`);
96
122
  }));
123
+ if (!taskDragService) {
124
+ return;
125
+ }
126
+ this.subscriptions.add(taskDragService.dragStart.subscribe((e) => {
127
+ if (e.dragTarget.classList.contains('k-task-draghandle')) {
128
+ this.completion = true;
129
+ const taskRect = this.taskDragService.currentDragTaskRect;
130
+ this.tooltip.position = 'top';
131
+ this.tooltip.callout = true;
132
+ this.tooltip.offset = taskRect.height + 6;
133
+ this.tooltip.collision = {
134
+ horizontal: 'fit',
135
+ vertical: 'fit'
136
+ };
137
+ }
138
+ else {
139
+ this.dragging = true;
140
+ }
141
+ }));
142
+ this.subscriptions.add(taskDragService.drag.subscribe((e) => {
143
+ this.dragResult = {
144
+ start: e.start,
145
+ end: e.end,
146
+ completionRatio: e.completionRatio
147
+ };
148
+ if (this.completion) {
149
+ const dragHandle = e.dragEvent.dragTarget;
150
+ this.tooltip.show(dragHandle);
151
+ }
152
+ else {
153
+ this.marquee.show = true;
154
+ this.marquee.left = e.offset;
155
+ this.marquee.width = e.width;
156
+ const taskEl = this.taskDragService.currentDragTask.taskElement;
157
+ const taskRect = this.taskDragService.currentDragTaskRect;
158
+ this.tooltip.hide();
159
+ this.tooltip.position = this.taskDragService.rightDragHandle ? 'right' : 'left';
160
+ this.tooltip.collision = {
161
+ horizontal: 'fit',
162
+ vertical: 'fit'
163
+ };
164
+ this.tooltip.show(taskEl);
165
+ this.popupRef = this.tooltip.popupRef;
166
+ const popup = this.popupRef?.popup.instance;
167
+ const popupEl = popup?.container.nativeElement;
168
+ const popupHeight = popupEl?.offsetHeight ?? 0;
169
+ const popupWidth = popupEl?.offsetWidth ?? 0;
170
+ const taskMove = !(this.taskDragService.leftDragHandle || this.taskDragService.rightDragHandle);
171
+ this.popupRef && (this.popupRef.popupElement.style.zIndex += 1000000);
172
+ this.popupRef && (popup.margin = {
173
+ horizontal: taskMove ? taskRect.left - e.offset - this.taskDragService.tasksContainerRect.left - popupWidth / 2 : e.width - taskEl.nativeElement.clientWidth - popupWidth / 2,
174
+ vertical: (taskEl.nativeElement.clientHeight + popupHeight) / 2
175
+ });
176
+ }
177
+ }));
178
+ this.subscriptions.add(taskDragService.dragEnd.subscribe(() => {
179
+ this.marquee = {
180
+ show: false,
181
+ left: 0,
182
+ width: 0
183
+ };
184
+ this.dragging = this.completion = false;
185
+ this.tooltip.hide();
186
+ this.dragResult = null;
187
+ this.tooltip.position = this.tooltipOptions.position;
188
+ this.tooltip.offset = 6;
189
+ }));
97
190
  }
98
191
  ngOnChanges(changes) {
99
192
  if (changes['currentTimeMarker']) {
@@ -109,6 +202,13 @@ export class GanttTimelineComponent {
109
202
  this.scrollSyncService.registerElement(rightContainer, 'timeline');
110
203
  this.scrollSyncService.registerElement(timelineHeader, 'header');
111
204
  this.dependencyDomService.registerContentContainer(this.tasksContainer.nativeElement);
205
+ if (this.taskDragService) {
206
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
207
+ this.taskDragService.tasksContainer = this.tasksContainer.nativeElement;
208
+ this.taskDragService.scrollableContainer = this.tasksContainer.nativeElement.closest('.k-grid-content');
209
+ this.taskDragService.tasksContainerRect = this.tasksContainer.nativeElement.getBoundingClientRect();
210
+ });
211
+ }
112
212
  }
113
213
  ngOnDestroy() {
114
214
  this.subscriptions.unsubscribe();
@@ -116,6 +216,9 @@ export class GanttTimelineComponent {
116
216
  isNonWorking(item) {
117
217
  return item.hasOwnProperty('isWorking') && !item.isWorking;
118
218
  }
219
+ messageFor(token) {
220
+ return this.localization.get(token);
221
+ }
119
222
  createTimeMarker() {
120
223
  this.zone.runOutsideAngular(() => {
121
224
  this.currentTimeMarkerService.removeTimeMarker();
@@ -124,8 +227,8 @@ export class GanttTimelineComponent {
124
227
  }
125
228
  });
126
229
  }
127
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GanttTimelineComponent, deps: [{ token: i1.ScrollSyncService }, { token: i2.DependencyDomService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i3.CurrentTimeMarkerService }], target: i0.ɵɵFactoryTarget.Component });
128
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GanttTimelineComponent, isStandalone: true, selector: "kendo-gantt-timeline", inputs: { rows: "rows", slots: "slots", groupSlots: "groupSlots", tableWidth: "tableWidth", activeView: "activeView", taskContentTemplate: "taskContentTemplate", taskTemplate: "taskTemplate", summaryTaskTemplate: "summaryTaskTemplate", taskClass: "taskClass", renderDependencyDragClues: "renderDependencyDragClues", dragScrollSettings: "dragScrollSettings", currentTimeMarker: "currentTimeMarker", selectable: "selectable", isTaskSelected: "isTaskSelected", isExpanded: "isExpanded", dependencies: "dependencies" }, outputs: { timelineContainerPress: "timelineContainerPress", timelineContainerDrag: "timelineContainerDrag", timelineContainerRelease: "timelineContainerRelease" }, viewQueries: [{ propertyName: "timelineContent", first: true, predicate: ["timelineContent"], descendants: true, static: true }, { propertyName: "timelineColumns", first: true, predicate: ["timelineColumns"], descendants: true, static: true }, { propertyName: "timelineHeaderWrap", first: true, predicate: ["timelineHeaderWrap"], descendants: true, static: true }, { propertyName: "tasksContainer", first: true, predicate: ["tasksContainer"], descendants: true, static: true }, { propertyName: "dragPopupContainer", first: true, predicate: ["dragPopupContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dependencyDragCreatePolyline", first: true, predicate: ["dependencyDragCreatePolyline"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
230
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GanttTimelineComponent, deps: [{ token: i1.ScrollSyncService }, { token: i2.DependencyDomService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i3.CurrentTimeMarkerService }, { token: i4.GanttLocalizationService }, { token: i5.TaskDragService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
231
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GanttTimelineComponent, isStandalone: true, selector: "kendo-gantt-timeline", inputs: { rows: "rows", slots: "slots", groupSlots: "groupSlots", tableWidth: "tableWidth", activeView: "activeView", taskContentTemplate: "taskContentTemplate", taskTemplate: "taskTemplate", summaryTaskTemplate: "summaryTaskTemplate", taskClass: "taskClass", renderDependencyDragClues: "renderDependencyDragClues", dragScrollSettings: "dragScrollSettings", currentTimeMarker: "currentTimeMarker", customTooltipTemplate: "customTooltipTemplate", tooltipOptions: "tooltipOptions", selectable: "selectable", isTaskSelected: "isTaskSelected", isExpanded: "isExpanded", dependencies: "dependencies" }, outputs: { timelineContainerPress: "timelineContainerPress", timelineContainerDrag: "timelineContainerDrag", timelineContainerRelease: "timelineContainerRelease" }, viewQueries: [{ propertyName: "timelineContent", first: true, predicate: ["timelineContent"], descendants: true, static: true }, { propertyName: "timelineColumns", first: true, predicate: ["timelineColumns"], descendants: true, static: true }, { propertyName: "timelineHeaderWrap", first: true, predicate: ["timelineHeaderWrap"], descendants: true, static: true }, { propertyName: "tasksContainer", first: true, predicate: ["tasksContainer"], descendants: true, static: true }, { propertyName: "tooltip", first: true, predicate: TooltipDirective, descendants: true }, { propertyName: "dragPopupContainer", first: true, predicate: ["dragPopupContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dependencyDragCreatePolyline", first: true, predicate: ["dependencyDragCreatePolyline"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
129
232
  <div class="k-gantt-timeline k-grid k-grid-md">
130
233
  <div class="k-grid-header">
131
234
  <div #timelineHeaderWrap class="k-grid-header-wrap">
@@ -191,7 +294,14 @@ export class GanttTimelineComponent {
191
294
  </tbody>
192
295
  </table>
193
296
 
194
- <table
297
+ <table kendoTooltip
298
+ #tooltip="kendoTooltip"
299
+ [tooltipTemplate]="completion ? completionRatioTooltip : dragging ? resizingTooltip : customTooltipTemplate ? customTooltip : tooltipTemplate"
300
+ [position]="tooltipOptions.position"
301
+ [callout]="!dragging"
302
+ [tooltipClass]="dragging ? 'k-gantt-resize-hint' : undefined"
303
+ filter=".k-task"
304
+ [showOn]="dragging || completion ? 'none' : 'hover'"
195
305
  #tasksContainer
196
306
  class="k-table k-table-md k-gantt-tasks"
197
307
  role="presentation"
@@ -211,10 +321,39 @@ export class GanttTimelineComponent {
211
321
  [selectable]="selectable"
212
322
  [isTaskSelected]="isTaskSelected"
213
323
  [renderDependencyDragClues]="renderDependencyDragClues"
324
+ (taskPointerEnter)="task = $event"
325
+ (taskPointerLeave)="task = null"
214
326
  >
215
327
  </tbody>
216
328
  </table>
217
329
  </div>
330
+ <ng-template #tooltipTemplate>
331
+ <div class="k-task-content">
332
+ <div class="k-task-details">
333
+ <strong>{{task?.title}}</strong>
334
+ <div class="k-task-pct">{{task?.completionRatio | kendoNumber: 'p'}}</div>
335
+ <ul class="k-reset">
336
+ <li>{{messageFor('tooltipStartDateText')}}: {{task?.start | kendoDate: 'HH:mm a EEE, MMM d'}}</li>
337
+ <li>{{messageFor('tooltipEndDateText')}}: {{task?.end | kendoDate: 'HH:mm a EEE, MMM d'}}</li>
338
+ </ul>
339
+ </div>
340
+ </div>
341
+ </ng-template>
342
+ <ng-template #customTooltip>
343
+ <ng-container *ngTemplateOutlet="customTooltipTemplate.templateRef; context: { $implicit: task, task }"></ng-container>
344
+ </ng-template>
345
+ <ng-template #resizingTooltip>
346
+ <div class="k-tooltip-content">
347
+ <div>{{messageFor('tooltipStartDateText')}}: {{dragResult?.start | kendoDate: 'HH:mm a EEE, MMM d'}}</div>
348
+ <div>{{messageFor('tooltipEndDateText')}}: {{dragResult?.end | kendoDate: 'HH:mm a EEE, MMM d'}}</div>
349
+ </div>
350
+ </ng-template>
351
+ <ng-template #completionRatioTooltip>
352
+ <div class="k-tooltip-content">
353
+ <div>{{dragResult?.completionRatio | kendoNumber: 'p'}}</div>
354
+ </div>
355
+ </ng-template>
356
+
218
357
  <svg class="k-gantt-dependencies-svg">
219
358
  <polyline
220
359
  *ngFor="let dependency of dependencies"
@@ -223,12 +362,15 @@ export class GanttTimelineComponent {
223
362
  />
224
363
  <polyline #dependencyDragCreatePolyline />
225
364
  </svg>
226
-
365
+ <div class="k-marquee k-gantt-marquee" *ngIf="marquee.show" style="top: 0px; height: {{tasksContainer.offsetHeight}}px; left: {{marquee.left}}px; width: {{marquee.width}}px;">
366
+ <div class="k-marquee-color"></div>
367
+ </div>
227
368
  <!-- placeholder for the dependency drag popup; its position is not arbitrary - the popup is intended to be absolutely positioned inside the .k-grid-content element -->
228
369
  <ng-container #dragPopupContainer></ng-container>
229
370
  </div>
230
371
  </div>
231
- `, isInline: true, dependencies: [{ kind: "component", type: GanttHeaderTableBodyComponent, selector: "[kendoGanttHeaderTableBody]", inputs: ["groupSlots", "slots"] }, { kind: "directive", type: TimelineScrollableDirective, selector: "[kendoGanttTimelineScrollable]", inputs: ["scrollSettings"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: GanttTasksTableBodyComponent, selector: "[kendoGanttTasksTableBody]", inputs: ["selectable", "rows", "activeView", "taskContentTemplate", "taskTemplate", "summaryTaskTemplate", "taskClass", "isExpanded", "isTaskSelected", "renderDependencyDragClues"] }, { kind: "directive", type: GanttDependencyDirective, selector: "[kendoGanttDependency]", inputs: ["dependency"] }] });
372
+
373
+ `, isInline: true, dependencies: [{ kind: "component", type: GanttHeaderTableBodyComponent, selector: "[kendoGanttHeaderTableBody]", inputs: ["groupSlots", "slots"] }, { kind: "directive", type: TimelineScrollableDirective, selector: "[kendoGanttTimelineScrollable]", inputs: ["scrollSettings"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: GanttTasksTableBodyComponent, selector: "[kendoGanttTasksTableBody]", inputs: ["selectable", "rows", "activeView", "taskContentTemplate", "taskTemplate", "summaryTaskTemplate", "taskClass", "isExpanded", "isTaskSelected", "renderDependencyDragClues"], outputs: ["taskPointerEnter", "taskPointerLeave"] }, { kind: "directive", type: GanttDependencyDirective, selector: "[kendoGanttDependency]", inputs: ["dependency"] }, { kind: "directive", type: i6.TooltipDirective, selector: "[kendoTooltip]", inputs: ["filter", "position", "titleTemplate", "showOn", "showAfter", "callout", "closable", "offset", "tooltipWidth", "tooltipHeight", "tooltipClass", "tooltipContentClass", "collision", "closeTitle", "tooltipTemplate"], exportAs: ["kendoTooltip"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: DatePipe, name: "kendoDate" }, { kind: "pipe", type: NumberPipe, name: "kendoNumber" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
232
374
  }
233
375
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GanttTimelineComponent, decorators: [{
234
376
  type: Component,
@@ -300,7 +442,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
300
442
  </tbody>
301
443
  </table>
302
444
 
303
- <table
445
+ <table kendoTooltip
446
+ #tooltip="kendoTooltip"
447
+ [tooltipTemplate]="completion ? completionRatioTooltip : dragging ? resizingTooltip : customTooltipTemplate ? customTooltip : tooltipTemplate"
448
+ [position]="tooltipOptions.position"
449
+ [callout]="!dragging"
450
+ [tooltipClass]="dragging ? 'k-gantt-resize-hint' : undefined"
451
+ filter=".k-task"
452
+ [showOn]="dragging || completion ? 'none' : 'hover'"
304
453
  #tasksContainer
305
454
  class="k-table k-table-md k-gantt-tasks"
306
455
  role="presentation"
@@ -320,10 +469,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
320
469
  [selectable]="selectable"
321
470
  [isTaskSelected]="isTaskSelected"
322
471
  [renderDependencyDragClues]="renderDependencyDragClues"
472
+ (taskPointerEnter)="task = $event"
473
+ (taskPointerLeave)="task = null"
323
474
  >
324
475
  </tbody>
325
476
  </table>
326
477
  </div>
478
+ <ng-template #tooltipTemplate>
479
+ <div class="k-task-content">
480
+ <div class="k-task-details">
481
+ <strong>{{task?.title}}</strong>
482
+ <div class="k-task-pct">{{task?.completionRatio | kendoNumber: 'p'}}</div>
483
+ <ul class="k-reset">
484
+ <li>{{messageFor('tooltipStartDateText')}}: {{task?.start | kendoDate: 'HH:mm a EEE, MMM d'}}</li>
485
+ <li>{{messageFor('tooltipEndDateText')}}: {{task?.end | kendoDate: 'HH:mm a EEE, MMM d'}}</li>
486
+ </ul>
487
+ </div>
488
+ </div>
489
+ </ng-template>
490
+ <ng-template #customTooltip>
491
+ <ng-container *ngTemplateOutlet="customTooltipTemplate.templateRef; context: { $implicit: task, task }"></ng-container>
492
+ </ng-template>
493
+ <ng-template #resizingTooltip>
494
+ <div class="k-tooltip-content">
495
+ <div>{{messageFor('tooltipStartDateText')}}: {{dragResult?.start | kendoDate: 'HH:mm a EEE, MMM d'}}</div>
496
+ <div>{{messageFor('tooltipEndDateText')}}: {{dragResult?.end | kendoDate: 'HH:mm a EEE, MMM d'}}</div>
497
+ </div>
498
+ </ng-template>
499
+ <ng-template #completionRatioTooltip>
500
+ <div class="k-tooltip-content">
501
+ <div>{{dragResult?.completionRatio | kendoNumber: 'p'}}</div>
502
+ </div>
503
+ </ng-template>
504
+
327
505
  <svg class="k-gantt-dependencies-svg">
328
506
  <polyline
329
507
  *ngFor="let dependency of dependencies"
@@ -332,16 +510,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
332
510
  />
333
511
  <polyline #dependencyDragCreatePolyline />
334
512
  </svg>
335
-
513
+ <div class="k-marquee k-gantt-marquee" *ngIf="marquee.show" style="top: 0px; height: {{tasksContainer.offsetHeight}}px; left: {{marquee.left}}px; width: {{marquee.width}}px;">
514
+ <div class="k-marquee-color"></div>
515
+ </div>
336
516
  <!-- placeholder for the dependency drag popup; its position is not arbitrary - the popup is intended to be absolutely positioned inside the .k-grid-content element -->
337
517
  <ng-container #dragPopupContainer></ng-container>
338
518
  </div>
339
519
  </div>
520
+
340
521
  `,
341
522
  standalone: true,
342
- imports: [GanttHeaderTableBodyComponent, TimelineScrollableDirective, DraggableDirective, NgFor, GanttTasksTableBodyComponent, GanttDependencyDirective]
523
+ encapsulation: ViewEncapsulation.None,
524
+ imports: [GanttHeaderTableBodyComponent, TimelineScrollableDirective, DraggableDirective, NgFor, GanttTasksTableBodyComponent,
525
+ GanttDependencyDirective, KENDO_TOOLTIP, NgIf, DatePipe, NumberPipe, NgTemplateOutlet],
343
526
  }]
344
- }], ctorParameters: function () { return [{ type: i1.ScrollSyncService }, { type: i2.DependencyDomService }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i3.CurrentTimeMarkerService }]; }, propDecorators: { timelineContent: [{
527
+ }], ctorParameters: function () { return [{ type: i1.ScrollSyncService }, { type: i2.DependencyDomService }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i3.CurrentTimeMarkerService }, { type: i4.GanttLocalizationService }, { type: i5.TaskDragService, decorators: [{
528
+ type: Optional
529
+ }] }]; }, propDecorators: { timelineContent: [{
345
530
  type: ViewChild,
346
531
  args: ['timelineContent', { static: true }]
347
532
  }], timelineColumns: [{
@@ -353,12 +538,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
353
538
  }], tasksContainer: [{
354
539
  type: ViewChild,
355
540
  args: ['tasksContainer', { static: true }]
541
+ }], tooltip: [{
542
+ type: ViewChild,
543
+ args: [TooltipDirective]
356
544
  }], dragPopupContainer: [{
357
545
  type: ViewChild,
358
546
  args: ['dragPopupContainer', { static: false, read: ViewContainerRef }]
359
547
  }], dependencyDragCreatePolyline: [{
360
548
  type: ViewChild,
361
- args: ['dependencyDragCreatePolyline', { static: false }]
549
+ args: ['dependencyDragCreatePolyline']
362
550
  }], rows: [{
363
551
  type: Input
364
552
  }], slots: [{
@@ -383,6 +571,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
383
571
  type: Input
384
572
  }], currentTimeMarker: [{
385
573
  type: Input
574
+ }], customTooltipTemplate: [{
575
+ type: Input
576
+ }], tooltipOptions: [{
577
+ type: Input
386
578
  }], selectable: [{
387
579
  type: Input
388
580
  }], isTaskSelected: [{