@toclocoinc/lattice-grid 1.34.0 → 1.35.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 (68) hide show
  1. package/README.md +1 -1
  2. package/docs/API.html +197 -1
  3. package/docs/api-detail.html +3 -2
  4. package/lattice-grid.d.ts +244 -12
  5. package/lattice-grid.esm.min.js +6 -4
  6. package/lattice-grid.min.cjs +6 -4
  7. package/lattice-grid.min.js +6 -4
  8. package/modules/angular.esm.min.js +2 -2
  9. package/modules/angular.min.cjs +2 -2
  10. package/modules/angular.min.js +2 -2
  11. package/modules/chart-alluvial.esm.min.js +1 -1
  12. package/modules/chart-arc.esm.min.js +1 -1
  13. package/modules/chart-bubblemap.esm.min.js +1 -1
  14. package/modules/chart-bump.esm.min.js +1 -1
  15. package/modules/chart-calendar.esm.min.js +1 -1
  16. package/modules/chart-decomposition.esm.min.js +1 -1
  17. package/modules/chart-diverging.esm.min.js +1 -1
  18. package/modules/chart-dumbbell.esm.min.js +1 -1
  19. package/modules/chart-fan.esm.min.js +1 -1
  20. package/modules/chart-hexbin.esm.min.js +1 -1
  21. package/modules/chart-hexmap.esm.min.js +1 -1
  22. package/modules/chart-icicle.esm.min.js +1 -1
  23. package/modules/chart-parallel.esm.min.js +1 -1
  24. package/modules/chart-ridgeline.esm.min.js +1 -1
  25. package/modules/chart-roc.esm.min.js +1 -1
  26. package/modules/chart-slope.esm.min.js +1 -1
  27. package/modules/chart-splom.esm.min.js +1 -1
  28. package/modules/chart-waffle.esm.min.js +1 -1
  29. package/modules/charts.esm.min.js +4 -4
  30. package/modules/charts.min.cjs +4 -4
  31. package/modules/charts.min.js +4 -4
  32. package/modules/data-router.esm.min.js +4 -4
  33. package/modules/data-router.min.cjs +4 -4
  34. package/modules/data-router.min.js +4 -4
  35. package/modules/devtools.esm.min.js +2 -2
  36. package/modules/devtools.min.cjs +2 -2
  37. package/modules/devtools.min.js +2 -2
  38. package/modules/dhtmlx-compat.esm.min.js +4 -4
  39. package/modules/dhtmlx-compat.min.cjs +4 -4
  40. package/modules/dhtmlx-compat.min.js +4 -4
  41. package/modules/gantt.esm.min.js +783 -40
  42. package/modules/gantt.min.cjs +783 -40
  43. package/modules/gantt.min.js +783 -40
  44. package/modules/htmx.esm.min.js +6 -4
  45. package/modules/htmx.min.cjs +6 -4
  46. package/modules/htmx.min.js +6 -4
  47. package/modules/kanban.esm.min.js +176 -23
  48. package/modules/kanban.min.cjs +176 -23
  49. package/modules/kanban.min.js +176 -23
  50. package/modules/kpi.esm.min.js +978 -0
  51. package/modules/kpi.min.cjs +981 -0
  52. package/modules/kpi.min.js +981 -0
  53. package/modules/mock-socket.esm.min.js +2 -2
  54. package/modules/mock-socket.min.cjs +2 -2
  55. package/modules/mock-socket.min.js +2 -2
  56. package/modules/react.esm.min.js +2 -2
  57. package/modules/react.min.cjs +2 -2
  58. package/modules/react.min.js +2 -2
  59. package/modules/svelte.esm.min.js +2 -2
  60. package/modules/svelte.min.cjs +2 -2
  61. package/modules/svelte.min.js +2 -2
  62. package/modules/vue.esm.min.js +2 -2
  63. package/modules/vue.min.cjs +2 -2
  64. package/modules/vue.min.js +2 -2
  65. package/modules/webcomponent.esm.min.js +6 -4
  66. package/modules/webcomponent.min.cjs +6 -4
  67. package/modules/webcomponent.min.js +6 -4
  68. package/package.json +1 -1
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.34.0, type declarations
2
+ * Lattice Grid 1.35.0, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -6276,21 +6276,43 @@ declare module 'lattice-grid/modules/gantt' {
6276
6276
  /** One of the four dependency link types (finish-to-start, start-to-start, finish-to-finish, start-to-finish). */
6277
6277
  export type GanttLinkType = 'FS' | 'SS' | 'FF' | 'SF';
6278
6278
 
6279
+ /** A scheduling constraint: pin the start, pin the finish, or schedule as late as possible. */
6280
+ export type GanttConstraintType =
6281
+ | 'must-start-on' | 'must-finish-on' | 'as-late-as-possible' | 'MSO' | 'MFO' | 'ALAP';
6282
+
6283
+ /** A working-time calendar: a Monday–Friday preset, or explicit working weekdays and holidays. */
6284
+ export type GanttCalendar =
6285
+ | 'weekends'
6286
+ | { workdays?: number[]; holidays?: Array<string | number | Date> };
6287
+
6279
6288
  /**
6280
- * A task in a Gantt plan. Give a `duration` or a numeric `start`+`end` (one is
6281
- * derived from the other). `milestone: true` (or `duration: 0`) is a
6282
- * zero-duration point. `parent` nests a task under a summary task, whose window
6283
- * and progress are DERIVED from its children rather than scheduled.
6289
+ * A task in a Gantt plan. Give a `duration` or a `start`+`end` (a day-number,
6290
+ * ISO date string or `Date`; one is derived from the other). `milestone: true`
6291
+ * (or `duration: 0`) is a zero-duration point. `parent` nests a task under a
6292
+ * summary, whose window and progress are DERIVED from its children.
6293
+ * `baselineStart`/`baselineEnd` (host-stored) drive planned-vs-actual variance;
6294
+ * `constraint` pins or pulls the task; `assignee` and `height` feed the split
6295
+ * view's grid panel.
6284
6296
  */
6285
6297
  export interface GanttTask {
6286
6298
  id: string | number;
6287
6299
  name?: string;
6288
- start?: number;
6289
- end?: number;
6300
+ start?: number | string | Date;
6301
+ end?: number | string | Date;
6290
6302
  duration?: number;
6291
6303
  percentComplete?: number;
6292
6304
  milestone?: boolean;
6293
6305
  parent?: string | number;
6306
+ baselineStart?: number | string | Date;
6307
+ baselineEnd?: number | string | Date;
6308
+ baseline?: { start?: number | string | Date; end?: number | string | Date };
6309
+ constraint?: GanttConstraintType;
6310
+ constraintDate?: number | string | Date;
6311
+ assignee?: string | string[];
6312
+ assignees?: string[];
6313
+ owner?: string;
6314
+ /** An explicit row height (px) for the split view; applied to both panels. */
6315
+ height?: number;
6294
6316
  }
6295
6317
 
6296
6318
  /**
@@ -6320,6 +6342,21 @@ declare module 'lattice-grid/modules/gantt' {
6320
6342
  isSummary: boolean;
6321
6343
  isMilestone: boolean;
6322
6344
  children: string[];
6345
+ /** The planned (baseline) window, present only when the task carries a baseline. */
6346
+ baselineStart?: number | null;
6347
+ baselineEnd?: number | null;
6348
+ /** Variance vs the baseline (actual − planned, day-numbers); a positive value is a slip. */
6349
+ startVariance?: number | null;
6350
+ finishVariance?: number | null;
6351
+ durationVariance?: number | null;
6352
+ }
6353
+
6354
+ /** An unhonourable scheduling constraint, reported rather than obeyed. */
6355
+ interface GanttConflict {
6356
+ id: string;
6357
+ type: string;
6358
+ at: number | null;
6359
+ earliestFeasible: number;
6323
6360
  }
6324
6361
 
6325
6362
  /** A CPM schedule result: per-task dates/float and the critical path, or an error. */
@@ -6333,6 +6370,10 @@ declare module 'lattice-grid/modules/gantt' {
6333
6370
  projectStart?: number;
6334
6371
  projectFinish?: number;
6335
6372
  projectDuration?: number;
6373
+ /** Constraints a predecessor made infeasible (empty when all are satisfied). */
6374
+ conflicts?: GanttConflict[];
6375
+ /** Whether a working-time calendar was applied. */
6376
+ calendar?: boolean;
6336
6377
  }
6337
6378
 
6338
6379
  /** A placement violation flagged by `findViolations`. */
@@ -6355,7 +6396,7 @@ declare module 'lattice-grid/modules/gantt' {
6355
6396
  * and the zero-float critical path, with summaries derived from their children,
6356
6397
  * milestones scheduled as points, and dependency cycles refused (never looped).
6357
6398
  */
6358
- export function computeSchedule(tasks: GanttTask[], deps?: GanttDependency[], options?: { projectStart?: number; deadline?: number }): GanttSchedule;
6399
+ export function computeSchedule(tasks: GanttTask[], deps?: GanttDependency[], options?: { projectStart?: number | string | Date; deadline?: number | string | Date; calendar?: GanttCalendar | null }): GanttSchedule;
6359
6400
 
6360
6401
  /** The tasks placed earlier than their earliest feasible start (manual validation). */
6361
6402
  export function findViolations(tasks: GanttTask[], schedule: GanttSchedule): GanttViolation[];
@@ -6369,6 +6410,8 @@ declare module 'lattice-grid/modules/gantt' {
6369
6410
  readonly dependencies: GanttDependency[];
6370
6411
  readonly schedule: GanttSchedule | null;
6371
6412
  readonly critical: string[];
6413
+ /** Constraints the latest schedule could not honour (empty when all are satisfied). */
6414
+ readonly conflicts: GanttConflict[];
6372
6415
  readonly autoSchedule: boolean;
6373
6416
  readonly grid: unknown;
6374
6417
  setTasks(tasks: GanttTask[]): GanttSchedule;
@@ -6423,6 +6466,36 @@ declare module 'lattice-grid/modules/gantt' {
6423
6466
  /** Days a keyboard arrow moves/resizes a task (default 1). */
6424
6467
  moveStep?: number;
6425
6468
  }): unknown;
6469
+ /**
6470
+ * Mount the JOINED split view (BACKLOG-0000938): one continuous, row-aligned
6471
+ * surface with a left task-grid panel (Task Name tree with expand/collapse,
6472
+ * assignee avatars, a circular % ring, plus any host columns) and the right
6473
+ * timeline, sharing a single vertical scroll so every grid row lines up
6474
+ * exactly with its bar row. The timeline scrolls horizontally on its own.
6475
+ * Composes the controller's schedule; makes no change to grid core.
6476
+ */
6477
+ mountSplit(container: unknown, options?: {
6478
+ height?: number;
6479
+ rowHeight?: number;
6480
+ headerHeight?: number;
6481
+ gridWidth?: number;
6482
+ indent?: number;
6483
+ zoom?: 'day' | 'week' | 'month' | 'quarter' | number;
6484
+ today?: number;
6485
+ nonWorking?: 'weekends' | ((day: number) => boolean);
6486
+ calendar?: GanttCalendar | null;
6487
+ showArrows?: boolean;
6488
+ showProgress?: boolean;
6489
+ showBaseline?: boolean;
6490
+ barLabel?: 'name' | 'percent' | 'dates' | 'none' | ((task: GanttScheduledTask) => string);
6491
+ columns?: Array<{ key: string; title?: string; width?: number; kind?: 'name' | 'assignee' | 'progress'; render?: (task: GanttScheduledTask, ctx: { rawTask: GanttTask; depth: number }) => unknown }>;
6492
+ }): unknown;
6493
+ /**
6494
+ * Capture a baseline (planned) snapshot of the current schedule as HOST data
6495
+ * (this does not mutate the tasks). Store it and feed it back as
6496
+ * `baselineStart`/`baselineEnd` task fields to get variance and ghost bars.
6497
+ */
6498
+ captureBaseline(): Array<{ id: string; baselineStart: number; baselineEnd: number; baselineDuration: number }>;
6426
6499
  /** Detach the mounted view, if any. The host still owns the container. */
6427
6500
  unmount(): void;
6428
6501
  /** The mounted view, or null. */
@@ -6440,9 +6513,12 @@ declare module 'lattice-grid/modules/gantt' {
6440
6513
  export function createGantt(opts?: {
6441
6514
  tasks?: GanttTask[];
6442
6515
  dependencies?: GanttDependency[];
6443
- projectStart?: number;
6444
- /** A project deadline (day-number); tasks that cannot meet it get negative float. */
6445
- deadline?: number;
6516
+ /** The schedule anchor: a day-number, ISO date string or Date. It only sets the floor a task with no predecessor starts on; it does not change how the schedule is computed. */
6517
+ projectStart?: number | string | Date;
6518
+ /** A project deadline (a day-number, ISO string or Date); tasks that cannot meet it get negative float. */
6519
+ deadline?: number | string | Date;
6520
+ /** A working-time calendar: skip weekends/holidays, durations in working days. */
6521
+ calendar?: GanttCalendar | null;
6446
6522
  autoSchedule?: boolean;
6447
6523
  grid?: unknown;
6448
6524
  /** Map task fields to grid column ids to enable drag write-back. */
@@ -6789,8 +6865,16 @@ declare module 'lattice-grid/modules/kanban' {
6789
6865
  swimlanes?: boolean;
6790
6866
  /** Explicit lane definitions; otherwise lanes come from the distinct swimlane values. */
6791
6867
  lanes?: (string | { id: string; title?: string })[];
6868
+ /** An explicit lane order by id (also set by a lane-header-drag reorder). */
6869
+ laneOrder?: string[];
6870
+ /** Enforce `wipLimit` as a hard gate: a move that would exceed it is refused (default false). */
6871
+ enforceWip?: boolean;
6872
+ /** A custom card template: return an HTML string or a DOM node to own the whole card body. */
6873
+ cardRenderer?: (card: KanbanCard, ctx: { column: KanbanColumn; readonly: boolean; el: HTMLElement; doc: Document }) => string | Node | void;
6792
6874
  sprintProperty?: string;
6793
6875
  epicProperty?: string;
6876
+ /** A configurable sprint dataset: the canonical sprint list (order + titles), shown even when empty. */
6877
+ sprints?: (string | { id: unknown; title?: string })[];
6794
6878
  /** The initially selected sprint id, `Kanban.BACKLOG`, or undefined for all. */
6795
6879
  sprint?: unknown;
6796
6880
  /** The initially selected epic id, or undefined for all. */
@@ -6933,6 +7017,10 @@ declare module 'lattice-grid/modules/kanban' {
6933
7017
  reorderColumns(order: string[]): Kanban;
6934
7018
  /** Move one column before another (or to the end); emits `column:reorder`. */
6935
7019
  moveColumn(id: string, beforeId: string | null): Kanban;
7020
+ /** Reorder the swimlanes to the given id order (emits `swimlane:reorder`). */
7021
+ reorderLanes(order: string[]): Kanban;
7022
+ /** Move one swimlane before another (or to the end); emits `swimlane:reorder`. */
7023
+ moveLane(id: string, beforeId: string | null): Kanban;
6936
7024
  /** Set a predicate filter over cards, or clear it with null. */
6937
7025
  setFilter(fn: ((row: KanbanRow, card: KanbanCard) => boolean) | null): Kanban;
6938
7026
  /** Set the quick-filter text matched across card fields. */
@@ -6947,8 +7035,10 @@ declare module 'lattice-grid/modules/kanban' {
6947
7035
  showBacklog(): Kanban;
6948
7036
  /** Select the shown epic (undefined for all); emits `epic:changed`. */
6949
7037
  setEpic(epic: unknown): Kanban;
6950
- /** The distinct sprint values (the switcher's options). */
7038
+ /** The distinct sprint values (the switcher's options); a configured `sprints` dataset pins the order. */
6951
7039
  sprints(): unknown[];
7040
+ /** The sprint dataset as `{ id, title }` descriptors — the configured list plus any data-only sprint. */
7041
+ sprintDefs(): { id: unknown; title: string }[];
6952
7042
  /** The distinct epic values. */
6953
7043
  epics(): unknown[];
6954
7044
  /** Roll rows up by a property: per-bucket count, points, done and progress. */
@@ -6990,3 +7080,145 @@ declare module 'lattice-grid/modules/kanban' {
6990
7080
  export function createKanban(el: HTMLElement | null, config?: KanbanConfig): Kanban;
6991
7081
  export default createKanban;
6992
7082
  }
7083
+
7084
+ declare module 'lattice-grid/modules/kpi' {
7085
+ /** A row backing a KPI aggregate: any object. Its identity comes from `rowKey`. */
7086
+ type KPIRow = Record<string, unknown>;
7087
+
7088
+ /** The aggregation kinds a tile can compute. `custom` is a host reducer over the rows. */
7089
+ type KPIAggregation = 'sum' | 'avg' | 'min' | 'max' | 'count' | 'countDistinct' | 'custom';
7090
+
7091
+ /** Number formatting for a tile value. `percent` treats the value as a ratio (0.42 → 42%). */
7092
+ type KPIFormat =
7093
+ | 'number' | 'currency' | 'percent' | 'compact'
7094
+ | { type?: 'number' | 'currency' | 'percent' | 'compact'; decimals?: number; currency?: string; locale?: string };
7095
+
7096
+ /**
7097
+ * A semantic threshold: two cut points and a direction. `higherIsBetter` (the
7098
+ * default) makes a value at/above `warn` good, at/above `critical` a warning,
7099
+ * below it critical; `lowerIsBetter` mirrors it. Colour is a host concern.
7100
+ */
7101
+ interface KPIThresholds {
7102
+ warn: number;
7103
+ critical: number;
7104
+ direction?: 'higherIsBetter' | 'lowerIsBetter';
7105
+ }
7106
+
7107
+ /** An explicit band: the `status` of the first band whose half-open `[min, max)` contains the value. */
7108
+ interface KPIBand {
7109
+ min?: number;
7110
+ max?: number;
7111
+ status: 'good' | 'warn' | 'critical';
7112
+ }
7113
+
7114
+ /** An optional sparkline series: the `y` field plotted in order of the `x` field (or insertion). */
7115
+ interface KPISparkline {
7116
+ x?: string;
7117
+ y: string | ((row: KPIRow) => unknown);
7118
+ }
7119
+
7120
+ /** One tile: an aggregate over the routed rows, with optional filter, format, threshold and trend. */
7121
+ interface KPITile {
7122
+ /** A stable identity for the tile (defaults to the label, then the index). */
7123
+ id?: string;
7124
+ /** The tile's accessible label. */
7125
+ label?: string;
7126
+ /** The aggregation kind, or a reducer `(rows, tile) => value` for a custom tile. */
7127
+ aggregation?: KPIAggregation | ((rows: KPIRow[], tile: object) => unknown);
7128
+ /** The reducer for a `custom` aggregation, when `aggregation` is the string `'custom'`. */
7129
+ compute?: (rows: KPIRow[], tile: object) => unknown;
7130
+ /** The field the aggregation reads (a path or accessor). Ignored by `count`. */
7131
+ field?: string | ((row: KPIRow) => unknown);
7132
+ /** A predicate limiting the rows this tile aggregates. */
7133
+ filter?: (row: KPIRow) => boolean;
7134
+ /** Value formatting. */
7135
+ format?: KPIFormat;
7136
+ /** A comparison target rendered alongside the value. */
7137
+ target?: number;
7138
+ /** A baseline the tile's delta is measured against. */
7139
+ baseline?: number;
7140
+ /** Threshold bands, either two cut points or an explicit band list. */
7141
+ thresholds?: KPIThresholds;
7142
+ /** Explicit status bands (an alternative to `thresholds`). */
7143
+ bands?: KPIBand[];
7144
+ /** A trend sparkline series. */
7145
+ sparkline?: KPISparkline | string;
7146
+ }
7147
+
7148
+ /** A computed tile, as it appears in the model. */
7149
+ interface KPITileModel {
7150
+ id: string;
7151
+ label: string;
7152
+ aggregation: string;
7153
+ field?: string;
7154
+ value: unknown;
7155
+ formatted: string;
7156
+ status: 'good' | 'warn' | 'critical' | null;
7157
+ target?: number;
7158
+ baseline?: number;
7159
+ delta: number | null;
7160
+ deltaPercent: number | null;
7161
+ deltaFormatted?: string;
7162
+ count: number;
7163
+ sparkline: number[] | null;
7164
+ }
7165
+
7166
+ /** The payload every tile event carries. */
7167
+ interface KPIEvent {
7168
+ tile: KPITileModel;
7169
+ id: string;
7170
+ originalEvent?: unknown;
7171
+ }
7172
+
7173
+ /** KPI panel configuration. */
7174
+ interface KPIConfig {
7175
+ rows?: KPIRow[];
7176
+ grid?: unknown;
7177
+ rowKey?: string | ((row: KPIRow) => unknown);
7178
+ tiles?: KPITile[];
7179
+ columns?: number;
7180
+ ariaLabel?: string;
7181
+ nullText?: string;
7182
+ onTileClick?: (event: KPIEvent) => void;
7183
+ onTileDblClick?: (event: KPIEvent) => void;
7184
+ onTileContextMenu?: (event: KPIEvent) => void;
7185
+ onChange?: (event: { model: { tiles: KPITileModel[] } }) => void;
7186
+ }
7187
+
7188
+ /** The keyed-diff consumer surface a KPI panel shares with a grid, so a Data Router routes to it directly. */
7189
+ interface KPIRows {
7190
+ apply(change: { add?: KPIRow[]; update?: KPIRow[]; remove?: unknown[] }): void;
7191
+ forEach(fn: (row: KPIRow, key: unknown) => void): void;
7192
+ readonly count: number;
7193
+ }
7194
+
7195
+ /**
7196
+ * A KPI / stat-tile panel: a grid of aggregate tiles over a dataset. It
7197
+ * consumes data through the same keyed-diff `rows.apply` contract a grid
7198
+ * exposes, so `dataRouter.attach(value, kpi)` drives it like any other viewer,
7199
+ * updating each tile incrementally from the routed delta.
7200
+ */
7201
+ interface KPI {
7202
+ readonly el: unknown | null;
7203
+ readonly rowKey: string | ((row: KPIRow) => unknown);
7204
+ rows: KPIRows;
7205
+ tiles(): KPITileModel[];
7206
+ tile(id: string): KPITileModel | undefined;
7207
+ value(id: string): unknown;
7208
+ setRows(rows: KPIRow[]): KPI;
7209
+ refresh(): KPI;
7210
+ getState(): object;
7211
+ setState(snapshot: object): KPI;
7212
+ on(name: string, fn: (event: KPIEvent) => void): () => void;
7213
+ off(name: string, fn: (event: KPIEvent) => void): void;
7214
+ destroy(): void;
7215
+ }
7216
+
7217
+ /**
7218
+ * Create a KPI / stat-tile panel over rows or a bound grid. Pass a DOM element
7219
+ * to render into, or `null` for a headless panel that computes the same tile
7220
+ * model without a DOM.
7221
+ */
7222
+ export function createKPI(el: HTMLElement | null, config?: KPIConfig): KPI;
7223
+ export default createKPI;
7224
+ }