@toclocoinc/lattice-grid 1.68.0 → 1.68.2

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 (164) hide show
  1. package/README.md +26 -1
  2. package/angular/fesm2022/toclocoinc-lattice-grid-angular.mjs +1 -0
  3. package/angular/package.json +1 -1
  4. package/docs/API.html +8058 -3962
  5. package/docs/api-detail.html +101 -4
  6. package/lattice-grid.d.ts +5917 -78
  7. package/lattice-grid.esm.min.js +197 -39
  8. package/lattice-grid.min.cjs +197 -39
  9. package/lattice-grid.min.js +197 -39
  10. package/modules/ai.d.ts +172 -11
  11. package/modules/ai.esm.min.js +3 -3
  12. package/modules/ai.min.cjs +3 -3
  13. package/modules/ai.min.js +3 -3
  14. package/modules/angular.d.ts +1 -1
  15. package/modules/angular.esm.min.js +3 -3
  16. package/modules/angular.min.cjs +3 -3
  17. package/modules/angular.min.js +3 -3
  18. package/modules/chart-alluvial.d.ts +1 -1
  19. package/modules/chart-alluvial.esm.min.js +1 -1
  20. package/modules/chart-alluvial.min.cjs +1 -1
  21. package/modules/chart-alluvial.min.js +1 -1
  22. package/modules/chart-arc.d.ts +1 -1
  23. package/modules/chart-arc.esm.min.js +1 -1
  24. package/modules/chart-arc.min.cjs +1 -1
  25. package/modules/chart-arc.min.js +1 -1
  26. package/modules/chart-bubblemap.d.ts +1 -1
  27. package/modules/chart-bubblemap.esm.min.js +1 -1
  28. package/modules/chart-bubblemap.min.cjs +1 -1
  29. package/modules/chart-bubblemap.min.js +1 -1
  30. package/modules/chart-bump.d.ts +1 -1
  31. package/modules/chart-bump.esm.min.js +1 -1
  32. package/modules/chart-bump.min.cjs +1 -1
  33. package/modules/chart-bump.min.js +1 -1
  34. package/modules/chart-calendar.d.ts +1 -1
  35. package/modules/chart-calendar.esm.min.js +1 -1
  36. package/modules/chart-calendar.min.cjs +1 -1
  37. package/modules/chart-calendar.min.js +1 -1
  38. package/modules/chart-decomposition.d.ts +1 -1
  39. package/modules/chart-decomposition.esm.min.js +1 -1
  40. package/modules/chart-decomposition.min.cjs +1 -1
  41. package/modules/chart-decomposition.min.js +1 -1
  42. package/modules/chart-diverging.d.ts +1 -1
  43. package/modules/chart-diverging.esm.min.js +1 -1
  44. package/modules/chart-diverging.min.cjs +1 -1
  45. package/modules/chart-diverging.min.js +1 -1
  46. package/modules/chart-dumbbell.d.ts +1 -1
  47. package/modules/chart-dumbbell.esm.min.js +1 -1
  48. package/modules/chart-dumbbell.min.cjs +1 -1
  49. package/modules/chart-dumbbell.min.js +1 -1
  50. package/modules/chart-fan.d.ts +1 -1
  51. package/modules/chart-fan.esm.min.js +1 -1
  52. package/modules/chart-fan.min.cjs +1 -1
  53. package/modules/chart-fan.min.js +1 -1
  54. package/modules/chart-hexbin.d.ts +1 -1
  55. package/modules/chart-hexbin.esm.min.js +1 -1
  56. package/modules/chart-hexbin.min.cjs +1 -1
  57. package/modules/chart-hexbin.min.js +1 -1
  58. package/modules/chart-hexmap.d.ts +1 -1
  59. package/modules/chart-hexmap.esm.min.js +1 -1
  60. package/modules/chart-hexmap.min.cjs +1 -1
  61. package/modules/chart-hexmap.min.js +1 -1
  62. package/modules/chart-icicle.d.ts +1 -1
  63. package/modules/chart-icicle.esm.min.js +1 -1
  64. package/modules/chart-icicle.min.cjs +1 -1
  65. package/modules/chart-icicle.min.js +1 -1
  66. package/modules/chart-markermap.d.ts +1 -1
  67. package/modules/chart-markermap.esm.min.js +1 -1
  68. package/modules/chart-markermap.min.cjs +1 -1
  69. package/modules/chart-markermap.min.js +1 -1
  70. package/modules/chart-parallel.d.ts +1 -1
  71. package/modules/chart-parallel.esm.min.js +1 -1
  72. package/modules/chart-parallel.min.cjs +1 -1
  73. package/modules/chart-parallel.min.js +1 -1
  74. package/modules/chart-ridgeline.d.ts +1 -1
  75. package/modules/chart-ridgeline.esm.min.js +1 -1
  76. package/modules/chart-ridgeline.min.cjs +1 -1
  77. package/modules/chart-ridgeline.min.js +1 -1
  78. package/modules/chart-roc.d.ts +1 -1
  79. package/modules/chart-roc.esm.min.js +1 -1
  80. package/modules/chart-roc.min.cjs +1 -1
  81. package/modules/chart-roc.min.js +1 -1
  82. package/modules/chart-slope.d.ts +1 -1
  83. package/modules/chart-slope.esm.min.js +1 -1
  84. package/modules/chart-slope.min.cjs +1 -1
  85. package/modules/chart-slope.min.js +1 -1
  86. package/modules/chart-splom.d.ts +1 -1
  87. package/modules/chart-splom.esm.min.js +1 -1
  88. package/modules/chart-splom.min.cjs +1 -1
  89. package/modules/chart-splom.min.js +1 -1
  90. package/modules/chart-waffle.d.ts +1 -1
  91. package/modules/chart-waffle.esm.min.js +1 -1
  92. package/modules/chart-waffle.min.cjs +1 -1
  93. package/modules/chart-waffle.min.js +1 -1
  94. package/modules/charts.d.ts +16 -1
  95. package/modules/charts.esm.min.js +23 -16
  96. package/modules/charts.min.cjs +23 -16
  97. package/modules/charts.min.js +23 -16
  98. package/modules/data-router.d.ts +259 -3
  99. package/modules/data-router.esm.min.js +9 -4
  100. package/modules/data-router.min.cjs +9 -4
  101. package/modules/data-router.min.js +9 -4
  102. package/modules/devtools.d.ts +1 -1
  103. package/modules/devtools.esm.min.js +1 -1
  104. package/modules/devtools.min.cjs +1 -1
  105. package/modules/devtools.min.js +1 -1
  106. package/modules/dhtmlx-compat.d.ts +1 -1
  107. package/modules/dhtmlx-compat.esm.min.js +3 -3
  108. package/modules/dhtmlx-compat.min.cjs +3 -3
  109. package/modules/dhtmlx-compat.min.js +3 -3
  110. package/modules/gantt.d.ts +563 -12
  111. package/modules/gantt.esm.min.js +8 -4
  112. package/modules/gantt.min.cjs +8 -4
  113. package/modules/gantt.min.js +8 -4
  114. package/modules/geo-europe-nuts.d.ts +1 -1
  115. package/modules/geo-europe-nuts.esm.min.js +1 -1
  116. package/modules/geo-uk.d.ts +1 -1
  117. package/modules/geo-uk.esm.min.js +1 -1
  118. package/modules/geo-us-states.d.ts +1 -1
  119. package/modules/geo-us-states.esm.min.js +1 -1
  120. package/modules/geo-world-110m.d.ts +1 -1
  121. package/modules/geo-world-110m.esm.min.js +1 -1
  122. package/modules/geo-world-50m.d.ts +1 -1
  123. package/modules/geo-world-50m.esm.min.js +1 -1
  124. package/modules/htmx.d.ts +1 -1
  125. package/modules/htmx.esm.min.js +197 -39
  126. package/modules/htmx.min.cjs +197 -39
  127. package/modules/htmx.min.js +197 -39
  128. package/modules/kanban.d.ts +687 -4
  129. package/modules/kanban.esm.min.js +3 -3
  130. package/modules/kanban.min.cjs +3 -3
  131. package/modules/kanban.min.js +3 -3
  132. package/modules/kpi.d.ts +237 -3
  133. package/modules/kpi.esm.min.js +4 -4
  134. package/modules/kpi.min.cjs +4 -4
  135. package/modules/kpi.min.js +4 -4
  136. package/modules/layout.d.ts +249 -7
  137. package/modules/layout.esm.min.js +3 -3
  138. package/modules/layout.min.cjs +3 -3
  139. package/modules/layout.min.js +3 -3
  140. package/modules/mock-socket.d.ts +6 -1
  141. package/modules/mock-socket.esm.min.js +1 -1
  142. package/modules/mock-socket.min.cjs +1 -1
  143. package/modules/mock-socket.min.js +1 -1
  144. package/modules/react.d.ts +18 -1
  145. package/modules/react.esm.min.js +3 -3
  146. package/modules/react.min.cjs +3 -3
  147. package/modules/react.min.js +3 -3
  148. package/modules/svelte.d.ts +1 -1
  149. package/modules/svelte.esm.min.js +3 -3
  150. package/modules/svelte.min.cjs +3 -3
  151. package/modules/svelte.min.js +3 -3
  152. package/modules/tabs.d.ts +116 -11
  153. package/modules/tabs.esm.min.js +3 -3
  154. package/modules/tabs.min.cjs +3 -3
  155. package/modules/tabs.min.js +3 -3
  156. package/modules/vue.d.ts +12 -1
  157. package/modules/vue.esm.min.js +3 -3
  158. package/modules/vue.min.cjs +3 -3
  159. package/modules/vue.min.js +3 -3
  160. package/modules/webcomponent.d.ts +89 -6
  161. package/modules/webcomponent.esm.min.js +242 -43
  162. package/modules/webcomponent.min.cjs +242 -43
  163. package/modules/webcomponent.min.js +242 -43
  164. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.68.0, gantt module type declarations
2
+ * Lattice Grid 1.68.2, gantt module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -25,21 +25,83 @@ export type GanttCalendar =
25
25
  * view's grid panel.
26
26
  */
27
27
  export interface GanttTask {
28
+ /**
29
+ * The task's identity, used by dependencies, edits and `rows.apply`. Stringified; a
30
+ * duplicate id fails the schedule with `duplicate-id`.
31
+ */
28
32
  id: string | number;
33
+ /** The task's label in the table and on its bar. Defaults to the id. */
29
34
  name?: string;
35
+ /**
36
+ * Where the task is placed — a day-number, an ISO date or a `Date`. It is a floor, not
37
+ * a pin: the forward pass never starts the task earlier, but a predecessor may push it
38
+ * later. Use a `constraint` to pin it.
39
+ */
30
40
  start?: number | string | Date;
41
+ /**
42
+ * The task's finish, in the same forms as `start`. Given with `start` and no
43
+ * `duration`, the duration becomes `end − start`.
44
+ */
31
45
  end?: number | string | Date;
46
+ /**
47
+ * How long the task takes, in working days (the plan's time unit). Negative fails the
48
+ * schedule with `bad-duration`; a leaf with no duration and no start/end pair is an
49
+ * error, while a summary's is ignored because its window comes from its children.
50
+ */
32
51
  duration?: number;
52
+ /**
53
+ * Progress, 0-100, drawn as the filled part of the bar and used as the earned-value
54
+ * multiplier. A summary's is the duration-weighted mean of its descendant leaves;
55
+ * anything unparseable reads as null.
56
+ */
33
57
  percentComplete?: number;
58
+ /**
59
+ * Marks a zero-duration point: the task is scheduled as an instant (start equals
60
+ * finish) and drawn as a diamond. `duration: 0` does the same.
61
+ */
34
62
  milestone?: boolean;
63
+ /**
64
+ * The id of the summary task this one sits under. A summary is never scheduled in its
65
+ * own right — its window, progress and criticality are derived from its children — and
66
+ * a parent chain that loops fails with `parent-cycle`.
67
+ */
35
68
  parent?: string | number;
69
+ /**
70
+ * The planned start the task is measured against, in the same forms as `start`. With a
71
+ * baseline the schedule reports `startVariance` (actual − planned; positive is a slip).
72
+ */
36
73
  baselineStart?: number | string | Date;
74
+ /**
75
+ * The planned finish. With both baseline dates the schedule reports `finishVariance`
76
+ * and `durationVariance` too.
77
+ */
37
78
  baselineEnd?: number | string | Date;
79
+ /** The planned window as one object, read when `baselineStart`/`baselineEnd` are absent. */
38
80
  baseline?: { start?: number | string | Date; end?: number | string | Date };
81
+ /**
82
+ * Pins or pulls the task: must-start-on and must-finish-on place it on
83
+ * `constraintDate`, as-late-as-possible pulls it into its late window, consuming its
84
+ * float. A constraint date earlier than the predecessors allow is reported in
85
+ * `schedule.conflicts` and the feasible date is used instead.
86
+ */
39
87
  constraint?: GanttConstraintType;
88
+ /**
89
+ * The date the constraint pins to — a day-number, ISO date or `Date`. Unused by
90
+ * as-late-as-possible.
91
+ */
40
92
  constraintDate?: number | string | Date;
93
+ /**
94
+ * Who is booked on the task: one name or a list. Each name is a full-time booking
95
+ * (units 1) for resource load, over-allocation and the split view's avatars. Ignored
96
+ * when `assignments` is present.
97
+ */
41
98
  assignee?: string | string[];
99
+ /** An alternative spelling of `assignee`, read when that is absent. */
42
100
  assignees?: string[];
101
+ /**
102
+ * A third spelling of `assignee`, read when neither `assignee` nor `assignees` is
103
+ * present.
104
+ */
43
105
  owner?: string;
44
106
  /**
45
107
  * Explicit resource assignments with fractional units:
@@ -101,55 +163,144 @@ export type GanttResourceSpec =
101
163
  * field warns; the explicit field wins.
102
164
  */
103
165
  export interface GanttDependency {
166
+ /**
167
+ * The predecessor task's id. A link naming a summary is expanded to its descendant
168
+ * leaves before scheduling.
169
+ */
104
170
  from: string | number;
171
+ /** The successor task's id. */
105
172
  to: string | number;
173
+ /**
174
+ * Which ends the link ties together — finish-to-start (the default), start-to-start,
175
+ * finish-to-finish or start-to-finish — optionally with the MS Project lag shorthand,
176
+ * `'FS+2'` or `'SS-1'`. It is normalised on the way in, so `gantt.dependencies` always
177
+ * reads back as `{ type, lag }`.
178
+ */
106
179
  type?: GanttLinkType | `${GanttLinkType}${'+' | '-'}${number}`;
180
+ /**
181
+ * A signed offset on the link in working days; a negative value is a lead. Given
182
+ * alongside a shorthand lag in `type`, this field wins and the mismatch is warned
183
+ * about.
184
+ */
107
185
  lag?: number;
108
186
  }
109
187
 
110
188
  /** The computed CPM values for one task (a leaf is scheduled, a summary derived). */
111
189
  interface GanttScheduledTask {
190
+ /** The task's id, as a string. */
112
191
  id: string;
192
+ /** The task's name, defaulting to its id. */
113
193
  name: string;
194
+ /** The task's length in working days. A summary's is its derived window, `ef − es`. */
114
195
  duration: number;
196
+ /**
197
+ * Early start: the earliest day the task can begin once every predecessor and its own
198
+ * placement floor are honoured.
199
+ */
115
200
  es: number;
201
+ /**
202
+ * Early finish, `es + duration` (mapped back to calendar days when a working-time
203
+ * calendar is in use).
204
+ */
116
205
  ef: number;
206
+ /**
207
+ * Late start: the latest the task can begin without pushing the project finish (or the
208
+ * deadline) out.
209
+ */
117
210
  ls: number;
211
+ /**
212
+ * Late finish, `ls + duration`. A task pinned by a constraint has `lf` equal to its
213
+ * `ef`, so it has no float.
214
+ */
118
215
  lf: number;
216
+ /**
217
+ * Slack in working days, `ls − es`. Zero means critical; a deadline earlier than the
218
+ * natural finish drives it negative, which is the at-risk signal.
219
+ */
119
220
  totalFloat: number;
221
+ /**
222
+ * True when the total float is zero or negative. A summary is critical when any child
223
+ * is; an as-late-as-possible task is always marked critical.
224
+ */
120
225
  critical: boolean;
226
+ /**
227
+ * The task's progress, or null when it states none. A summary's is the
228
+ * duration-weighted mean of its descendant leaves, and null when every one of them is a
229
+ * milestone.
230
+ */
121
231
  percentComplete: number | null;
232
+ /** The id of this task's summary, or null at the top level. */
122
233
  parent: string | null;
234
+ /** True when the task has children, and so was derived from them rather than scheduled. */
123
235
  isSummary: boolean;
236
+ /** True when the task's duration is zero — a point in the plan. */
124
237
  isMilestone: boolean;
238
+ /** A summary's direct children, by id, in input order. Empty for a leaf. */
125
239
  children: string[];
126
240
  /** The planned (baseline) window, present only when the task carries a baseline. */
127
241
  baselineStart?: number | null;
242
+ /** The planned finish day-number, or null when only a baseline start was given. */
128
243
  baselineEnd?: number | null;
129
244
  /** Variance vs the baseline (actual − planned, day-numbers); a positive value is a slip. */
130
245
  startVariance?: number | null;
246
+ /**
247
+ * `ef − baselineEnd` in days; positive means finishing later than planned. Null without
248
+ * a baseline finish.
249
+ */
131
250
  finishVariance?: number | null;
251
+ /**
252
+ * How much longer the task runs than its baseline window, in days. Null unless both
253
+ * baseline dates were given.
254
+ */
132
255
  durationVariance?: number | null;
133
256
  }
134
257
 
135
258
  /** An unhonourable scheduling constraint, reported rather than obeyed. */
136
259
  interface GanttConflict {
260
+ /** The task whose constraint could not be honoured. */
137
261
  id: string;
262
+ /** The constraint that was refused, as its normalised code (`MSO` or `MFO`). */
138
263
  type: string;
264
+ /** The date the constraint asked for, as a day-number, or null when it named none. */
139
265
  at: number | null;
266
+ /**
267
+ * The earliest start the predecessors actually allow — the day the engine used instead.
268
+ * It never places a task before its predecessors.
269
+ */
140
270
  earliestFeasible: number;
141
271
  }
142
272
 
143
273
  /** A CPM schedule result: per-task dates/float and the critical path, or an error. */
144
274
  interface GanttSchedule {
275
+ /**
276
+ * Whether the schedule computed. False leaves every other field absent except `error`,
277
+ * and the controller keeps its previous schedule.
278
+ */
145
279
  ok: boolean;
146
- error?: { code: string; message: string; cycle?: string[] };
280
+ /** Why the schedule was refused — the same object the `error` event carries. */
281
+ error?: GanttScheduleError;
282
+ /** Every task's computed values, keyed by id — leaves scheduled, summaries derived. */
147
283
  tasks?: Map<string, GanttScheduledTask>;
284
+ /** Every task id in input order, which is the order a table or WBS tree walks. */
148
285
  order?: string[];
286
+ /** The ids of the leaf tasks with no float, in input order. */
149
287
  critical?: string[];
288
+ /**
289
+ * Each zero-float chain through the network as its own list of ids, so a plan with
290
+ * several critical routes shows all of them.
291
+ */
150
292
  criticalPaths?: string[][];
293
+ /**
294
+ * The day the plan is anchored to — the `projectStart` option, or the calendar's first
295
+ * working day when one is set.
296
+ */
151
297
  projectStart?: number;
298
+ /** The latest early finish across every task, as a calendar day-number. */
152
299
  projectFinish?: number;
300
+ /**
301
+ * `projectFinish − projectStart` in days — calendar days when a working-time calendar
302
+ * stretched the plan, not the sum of the durations.
303
+ */
153
304
  projectDuration?: number;
154
305
  /** Constraints a predecessor made infeasible (empty when all are satisfied). */
155
306
  conflicts?: GanttConflict[];
@@ -163,46 +314,105 @@ interface GanttSchedule {
163
314
 
164
315
  /** One contiguous load segment for a resource: how many units are booked over a span. */
165
316
  interface GanttResourceSegment {
317
+ /** The day the segment begins (inclusive), as a calendar day-number. */
166
318
  start: number;
319
+ /**
320
+ * The day the segment ends (exclusive). A task that finishes as another starts does not
321
+ * double-count the boundary.
322
+ */
167
323
  end: number;
324
+ /**
325
+ * The units booked across the whole segment — the sum of the covering tasks' assignment
326
+ * units, where 1 is one full-time booking.
327
+ */
168
328
  load: number;
329
+ /** The tasks active during the segment, which is what makes a heavy stretch explainable. */
169
330
  taskIds: string[];
170
331
  }
171
332
 
172
333
  /** A resource booked beyond its capacity across concurrent tasks. */
173
334
  interface GanttOverAllocation {
335
+ /** The over-booked resource's name. */
174
336
  resource: string;
337
+ /**
338
+ * The resource's capacity in units — from the `resources` option, or `defaultCapacity`
339
+ * (1) when it names none.
340
+ */
175
341
  capacity: number;
342
+ /** The day the over-allocation begins, as a calendar day-number. */
176
343
  start: number;
344
+ /** The day it ends (exclusive). */
177
345
  end: number;
346
+ /**
347
+ * The units booked over that stretch — strictly greater than `capacity`, which is what
348
+ * makes it an over-allocation.
349
+ */
178
350
  load: number;
351
+ /** The tasks competing for the resource over that stretch. */
179
352
  taskIds: string[];
180
353
  }
181
354
 
182
355
  /** The per-resource load and the over-allocations across a schedule. */
183
356
  interface GanttResourceLoad {
357
+ /**
358
+ * Whether the load could be computed. False — with empty lists — when there is no
359
+ * successful schedule to read.
360
+ */
184
361
  ok: boolean;
362
+ /**
363
+ * One entry per resource that anything is booked on, sorted by name, each with its
364
+ * capacity, peak load and load segments. A resource named only in the capacities, with
365
+ * no booking, does not appear.
366
+ */
185
367
  resources: Array<{ resource: string; capacity: number; peak: number; segments: GanttResourceSegment[] }>;
368
+ /**
369
+ * Every stretch where a resource is booked beyond its capacity, earliest first. Empty
370
+ * when the plan fits.
371
+ */
186
372
  overAllocations: GanttOverAllocation[];
373
+ /** The same entries as `resources`, keyed by resource name for a direct lookup. */
187
374
  byResource: Map<string, { capacity: number; peak: number; segments: GanttResourceSegment[] }>;
188
375
  }
189
376
 
190
377
  /** The result of resource leveling: the shifted tasks and what moved. */
191
378
  interface GanttLevelResult {
379
+ /**
380
+ * Whether leveling ran. False only when the plan would not schedule, in which case
381
+ * `error` says why.
382
+ */
192
383
  ok: boolean;
384
+ /**
385
+ * Whether every over-allocation was cleared. False when only pinned tasks were left to
386
+ * move, or the iteration cap was hit — the partial result is still returned.
387
+ */
193
388
  resolved?: boolean;
389
+ /**
390
+ * The tasks with their new starts. These are copies; the controller adopts them unless
391
+ * the call was a dry run.
392
+ */
194
393
  tasks?: GanttTask[];
394
+ /** The schedule computed from the levelled tasks. */
195
395
  schedule?: GanttSchedule;
396
+ /**
397
+ * What actually moved: the task, its start before leveling, its start after, and the
398
+ * delay in days. Unmoved tasks are not listed.
399
+ */
196
400
  moves?: Array<{ id: string; from: number; to: number; delay: number }>;
401
+ /** The over-allocations leveling could not clear. Absent when it resolved everything. */
197
402
  remaining?: GanttOverAllocation[];
403
+ /** Why the plan would not schedule — the same codes `GanttSchedule.error` uses. */
198
404
  error?: { code: string; message: string };
199
405
  }
200
406
 
201
407
  /** A placement violation flagged by `findViolations`. */
202
408
  interface GanttViolation {
409
+ /** The task placed earlier than its predecessors allow. */
203
410
  id: string;
411
+ /** Where the plan puts the task — the `start` on the raw task, as a day-number. */
204
412
  placedStart: number;
413
+ /** The earliest start CPM allows, given the dependencies and the calendar. */
205
414
  earliestStart: number;
415
+ /** How many days early the placement is, `earliestStart − placedStart`. */
206
416
  by: number;
207
417
  }
208
418
 
@@ -227,12 +437,13 @@ export function findViolations(tasks: GanttTask[], schedule: GanttSchedule): Gan
227
437
  export function toISODate(day: number): string | null;
228
438
 
229
439
  /** Earned-value metrics for one task or the whole project. */
230
- interface GanttEarnedValueRow {
231
- id: string;
232
- name: string;
233
- isSummary: boolean;
234
- isMilestone: boolean;
235
- percentComplete: number | null;
440
+ /**
441
+ * The earned-value figures themselves, without the task they belong to.
442
+ *
443
+ * The project total is exactly this and no more, so it has its own type
444
+ * rather than claiming to be a row with five fields it has never carried.
445
+ */
446
+ interface GanttEarnedValueTotals {
236
447
  /** Whether a baseline (not the fallback scheduled window) drove PV. */
237
448
  hasBaseline: boolean;
238
449
  /** Whether any actual cost fed AC (else AC/CV/CPI are null). */
@@ -255,9 +466,31 @@ interface GanttEarnedValueRow {
255
466
  cpi: number | null;
256
467
  }
257
468
 
469
+ /** One task's earned-value figures. */
470
+ interface GanttEarnedValueRow extends GanttEarnedValueTotals {
471
+ /** The task the row is for. */
472
+ id: string;
473
+ /** The task's name. */
474
+ name: string;
475
+ /** True for a summary row, whose figures are the sums of its descendant leaves. */
476
+ isSummary: boolean;
477
+ /** True for a zero-duration task. */
478
+ isMilestone: boolean;
479
+ /**
480
+ * The task's progress, reported exactly as the task states it, or null when it states
481
+ * none — which earns nothing. The earned-value multiplier clamps it to 0-100 first.
482
+ */
483
+ percentComplete: number | null;
484
+ }
485
+
258
486
  /** The earned-value result at a status date. */
259
487
  interface GanttEarnedValue {
488
+ /**
489
+ * Whether the metrics could be computed. False when there is no successful schedule to
490
+ * measure against.
491
+ */
260
492
  ok: boolean;
493
+ /** Why the metrics were refused — `NO_SCHEDULE` when the plan has not scheduled. */
261
494
  error?: { code: string; message: string };
262
495
  /** The status date the metrics were evaluated at (day-number). */
263
496
  statusDate?: number;
@@ -265,8 +498,11 @@ interface GanttEarnedValue {
265
498
  byTask?: Map<string, GanttEarnedValueRow>;
266
499
  /** The same rows in schedule order. */
267
500
  rows?: GanttEarnedValueRow[];
268
- /** The project total, rolled up as money sums of the leaves. */
269
- project?: GanttEarnedValueRow;
501
+ /**
502
+ * The project total, rolled up as money sums of the leaves. The figures only:
503
+ * a total belongs to no task, so it carries no id, name or progress.
504
+ */
505
+ project?: GanttEarnedValueTotals;
270
506
  }
271
507
 
272
508
  /**
@@ -282,21 +518,294 @@ export function computeEarnedValue(
282
518
  options?: { statusDate?: number | string | Date; costField?: string; actualCostField?: string },
283
519
  ): GanttEarnedValue;
284
520
 
521
+ /**
522
+ * Why a schedule was refused.
523
+ *
524
+ * The payload of the `error` event — the very object the failed
525
+ * {@link GanttSchedule} carries, handed straight to the handler.
526
+ */
527
+ interface GanttScheduleError {
528
+ /**
529
+ * What was wrong: `cycle`, `duplicate-id`, `bad-duration`, `unknown-task`,
530
+ * `unknown-parent`, `parent-cycle`, `self-dependency`, `bad-link-type` or
531
+ * `dep-across-hierarchy`.
532
+ */
533
+ code: string;
534
+ /** The failure in one English sentence, naming the task or link it is about. */
535
+ message: string;
536
+ /** The ids that form the cycle, on a `cycle`. */
537
+ cycle?: string[];
538
+ /** The task the failure is about, where one task is to blame. */
539
+ id?: string;
540
+ /** A rejected dependency's predecessor, on `dep-across-hierarchy`. */
541
+ from?: string;
542
+ /** A rejected dependency's successor, on `dep-across-hierarchy`. */
543
+ to?: string;
544
+ }
545
+
546
+ /**
547
+ * What every cancellable Gantt event carries on top of its own context.
548
+ *
549
+ * The controller's bus mirrors the grid core's `emitBefore` contract exactly,
550
+ * so a host writes the same handler shape against a Gantt as against a grid: a
551
+ * handler refuses the action by calling `preventDefault(reason?)`, by returning
552
+ * `false`, or by throwing, and may be `async` — every thenable return is
553
+ * awaited before the decision, so a confirm dialog or a server check can hold
554
+ * the write. Veto wins. On a veto the matching `<action>:cancelled` fires with
555
+ * the reason and the model is untouched; an action re-validated after an await
556
+ * and no longer applicable is cancelled as `'stale'`.
557
+ *
558
+ * Only the user-initiated paths are gated. The live/router `rows.apply` path is
559
+ * remote truth and raises none of these.
560
+ */
561
+ interface GanttBeforeEvent {
562
+ /** Which event this is — `beforeTaskMove`, `beforeTaskDelete` and the rest. */
563
+ type: string;
564
+ /** True once a handler has refused the action. */
565
+ defaultPrevented: boolean;
566
+ /** The reason given to `preventDefault`, or null while nothing has refused it. */
567
+ reason: string | null;
568
+ /** Refuse the action; the optional reason is carried on the `<action>:cancelled` event. */
569
+ preventDefault(reason?: string): void;
570
+ }
571
+
572
+ /**
573
+ * An edit about to be applied to one task: the payload of `beforeTaskEdit`,
574
+ * `beforeTaskMove`, `beforeTaskResize`, `beforeProgressChange` and
575
+ * `beforeMilestoneMove`.
576
+ *
577
+ * One payload for the five, because they are one choke point — `applyEdit`
578
+ * classifies the patch and names the event, so which of the five fires says
579
+ * what kind of edit it is and the context below says what the edit is.
580
+ */
581
+ interface GanttTaskEditEvent extends GanttBeforeEvent {
582
+ /** The task being edited, by id. */
583
+ id: string;
584
+ /** The task as it stands before the edit, as a shallow copy. */
585
+ task: GanttTask;
586
+ /** The edit itself: only the fields it changes. */
587
+ patch: { id: string | number; start?: number; end?: number; duration?: number; percentComplete?: number; work?: unknown };
588
+ /** Always `user`: only the user-initiated path is gated. */
589
+ origin: string;
590
+ /** Where the task starts now, from the plan, or its computed early start when it holds no start. */
591
+ from?: number | string | Date;
592
+ /** Where the patch would move it to; absent unless the patch sets `start`. */
593
+ to?: number | string | Date;
594
+ /** The duration the patch asks for; absent unless the patch sets one. */
595
+ duration?: number;
596
+ /** The progress the patch asks for; present only on a `beforeProgressChange`. */
597
+ value?: number;
598
+ /** The progress before it; present only on a `beforeProgressChange`. */
599
+ oldValue?: number;
600
+ }
601
+
602
+ /**
603
+ * An edit that was refused: the payload of `taskEdit:cancelled`,
604
+ * `taskMove:cancelled`, `taskResize:cancelled`, `progressChange:cancelled` and
605
+ * `milestoneMove:cancelled`. The same context the before-event carried, plus
606
+ * the reason; a notification, so it carries no `preventDefault`.
607
+ */
608
+ interface GanttTaskEditCancelledEvent {
609
+ /** The task that was not edited. */
610
+ id: string;
611
+ /** The task, unchanged. */
612
+ task: GanttTask;
613
+ /** The edit that was not applied. */
614
+ patch: { id: string | number; start?: number; end?: number; duration?: number; percentComplete?: number; work?: unknown };
615
+ /** Always `user`. */
616
+ origin: string;
617
+ /** Where the task starts, still. */
618
+ from?: number | string | Date;
619
+ /** Where it would have gone. */
620
+ to?: number | string | Date;
621
+ /** The duration that was asked for. */
622
+ duration?: number;
623
+ /** The progress that was asked for. */
624
+ value?: number;
625
+ /** The progress before it. */
626
+ oldValue?: number;
627
+ /** The reason given to `preventDefault`, `'prevented'` when none was, or `'stale'` when the task had gone by the time a handler settled. */
628
+ reason: string;
629
+ }
630
+
631
+ /**
632
+ * Links about to be created: the payload of `beforeDependencyCreate`. A pure
633
+ * removal or reorder adds no link and is not gated at all.
634
+ */
635
+ interface GanttDependencyCreateEvent extends GanttBeforeEvent {
636
+ /** Only the links this call adds, normalised. */
637
+ added: GanttDependency[];
638
+ /** The whole list the call would leave behind. */
639
+ dependencies: GanttDependency[];
640
+ /** Always `user`. */
641
+ origin: string;
642
+ }
643
+
644
+ /**
645
+ * Links that were not created: the payload of `dependencyCreate:cancelled`. A
646
+ * notification, so it carries no `preventDefault`.
647
+ */
648
+ interface GanttDependencyCreateCancelledEvent {
649
+ /** The links that were not added. */
650
+ added: GanttDependency[];
651
+ /** The list that was not adopted; the controller kept the one it had. */
652
+ dependencies: GanttDependency[];
653
+ /** Always `user`. */
654
+ origin: string;
655
+ /** The reason given to `preventDefault`, or `'prevented'` when none was. */
656
+ reason: string;
657
+ }
658
+
659
+ /** A task about to be deleted, with its incident links: the payload of `beforeTaskDelete`. */
660
+ interface GanttTaskDeleteEvent extends GanttBeforeEvent {
661
+ /** The task being deleted, by id. */
662
+ id: string;
663
+ /** The task itself, as a shallow copy — the only chance a handler has to read it. */
664
+ task: GanttTask;
665
+ /** Always `user`: the live/router `rows.apply` remove is never gated. */
666
+ origin: string;
667
+ }
668
+
669
+ /**
670
+ * A task that was not deleted: the payload of `taskDelete:cancelled`. A
671
+ * notification, so it carries no `preventDefault`.
672
+ */
673
+ interface GanttTaskDeleteCancelledEvent {
674
+ /** The task that stayed. */
675
+ id: string;
676
+ /** The task itself. */
677
+ task: GanttTask;
678
+ /** Always `user`. */
679
+ origin: string;
680
+ /** The reason given to `preventDefault`, `'prevented'` when none was, or `'stale'`. */
681
+ reason: string;
682
+ }
683
+
684
+ /**
685
+ * The events a Gantt controller raises.
686
+ *
687
+ * The controller's own, not a grid's: `grid.on` takes {@link EventName} and
688
+ * knows nothing about these, and a grid-bound Gantt follows the grid's events
689
+ * itself rather than re-publishing them. `on()` takes a name and a listener and
690
+ * warns about nothing, so a misspelt name is a subscription that never fires.
691
+ *
692
+ * The seven `before…` events are cancellable ({@link GanttBeforeEvent}); each
693
+ * has a matching `<action>:cancelled` that fires when a handler refuses,
694
+ * carrying the same context plus the reason. `schedule` and `error` are the
695
+ * recompute's own pair and are raised on every recompute, whatever caused it.
696
+ */
697
+ type GanttEventName =
698
+ /** A recompute succeeded; the payload is the new schedule, resource load and over-allocations included. */
699
+ | 'schedule'
700
+ /** A recompute failed; the previous schedule is kept and the payload says what was wrong. */
701
+ | 'error'
702
+ /** A task edit that is not a move, a resize or a progress change is about to be applied; cancellable. */
703
+ | 'beforeTaskEdit'
704
+ /** A task is about to be moved — the patch sets `start` or `end`; cancellable. */
705
+ | 'beforeTaskMove'
706
+ /** A task is about to be resized — the patch sets `duration`; cancellable. */
707
+ | 'beforeTaskResize'
708
+ /** A task's progress is about to change — the patch sets `percentComplete`; cancellable. */
709
+ | 'beforeProgressChange'
710
+ /** A milestone is about to be moved — a move patch on a zero-length task; cancellable. */
711
+ | 'beforeMilestoneMove'
712
+ /** One or more dependency links are about to be created; cancellable. */
713
+ | 'beforeDependencyCreate'
714
+ /** A task is about to be deleted, along with every link touching it; cancellable. */
715
+ | 'beforeTaskDelete'
716
+ /** A `beforeTaskEdit` handler refused the edit. */
717
+ | 'taskEdit:cancelled'
718
+ /** A `beforeTaskMove` handler refused the move. */
719
+ | 'taskMove:cancelled'
720
+ /** A `beforeTaskResize` handler refused the resize. */
721
+ | 'taskResize:cancelled'
722
+ /** A `beforeProgressChange` handler refused the progress change. */
723
+ | 'progressChange:cancelled'
724
+ /** A `beforeMilestoneMove` handler refused the milestone move. */
725
+ | 'milestoneMove:cancelled'
726
+ /** A `beforeDependencyCreate` handler refused the links. */
727
+ | 'dependencyCreate:cancelled'
728
+ /** A `beforeTaskDelete` handler refused the delete. */
729
+ | 'taskDelete:cancelled';
730
+
731
+ /** What a handler receives, per Gantt event. */
732
+ interface GanttEventPayloads {
733
+ /** The recomputed schedule, exactly as `gantt.schedule` now reads. */
734
+ schedule: GanttSchedule;
735
+ /** Why the recompute failed. */
736
+ error: GanttScheduleError;
737
+ /** The edit about to be applied, with `preventDefault` to stop it. */
738
+ beforeTaskEdit: GanttTaskEditEvent;
739
+ /** The move about to be applied, with `preventDefault` to stop it. */
740
+ beforeTaskMove: GanttTaskEditEvent;
741
+ /** The resize about to be applied, with `preventDefault` to stop it. */
742
+ beforeTaskResize: GanttTaskEditEvent;
743
+ /** The progress about to be written, with `preventDefault` to stop it. */
744
+ beforeProgressChange: GanttTaskEditEvent;
745
+ /** The milestone move about to be applied, with `preventDefault` to stop it. */
746
+ beforeMilestoneMove: GanttTaskEditEvent;
747
+ /** The links about to be created, with `preventDefault` to stop them. */
748
+ beforeDependencyCreate: GanttDependencyCreateEvent;
749
+ /** The task about to be deleted, with `preventDefault` to stop it. */
750
+ beforeTaskDelete: GanttTaskDeleteEvent;
751
+ /** The edit that was not applied, and why. */
752
+ 'taskEdit:cancelled': GanttTaskEditCancelledEvent;
753
+ /** The move that was not applied, and why. */
754
+ 'taskMove:cancelled': GanttTaskEditCancelledEvent;
755
+ /** The resize that was not applied, and why. */
756
+ 'taskResize:cancelled': GanttTaskEditCancelledEvent;
757
+ /** The progress change that was not written, and why. */
758
+ 'progressChange:cancelled': GanttTaskEditCancelledEvent;
759
+ /** The milestone move that was not applied, and why. */
760
+ 'milestoneMove:cancelled': GanttTaskEditCancelledEvent;
761
+ /** The links that were not created, and why. */
762
+ 'dependencyCreate:cancelled': GanttDependencyCreateCancelledEvent;
763
+ /** The task that was not deleted, and why. */
764
+ 'taskDelete:cancelled': GanttTaskDeleteCancelledEvent;
765
+ }
766
+
285
767
  /** A headless Gantt controller: holds the model, recomputes on edits, emits changes. */
286
768
  interface Gantt {
769
+ /**
770
+ * The current tasks, as fresh shallow copies — mutating them changes nothing; call
771
+ * `applyEdit` or `setTasks`.
772
+ */
287
773
  readonly tasks: GanttTask[];
774
+ /**
775
+ * The current links, as fresh copies, always in the normalised `{ from, to, type, lag
776
+ * }` form.
777
+ */
288
778
  readonly dependencies: GanttDependency[];
779
+ /**
780
+ * The latest schedule result. It keeps the last successful one when a recompute fails,
781
+ * so a cycle does not blank the view.
782
+ */
289
783
  readonly schedule: GanttSchedule | null;
784
+ /** The critical task ids from the latest schedule; empty when the last compute failed. */
290
785
  readonly critical: string[];
291
786
  /** Constraints the latest schedule could not honour (empty when all are satisfied). */
292
787
  readonly conflicts: GanttConflict[];
788
+ /**
789
+ * Whether the controller was asked to cascade an edit down the dependency chain rather
790
+ * than only recomputing.
791
+ */
293
792
  readonly autoSchedule: boolean;
793
+ /** The grid this controller is bound to, or null for a standalone plan. */
294
794
  readonly grid: unknown;
295
795
  /** The over-allocations from the latest schedule. */
296
796
  readonly overAllocations: GanttOverAllocation[];
297
797
  /** The latest resource-load report, or null before a successful schedule. */
298
798
  readonly resourceLoad: GanttResourceLoad | null;
799
+ /**
800
+ * Replace the whole task list (copied in) and recompute, returning the new schedule.
801
+ * Ignored with a warning after `destroy()`.
802
+ */
299
803
  setTasks(tasks: GanttTask[]): GanttSchedule;
804
+ /**
805
+ * Replace the link list and recompute. Adding a link is gated on
806
+ * `beforeDependencyCreate`, so this returns undefined on a veto, or a promise when a
807
+ * handler defers; a pure removal or reorder applies straight away.
808
+ */
300
809
  setDependencies(deps: GanttDependency[]): GanttSchedule;
301
810
  /**
302
811
  * Apply one task edit and recompute — the single gated choke point every
@@ -311,7 +820,16 @@ interface Gantt {
311
820
  * resize stretches it across the new span at the same daily levels.
312
821
  */
313
822
  applyEdit(patch: { id: string | number; start?: number; end?: number; duration?: number; percentComplete?: number; work?: number | Array<{ date: number | string | Date; hours: number }> }, editOpts?: { writeBack?: boolean }): GanttSchedule;
823
+ /**
824
+ * Recompute the schedule now and return it. On success it emits `schedule` and
825
+ * refreshes the resource load; on a cycle or bad input it emits `error` and leaves the
826
+ * previous schedule in place.
827
+ */
314
828
  compute(): GanttSchedule;
829
+ /**
830
+ * The tasks placed earlier than CPM allows — the "manual with validation" flag. Empty
831
+ * when every placement is feasible, and when there is no successful schedule.
832
+ */
315
833
  findViolations(): GanttViolation[];
316
834
  /**
317
835
  * Compute the resource load and over-allocations on demand,
@@ -350,8 +868,14 @@ interface Gantt {
350
868
  added: GanttTask[]; updated: GanttTask[]; removed: string[];
351
869
  };
352
870
  };
353
- on(event: 'schedule' | 'error', fn: (payload: unknown) => void): () => void;
354
- off(event: 'schedule' | 'error', fn: (payload: unknown) => void): void;
871
+ /**
872
+ * Register an event listener; returns a function that unsubscribes. What each event
873
+ * carries is {@link GanttEventPayloads}; the listener is declared with the widest of
874
+ * them, so narrow on the name inside it.
875
+ */
876
+ on(event: GanttEventName, fn: (payload: GanttEventPayloads[GanttEventName]) => void): () => void;
877
+ /** Remove a listener registered with `on`. */
878
+ off(event: GanttEventName, fn: (payload: GanttEventPayloads[GanttEventName]) => void): void;
355
879
  /**
356
880
  * Render the plan into a container as an SVG timeline (bars, dependency
357
881
  * arrows, critical-path highlight, today line, non-working shading,
@@ -552,6 +1076,11 @@ interface Gantt {
552
1076
  unmount(): void;
553
1077
  /** The mounted view, or null. */
554
1078
  readonly view: unknown;
1079
+ /**
1080
+ * Destroy the mounted view, drop the grid subscriptions and clear the listeners. The
1081
+ * controller then refuses further edits with a warning; the host still owns the grid
1082
+ * and the container.
1083
+ */
555
1084
  destroy(): void;
556
1085
  }
557
1086
 
@@ -615,11 +1144,33 @@ export default createGantt;
615
1144
 
616
1145
  /** The model {@link importMSPDI} returns and {@link exportMSPDI} takes. */
617
1146
  interface GanttMSPDIModel {
1147
+ /**
1148
+ * The plan's tasks, written out with their outline level, summary and milestone flags,
1149
+ * constraints, baseline and progress.
1150
+ */
618
1151
  tasks: GanttTask[];
1152
+ /** The typed links, written as predecessor links with their lag on the successor task. */
619
1153
  dependencies?: GanttDependency[];
1154
+ /**
1155
+ * The resource list, written with each resource's capacity as `MaxUnits`. Only the
1156
+ * array form is read here: a name-to-capacity map is ignored, and its resources then
1157
+ * appear only through the tasks' assignments, at capacity 1.
1158
+ */
620
1159
  resources?: GanttResourceSpec;
1160
+ /**
1161
+ * The project's start date. Defaults to the schedule's own start when a schedule is
1162
+ * supplied.
1163
+ */
621
1164
  projectStart?: number | string | Date;
1165
+ /**
1166
+ * The working-time calendar written as the project's base calendar — a `weekends`
1167
+ * preset or explicit workdays and holidays. Null writes no calendar.
1168
+ */
622
1169
  calendar?: GanttCalendar | null;
1170
+ /**
1171
+ * A computed schedule, so the written start and finish dates are the scheduled ones.
1172
+ * Without it (or with a failed one) the tasks' own placements are used.
1173
+ */
623
1174
  schedule?: GanttSchedule;
624
1175
  }
625
1176