construction-gantt 0.1.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +5 -0
  3. package/dist/export/index.cjs +1 -0
  4. package/dist/export/index.d.cts +112 -0
  5. package/dist/export/index.d.cts.map +1 -0
  6. package/dist/export/index.d.ts +112 -0
  7. package/dist/export/index.d.ts.map +1 -0
  8. package/dist/export/index.js +1 -0
  9. package/dist/index.cjs +3492 -0
  10. package/dist/index.d.cts +628 -0
  11. package/dist/index.d.cts.map +1 -0
  12. package/dist/index.d.ts +628 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +3461 -0
  15. package/dist/pdf-CAQDrX0w.cjs +120 -0
  16. package/dist/pdf-CBaoJRTI.js +120 -0
  17. package/dist/png-C8t74695.cjs +88 -0
  18. package/dist/png-DKZeKnRh.js +88 -0
  19. package/dist/xlsx-5FRPFck7.js +89 -0
  20. package/dist/xlsx-Gh5L_NL3.cjs +111 -0
  21. package/package.json +86 -0
  22. package/src/Gantt.css +23 -0
  23. package/src/Gantt.tsx +636 -0
  24. package/src/SpikeGantt.tsx +114 -0
  25. package/src/analysis.ts +83 -0
  26. package/src/baseline.ts +119 -0
  27. package/src/calendars/canterbury-table.ts +44 -0
  28. package/src/calendars/internal/computus.ts +25 -0
  29. package/src/calendars/internal/date-utils.ts +13 -0
  30. package/src/calendars/internal/mondayisation.ts +46 -0
  31. package/src/calendars/internal/month-rules.ts +65 -0
  32. package/src/calendars/matariki-table.ts +63 -0
  33. package/src/calendars/nz-holidays.ts +214 -0
  34. package/src/editing/command-history.ts +78 -0
  35. package/src/editing/commands.ts +327 -0
  36. package/src/editing/composite-command.ts +64 -0
  37. package/src/editing/draft-project.ts +59 -0
  38. package/src/editing/errors.ts +14 -0
  39. package/src/editing/factories.ts +92 -0
  40. package/src/editing/use-editable-project.ts +122 -0
  41. package/src/export/index.ts +12 -0
  42. package/src/export/offscreen.tsx +89 -0
  43. package/src/export/pdf-dimensions.ts +64 -0
  44. package/src/export/pdf.ts +68 -0
  45. package/src/export/png.ts +48 -0
  46. package/src/export/types.ts +42 -0
  47. package/src/export/xlsx.ts +70 -0
  48. package/src/index.ts +89 -0
  49. package/src/mspdi/parse.ts +820 -0
  50. package/src/mspdi/serialize.ts +352 -0
  51. package/src/mspdi/types.ts +53 -0
  52. package/src/schedule.ts +470 -0
  53. package/src/topological-sort.ts +51 -0
  54. package/src/types.ts +254 -0
  55. package/src/visibility.ts +35 -0
  56. package/src/working-time.ts +235 -0
@@ -0,0 +1,628 @@
1
+ import * as react from 'react';
2
+ import { FC, ReactElement } from 'react';
3
+
4
+ type TaskId = string | number;
5
+ type LinkId = string | number;
6
+ type ResourceId = string | number;
7
+ type CalendarId = string | number;
8
+ type AssignmentId = string | number;
9
+ type TaskType = 'task' | 'summary' | 'milestone';
10
+ type ScheduleMode = 'auto' | 'manual';
11
+ /**
12
+ * MS Project's 8 constraint types.
13
+ *
14
+ * - ASAP / ALAP: scheduling preferences, no date required.
15
+ * - MSO / MFO: hard constraints, pin the date; override predecessor logic.
16
+ * - SNET / SNLT / FNET / FNLT: soft date bounds.
17
+ *
18
+ * Hard constraints can produce negative slack — the contract-trouble
19
+ * signal we surface rather than silently clip to zero (ADR-003).
20
+ */
21
+ type ConstraintType = 'ASAP' | 'ALAP' | 'MSO' | 'MFO' | 'SNET' | 'SNLT' | 'FNET' | 'FNLT';
22
+ interface Constraint {
23
+ type: ConstraintType;
24
+ /** Required for all types except ASAP and ALAP. */
25
+ date?: Date;
26
+ }
27
+ interface Task {
28
+ id: TaskId;
29
+ text: string;
30
+ /** Hierarchy parent. Undefined = top-level. */
31
+ parent?: TaskId;
32
+ type: TaskType;
33
+ scheduleMode: ScheduleMode;
34
+ /**
35
+ * For summary tasks: are children currently expanded?
36
+ * Default true (expanded). Toggled by the user via the renderer's
37
+ * collapse/expand chevron.
38
+ */
39
+ open?: boolean;
40
+ /** Working-time duration in minutes. For milestones this is 0. */
41
+ duration: number;
42
+ /**
43
+ * User-set start / end. For manual-scheduled tasks these are authoritative.
44
+ * For auto-scheduled tasks the engine recomputes them and writes the
45
+ * result back. Either way, the engine populates `computed` with the
46
+ * full forward/backward-pass data.
47
+ */
48
+ start: Date;
49
+ end: Date;
50
+ /** Percent complete, 0-100. */
51
+ progress: number;
52
+ constraint?: Constraint;
53
+ /** Resource assignments. Order is not meaningful. */
54
+ resourceIds?: ResourceId[];
55
+ /**
56
+ * Calendar override. If unset, the task uses the project default calendar.
57
+ * If a resource on the task has a calendar, the engine reconciles them
58
+ * (resource calendar wins for activities depending on that resource).
59
+ */
60
+ calendarId?: CalendarId;
61
+ /** Populated by the scheduling engine. Read-only for user code. */
62
+ computed?: TaskComputed;
63
+ }
64
+ /**
65
+ * Forward/backward-pass output. Filled in by `schedule()`.
66
+ *
67
+ * `totalSlack` is the contract-trouble signal: when negative, the task is
68
+ * already late against a downstream constraint and the schedule is
69
+ * infeasible without intervention. We display this; we don't clip it.
70
+ */
71
+ interface TaskComputed {
72
+ earlyStart: Date;
73
+ earlyFinish: Date;
74
+ lateStart: Date;
75
+ lateFinish: Date;
76
+ /** Working-minutes of total float. Can be negative. */
77
+ totalSlack: number;
78
+ /** Working-minutes of free float (slack against the earliest successor). */
79
+ freeSlack: number;
80
+ isCritical: boolean;
81
+ }
82
+ /**
83
+ * Dependency type, matching MS Project notation:
84
+ * - FS = Finish-to-Start (most common in construction)
85
+ * - SS = Start-to-Start (concurrent activities sharing a start trigger)
86
+ * - FF = Finish-to-Finish (concurrent activities sharing a finish gate)
87
+ * - SF = Start-to-Finish (rare; reverse-direction)
88
+ */
89
+ type DependencyType = 'FS' | 'SS' | 'FF' | 'SF';
90
+ interface Link {
91
+ id: LinkId;
92
+ source: TaskId;
93
+ target: TaskId;
94
+ type: DependencyType;
95
+ /**
96
+ * Lag in working-minutes. Positive = delay, negative = lead.
97
+ * Construction example: 3-day cure time on a FS link = lag of 3 working days
98
+ * converted to minutes via the calendar.
99
+ */
100
+ lag: number;
101
+ }
102
+ /** Minutes-from-midnight working interval. e.g. 8am-5pm = {480, 1020}. */
103
+ interface WorkInterval {
104
+ startMinutes: number;
105
+ endMinutes: number;
106
+ }
107
+ type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;
108
+ /**
109
+ * A calendar describes when work happens.
110
+ *
111
+ * - `workWeek` is the recurring base: 7 entries, each an array of intervals.
112
+ * Empty array = non-working day. Multiple intervals = split shift
113
+ * (e.g. 7-12 + 13-15 for concreting with a lunch break).
114
+ * - `exceptions` override specific dates: holidays, weather days, site
115
+ * shutdown periods, or "this Saturday is a working day."
116
+ * - `baseCalendarId` lets resource/task calendars inherit from a base
117
+ * and override only the differences.
118
+ */
119
+ interface Calendar {
120
+ id: CalendarId;
121
+ name: string;
122
+ workWeek: WorkInterval[][];
123
+ exceptions: CalendarException[];
124
+ baseCalendarId?: CalendarId;
125
+ }
126
+ interface CalendarException {
127
+ date: Date;
128
+ /** false = non-working day (holiday). true = working with given intervals. */
129
+ isWorking: boolean;
130
+ intervals?: WorkInterval[];
131
+ /** Display name. NZ Anzac Day, Auckland Anniversary, weather day, etc. */
132
+ name?: string;
133
+ }
134
+ interface Resource {
135
+ id: ResourceId;
136
+ name: string;
137
+ /** Optional per-resource calendar override (plasterer's 4-day week, etc.). */
138
+ calendarId?: CalendarId;
139
+ }
140
+ /**
141
+ * Allocates a Resource to a Task. v0.2 first cut carries only the core
142
+ * triple (taskId + resourceId + units) — enough to round-trip MSPDI
143
+ * <Assignment> elements without losing the allocation graph.
144
+ *
145
+ * Per-day timephased work data + cost tracking + EV fields are MSPDI-side
146
+ * concerns that we don't yet model internally; they appear in
147
+ * `droppedFields` on parse rather than entering our model.
148
+ *
149
+ * The eventual v0.4 editing-model expansion will likely add `actualWork`,
150
+ * `plannedWork`, and `progress` fields here, plus a separate
151
+ * `TimephasedSpread` type for per-day allocations.
152
+ */
153
+ interface Assignment {
154
+ id: AssignmentId;
155
+ taskId: TaskId;
156
+ resourceId: ResourceId;
157
+ /**
158
+ * Allocation share. 1.0 = 100% (fully assigned). 0.5 = part-time. >1.0
159
+ * is over-allocated (MS Project allows this — the renderer surfaces it
160
+ * with the OverAllocated flag). Default 1.0 if omitted.
161
+ */
162
+ units?: number;
163
+ }
164
+ /** MS Project supports 11 baselines (Baseline 0-10). We match. */
165
+ type BaselineIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
166
+ interface Baseline {
167
+ index: BaselineIndex;
168
+ /** Display name. "Original contract programme", "Variation 1 reprogramme", etc. */
169
+ name?: string;
170
+ capturedAt: Date;
171
+ /** Snapshot of task dates + durations at capture time. */
172
+ tasks: Map<TaskId, BaselineTaskSnapshot>;
173
+ }
174
+ interface BaselineTaskSnapshot {
175
+ start: Date;
176
+ end: Date;
177
+ duration: number;
178
+ }
179
+ interface Project {
180
+ /** Project start anchor. Forward pass starts here. */
181
+ start: Date;
182
+ /** Optional finish anchor. If set, backward pass terminates here instead of latest task EarlyFinish. */
183
+ end?: Date;
184
+ defaultCalendarId: CalendarId;
185
+ tasks: Task[];
186
+ links: Link[];
187
+ resources: Resource[];
188
+ calendars: Calendar[];
189
+ /** Up to 11 entries (Baseline 0-10). */
190
+ baselines: Baseline[];
191
+ /** Resource-to-task allocations. Empty array if no resources are allocated. */
192
+ assignments: Assignment[];
193
+ }
194
+
195
+ /**
196
+ * Return the critical-path leaf tasks (summary tasks excluded), ordered
197
+ * by `earlyStart` ascending. A construction PM reading this list is
198
+ * looking at "the tasks that, if any of them slip, the contract finish
199
+ * slips."
200
+ *
201
+ * The list mirrors what `task.computed.isCritical` says — i.e., includes
202
+ * tasks with negative total slack (already-late tasks).
203
+ */
204
+ declare function getCriticalPath(project: Project): Task[];
205
+ interface ProjectStats {
206
+ /** Leaf task count (summaries excluded). */
207
+ totalTasks: number;
208
+ /** Leaf tasks on the critical path (totalSlack <= 0). */
209
+ criticalTasks: number;
210
+ /** Leaf tasks with strictly negative totalSlack (the contract-trouble subset). */
211
+ lateTasks: number;
212
+ /** Latest earlyFinish across leaf tasks. Project's natural finish date. */
213
+ projectFinish?: Date;
214
+ /** Duration-weighted average progress across leaf tasks. 0 if no tasks. */
215
+ weightedProgress: number;
216
+ }
217
+ /**
218
+ * Summary statistics over a scheduled Project. Useful for status
219
+ * dashboards, programme-health badges in management views, and CI
220
+ * checks that flag "did the critical path grow this commit?".
221
+ */
222
+ declare function getProjectStats(project: Project): ProjectStats;
223
+
224
+ /**
225
+ * Snapshot the current schedule (task starts, ends, durations) as a baseline
226
+ * at the given index. Returns a new Project with the baseline added; the
227
+ * input is not mutated. If a baseline already exists at this index, it is
228
+ * replaced (matches MS Project "Save Baseline" behavior).
229
+ */
230
+ declare function captureBaseline(project: Project, index: BaselineIndex, options?: {
231
+ name?: string;
232
+ capturedAt?: Date;
233
+ }): Project;
234
+ interface TaskBaselineVariance {
235
+ /** Working-minute drift in start. Positive = task is later than baseline. */
236
+ startVariance: number;
237
+ /** Working-minute drift in finish. Positive = task is later than baseline. */
238
+ finishVariance: number;
239
+ /** Change in duration (calendar-minute units of the task model). */
240
+ durationVariance: number;
241
+ }
242
+ /**
243
+ * Compute baseline variance for every task in `project`. Returns a Map
244
+ * keyed by TaskId. Tasks not present in the named baseline are omitted
245
+ * from the returned map.
246
+ *
247
+ * `baselineIndex` selects the baseline on `project.baselines`. If the
248
+ * project has no baseline at that index, returns an empty Map (caller
249
+ * decides whether to treat this as a soft error or hard error).
250
+ *
251
+ * The calendar used for working-time variance arithmetic is the project
252
+ * default calendar, looked up by `project.defaultCalendarId`. If that
253
+ * lookup fails, throw an Error (consistent with `schedule()`'s behavior
254
+ * on a missing default calendar).
255
+ */
256
+ declare function getTaskBaselineVarianceAll(project: Project, baselineIndex: BaselineIndex): Map<TaskId, TaskBaselineVariance>;
257
+ /**
258
+ * Compute working-time variance between a task's current dates and its
259
+ * snapshot in a baseline. Returns undefined if the task isn't in the
260
+ * baseline (added after the baseline was captured).
261
+ */
262
+ declare function getTaskBaselineVariance(task: Task, baseline: Baseline, calendar: Calendar): TaskBaselineVariance | undefined;
263
+
264
+ /**
265
+ * The 13 statutory NZ regions with their own anniversary day, plus Northland
266
+ * which observes Waitangi Day per Holidays Act 2003 (no extra exception
267
+ * is added for `'northland'` — the region value is accepted, the
268
+ * national-only set is returned).
269
+ */
270
+ type NZRegion = 'auckland' | 'canterbury' | 'chatham-islands' | 'hawkes-bay' | 'marlborough' | 'nelson' | 'northland' | 'otago' | 'south-canterbury' | 'southland' | 'taranaki' | 'wellington' | 'westland';
271
+ interface NZDefaultCalendarOptions {
272
+ /** Year (single) or years (array). 2022 ≤ year ≤ 2052. Duplicates deduplicated. */
273
+ years: number | number[];
274
+ /** Optional regional anniversary on top of the 11 national holidays. */
275
+ region?: NZRegion;
276
+ /**
277
+ * Override the default Mon–Fri 8am–5pm working week.
278
+ * 7 entries, Sunday=0 … Saturday=6.
279
+ */
280
+ workWeek?: WorkInterval[][];
281
+ /** Calendar.id. Default: 'nz-default'. */
282
+ id?: CalendarId;
283
+ /** Calendar.name. Default: 'New Zealand Standard'. */
284
+ name?: string;
285
+ }
286
+ declare function nzPublicHolidays(years: number | number[], region?: NZRegion): CalendarException[];
287
+ declare function nzDefaultCalendar(options: NZDefaultCalendarOptions): Calendar;
288
+
289
+ /**
290
+ * The contract every edit command must satisfy. apply must be pure
291
+ * (no mutation, no I/O) — returns a new Project. inverse(project)
292
+ * captures the state needed to reverse the edit when applied to the
293
+ * post-edit Project.
294
+ *
295
+ * Per ADR-006: every edit flows through schedule() recompute at the
296
+ * hook layer, not inside apply(). Commands operate on raw data only.
297
+ */
298
+ interface EditCommand {
299
+ /** Discriminator for command kind. */
300
+ readonly kind: string;
301
+ /** Human-readable label for UI undo text (e.g. "Rename Foundation pour"). */
302
+ readonly label: string;
303
+ /** Pure: applies the edit to a Project, returning a new Project. Throws EditError on invalid input. */
304
+ apply(project: Project): Project;
305
+ /**
306
+ * Returns an inverse command: applying inverse(P) on apply(P) yields P.
307
+ *
308
+ * Pre-edit state capture timing varies by command kind:
309
+ * - Create*Command: constructor argument is the inverse's only input
310
+ * - Update*Command, Delete*Command: snapshot pre-state internally during
311
+ * apply() (single-use per instance). The `project` argument is
312
+ * accepted for interface consistency but ignored.
313
+ *
314
+ * Consumers (CompositeCommand, CommandHistory) only need to call apply()
315
+ * before inverse() and pass the current project to inverse().
316
+ */
317
+ inverse(project: Project): EditCommand;
318
+ }
319
+
320
+ /**
321
+ * Thrown when an EditCommand's pre-conditions fail (e.g. target task
322
+ * doesn't exist, FS-link-to-self, malformed patch). Caught at the hook
323
+ * boundary so consumers see a typed error rather than a generic Error.
324
+ */
325
+ declare class EditError extends Error {
326
+ readonly commandKind: string;
327
+ constructor(message: string, commandKind: string);
328
+ }
329
+
330
+ /**
331
+ * Ergonomic factory functions for constructing edit commands with
332
+ * descriptive labels. Consumers call these instead of `new
333
+ * UpdateTaskCommand(...)` so undo UI shows "Rename task to 'Foundation'"
334
+ * rather than the generic "Update task 'a' (text)".
335
+ */
336
+ declare function renameTask(id: TaskId, text: string): EditCommand;
337
+ declare function setTaskStart(id: TaskId, start: Date): EditCommand;
338
+ declare function setTaskDuration(id: TaskId, minutes: number): EditCommand;
339
+ declare function setTaskProgress(id: TaskId, percent: number): EditCommand;
340
+ declare function updateTask(id: TaskId, patch: Partial<Task>): EditCommand;
341
+ declare function createTask(task: Task, _parent?: TaskId, _insertAfter?: TaskId): EditCommand;
342
+ declare function deleteTask(id: TaskId): EditCommand;
343
+ /**
344
+ * Creates a CreateLinkCommand with a **deterministic** link id derived
345
+ * from `${source}->${target}`. This means calling `linkTasks('a', 'b')`
346
+ * twice produces the same id — and the second `apply()` will throw
347
+ * `EditError: duplicate link id`. By design: duplicate enqueues are a
348
+ * consumer bug we surface loudly rather than silently coalesce.
349
+ *
350
+ * Consumers who legitimately need to re-add a previously-deleted link
351
+ * (e.g. delete A→B, then re-create it without bringing the deleted one
352
+ * back via undo) should use `new CreateLinkCommand({ id: customId, … })`
353
+ * directly with a fresh id.
354
+ */
355
+ declare function linkTasks(source: TaskId, target: TaskId, type?: DependencyType, lag?: number): EditCommand;
356
+ declare function updateLink(id: LinkId, patch: Partial<Link>): EditCommand;
357
+ declare function deleteLink(id: LinkId): EditCommand;
358
+
359
+ /**
360
+ * Consumer-facing return shape. The renderer reads `project`
361
+ * unconditionally — it's always the scheduled, effective state.
362
+ */
363
+ interface EditableProject {
364
+ readonly project: Project;
365
+ readonly isDirty: boolean;
366
+ readonly canUndo: boolean;
367
+ readonly canRedo: boolean;
368
+ enqueue(command: EditCommand): void;
369
+ commit(label?: string): void;
370
+ cancel(): void;
371
+ undo(): void;
372
+ redo(): void;
373
+ }
374
+ /**
375
+ * The single hook entry point for v0.4 editing. Captures `initial` once
376
+ * on first mount (subsequent renders with a different `initial` are
377
+ * ignored — consumers reset by remounting via `key={projectId}`).
378
+ *
379
+ * Every effective state change is run through `schedule()` so the
380
+ * returned `project` always has fresh CPM data. Per ADR-005 (engine-first).
381
+ */
382
+ declare function useEditableProject(initial: Project): EditableProject;
383
+
384
+ interface PngExportOptions {
385
+ /** Background colour for the captured canvas. Defaults to '#ffffff'. */
386
+ backgroundColor?: string;
387
+ /** Pixel ratio. Defaults to window.devicePixelRatio || 2. */
388
+ pixelRatio?: number;
389
+ }
390
+ interface PdfExportOptions {
391
+ /** Page orientation. Defaults to 'landscape' (Gantt charts are wide). */
392
+ orientation?: 'landscape' | 'portrait';
393
+ /** Page size. Defaults to 'a3'. */
394
+ format?: 'a4' | 'a3' | 'letter';
395
+ /** Margin in mm. Defaults to 10. */
396
+ margin?: number;
397
+ /** Background colour for the underlying PNG. Defaults to '#ffffff'. */
398
+ backgroundColor?: string;
399
+ }
400
+ interface XlsxColumn {
401
+ header: string;
402
+ /** A key on Task, or a function returning the cell value. */
403
+ value: keyof Task | ((task: Task) => string | number | Date | undefined);
404
+ }
405
+ interface XlsxExportOptions {
406
+ /** Sheet name. Defaults to 'Programme'. */
407
+ sheetName?: string;
408
+ /** Override the default column set. */
409
+ columns?: XlsxColumn[];
410
+ }
411
+ interface GanttHandle {
412
+ exportPNG(options?: PngExportOptions): Promise<Blob>;
413
+ exportPDF(options?: PdfExportOptions): Promise<Blob>;
414
+ exportXLSX(options?: XlsxExportOptions): Promise<Blob>;
415
+ }
416
+
417
+ interface GanttMarker {
418
+ start: Date;
419
+ text?: string;
420
+ /**
421
+ * Visual style. 'today' renders as a red line; 'milestone' as blue;
422
+ * 'custom' lets you supply a `css` class name yourself.
423
+ */
424
+ variant?: 'today' | 'milestone' | 'custom';
425
+ /** CSS class name when `variant: 'custom'`. */
426
+ css?: string;
427
+ }
428
+ /**
429
+ * Defines a column in the left-hand grid of the Gantt chart.
430
+ * Construction-PM-facing: these are the columns site PMs expect alongside
431
+ * the task name (WBS code, trade package, assigned subcontractor, etc.).
432
+ *
433
+ * This is a SVAR-agnostic type — internal conversion to SVAR's IColumnConfig
434
+ * happens inside the <Gantt> wrapper.
435
+ */
436
+ interface GanttColumn<TTask = Task> {
437
+ /** Identifier; used as SVAR column id. */
438
+ id: string;
439
+ /** Header label rendered in the column header row. */
440
+ header: string;
441
+ /**
442
+ * The field on the task to pluck for the default cell render.
443
+ * Optional — if `render` is provided, this is ignored.
444
+ */
445
+ field?: keyof TTask;
446
+ /** Column width in pixels. Defaults to SVAR's default if unset. */
447
+ width?: number;
448
+ /** Text alignment for the cell. */
449
+ align?: 'left' | 'center' | 'right';
450
+ /**
451
+ * Custom cell render. Receives the live (scheduled) task. Use for any
452
+ * column more complex than displaying a single field value.
453
+ */
454
+ render?: FC<{
455
+ task: Task;
456
+ }>;
457
+ }
458
+ interface GanttProps {
459
+ project: Project;
460
+ /** Container height. Defaults to 500 (px). */
461
+ height?: number | string;
462
+ /** Width of one time-scale cell (per `cellWidth` SVAR prop). Default 48. */
463
+ cellWidth?: number;
464
+ /** Height of one row. */
465
+ cellHeight?: number;
466
+ /**
467
+ * Skip running the scheduling engine. Use when the project's tasks
468
+ * already have `computed` populated by a prior `schedule()` call.
469
+ */
470
+ preScheduled?: boolean;
471
+ /**
472
+ * Vertical markers (today line + arbitrary milestones).
473
+ * Default: a today line if the current date falls within the project
474
+ * window. Pass an empty array to suppress, or your own markers list to
475
+ * override.
476
+ */
477
+ markers?: GanttMarker[];
478
+ /**
479
+ * Show variance against this baseline index. If unset (or no matching
480
+ * baseline exists on `project.baselines`), bars render without variance
481
+ * pills. Construction-vertical use case (ADR-003): comparing the live
482
+ * programme against the original contract programme captured under
483
+ * NZS 3910 / AS 4000.
484
+ */
485
+ baselineIndex?: BaselineIndex;
486
+ /**
487
+ * Render the baseline as a separate "ghost" bar beneath each live task.
488
+ * Matches the MS Project baseline-view idiom construction PMs expect
489
+ * when reviewing variation claims. Default true when `baselineIndex`
490
+ * is set; pass `false` to keep variance shown only as in-bar pills.
491
+ */
492
+ showBaselineBars?: boolean;
493
+ /**
494
+ * Grid columns displayed alongside the Gantt bars.
495
+ *
496
+ * - `undefined` (default): SVAR renders its built-in columns (task name +
497
+ * duration + start + end).
498
+ * - `[]` (empty array): hides the grid entirely (passes `columns={false}`
499
+ * to SVAR).
500
+ * - `GanttColumn[]`: replaces SVAR's default columns with the supplied set.
501
+ *
502
+ * Construction-PM-facing columns live here: WBS code, trade package,
503
+ * assigned subcontractor, and similar project-specific fields.
504
+ */
505
+ columns?: GanttColumn[];
506
+ /**
507
+ * Render-only visibility filter. When set, only tasks whose `id` is in
508
+ * the set are rendered. **CPM still runs on the full task set** — hidden
509
+ * predecessors continue to drive their visible successors' computed
510
+ * fields. The visibility filter is a render-only concern (ADR-005).
511
+ *
512
+ * - `undefined` (default): no filter; render everything.
513
+ * - empty set: render nothing.
514
+ * - set containing ids not present in `project.tasks`: those ids are
515
+ * ignored; only matching tasks render.
516
+ *
517
+ * Lifts the "filter-while-keeping-CPM-correct" domain rule that
518
+ * consumer apps would otherwise have to write themselves. See
519
+ * `visibility.ts` for the contract test.
520
+ */
521
+ visibleTaskIds?: ReadonlySet<TaskId>;
522
+ }
523
+ declare const Gantt: react.ForwardRefExoticComponent<GanttProps & react.RefAttributes<GanttHandle>>;
524
+
525
+ /**
526
+ * Result of parsing an MSPDI XML document.
527
+ *
528
+ * `project` is our internal SVAR-agnostic Project shape.
529
+ * `droppedFields` enumerates MSPDI fields we encountered but did not map,
530
+ * for consumer transparency. Each entry: the JSON-path-like location, the
531
+ * raw value, and a short reason (`'unsupported-element'`, `'unsupported-attribute'`,
532
+ * `'lossy-on-roundtrip'`).
533
+ */
534
+ interface MspdiParseResult {
535
+ project: Project;
536
+ droppedFields: DroppedField[];
537
+ }
538
+ interface DroppedField {
539
+ /** Dotted path to the location in the MSPDI document, e.g. `Project.Tasks.Task[2].Notes`. */
540
+ path: string;
541
+ /** The raw value we saw and chose not to map. Stringified for diagnostic only. */
542
+ value: string;
543
+ /** Why it wasn't carried into the internal Project. */
544
+ reason: 'unsupported-element' | 'unsupported-attribute' | 'lossy-on-roundtrip';
545
+ }
546
+ /**
547
+ * Options accepted by `serializeMspdi`.
548
+ */
549
+ interface MspdiSerializeOptions {
550
+ /**
551
+ * Override the root project metadata. Defaults match MS Project 2016+
552
+ * defaults where applicable. Optional fields not set here are omitted
553
+ * from the output.
554
+ */
555
+ meta?: {
556
+ /** `<Name>` — defaults to 'Untitled'. */
557
+ name?: string;
558
+ /** `<Author>` — defaults to omitted. */
559
+ author?: string;
560
+ /** `<Title>` — defaults to the same as `name`. */
561
+ title?: string;
562
+ };
563
+ }
564
+
565
+ declare function parseMspdi(xml: string): MspdiParseResult;
566
+
567
+ declare function serializeMspdi(project: Project, options?: MspdiSerializeOptions): string;
568
+
569
+ declare function SpikeGantt(): ReactElement;
570
+
571
+ declare function schedule(project: Project): Project;
572
+
573
+ /**
574
+ * Order tasks so that every predecessor appears before its successors.
575
+ *
576
+ * Operates on link-based ordering only (all dependency types FS/SS/FF/SF
577
+ * establish "source must be visited before target" for scheduling-pass
578
+ * purposes). Hierarchy (parent/summary) is not considered here — summary
579
+ * task dates are derived from children after the forward/backward pass.
580
+ *
581
+ * Throws if the link graph contains a cycle.
582
+ */
583
+ declare function topologicalSort(tasks: Task[], links: Link[]): Task[];
584
+
585
+ declare function isWorkingDay(date: Date, calendar: Calendar): boolean;
586
+ declare function getDayWorkingMinutes(date: Date, calendar: Calendar): number;
587
+ /**
588
+ * Add `minutes` of working time to `start`, skipping non-working time
589
+ * (weekends, holidays, partial-day shift gaps). The result is the wall-clock
590
+ * Date exactly `minutes` working-time-minutes after `start`.
591
+ *
592
+ * If `start` falls in a non-working moment (weekend, after-hours, lunch
593
+ * break), the working-time clock begins from the next working interval.
594
+ *
595
+ * Note: not DST-aware. Working hours are wall-clock; cross-DST scheduling
596
+ * is approximate. Real DST handling is a future enhancement.
597
+ */
598
+ declare function addWorkingMinutes(start: Date, minutes: number, calendar: Calendar): Date;
599
+ /**
600
+ * Subtract `minutes` of working time from `end`, walking backward through
601
+ * working intervals. Backward-pass mirror of {@link addWorkingMinutes}.
602
+ *
603
+ * If `end` falls in a non-working moment, the clock begins from the end of
604
+ * the most recent working interval.
605
+ */
606
+ declare function subtractWorkingMinutes(end: Date, minutes: number, calendar: Calendar): Date;
607
+ /**
608
+ * Return the next working moment at or after `date`. If `date` already falls
609
+ * inside a working interval, returns it unchanged. If it falls in non-working
610
+ * time (weekend, after-hours, lunch break, holiday), returns the start of the
611
+ * next working interval.
612
+ */
613
+ declare function snapToNextWorkingMoment(date: Date, calendar: Calendar): Date;
614
+ /**
615
+ * Return the previous working moment at or before `date`. Mirror of
616
+ * {@link snapToNextWorkingMoment} for backward-pass scheduling.
617
+ */
618
+ declare function snapToPreviousWorkingMoment(date: Date, calendar: Calendar): Date;
619
+ /**
620
+ * Working-minute distance from `a` to `b`. Positive if `a` is earlier than
621
+ * `b`, negative if `a` is later. Used to compute slack (lateStart - earlyStart
622
+ * in working time).
623
+ */
624
+ declare function workingMinutesBetween(a: Date, b: Date, calendar: Calendar): number;
625
+
626
+ export { EditError, Gantt, SpikeGantt, addWorkingMinutes, captureBaseline, createTask, deleteLink, deleteTask, getCriticalPath, getDayWorkingMinutes, getProjectStats, getTaskBaselineVariance, getTaskBaselineVarianceAll, isWorkingDay, linkTasks, nzDefaultCalendar, nzPublicHolidays, parseMspdi, renameTask, schedule, serializeMspdi, setTaskDuration, setTaskProgress, setTaskStart, snapToNextWorkingMoment, snapToPreviousWorkingMoment, subtractWorkingMinutes, topologicalSort, updateLink, updateTask, useEditableProject, workingMinutesBetween };
627
+ export type { Assignment, AssignmentId, Baseline, BaselineIndex, BaselineTaskSnapshot, Calendar, CalendarException, CalendarId, Constraint, ConstraintType, DayOfWeek, DependencyType, DroppedField, EditCommand, EditableProject, GanttColumn, GanttHandle, GanttMarker, GanttProps, Link, LinkId, MspdiParseResult, MspdiSerializeOptions, NZDefaultCalendarOptions, NZRegion, PdfExportOptions, PngExportOptions, Project, ProjectStats, Resource, ResourceId, ScheduleMode, Task, TaskBaselineVariance, TaskComputed, TaskId, TaskType, WorkInterval, XlsxColumn, XlsxExportOptions };
628
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sources":["../src/types.ts","../src/analysis.ts","../src/baseline.ts","../src/calendars/nz-holidays.ts","../src/editing/commands.ts","../src/editing/errors.ts","../src/editing/factories.ts","../src/editing/use-editable-project.ts","../src/export/types.ts","../src/Gantt.tsx","../src/mspdi/types.ts","../src/mspdi/parse.ts","../src/mspdi/serialize.ts","../src/SpikeGantt.tsx","../src/schedule.ts","../src/topological-sort.ts","../src/working-time.ts"],"mappings":";;;AAAA,KAAK,MAAM;AACX,KAAK,MAAM;AACX,KAAK,UAAU;AACf,KAAK,UAAU;AACf,KAAK,YAAY;AACjB,KAAK,QAAQ;AACb,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB,UAAU,UAAU;AACpB,UAAU,cAAc;AACxB;AACA,WAAW,IAAI;AACf;AACA,UAAU,IAAI;AACd,QAAQ,MAAM;AACd;AACA;AACA,aAAa,MAAM;AACnB,UAAU,QAAQ;AAClB,kBAAkB,YAAY;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,IAAI;AACf,SAAS,IAAI;AACb;AACA;AACA,iBAAiB,UAAU;AAC3B;AACA,kBAAkB,UAAU;AAC5B;AACA;AACA;AACA;AACA;AACA,iBAAiB,UAAU;AAC3B;AACA,eAAe,YAAY;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,YAAY;AACtB,gBAAgB,IAAI;AACpB,iBAAiB,IAAI;AACrB,eAAe,IAAI;AACnB,gBAAgB,IAAI;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB,UAAU,IAAI;AACd,QAAQ,MAAM;AACd,YAAY,MAAM;AAClB,YAAY,MAAM;AAClB,UAAU,cAAc;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,YAAY;AACtB;AACA;AACA;AACA,KAAK,SAAS;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,QAAQ;AAClB,QAAQ,UAAU;AAClB;AACA,cAAc,YAAY;AAC1B,gBAAgB,iBAAiB;AACjC,qBAAqB,UAAU;AAC/B;AACA,UAAU,iBAAiB;AAC3B,UAAU,IAAI;AACd;AACA;AACA,gBAAgB,YAAY;AAC5B;AACA;AACA;AACA,UAAU,QAAQ;AAClB,QAAQ,UAAU;AAClB;AACA;AACA,iBAAiB,UAAU;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,UAAU;AACpB,QAAQ,YAAY;AACpB,YAAY,MAAM;AAClB,gBAAgB,UAAU;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,aAAa;AAClB,UAAU,QAAQ;AAClB,WAAW,aAAa;AACxB;AACA;AACA,gBAAgB,IAAI;AACpB;AACA,WAAW,GAAG,CAAC,MAAM,EAAE,oBAAoB;AAC3C;AACA,UAAU,oBAAoB;AAC9B,WAAW,IAAI;AACf,SAAS,IAAI;AACb;AACA;AACA,UAAU,OAAO;AACjB;AACA,WAAW,IAAI;AACf;AACA,UAAU,IAAI;AACd,uBAAuB,UAAU;AACjC,WAAW,IAAI;AACf,WAAW,IAAI;AACf,eAAe,QAAQ;AACvB,eAAe,QAAQ;AACvB;AACA,eAAe,QAAQ;AACvB;AACA,iBAAiB,UAAU;AAC3B;;AC5LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,eAAe,UAAU,OAAO,GAAG,IAAI;AACxD,UAAU,YAAY;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,IAAI;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,eAAe,UAAU,OAAO,GAAG,YAAY;;AC3BhE;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,eAAe,UAAU,OAAO,SAAS,aAAa;AACvE;AACA,iBAAiB,IAAI;AACrB,IAAI,OAAO;AACX,UAAU,oBAAoB;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,0BAA0B,UAAU,OAAO,iBAAiB,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,oBAAoB;AAC7H;AACA;AACA;AACA;AACA;AACA,iBAAiB,uBAAuB,OAAO,IAAI,YAAY,QAAQ,YAAY,QAAQ,GAAG,oBAAoB;;ACtClH;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,QAAQ;AACb,UAAU,wBAAwB;AAClC;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA;AACA;AACA;AACA,eAAe,YAAY;AAC3B;AACA,SAAS,UAAU;AACnB;AACA;AACA;AACA,iBAAiB,gBAAgB,oCAAoC,QAAQ,GAAG,iBAAiB;AACjG,iBAAiB,iBAAiB,UAAU,wBAAwB,GAAG,QAAQ;;ACvB/E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,WAAW;AACrB;AACA;AACA;AACA;AACA;AACA,mBAAmB,OAAO,GAAG,OAAO;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,OAAO,GAAG,WAAW;AAC1C;;AC9BA;AACA;AACA;AACA;AACA;AACA,cAAc,SAAS,SAAS,KAAK;AACrC;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,UAAU,KAAK,MAAM,iBAAiB,WAAW;AAClE,iBAAiB,YAAY,KAAK,MAAM,SAAS,IAAI,GAAG,WAAW;AACnE,iBAAiB,eAAe,KAAK,MAAM,oBAAoB,WAAW;AAC1E,iBAAiB,eAAe,KAAK,MAAM,oBAAoB,WAAW;AAC1E,iBAAiB,UAAU,KAAK,MAAM,SAAS,OAAO,CAAC,IAAI,IAAI,WAAW;AAC1E,iBAAiB,UAAU,OAAO,IAAI,YAAY,MAAM,iBAAiB,MAAM,GAAG,WAAW;AAC7F,iBAAiB,UAAU,KAAK,MAAM,GAAG,WAAW;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,SAAS,SAAS,MAAM,UAAU,MAAM,SAAS,cAAc,iBAAiB,WAAW;AAC5G,iBAAiB,UAAU,KAAK,MAAM,SAAS,OAAO,CAAC,IAAI,IAAI,WAAW;AAC1E,iBAAiB,UAAU,KAAK,MAAM,GAAG,WAAW;;AC3BpD;AACA;AACA;AACA;AACA,UAAU,eAAe;AACzB,sBAAsB,OAAO;AAC7B;AACA;AACA;AACA,qBAAqB,WAAW;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,kBAAkB,UAAU,OAAO,GAAG,eAAe;;ACxBtE,UAAU,gBAAgB;AAC1B;AACA;AACA;AACA;AACA;AACA,UAAU,gBAAgB;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,UAAU;AACpB;AACA;AACA,iBAAiB,IAAI,WAAW,IAAI,uBAAuB,IAAI;AAC/D;AACA,UAAU,iBAAiB;AAC3B;AACA;AACA;AACA,cAAc,UAAU;AACxB;AACA,UAAU,WAAW;AACrB,wBAAwB,gBAAgB,GAAG,OAAO,CAAC,IAAI;AACvD,wBAAwB,gBAAgB,GAAG,OAAO,CAAC,IAAI;AACvD,yBAAyB,iBAAiB,GAAG,OAAO,CAAC,IAAI;AACzD;;AC1BA,UAAU,WAAW;AACrB,WAAW,IAAI;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,WAAW,SAAS,IAAI;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,EAAE;AACf,cAAc,IAAI;AAClB;AACA;AACA,UAAU,UAAU;AACpB,aAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,WAAW;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,aAAa;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,WAAW;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,WAAW,CAAC,MAAM;AACvC;AACA,cAAc,KAAK,EAAE,KAAK,CAAC,yBAAyB,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW;;AC/GjG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,gBAAgB;AAC1B,aAAa,OAAO;AACpB,mBAAmB,YAAY;AAC/B;AACA,UAAU,YAAY;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,qBAAqB;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA,iBAAiB,UAAU,eAAe,gBAAgB;;ACA1D,iBAAiB,cAAc,UAAU,OAAO,YAAY,qBAAqB;;ACAjF,iBAAiB,UAAU,IAAI,YAAY;;ACD3C,iBAAiB,QAAQ,UAAU,OAAO,GAAG,OAAO;;ACApD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,eAAe,QAAQ,IAAI,WAAW,IAAI,KAAK,IAAI;;ACVpE,iBAAiB,YAAY,OAAO,IAAI,YAAY,QAAQ;AAC5D,iBAAiB,oBAAoB,OAAO,IAAI,YAAY,QAAQ;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,iBAAiB,QAAQ,IAAI,6BAA6B,QAAQ,GAAG,IAAI;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,sBAAsB,MAAM,IAAI,6BAA6B,QAAQ,GAAG,IAAI;AAC7F;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,uBAAuB,OAAO,IAAI,YAAY,QAAQ,GAAG,IAAI;AAC9E;AACA;AACA;AACA;AACA,iBAAiB,2BAA2B,OAAO,IAAI,YAAY,QAAQ,GAAG,IAAI;AAClF;AACA;AACA;AACA;AACA;AACA,iBAAiB,qBAAqB,IAAI,IAAI,KAAK,IAAI,YAAY,QAAQ;;;;","names":[]}