@toclocoinc/lattice-grid 1.36.0 → 1.38.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 (69) hide show
  1. package/README.md +1 -1
  2. package/docs/API.html +183 -6
  3. package/docs/api-detail.html +44 -1
  4. package/lattice-grid.d.ts +357 -10
  5. package/lattice-grid.esm.min.js +782 -58
  6. package/lattice-grid.min.cjs +779 -58
  7. package/lattice-grid.min.css +1 -1
  8. package/lattice-grid.min.js +779 -58
  9. package/modules/angular.esm.min.js +2 -2
  10. package/modules/angular.min.cjs +2 -2
  11. package/modules/angular.min.js +2 -2
  12. package/modules/chart-alluvial.esm.min.js +1 -1
  13. package/modules/chart-arc.esm.min.js +1 -1
  14. package/modules/chart-bubblemap.esm.min.js +1 -1
  15. package/modules/chart-bump.esm.min.js +1 -1
  16. package/modules/chart-calendar.esm.min.js +1 -1
  17. package/modules/chart-decomposition.esm.min.js +1 -1
  18. package/modules/chart-diverging.esm.min.js +1 -1
  19. package/modules/chart-dumbbell.esm.min.js +1 -1
  20. package/modules/chart-fan.esm.min.js +1 -1
  21. package/modules/chart-hexbin.esm.min.js +1 -1
  22. package/modules/chart-hexmap.esm.min.js +1 -1
  23. package/modules/chart-icicle.esm.min.js +1 -1
  24. package/modules/chart-parallel.esm.min.js +1 -1
  25. package/modules/chart-ridgeline.esm.min.js +1 -1
  26. package/modules/chart-roc.esm.min.js +1 -1
  27. package/modules/chart-slope.esm.min.js +1 -1
  28. package/modules/chart-splom.esm.min.js +1 -1
  29. package/modules/chart-waffle.esm.min.js +1 -1
  30. package/modules/charts.esm.min.js +450 -7
  31. package/modules/charts.min.cjs +450 -7
  32. package/modules/charts.min.js +450 -7
  33. package/modules/data-router.esm.min.js +4 -4
  34. package/modules/data-router.min.cjs +4 -4
  35. package/modules/data-router.min.js +4 -4
  36. package/modules/devtools.esm.min.js +13 -2
  37. package/modules/devtools.min.cjs +13 -2
  38. package/modules/devtools.min.js +13 -2
  39. package/modules/dhtmlx-compat.esm.min.js +4 -4
  40. package/modules/dhtmlx-compat.min.cjs +4 -4
  41. package/modules/dhtmlx-compat.min.js +4 -4
  42. package/modules/gantt.esm.min.js +714 -16
  43. package/modules/gantt.min.cjs +712 -16
  44. package/modules/gantt.min.js +712 -16
  45. package/modules/htmx.esm.min.js +776 -58
  46. package/modules/htmx.min.cjs +776 -58
  47. package/modules/htmx.min.js +776 -58
  48. package/modules/kanban.esm.min.js +379 -5
  49. package/modules/kanban.min.cjs +379 -5
  50. package/modules/kanban.min.js +379 -5
  51. package/modules/kpi.esm.min.js +4 -4
  52. package/modules/kpi.min.cjs +4 -4
  53. package/modules/kpi.min.js +4 -4
  54. package/modules/mock-socket.esm.min.js +2 -2
  55. package/modules/mock-socket.min.cjs +2 -2
  56. package/modules/mock-socket.min.js +2 -2
  57. package/modules/react.esm.min.js +2 -2
  58. package/modules/react.min.cjs +2 -2
  59. package/modules/react.min.js +2 -2
  60. package/modules/svelte.esm.min.js +2 -2
  61. package/modules/svelte.min.cjs +2 -2
  62. package/modules/svelte.min.js +2 -2
  63. package/modules/vue.esm.min.js +2 -2
  64. package/modules/vue.min.cjs +2 -2
  65. package/modules/vue.min.js +2 -2
  66. package/modules/webcomponent.esm.min.js +779 -58
  67. package/modules/webcomponent.min.cjs +779 -58
  68. package/modules/webcomponent.min.js +779 -58
  69. package/package.json +1 -1
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.36.0, type declarations
2
+ * Lattice Grid 1.38.0, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -182,6 +182,13 @@ export interface CellParams extends ValueParams {
182
182
  text: string;
183
183
  index: number;
184
184
  props?: Record<string, unknown>;
185
+ /**
186
+ * Format a message from the grid's catalogue, for a renderer that wants its
187
+ * own accessible names and labels localised rather than hard-coded (§17,
188
+ * WCAG 4.1.2). The built-in renderers use this; a custom renderer may too.
189
+ * Optional: absent when a renderer is exercised without a grid to ask.
190
+ */
191
+ t?: (key: string, vars?: Record<string, unknown>) => string;
185
192
  }
186
193
 
187
194
  export interface FormatParams extends ValueParams { locale: string }
@@ -1883,6 +1890,24 @@ export interface GridConfig {
1883
1890
  * menu offers Paste, Clear and Fill down.
1884
1891
  */
1885
1892
  contextMenu?: boolean | ((p: CellMenuParams, defaults: MenuItem[]) => MenuItem[] | void);
1893
+ /**
1894
+ * Bringing rows in from a file, the clipboard or a drop (§14, the mirror of
1895
+ * export). `true` adds a "Import rows from CSV…" item to the cell menu, makes
1896
+ * the grid a drop target for `.csv`/`.tsv` files, and reads a pasted
1897
+ * spreadsheet block, each opening a preview the user confirms. An object tunes
1898
+ * the affordances. Off by default; the `grid.import` API is always present.
1899
+ * Import is a client-side data operation, so it applies to a memory grid.
1900
+ */
1901
+ import?: boolean | ImportSettings;
1902
+ /**
1903
+ * Enable the built-in row-delete gesture (§18.4, BACKLOG-0000968) — the
1904
+ * Delete/Backspace key on selected rows and a "Delete row" cell-menu item —
1905
+ * and the `grid.edit.deleteRows` API. Off by default, because deleting data
1906
+ * on a keystroke is destructive and opt-in. Every deletion flows through the
1907
+ * cancellable `beforeDelete` event, so a handler can confirm or veto it, on a
1908
+ * memory-source grid as well as a remote one.
1909
+ */
1910
+ rowDelete?: boolean;
1886
1911
  /**
1887
1912
  * The header's 3-dot menu, and the right-click menu on a column heading.
1888
1913
  * `false` suppresses both. A function supplies custom items, receiving the
@@ -2540,8 +2565,8 @@ export interface StatisticsApi {
2540
2565
  * verdict from nowhere. Non-numeric columns are returned under `skipped`.
2541
2566
  */
2542
2567
  anomalies(opts?: { columns?: string[];
2543
- method?: 'modifiedZScore' | 'iqr' | 'mahalanobis';
2544
- threshold?: number; k?: number; p?: number }): AnomalyReport;
2568
+ method?: 'modifiedZScore' | 'iqr' | 'mahalanobis' | 'rollingModifiedZScore' | 'rollingIqr';
2569
+ threshold?: number; k?: number; p?: number; windowLen?: number; minPeriods?: number }): AnomalyReport;
2545
2570
  /**
2546
2571
  * Which columns differ most between the filtered subset and the whole
2547
2572
  * population it was drawn from, ranked by effect size — never by a p-value.
@@ -2813,6 +2838,52 @@ export function mahalanobis(
2813
2838
  distances: (number | null)[]; squared: (number | null)[]; flags: boolean[];
2814
2839
  flagged: number } | null;
2815
2840
 
2841
+ /**
2842
+ * The rolling (windowed) anomaly methods (BACKLOG-0000954): the robust modified
2843
+ * z-score and Tukey's IQR fences, each computed over a trailing window rather
2844
+ * than the whole series, for live monitoring where a drift or a shifted regime
2845
+ * must not poison a global baseline.
2846
+ */
2847
+ export const ROLLING_ANOMALY_METHODS: readonly ('rollingModifiedZScore' | 'rollingIqr')[];
2848
+
2849
+ /**
2850
+ * Rolling (windowed) anomaly detection (BACKLOG-0000954): judge every reading
2851
+ * against a causal trailing window ending at it — the current point and the
2852
+ * `window − 1` before it — so a spike is caught against its recent neighbours and
2853
+ * a slow drift does not permanently poison the baseline. With a window at least
2854
+ * as long as the series (and `minPeriods` of 1) the last point's score equals the
2855
+ * static {@link modifiedZScores} score. A non-finite reading, a too-short window
2856
+ * (`minPeriods`) or a zero-MAD window yields a null score and no flag.
2857
+ */
2858
+ export function rollingAnomalies(
2859
+ values: ArrayLike<number>,
2860
+ opts?: {
2861
+ method?: 'rollingModifiedZScore' | 'rollingIqr';
2862
+ windowLen?: number; threshold?: number; k?: number; minPeriods?: number;
2863
+ },
2864
+ ): { method: string; windowLen: number; minPeriods: number; threshold: number; k: number;
2865
+ scores: (number | null)[]; flags: boolean[]; flagged: number };
2866
+
2867
+ /**
2868
+ * Build a Data Router alert condition from an anomaly detector (BACKLOG-0000954):
2869
+ * a `(rows) => signal` for the router's existing `router.alert(value, condition,
2870
+ * handler)` (BACKLOG-0000909), so live monitoring reuses the router's
2871
+ * partitioning, debounce and rising-edge re-arm rather than duplicating any of
2872
+ * it. Reads one numeric `field` off each row, runs the chosen detector, and
2873
+ * returns the flagged rows and scores when anything is anomalous or `false` when
2874
+ * nothing is. `orderBy` names the axis rolling methods window on; `latest` signals
2875
+ * only when the newest reading is the anomaly.
2876
+ */
2877
+ export function anomalyCondition(
2878
+ opts: {
2879
+ field: string;
2880
+ method?: 'modifiedZScore' | 'iqr' | 'rollingModifiedZScore' | 'rollingIqr';
2881
+ orderBy?: string; latest?: boolean;
2882
+ windowLen?: number; threshold?: number; k?: number; minPeriods?: number;
2883
+ },
2884
+ ): (rows: Iterable<Record<string, unknown>>) =>
2885
+ false | { method: string; field: string; flagged: { row: Record<string, unknown>; score: number | null }[] };
2886
+
2816
2887
  export type ShadowKind =
2817
2888
  | 'updates' | 'updatedAt' | 'sinceUpdate' | 'delta' | 'deltaPercent'
2818
2889
  | 'rate' | 'history' | 'firstValue' | 'streak'
@@ -3858,6 +3929,19 @@ export interface EditApi {
3858
3929
  * @returns the id the op is tracked under, or null when delete is not available
3859
3930
  */
3860
3931
  deleteRow(key: string): string | null;
3932
+ /**
3933
+ * Delete rows on a user gesture, through the cancellable `beforeDelete` event
3934
+ * (§18.4, BACKLOG-0000968) — what the built-in Delete-key and "Delete row"
3935
+ * gestures call. Unlike {@link deleteRow}, `beforeDelete` fires on a
3936
+ * memory-source grid too, so the row can be confirmed or vetoed there. Off
3937
+ * until `config.rowDelete` opts in; the keys default to the row selection.
3938
+ * Returns the keys removed (empty on a veto or when disabled), or a Promise of
3939
+ * them when a `beforeDelete` handler deferred.
3940
+ * @param keys the row keys; defaults to the current selection
3941
+ * @param opts `origin` names the provenance carried onto the events
3942
+ * @returns the removed keys, or a Promise of them on the async path
3943
+ */
3944
+ deleteRows(keys?: string | string[], opts?: { origin?: string }): string[] | Promise<string[]>;
3861
3945
  /**
3862
3946
  * Report the outcome of an optimistic structural write (§5.3), the counterpart
3863
3947
  * to {@link settle} for `edit.confirm: 'manual'` over a backend that
@@ -3907,6 +3991,65 @@ export interface ExportApi {
3907
3991
  print(): void;
3908
3992
  }
3909
3993
 
3994
+ /** How `config.import` tunes the DOM import affordances (§14). */
3995
+ export interface ImportSettings {
3996
+ /** Add the cell-menu item and open a file picker for CSV/TSV. Default true. */
3997
+ file?: boolean;
3998
+ /** Make the grid a drop target for `.csv`/`.tsv` files. Default true. */
3999
+ drop?: boolean;
4000
+ /** Read a pasted spreadsheet block into a preview. Default true. */
4001
+ paste?: boolean;
4002
+ /** How a confirmed import lands: append (default) or replace the dataset. */
4003
+ mode?: 'append' | 'replace';
4004
+ }
4005
+
4006
+ /** One source column as understood by the importer, after type inference (§14). */
4007
+ export interface ImportColumn {
4008
+ /** The heading as written in the file. */
4009
+ source: string;
4010
+ /** The column's position in each row. */
4011
+ index: number;
4012
+ /** The grid field this column maps onto; empty to exclude it from the import. */
4013
+ field: string;
4014
+ /** The inferred (or grid-dictated) type used to coerce the column's values. */
4015
+ type: string;
4016
+ /** A few non-blank sample values, for the preview. */
4017
+ samples: string[];
4018
+ /** Whether the heading matched one of the grid's own columns. */
4019
+ matched: boolean;
4020
+ }
4021
+
4022
+ /** What a preview carries — everything a confirm dialog needs (§14). */
4023
+ export interface ImportPreview {
4024
+ /** The delimiter that was used, detected or supplied. */
4025
+ delimiter: string;
4026
+ /** The source column headings. */
4027
+ header: string[];
4028
+ /** The per-column mapping and inference the user may edit before confirming. */
4029
+ columns: ImportColumn[];
4030
+ /** Every mapped, coerced record the import would add. */
4031
+ records: Record<string, unknown>[];
4032
+ /** The leading records, for a preview table. */
4033
+ sample: Record<string, unknown>[];
4034
+ /** How many data rows the file holds. */
4035
+ rowCount: number;
4036
+ /** Anything worth flagging before confirming — a ragged file, a bad quote. */
4037
+ warnings: string[];
4038
+ }
4039
+
4040
+ /** Bringing rows in — the mirror of {@link ExportApi} (§14, BACKLOG-0000949). */
4041
+ export interface ImportApi {
4042
+ /** Parse delimited text into a preview, changing nothing. */
4043
+ preview(text: string, opts?: object): ImportPreview;
4044
+ /** Parse delimited text into coerced records — the inverse of `export.csv`. */
4045
+ csv(text: string, opts?: object): Record<string, unknown>[];
4046
+ /** Add or replace the grid's rows from text, a preview or records. */
4047
+ apply(
4048
+ input: string | ImportPreview | Record<string, unknown>[],
4049
+ opts?: { mode?: 'append' | 'replace' },
4050
+ ): ChangeResult | null;
4051
+ }
4052
+
3910
4053
  export interface SavedView {
3911
4054
  id: string;
3912
4055
  name: string;
@@ -4702,6 +4845,8 @@ export interface Grid {
4702
4845
  readonly scroll: ScrollApi;
4703
4846
  /** CSV, Excel and clipboard. */
4704
4847
  readonly export: ExportApi;
4848
+ /** Bringing rows in from CSV/TSV text, a file, the clipboard or a drop. */
4849
+ readonly import: ImportApi;
4705
4850
  /** Everything the user arranged, as a serialisable object. */
4706
4851
  readonly state: StateApi;
4707
4852
  /** The loading, empty and error surfaces drawn over the grid. */
@@ -5614,22 +5759,82 @@ export interface ChartAxis {
5614
5759
  * placed against the wrong scale, and is written into the accessible table as a
5615
5760
  * sentence.
5616
5761
  */
5762
+ /**
5763
+ * A trend or forecast overlay method (BACKLOG-0000952). Each name has aliases:
5764
+ * `linear` (also `lr`, `ols`, `regression`); `movingAverage` (also `ma`, `sma`,
5765
+ * `rolling`); `exponential` (also `ewma`, `ses`, `holt`, `smoothing`).
5766
+ */
5767
+ export type ChartTrendMethod = 'linear' | 'movingAverage' | 'exponential'
5768
+ | 'lr' | 'ols' | 'regression' | 'ma' | 'sma' | 'rolling'
5769
+ | 'ewma' | 'ses' | 'holt' | 'smoothing';
5770
+
5771
+ /** One trend or forecast overlay (BACKLOG-0000952). */
5772
+ export interface ChartTrend {
5773
+ /** The overlay method; `linear` by default. */
5774
+ method?: ChartTrendMethod;
5775
+ /**
5776
+ * For the linear method, how many steps to project the line past the data as a
5777
+ * dashed forecast. Ignored by the moving-average and exponential methods,
5778
+ * which have no slope to extrapolate.
5779
+ */
5780
+ forecast?: number;
5781
+ /** For the moving-average method, the trailing window in points; 3 by default. */
5782
+ window?: number;
5783
+ /** An alias for `window`. */
5784
+ period?: number;
5785
+ /** For the exponential method, single smoothing (`ses`) or Holt's level+trend (`holt`). */
5786
+ kind?: 'ses' | 'holt';
5787
+ /** For the exponential method, the level factor in `[0, 1]`; omit to fit it. */
5788
+ alpha?: number;
5789
+ /** For Holt's exponential smoothing, the trend factor in `[0, 1]`; omit to fit it. */
5790
+ beta?: number;
5791
+ /** `false` suppresses the R² label on a linear trend. */
5792
+ label?: boolean;
5793
+ }
5794
+
5795
+ /**
5796
+ * One declarative annotation (BACKLOG-0000744, extended by BACKLOG-0000953). A
5797
+ * reference or target line, a shaded band, a callout, or an `event` marker. Its
5798
+ * value is a constant `value` (or `from`/`to` for a band), or a `compute`
5799
+ * reduction of the data it annotates — `mean`, `median`, `min`, `max`, or `p95`
5800
+ * for a percentile — so it follows the data as the grid is filtered. A band with
5801
+ * `orient: 'vertical'` shades an x-range instead — an event window, a
5802
+ * maintenance period — and an `event` marker is a labelled vertical rule with a
5803
+ * flag at a position on the x axis. Every annotation names the axis it reads,
5804
+ * which on a dual-axis chart is what stops it being placed against the wrong
5805
+ * scale, and is written into the accessible table as a sentence — a vertical
5806
+ * marker and an event stating the position they sit at, because a screen-reader
5807
+ * user needs where and when, not only that a marker exists.
5808
+ */
5617
5809
  export interface ChartAnnotation {
5618
- /** The default is a reference line. */
5619
- kind?: 'line' | 'target' | 'band' | 'callout';
5810
+ /**
5811
+ * The default is a reference line. `event` is a labelled vertical marker with
5812
+ * a flag at a position on the x axis, described into the accessible table with
5813
+ * that position stated (BACKLOG-0000953).
5814
+ */
5815
+ kind?: 'line' | 'target' | 'band' | 'callout' | 'event';
5620
5816
  /** A constant value, for a line, target or callout's measure position. */
5621
5817
  value?: number;
5622
5818
  /** A reduction of the annotated data instead of a constant. */
5623
5819
  compute?: 'mean' | 'avg' | 'median' | 'min' | 'max' | string;
5624
- /** A band's two edges, each a constant or (with `fromCompute`/`toCompute`) computed. */
5625
- from?: number;
5626
- to?: number;
5820
+ /**
5821
+ * A band's two edges. On a horizontal band each is a measure value, a constant
5822
+ * or (with `fromCompute`/`toCompute`) computed. On a vertical band (`orient:
5823
+ * 'vertical'`, BACKLOG-0000953) each is an x position — a category or a number
5824
+ * — and the band shades the x-range between them: an event window, a
5825
+ * maintenance period, a recession.
5826
+ */
5827
+ from?: number | string;
5828
+ to?: number | string;
5627
5829
  fromCompute?: string;
5628
5830
  toCompute?: string;
5629
- /** A vertical line's or callout's x position: a category or a number. */
5831
+ /** A vertical line's, event marker's or callout's x position: a category or a number. */
5630
5832
  x?: unknown;
5631
5833
  at?: unknown;
5632
- /** Force a line vertical rather than horizontal. */
5834
+ /**
5835
+ * Force a line vertical rather than horizontal, or shade a `band` across an
5836
+ * x-range rather than a measure range (BACKLOG-0000953).
5837
+ */
5633
5838
  orient?: 'horizontal' | 'vertical';
5634
5839
  /** Which measure axis the annotation reads. */
5635
5840
  axis?: 'left' | 'right' | 'y2';
@@ -5722,6 +5927,23 @@ export interface ChartSpec {
5722
5927
  * through the order they happened to be listed in.
5723
5928
  */
5724
5929
  fit?: boolean | 'line';
5930
+ /**
5931
+ * Trend and forecast overlays (BACKLOG-0000952): a least-squares line, a
5932
+ * trailing moving average, or exponential smoothing, drawn over a line, area
5933
+ * or scatter chart. `true` draws a single linear trend; a method name or a
5934
+ * {@link ChartTrend} object configures one; an array draws several.
5935
+ *
5936
+ * The maths matches the core stats engine to the last digit — the same
5937
+ * least-squares fit, rolling window and exponential recursions — but is
5938
+ * computed locally in the charts module rather than imported, because the
5939
+ * in-tree bundler does not tree-shake and the import would inline the whole
5940
+ * statistics closure; a test asserts the parity. A `forecast` count projects
5941
+ * the linear line that many steps past the data, drawn dashed so it never
5942
+ * reads as a reading; a moving average and a smoothed level have no slope to
5943
+ * project, so `forecast` is ignored for them and the fact is stated in the
5944
+ * accessible description rather than faked.
5945
+ */
5946
+ trend?: boolean | ChartTrendMethod | ChartTrend | Array<ChartTrendMethod | ChartTrend>;
5725
5947
  /**
5726
5948
  * A pointwise confidence band, drawn as a varying-width ribbon beneath the fit
5727
5949
  * line (BACKLOG-0000812). Fed by a fitted model's own interval — the `band`
@@ -6397,10 +6619,28 @@ declare module 'lattice-grid/modules/gantt' {
6397
6619
  assignee?: string | string[];
6398
6620
  assignees?: string[];
6399
6621
  owner?: string;
6622
+ /**
6623
+ * Explicit resource assignments with fractional units (BACKLOG-0000948):
6624
+ * `units` is a multiplier where 1 is a full-time booking. Use this when a
6625
+ * task books a resource at less (or more) than 100%; a bare `assignee` is
6626
+ * `units: 1`.
6627
+ */
6628
+ assignments?: Array<{ resource?: string; name?: string; id?: string; units?: number }>;
6629
+ /** Leveling priority: a higher value is delayed last (default 0). */
6630
+ priority?: number;
6400
6631
  /** An explicit row height (px) for the split view; applied to both panels. */
6401
6632
  height?: number;
6402
6633
  }
6403
6634
 
6635
+ /**
6636
+ * Resource capacities for over-allocation detection and leveling
6637
+ * (BACKLOG-0000948): either a list of resources with a capacity (max
6638
+ * concurrent units, default 1) or a name→capacity map.
6639
+ */
6640
+ export type GanttResourceSpec =
6641
+ | Array<{ id?: string; name?: string; resource?: string; capacity?: number; maxUnits?: number; max?: number; units?: number }>
6642
+ | Record<string, number>;
6643
+
6404
6644
  /**
6405
6645
  * A typed dependency between two tasks (by id), with optional lag/lead. `type`
6406
6646
  * defaults to `'FS'`; either endpoint may be a leaf or a summary.
@@ -6460,6 +6700,47 @@ declare module 'lattice-grid/modules/gantt' {
6460
6700
  conflicts?: GanttConflict[];
6461
6701
  /** Whether a working-time calendar was applied. */
6462
6702
  calendar?: boolean;
6703
+ /** The resource over-allocations for this schedule (BACKLOG-0000948). */
6704
+ overAllocations?: GanttOverAllocation[];
6705
+ /** The full resource-load report for this schedule (BACKLOG-0000948). */
6706
+ resourceLoad?: GanttResourceLoad;
6707
+ }
6708
+
6709
+ /** One contiguous load segment for a resource: how many units are booked over a span. */
6710
+ interface GanttResourceSegment {
6711
+ start: number;
6712
+ end: number;
6713
+ load: number;
6714
+ taskIds: string[];
6715
+ }
6716
+
6717
+ /** A resource booked beyond its capacity across concurrent tasks (BACKLOG-0000948). */
6718
+ interface GanttOverAllocation {
6719
+ resource: string;
6720
+ capacity: number;
6721
+ start: number;
6722
+ end: number;
6723
+ load: number;
6724
+ taskIds: string[];
6725
+ }
6726
+
6727
+ /** The per-resource load and the over-allocations across a schedule (BACKLOG-0000948). */
6728
+ interface GanttResourceLoad {
6729
+ ok: boolean;
6730
+ resources: Array<{ resource: string; capacity: number; peak: number; segments: GanttResourceSegment[] }>;
6731
+ overAllocations: GanttOverAllocation[];
6732
+ byResource: Map<string, { capacity: number; peak: number; segments: GanttResourceSegment[] }>;
6733
+ }
6734
+
6735
+ /** The result of resource leveling: the shifted tasks and what moved (BACKLOG-0000948). */
6736
+ interface GanttLevelResult {
6737
+ ok: boolean;
6738
+ resolved?: boolean;
6739
+ tasks?: GanttTask[];
6740
+ schedule?: GanttSchedule;
6741
+ moves?: Array<{ id: string; from: number; to: number; delay: number }>;
6742
+ remaining?: GanttOverAllocation[];
6743
+ error?: { code: string; message: string };
6463
6744
  }
6464
6745
 
6465
6746
  /** A placement violation flagged by `findViolations`. */
@@ -6500,13 +6781,43 @@ declare module 'lattice-grid/modules/gantt' {
6500
6781
  readonly conflicts: GanttConflict[];
6501
6782
  readonly autoSchedule: boolean;
6502
6783
  readonly grid: unknown;
6784
+ /** The over-allocations from the latest schedule (BACKLOG-0000948). */
6785
+ readonly overAllocations: GanttOverAllocation[];
6786
+ /** The latest resource-load report, or null before a successful schedule (BACKLOG-0000948). */
6787
+ readonly resourceLoad: GanttResourceLoad | null;
6503
6788
  setTasks(tasks: GanttTask[]): GanttSchedule;
6504
6789
  setDependencies(deps: GanttDependency[]): GanttSchedule;
6505
6790
  applyEdit(patch: { id: string | number; start?: number; end?: number; duration?: number }, editOpts?: { writeBack?: boolean }): GanttSchedule;
6506
6791
  compute(): GanttSchedule;
6507
6792
  findViolations(): GanttViolation[];
6793
+ /**
6794
+ * Compute the resource load and over-allocations on demand (BACKLOG-0000948),
6795
+ * optionally overriding the capacities for this call.
6796
+ */
6797
+ resources(loadOpts?: { resources?: GanttResourceSpec; defaultCapacity?: number }): GanttResourceLoad;
6798
+ /**
6799
+ * Resolve resource over-allocation by shifting tasks later — resource
6800
+ * leveling (BACKLOG-0000948). Honours the CPM dependencies and the
6801
+ * working-time calendar. Mutates the model unless `{ dryRun: true }`; with
6802
+ * `{ writeBack: true }` and a bound grid the moved tasks are pushed through
6803
+ * the grid's edit surface.
6804
+ */
6805
+ level(levelOpts?: {
6806
+ dryRun?: boolean;
6807
+ writeBack?: boolean;
6808
+ priorityField?: string;
6809
+ maxIterations?: number;
6810
+ resources?: GanttResourceSpec;
6811
+ defaultCapacity?: number;
6812
+ }): GanttLevelResult;
6508
6813
  /** Export the scheduled tasks as CSV; `{ dates: true }` writes ISO dates. */
6509
6814
  toCSV(csvOpts?: { dates?: boolean }): string;
6815
+ /**
6816
+ * Export the current plan as Microsoft Project (MSPDI) XML (BACKLOG-0000950):
6817
+ * tasks, dependencies, constraints, baseline, resources and assignments, plus
6818
+ * the working-time calendar, serialised with the computed schedule.
6819
+ */
6820
+ toMSPDI(xmlOpts?: { hoursPerDay?: number; projectName?: string }): string;
6510
6821
  /**
6511
6822
  * The live consumer surface, mirroring `grid.rows.apply`, so a Data Router
6512
6823
  * can drive the Gantt like any other view. Keyed by the controller's rowKey.
@@ -6605,6 +6916,10 @@ declare module 'lattice-grid/modules/gantt' {
6605
6916
  deadline?: number | string | Date;
6606
6917
  /** A working-time calendar: skip weekends/holidays, durations in working days. */
6607
6918
  calendar?: GanttCalendar | null;
6919
+ /** Resource capacities for over-allocation detection and leveling (BACKLOG-0000948). */
6920
+ resources?: GanttResourceSpec;
6921
+ /** The capacity for a resource with none stated (default 1 = one full-time booking). */
6922
+ defaultCapacity?: number;
6608
6923
  autoSchedule?: boolean;
6609
6924
  grid?: unknown;
6610
6925
  /** Map task fields to grid column ids to enable drag write-back. */
@@ -6615,6 +6930,38 @@ declare module 'lattice-grid/modules/gantt' {
6615
6930
  element?: unknown;
6616
6931
  }): Gantt;
6617
6932
  export default createGantt;
6933
+
6934
+ /** The model {@link importMSPDI} returns and {@link exportMSPDI} takes. */
6935
+ interface GanttMSPDIModel {
6936
+ tasks: GanttTask[];
6937
+ dependencies?: GanttDependency[];
6938
+ resources?: GanttResourceSpec;
6939
+ projectStart?: number | string | Date;
6940
+ calendar?: GanttCalendar | null;
6941
+ schedule?: GanttSchedule;
6942
+ }
6943
+
6944
+ /**
6945
+ * Import a Microsoft Project (MSPDI) XML document (BACKLOG-0000950) into the
6946
+ * module's model: the task tree, typed dependencies with lag, constraints,
6947
+ * baseline, %complete, resources with capacity, the resource assignments, and
6948
+ * the working-time calendar. The result is ready to pass to {@link createGantt}.
6949
+ */
6950
+ export function importMSPDI(xml: string, opts?: { hoursPerDay?: number }): {
6951
+ ok: boolean;
6952
+ error?: string;
6953
+ tasks: GanttTask[];
6954
+ dependencies: GanttDependency[];
6955
+ resources: Array<{ id: string; name: string; capacity: number }>;
6956
+ projectStart?: number;
6957
+ calendar?: null | { workdays: number[]; holidays: number[] };
6958
+ };
6959
+
6960
+ /**
6961
+ * Export a Gantt model to Microsoft Project (MSPDI) XML (BACKLOG-0000950). A
6962
+ * scheduled model may be passed so start/finish dates are the computed ones.
6963
+ */
6964
+ export function exportMSPDI(model: GanttMSPDIModel, opts?: { hoursPerDay?: number; projectName?: string }): string;
6618
6965
  }
6619
6966
 
6620
6967
  declare module 'lattice-grid/modules/webcomponent' {