@ganttloom/gantt-core 0.2.1 → 0.4.3

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.d.cts CHANGED
@@ -123,7 +123,7 @@ interface GanttTask {
123
123
  /** the date the constraint is relative to (ignored for "asap"/"alap") */
124
124
  constraintDate?: Date;
125
125
  assignees?: GanttAssignee[];
126
- /** shown as a native hover tooltip on the bar (an SVG <title>, so it works with zero extra markup/JS) */
126
+ /** shown as an extra line in the default hover tooltip (see GanttOptions.showTooltip/renderTooltip) */
127
127
  notes?: string;
128
128
  /** additional named baseline snapshots beyond baselineStart/baselineEnd (e.g. "as of last Friday") - rendered as extra faint bars, oldest furthest back */
129
129
  baselines?: {
@@ -152,6 +152,14 @@ interface GanttColumn {
152
152
  /** anchor target, defaults to "_blank" */
153
153
  linkTarget?: string;
154
154
  align?: "left" | "center" | "right";
155
+ /**
156
+ * Lets clicking this column's header cycle sort asc -> desc -> none. Sorting reorders
157
+ * siblings at every tree level by this column's value (via `accessor`, or `task.name` for
158
+ * the conventional unaccessored "name" column) - the group/parent hierarchy itself is
159
+ * never reshuffled, only the order within it. A column with neither `accessor` nor the id
160
+ * "name" has nothing sortable to read and is a no-op if marked sortable.
161
+ */
162
+ sortable?: boolean;
155
163
  }
156
164
  interface GanttTheme {
157
165
  rowHeight: number;
@@ -174,6 +182,7 @@ interface GanttTheme {
174
182
  fontFamily: string;
175
183
  fontSize: number;
176
184
  borderRadius: number;
185
+ borderColor?: string;
177
186
  }
178
187
  /**
179
188
  * Fully-resolved, framework-agnostic geometry for one render pass.
@@ -245,6 +254,7 @@ interface GanttRenderMarker {
245
254
  interface GanttRenderTick {
246
255
  x: number;
247
256
  label: string;
257
+ parentLabel: string;
248
258
  isWeekend: boolean;
249
259
  /** weekend OR a calendar holiday; only meaningful when a WorkingCalendar was supplied */
250
260
  isNonWorking: boolean;
@@ -265,6 +275,10 @@ interface GanttRenderModel {
265
275
  markers: GanttRenderMarker[];
266
276
  /** start of the timeline's date range, in real time - lets callers convert chart-space x back to a Date */
267
277
  rangeStart: Date;
278
+ sort: {
279
+ columnId: string;
280
+ direction: "asc" | "desc";
281
+ } | null;
268
282
  }
269
283
  interface GanttOptions {
270
284
  viewMode?: ViewMode;
@@ -274,6 +288,8 @@ interface GanttOptions {
274
288
  colorScheme?: "light" | "dark" | "auto";
275
289
  /** px per smallest time unit column, auto if omitted */
276
290
  columnWidth?: number;
291
+ /** Positions the grid and timeline headers. Default is "top". */
292
+ headerPosition?: "top" | "bottom" | "none";
277
293
  readonly?: boolean;
278
294
  showProgress?: boolean;
279
295
  showDependencies?: boolean;
@@ -281,6 +297,24 @@ interface GanttOptions {
281
297
  showCriticalPath?: boolean;
282
298
  showBaseline?: boolean;
283
299
  showDeadlines?: boolean;
300
+ /**
301
+ * Stretch (never shrink) the timeline so it fills the container's width instead of leaving
302
+ * empty space to the right - the common "short project at month/year zoom" or "just a
303
+ * handful of tasks" case, where the natural columnWidth would otherwise render a narrow
304
+ * chart floating in a mostly-empty viewport. Re-evaluated on viewMode/task changes and on
305
+ * container resize (via ResizeObserver). Never applied if the content is already wider than
306
+ * the container (that's what normal horizontal scrolling is for). Default false.
307
+ */
308
+ autoFitToViewport?: boolean;
309
+ /** hover tooltip on task bars, defaults to true. A floating, CSS-customizable element (see `.gantt-tooltip` in styles.css) - not the browser's native title tooltip. */
310
+ showTooltip?: boolean;
311
+ /**
312
+ * Fully control tooltip content/markup. Return an HTMLElement to mount directly, or a plain
313
+ * string rendered as text (never parsed as HTML, same XSS-safe contract as GanttColumn.render);
314
+ * return null/undefined to suppress the tooltip for that specific task. Defaults to task name,
315
+ * dates, progress, assignees, and notes.
316
+ */
317
+ renderTooltip?: (task: GanttTask) => HTMLElement | string | null | undefined;
284
318
  showAssigneeAvatars?: boolean;
285
319
  /** working-day/holiday definition used to shade non-working time and (with autoSchedule) skip it when cascading */
286
320
  calendar?: WorkingCalendar;
@@ -291,6 +325,11 @@ interface GanttOptions {
291
325
  /** enables click/ctrl-click/shift-click multi-selection of task bars, and chart.bulkShiftDates()/bulkDelete() */
292
326
  selectable?: boolean;
293
327
  onSelectionChange?: (taskIds: string[]) => void;
328
+ /** fired whenever the sort state changes, via a sortable column header click or chart.setSort() */
329
+ onSortChange?: (sort: {
330
+ columnId: string;
331
+ direction: "asc" | "desc";
332
+ } | null) => void;
294
333
  /** enable Ctrl+Z / Ctrl+Y undo-redo history for move/resize/link actions */
295
334
  enableHistory?: boolean;
296
335
  /** enable arrow-key task movement + ARIA labels on bars/rows */
@@ -314,6 +353,8 @@ interface GanttOptions {
314
353
  /** called on double-click of a dependency link, for building your own "edit this link" UI (see chart.updateDependency) */
315
354
  onDependencyDblClick?: (dep: GanttDependency) => void;
316
355
  onTaskClick?: (task: GanttTask) => void;
356
+ /** called on double-click of a task bar (distinct from onDependencyDblClick, which is for links) */
357
+ onTaskDblClick?: (task: GanttTask) => void;
317
358
  onGroupToggle?: (task: GanttTask, collapsed: boolean) => void;
318
359
  /** called when a task is created via drag-to-create on an empty timeline row */
319
360
  onTaskCreate?: (task: GanttTask) => void;
@@ -369,6 +410,9 @@ type GanttEventMap = {
369
410
  order: string[];
370
411
  };
371
412
  "dependency-dblclick": GanttDependency;
413
+ "task-dblclick": {
414
+ task: GanttTask;
415
+ };
372
416
  "task-reorder": {
373
417
  draggedTaskId: string;
374
418
  targetTaskId: string;
@@ -377,6 +421,12 @@ type GanttEventMap = {
377
421
  "selection-change": {
378
422
  taskIds: string[];
379
423
  };
424
+ "sort-change": {
425
+ sort: {
426
+ columnId: string;
427
+ direction: "asc" | "desc";
428
+ } | null;
429
+ };
380
430
  };
381
431
 
382
432
  interface ResourceLevelingOptions {
@@ -479,6 +529,13 @@ interface LayoutInput {
479
529
  pageSize: number;
480
530
  page: number;
481
531
  };
532
+ /** sort siblings at every tree level by a column's value, preserving the group/parent hierarchy */
533
+ sort?: {
534
+ columnId: string;
535
+ direction: "asc" | "desc";
536
+ } | null;
537
+ /** available pixel width of the scrolling timeline area, used to pad empty grids if chart is too short */
538
+ timelineViewportWidth?: number;
482
539
  }
483
540
  declare function computeLayout(input: LayoutInput): GanttRenderModel;
484
541
 
@@ -552,6 +609,7 @@ interface GeneratedTick {
552
609
  date: Date;
553
610
  x: number;
554
611
  label: string;
612
+ parentLabel: string;
555
613
  isWeekend: boolean;
556
614
  isNonWorking: boolean;
557
615
  isToday: boolean;
@@ -657,6 +715,9 @@ declare class GanttChart {
657
715
  private history;
658
716
  private renderer;
659
717
  private interactions;
718
+ private tooltip;
719
+ private resizeObserver;
720
+ private sort;
660
721
  private renderModel;
661
722
  private rafHandle;
662
723
  private currentPage;
@@ -676,6 +737,7 @@ declare class GanttChart {
676
737
  updateDependency(fromId: string, toId: string, partial: Partial<GanttDependency>): void;
677
738
  private handleProgressDrag;
678
739
  private handleCreateTaskDrag;
740
+ private handleAddChild;
679
741
  private handleBarClick;
680
742
  /** Replace (default) or add to (`additive: true`) the current selection. Requires `selectable`. */
681
743
  selectTask(id: string, options?: {
@@ -690,6 +752,14 @@ declare class GanttChart {
690
752
  private runCommand;
691
753
  private handleColumnResize;
692
754
  private handleColumnReorder;
755
+ /** Cycles a sortable column's header through asc -> desc -> none; clicking a different column starts it fresh at asc. */
756
+ private handleSortClick;
757
+ /** Sorts siblings at every tree level by a column's value (see GanttColumn.sortable); `direction: null`/omitted `columnId` clears it. */
758
+ setSort(columnId: string | null, direction?: "asc" | "desc" | null): void;
759
+ getSort(): {
760
+ columnId: string;
761
+ direction: "asc" | "desc";
762
+ } | null;
693
763
  private handleRowReorder;
694
764
  toggleGroup(taskId: string): void;
695
765
  expandAll(): void;
@@ -727,6 +797,12 @@ declare class GanttChart {
727
797
  private computeModel;
728
798
  private scheduleRender;
729
799
  private doRender;
800
+ /**
801
+ * Stretch-only fit: bump columnWidth up so the timeline fills the container's available
802
+ * width, but never shrink it below what the current zoom level already implies - a project
803
+ * wider than the container should still scroll normally, not get crammed to fit.
804
+ */
805
+ private applyAutoFit;
730
806
  undo(): void;
731
807
  redo(): void;
732
808
  get canUndo(): boolean;
package/dist/index.d.ts CHANGED
@@ -123,7 +123,7 @@ interface GanttTask {
123
123
  /** the date the constraint is relative to (ignored for "asap"/"alap") */
124
124
  constraintDate?: Date;
125
125
  assignees?: GanttAssignee[];
126
- /** shown as a native hover tooltip on the bar (an SVG <title>, so it works with zero extra markup/JS) */
126
+ /** shown as an extra line in the default hover tooltip (see GanttOptions.showTooltip/renderTooltip) */
127
127
  notes?: string;
128
128
  /** additional named baseline snapshots beyond baselineStart/baselineEnd (e.g. "as of last Friday") - rendered as extra faint bars, oldest furthest back */
129
129
  baselines?: {
@@ -152,6 +152,14 @@ interface GanttColumn {
152
152
  /** anchor target, defaults to "_blank" */
153
153
  linkTarget?: string;
154
154
  align?: "left" | "center" | "right";
155
+ /**
156
+ * Lets clicking this column's header cycle sort asc -> desc -> none. Sorting reorders
157
+ * siblings at every tree level by this column's value (via `accessor`, or `task.name` for
158
+ * the conventional unaccessored "name" column) - the group/parent hierarchy itself is
159
+ * never reshuffled, only the order within it. A column with neither `accessor` nor the id
160
+ * "name" has nothing sortable to read and is a no-op if marked sortable.
161
+ */
162
+ sortable?: boolean;
155
163
  }
156
164
  interface GanttTheme {
157
165
  rowHeight: number;
@@ -174,6 +182,7 @@ interface GanttTheme {
174
182
  fontFamily: string;
175
183
  fontSize: number;
176
184
  borderRadius: number;
185
+ borderColor?: string;
177
186
  }
178
187
  /**
179
188
  * Fully-resolved, framework-agnostic geometry for one render pass.
@@ -245,6 +254,7 @@ interface GanttRenderMarker {
245
254
  interface GanttRenderTick {
246
255
  x: number;
247
256
  label: string;
257
+ parentLabel: string;
248
258
  isWeekend: boolean;
249
259
  /** weekend OR a calendar holiday; only meaningful when a WorkingCalendar was supplied */
250
260
  isNonWorking: boolean;
@@ -265,6 +275,10 @@ interface GanttRenderModel {
265
275
  markers: GanttRenderMarker[];
266
276
  /** start of the timeline's date range, in real time - lets callers convert chart-space x back to a Date */
267
277
  rangeStart: Date;
278
+ sort: {
279
+ columnId: string;
280
+ direction: "asc" | "desc";
281
+ } | null;
268
282
  }
269
283
  interface GanttOptions {
270
284
  viewMode?: ViewMode;
@@ -274,6 +288,8 @@ interface GanttOptions {
274
288
  colorScheme?: "light" | "dark" | "auto";
275
289
  /** px per smallest time unit column, auto if omitted */
276
290
  columnWidth?: number;
291
+ /** Positions the grid and timeline headers. Default is "top". */
292
+ headerPosition?: "top" | "bottom" | "none";
277
293
  readonly?: boolean;
278
294
  showProgress?: boolean;
279
295
  showDependencies?: boolean;
@@ -281,6 +297,24 @@ interface GanttOptions {
281
297
  showCriticalPath?: boolean;
282
298
  showBaseline?: boolean;
283
299
  showDeadlines?: boolean;
300
+ /**
301
+ * Stretch (never shrink) the timeline so it fills the container's width instead of leaving
302
+ * empty space to the right - the common "short project at month/year zoom" or "just a
303
+ * handful of tasks" case, where the natural columnWidth would otherwise render a narrow
304
+ * chart floating in a mostly-empty viewport. Re-evaluated on viewMode/task changes and on
305
+ * container resize (via ResizeObserver). Never applied if the content is already wider than
306
+ * the container (that's what normal horizontal scrolling is for). Default false.
307
+ */
308
+ autoFitToViewport?: boolean;
309
+ /** hover tooltip on task bars, defaults to true. A floating, CSS-customizable element (see `.gantt-tooltip` in styles.css) - not the browser's native title tooltip. */
310
+ showTooltip?: boolean;
311
+ /**
312
+ * Fully control tooltip content/markup. Return an HTMLElement to mount directly, or a plain
313
+ * string rendered as text (never parsed as HTML, same XSS-safe contract as GanttColumn.render);
314
+ * return null/undefined to suppress the tooltip for that specific task. Defaults to task name,
315
+ * dates, progress, assignees, and notes.
316
+ */
317
+ renderTooltip?: (task: GanttTask) => HTMLElement | string | null | undefined;
284
318
  showAssigneeAvatars?: boolean;
285
319
  /** working-day/holiday definition used to shade non-working time and (with autoSchedule) skip it when cascading */
286
320
  calendar?: WorkingCalendar;
@@ -291,6 +325,11 @@ interface GanttOptions {
291
325
  /** enables click/ctrl-click/shift-click multi-selection of task bars, and chart.bulkShiftDates()/bulkDelete() */
292
326
  selectable?: boolean;
293
327
  onSelectionChange?: (taskIds: string[]) => void;
328
+ /** fired whenever the sort state changes, via a sortable column header click or chart.setSort() */
329
+ onSortChange?: (sort: {
330
+ columnId: string;
331
+ direction: "asc" | "desc";
332
+ } | null) => void;
294
333
  /** enable Ctrl+Z / Ctrl+Y undo-redo history for move/resize/link actions */
295
334
  enableHistory?: boolean;
296
335
  /** enable arrow-key task movement + ARIA labels on bars/rows */
@@ -314,6 +353,8 @@ interface GanttOptions {
314
353
  /** called on double-click of a dependency link, for building your own "edit this link" UI (see chart.updateDependency) */
315
354
  onDependencyDblClick?: (dep: GanttDependency) => void;
316
355
  onTaskClick?: (task: GanttTask) => void;
356
+ /** called on double-click of a task bar (distinct from onDependencyDblClick, which is for links) */
357
+ onTaskDblClick?: (task: GanttTask) => void;
317
358
  onGroupToggle?: (task: GanttTask, collapsed: boolean) => void;
318
359
  /** called when a task is created via drag-to-create on an empty timeline row */
319
360
  onTaskCreate?: (task: GanttTask) => void;
@@ -369,6 +410,9 @@ type GanttEventMap = {
369
410
  order: string[];
370
411
  };
371
412
  "dependency-dblclick": GanttDependency;
413
+ "task-dblclick": {
414
+ task: GanttTask;
415
+ };
372
416
  "task-reorder": {
373
417
  draggedTaskId: string;
374
418
  targetTaskId: string;
@@ -377,6 +421,12 @@ type GanttEventMap = {
377
421
  "selection-change": {
378
422
  taskIds: string[];
379
423
  };
424
+ "sort-change": {
425
+ sort: {
426
+ columnId: string;
427
+ direction: "asc" | "desc";
428
+ } | null;
429
+ };
380
430
  };
381
431
 
382
432
  interface ResourceLevelingOptions {
@@ -479,6 +529,13 @@ interface LayoutInput {
479
529
  pageSize: number;
480
530
  page: number;
481
531
  };
532
+ /** sort siblings at every tree level by a column's value, preserving the group/parent hierarchy */
533
+ sort?: {
534
+ columnId: string;
535
+ direction: "asc" | "desc";
536
+ } | null;
537
+ /** available pixel width of the scrolling timeline area, used to pad empty grids if chart is too short */
538
+ timelineViewportWidth?: number;
482
539
  }
483
540
  declare function computeLayout(input: LayoutInput): GanttRenderModel;
484
541
 
@@ -552,6 +609,7 @@ interface GeneratedTick {
552
609
  date: Date;
553
610
  x: number;
554
611
  label: string;
612
+ parentLabel: string;
555
613
  isWeekend: boolean;
556
614
  isNonWorking: boolean;
557
615
  isToday: boolean;
@@ -657,6 +715,9 @@ declare class GanttChart {
657
715
  private history;
658
716
  private renderer;
659
717
  private interactions;
718
+ private tooltip;
719
+ private resizeObserver;
720
+ private sort;
660
721
  private renderModel;
661
722
  private rafHandle;
662
723
  private currentPage;
@@ -676,6 +737,7 @@ declare class GanttChart {
676
737
  updateDependency(fromId: string, toId: string, partial: Partial<GanttDependency>): void;
677
738
  private handleProgressDrag;
678
739
  private handleCreateTaskDrag;
740
+ private handleAddChild;
679
741
  private handleBarClick;
680
742
  /** Replace (default) or add to (`additive: true`) the current selection. Requires `selectable`. */
681
743
  selectTask(id: string, options?: {
@@ -690,6 +752,14 @@ declare class GanttChart {
690
752
  private runCommand;
691
753
  private handleColumnResize;
692
754
  private handleColumnReorder;
755
+ /** Cycles a sortable column's header through asc -> desc -> none; clicking a different column starts it fresh at asc. */
756
+ private handleSortClick;
757
+ /** Sorts siblings at every tree level by a column's value (see GanttColumn.sortable); `direction: null`/omitted `columnId` clears it. */
758
+ setSort(columnId: string | null, direction?: "asc" | "desc" | null): void;
759
+ getSort(): {
760
+ columnId: string;
761
+ direction: "asc" | "desc";
762
+ } | null;
693
763
  private handleRowReorder;
694
764
  toggleGroup(taskId: string): void;
695
765
  expandAll(): void;
@@ -727,6 +797,12 @@ declare class GanttChart {
727
797
  private computeModel;
728
798
  private scheduleRender;
729
799
  private doRender;
800
+ /**
801
+ * Stretch-only fit: bump columnWidth up so the timeline fills the container's available
802
+ * width, but never shrink it below what the current zoom level already implies - a project
803
+ * wider than the container should still scroll normally, not get crammed to fit.
804
+ */
805
+ private applyAutoFit;
730
806
  undo(): void;
731
807
  redo(): void;
732
808
  get canUndo(): boolean;