@toclocoinc/lattice-grid 1.54.0 → 1.56.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 (78) hide show
  1. package/README.md +6 -4
  2. package/docs/API.html +360 -62
  3. package/docs/api-detail.html +348 -15
  4. package/lattice-grid.d.ts +287 -27
  5. package/lattice-grid.esm.min.js +1610 -622
  6. package/lattice-grid.min.cjs +1610 -622
  7. package/lattice-grid.min.css +1 -1
  8. package/lattice-grid.min.js +1610 -622
  9. package/modules/ai.esm.min.js +19 -4
  10. package/modules/ai.min.cjs +19 -4
  11. package/modules/ai.min.js +19 -4
  12. package/modules/angular.esm.min.js +2 -2
  13. package/modules/angular.min.cjs +2 -2
  14. package/modules/angular.min.js +2 -2
  15. package/modules/chart-alluvial.esm.min.js +1 -1
  16. package/modules/chart-arc.esm.min.js +1 -1
  17. package/modules/chart-bubblemap.esm.min.js +1 -1
  18. package/modules/chart-bump.esm.min.js +1 -1
  19. package/modules/chart-calendar.esm.min.js +1 -1
  20. package/modules/chart-decomposition.esm.min.js +1 -1
  21. package/modules/chart-diverging.esm.min.js +1 -1
  22. package/modules/chart-dumbbell.esm.min.js +1 -1
  23. package/modules/chart-fan.esm.min.js +1 -1
  24. package/modules/chart-hexbin.esm.min.js +1 -1
  25. package/modules/chart-hexmap.esm.min.js +1 -1
  26. package/modules/chart-icicle.esm.min.js +1 -1
  27. package/modules/chart-parallel.esm.min.js +1 -1
  28. package/modules/chart-ridgeline.esm.min.js +1 -1
  29. package/modules/chart-roc.esm.min.js +1 -1
  30. package/modules/chart-slope.esm.min.js +1 -1
  31. package/modules/chart-splom.esm.min.js +1 -1
  32. package/modules/chart-waffle.esm.min.js +1 -1
  33. package/modules/charts.esm.min.js +115 -29
  34. package/modules/charts.min.cjs +115 -29
  35. package/modules/charts.min.js +115 -29
  36. package/modules/data-router.esm.min.js +37 -4
  37. package/modules/data-router.min.cjs +37 -4
  38. package/modules/data-router.min.js +37 -4
  39. package/modules/devtools.esm.min.js +2 -2
  40. package/modules/devtools.min.cjs +2 -2
  41. package/modules/devtools.min.js +2 -2
  42. package/modules/dhtmlx-compat.esm.min.js +4 -4
  43. package/modules/dhtmlx-compat.min.cjs +4 -4
  44. package/modules/dhtmlx-compat.min.js +4 -4
  45. package/modules/gantt.esm.min.js +32 -6
  46. package/modules/gantt.min.cjs +32 -6
  47. package/modules/gantt.min.js +32 -6
  48. package/modules/htmx.esm.min.js +1610 -622
  49. package/modules/htmx.min.cjs +1610 -622
  50. package/modules/htmx.min.js +1610 -622
  51. package/modules/kanban.esm.min.js +49 -9
  52. package/modules/kanban.min.cjs +49 -9
  53. package/modules/kanban.min.js +49 -9
  54. package/modules/kpi.esm.min.js +4141 -13
  55. package/modules/kpi.min.cjs +4141 -13
  56. package/modules/kpi.min.js +4141 -13
  57. package/modules/layout.esm.min.js +12 -8
  58. package/modules/layout.min.cjs +12 -8
  59. package/modules/layout.min.js +12 -8
  60. package/modules/mock-socket.esm.min.js +2 -2
  61. package/modules/mock-socket.min.cjs +2 -2
  62. package/modules/mock-socket.min.js +2 -2
  63. package/modules/react.esm.min.js +2 -2
  64. package/modules/react.min.cjs +2 -2
  65. package/modules/react.min.js +2 -2
  66. package/modules/svelte.esm.min.js +2 -2
  67. package/modules/svelte.min.cjs +2 -2
  68. package/modules/svelte.min.js +2 -2
  69. package/modules/tabs.esm.min.js +4 -4
  70. package/modules/tabs.min.cjs +4 -4
  71. package/modules/tabs.min.js +4 -4
  72. package/modules/vue.esm.min.js +2 -2
  73. package/modules/vue.min.cjs +2 -2
  74. package/modules/vue.min.js +2 -2
  75. package/modules/webcomponent.esm.min.js +1610 -622
  76. package/modules/webcomponent.min.cjs +1610 -622
  77. package/modules/webcomponent.min.js +1610 -622
  78. package/package.json +3 -2
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.54.0, type declarations
2
+ * Lattice Grid 1.56.0, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -250,11 +250,6 @@ export interface NumberFormat {
250
250
  * leaves the remainder in English rather than showing raw keys.
251
251
  */
252
252
  messages?: Record<string, string | Record<string, string>>;
253
- /**
254
- * Writing direction. Omit to settle it from the element's own `dir` and then
255
- * from `locale`: `ar`, `he`, `fa` and the rest resolve to `rtl`.
256
- */
257
- direction?: 'ltr' | 'rtl';
258
253
  scale?: number;
259
254
  }
260
255
 
@@ -631,7 +626,10 @@ export interface ColumnHeaderSpec {
631
626
  render?: string | RendererCtor;
632
627
  /** Props passed to `render` as `params.props`. */
633
628
  props?: Record<string, unknown>;
634
- /** A class, or classes, added to the heading cell. */
629
+ /**
630
+ * A class, or classes, added to the heading cell. A string may hold several
631
+ * space-separated tokens (`'a b'`), each applied individually.
632
+ */
635
633
  class?: string | string[];
636
634
  tooltip?: string;
637
635
  align?: Align;
@@ -1359,8 +1357,9 @@ export interface DerivedSourceConfig {
1359
1357
  * change on the parent re-derives the whole thing. `correlation` additionally
1360
1358
  * scans the rows once *per pair*, so N columns cost N·(N−1)/2 passes. Use
1361
1359
  * `refresh` (`'idle'` is the default; `'manual'` or a debounce in ms for an
1362
- * expensive analysis over a live feed) — see `docs/api-detail.html` for the
1363
- * measured figures.
1360
+ * expensive analysis over a live feed; under `'manual'` the host re-derives
1361
+ * by calling `rows.load()` on the derived grid) — see `docs/api-detail.html`
1362
+ * for the measured figures.
1364
1363
  *
1365
1364
  * Every row carries `n`, the rows the figure covered, because a derived
1366
1365
  * statistic travels into an export or a chart without its grid and "r = 0.98
@@ -1373,7 +1372,15 @@ export interface DerivedSourceConfig {
1373
1372
  */
1374
1373
  statistics?: DerivedStatistics;
1375
1374
 
1376
- /** When to re-derive. `idle` by default: coalesced to a frame. */
1375
+ /**
1376
+ * When to re-derive. `idle` by default: coalesced to a frame. A number
1377
+ * debounces by that many milliseconds; `live` re-derives on every change.
1378
+ * `manual` never re-derives on its own: the host triggers it by calling
1379
+ * `rows.load()`, with no argument, on the derived grid - from a Refresh
1380
+ * button, say. Each call re-reads `from` there and then and replaces the
1381
+ * rows; a derived grid takes its rows from `from`, so anything passed to
1382
+ * `load` is not used. Executed example: `docs/api-detail.html#derived-manual-refresh`.
1383
+ */
1377
1384
  refresh?: 'live' | 'idle' | 'manual' | number;
1378
1385
 
1379
1386
  /**
@@ -1571,9 +1578,20 @@ export interface DetailConfig {
1571
1578
  }
1572
1579
 
1573
1580
  export interface SelectionConfig {
1581
+ /** `'none'` also turns off `ranges` and `fillHandle` unless either is set explicitly alongside it. */
1574
1582
  mode?: 'none' | 'single' | 'multiple';
1575
1583
  checkbox?: boolean;
1576
1584
  headerCheckbox?: boolean;
1585
+ /**
1586
+ * Only the `checkbox` column may change row selection — a click anywhere
1587
+ * else in the row, and Space with focus anywhere but the checkbox, leave
1588
+ * selection untouched. Range and cell selection are unaffected either way.
1589
+ * For a host whose row click is bound to its own action (opening a record):
1590
+ * without this, that click also selects the row, so a later bulk action can
1591
+ * reach rows nobody chose. Off by default. `mode: 'none'` already refuses
1592
+ * every selection path regardless of this flag.
1593
+ */
1594
+ checkboxOnly?: boolean;
1577
1595
  groupSelectsChildren?: boolean;
1578
1596
  groupSelectsFiltered?: boolean;
1579
1597
  ranges?: boolean;
@@ -1708,8 +1726,13 @@ export interface GridConfig {
1708
1726
  * What identifies a row. Everything that survives a refresh (selection,
1709
1727
  * expansion, and edits in flight) is keyed on it, so it must be stable and
1710
1728
  * unique. A derived grid defaults to its own derived key.
1729
+ *
1730
+ * Three shapes: a field name (`'id'`, dot paths allowed); an array of field
1731
+ * names, joined into one composite key (`['tenantId', 'circuitId']`); or a
1732
+ * function of the row (`row => \`${row.tenantId}#${row.circuitId}\``),
1733
+ * itself allowed to return an array to the same effect.
1711
1734
  */
1712
- rowKey?: string | ((row: unknown) => string);
1735
+ rowKey?: string | string[] | ((row: unknown) => string | string[]);
1713
1736
  /** Where rows come from: memory, paged, remote, stream or derived. */
1714
1737
  source?: SourceConfig;
1715
1738
  /** How rows are ingested into the column store. */
@@ -1740,13 +1763,25 @@ export interface GridConfig {
1740
1763
  tree?: TreeConfig;
1741
1764
  /** The expandable panel beneath a row. */
1742
1765
  detail?: DetailConfig;
1743
- /** What the user may select, and how selection behaves across groups. */
1766
+ /**
1767
+ * What the user may select, and how selection behaves across groups.
1768
+ * The `'none'` shorthand is `{ mode: 'none' }` and behaves identically: no
1769
+ * row selection, and no cell ranges or fill handle either.
1770
+ */
1744
1771
  selection?: SelectionConfig | 'single' | 'multiple' | 'none';
1745
1772
  /** Editing, and how a change is committed and validated. */
1746
1773
  edit?: EditConfig | boolean;
1747
1774
  /** Page the rows rather than scrolling them. */
1748
1775
  pagination?: PaginationConfig | boolean;
1749
1776
  locale?: string;
1777
+ /**
1778
+ * Writing direction. Omit it, or say `'auto'`, to settle it from the
1779
+ * element's own computed `dir` and then from `locale`: `ar`, `he`, `fa` and
1780
+ * the rest resolve to `rtl`. In a right-to-left grid the logical alignments
1781
+ * `start`/`end` mirror while the physical `left`/`right` do not (see
1782
+ * {@link Align}).
1783
+ */
1784
+ direction?: 'ltr' | 'rtl' | 'auto';
1750
1785
  /**
1751
1786
  * IANA zone every date column formats in, e.g. 'Europe/London' or 'UTC'.
1752
1787
  * Omit to use each viewer's own zone. A column's own `format.timeZone` wins.
@@ -2155,7 +2190,12 @@ export interface GridConfig {
2155
2190
  * measured; it is about whether the ceiling applies.
2156
2191
  */
2157
2192
  autoHeight?: boolean | 'visible';
2158
- /** Sort, filters, grouping, widths and the rest, restored at construction. */
2193
+ /**
2194
+ * Sort, filters, grouping, widths and the rest, restored at construction.
2195
+ * Takes precedence over a saved view flagged `isDefault`: when both are
2196
+ * present, this wins outright and the default view is never applied — the
2197
+ * active view id stays `null`.
2198
+ */
2159
2199
  state?: GridState;
2160
2200
  /** Your licence key. Without one the grid renders in full and watermarks off localhost. */
2161
2201
  licence?: string;
@@ -2661,6 +2701,15 @@ export interface GridState {
2661
2701
  /** The banded-header tree, when the grid has one (BACKLOG-0000739). */
2662
2702
  columnGroups?: ColumnGroupState[];
2663
2703
  filters?: FilterSet;
2704
+ /**
2705
+ * The `where` predicates that were in force, as names only (BACKLOG-0001202).
2706
+ * A predicate is host code: it cannot be serialised into a view or restored
2707
+ * from one. `apply` reconciles these against what the host has registered and
2708
+ * reports every name it cannot honour rather than restoring a view that
2709
+ * silently shows more rows than the one that was saved. Absent when none is
2710
+ * registered.
2711
+ */
2712
+ where?: string[];
2664
2713
  quick?: string;
2665
2714
  sort?: SortEntry[];
2666
2715
  group?: string[];
@@ -2689,6 +2738,27 @@ export interface StateApplyReport {
2689
2738
  skipped: { key: string; reason: string }[];
2690
2739
  }
2691
2740
 
2741
+ /**
2742
+ * Every top-level section of a {@link GridState} bar `version` — the
2743
+ * vocabulary `state.apply`'s `skip` list, `StateApplyReport.applied` and
2744
+ * `StateChangedEvent.sections` all speak, derived from `GridState` itself so a
2745
+ * new section cannot appear in one and be missing from the others.
2746
+ */
2747
+ export type StateSection = Exclude<keyof GridState, 'version'>;
2748
+
2749
+ /**
2750
+ * What caused a `state:changed` (BACKLOG-0001182).
2751
+ *
2752
+ * `'user'` is a change to one part of the view — a sort, a filter, a column
2753
+ * moved, resized, pinned or hidden, a grouping, a page — whether it arrived as
2754
+ * a gesture or as the equivalent API call. `'apply'` is `state.apply()`,
2755
+ * including the restore an undo performs and a `config.state` seed at
2756
+ * construction. `'reset'` is `state.reset()`, and is the one a persistence
2757
+ * layer skips: saving the reset arrangement writes the default straight back
2758
+ * over the view the user had just abandoned.
2759
+ */
2760
+ export type StateChangeCause = 'user' | 'apply' | 'reset';
2761
+
2692
2762
  // ---------------------------------------------------------------------------
2693
2763
  // Conditional formatting (spec 8.12)
2694
2764
  // ---------------------------------------------------------------------------
@@ -4188,6 +4258,43 @@ export interface BeforeEvent extends GridEvent {
4188
4258
  reason: string | null;
4189
4259
  }
4190
4260
 
4261
+ /**
4262
+ * The `state:changed` event (BACKLOG-0001182).
4263
+ *
4264
+ * Fires once per logical state change, whether it began as a user gesture or
4265
+ * as a programmatic call, so view persistence is built on this one event
4266
+ * rather than on the ten individual ones — `reset()` raises those too, which
4267
+ * made a debounced save write the reset arrangement back.
4268
+ *
4269
+ * **Exactly one event per change.** A change that internally routes through
4270
+ * `state.apply()` — applying a saved view, an undo, a reset — announces itself
4271
+ * once, carrying the outermost cause rather than the inner mechanism's.
4272
+ *
4273
+ * **One known gap** (BACKLOG-0001235): a host predicate registered through
4274
+ * `filters.where(name, fn)` changes the `where` section and the rows on screen
4275
+ * without raising this event, so a persistence layer does not yet see it.
4276
+ */
4277
+ export interface StateChangedEvent extends GridEvent {
4278
+ /** Why the state changed. `'reset'` is the one a save should ignore. */
4279
+ cause: StateChangeCause;
4280
+ /**
4281
+ * Which sections moved, sorted and de-duplicated. For `'apply'` and
4282
+ * `'reset'` these are the sections the report applied; for `'user'`, the
4283
+ * sections the change touches.
4284
+ */
4285
+ sections: StateSection[];
4286
+ /**
4287
+ * The state that was applied — present for `'apply'` and `'reset'`, null for
4288
+ * `'user'`. A full capture on every gesture would put an unsanitised copy of
4289
+ * the state, hidden column ids and widths included, on the bus for every
4290
+ * listener; a host calls `grid.state.get()` when it decides to write, which
4291
+ * is permission-sanitised.
4292
+ */
4293
+ state: GridState | null;
4294
+ /** What an apply could not restore; null for `'user'`. */
4295
+ report: StateApplyReport | null;
4296
+ }
4297
+
4191
4298
  export type EventHandler = (e: GridEvent) => void;
4192
4299
  export type Unsubscribe = () => void;
4193
4300
 
@@ -4410,6 +4517,22 @@ export interface ColumnsApi {
4410
4517
  */
4411
4518
  decorate(id: string, decoration: DecorationName | DecorationSpec | null, opts?: { variant?: VariantSpec }): void;
4412
4519
  autoSize(ids?: string | string[]): void;
4520
+ /**
4521
+ * Size the visible resizable columns so that every column the grid draws,
4522
+ * together, exactly fills the width the cells occupy: the body viewport's
4523
+ * client width at the moment of the call, which excludes the vertical
4524
+ * scrollbar when the grid draws one and is the full inner width when it does
4525
+ * not. Columns it does not size keep their width and are taken out of that
4526
+ * width first: `resizable: false` columns and the grid's own selection
4527
+ * checkbox, detail expander, group and tree columns. The rest share what is
4528
+ * left in proportion to their current widths, within each `min`/`max`. If
4529
+ * that leaves less than their minimums, each is set to its minimum (never
4530
+ * below), the grid scrolls horizontally, and a `[lattice]` warning says so.
4531
+ * Rows given to `createGrid` or `rows.load()` before the call are counted.
4532
+ * One-shot: it sets fixed widths once (a `flex` column included) and does not
4533
+ * follow later changes; after a resize, or after rows arriving later bring a
4534
+ * vertical scrollbar in, call it again.
4535
+ */
4413
4536
  fit(): void;
4414
4537
  group(ids: string | string[]): void;
4415
4538
  pivot(ids: string | string[]): void;
@@ -4470,17 +4593,84 @@ export interface CellRange {
4470
4593
  columns: string[];
4471
4594
  }
4472
4595
 
4596
+ /**
4597
+ * How a `where` predicate is re-evaluated, whether `filters.clear()` may remove
4598
+ * it, and what the source may be told about it (BACKLOG-0001202).
4599
+ */
4600
+ export interface WhereOptions {
4601
+ /**
4602
+ * The columns the predicate reads, in the same spirit as `value.deps` on a
4603
+ * computed column (§8.4.2). Declared, the verdict is cached per row and
4604
+ * re-run only when one of these columns changes on that row. Omitted, the
4605
+ * predicate is treated as reading the whole row and is called on every pass —
4606
+ * never stale, and never skipped either.
4607
+ */
4608
+ deps?: string[];
4609
+ /**
4610
+ * Survive `filters.clear()`. For a predicate that is not the user's filter —
4611
+ * row-level permissions, tenant scoping — where a "clear filters" button must
4612
+ * never widen what the user can see.
4613
+ */
4614
+ pinned?: boolean;
4615
+ /**
4616
+ * A declarative twin of the predicate, pushed to the source while the function
4617
+ * stays as the residual. On a pushdown engine this narrows the fetch instead
4618
+ * of filtering a page client-side. It must be implied by the predicate: the
4619
+ * grid ANDs both, so a twin wider than the function costs only time, while one
4620
+ * narrower than it hides rows the function would have kept.
4621
+ */
4622
+ condition?: FilterSet;
4623
+ }
4624
+
4473
4625
  export interface FiltersApi {
4474
4626
  /** The quick filter's text and match mode, for restoring a control. */
4475
4627
  quickState(): { text: string; mode: string };
4476
4628
  get(): FilterSet;
4477
4629
  set(filters: FilterSet): void;
4630
+ /**
4631
+ * Drop the condition tree, the quick filter, and every `where` predicate that
4632
+ * was not registered `{ pinned: true }`.
4633
+ */
4478
4634
  clear(): void;
4479
4635
  quick(text: string): void;
4636
+ /** The names of the `where` predicates in force, in registration order. */
4637
+ where(): string[];
4638
+ /**
4639
+ * Register, replace or remove a named row predicate composed with the filter
4640
+ * set (BACKLOG-0001202).
4641
+ *
4642
+ * Registering *is* activating: there is no companion "a predicate is present"
4643
+ * flag to keep in sync, which is the failure mode this replaces. Several may
4644
+ * be in force at once under their own names, ANDed with each other and with
4645
+ * the declarative set, and removing one leaves the rest alone. The predicate
4646
+ * is handed the **data row**.
4647
+ *
4648
+ * grid.filters.where('visibleToMe', row => row.owner === me);
4649
+ * grid.filters.where('rateKnown', row => rates.has(row.ccy),
4650
+ * { deps: ['ccy'], pinned: true });
4651
+ * grid.filters.where('visibleToMe', null); // remove
4652
+ *
4653
+ * Only the names reach `filters.get()` and `state.get()`; the functions never
4654
+ * do.
4655
+ * @param name the name to register under
4656
+ * @param predicate the predicate, or null to remove it
4657
+ * @param opts re-evaluation, pinning, and the pushed-down twin
4658
+ */
4659
+ where(name: string, predicate: ((row: any) => boolean) | null, opts?: WhereOptions): void;
4660
+ /**
4661
+ * Re-run `where` predicates whose inputs changed where the grid could not see
4662
+ * it — a rate table that arrived late, a permission set that refreshed. The
4663
+ * out-of-band half of re-evaluation; `deps` is the half the grid observes for
4664
+ * itself. Together they replace the manual "filter again" call.
4665
+ * @param name the predicate to re-run; every one when omitted
4666
+ * @returns whether anything was re-run
4667
+ */
4668
+ reapply(name?: string): boolean;
4480
4669
  }
4481
4670
 
4482
4671
  export interface SortApi {
4483
4672
  get(): SortEntry[];
4673
+ /** Replace the sort model; an entry naming no known column is dropped with a warning. */
4484
4674
  set(entries: SortEntry[]): void;
4485
4675
  clear(): void;
4486
4676
  }
@@ -4724,6 +4914,11 @@ export interface SavedView {
4724
4914
  name: string;
4725
4915
  description: string;
4726
4916
  shared: boolean;
4917
+ /**
4918
+ * Applied on load when no `config.state` is given. `config.state` wins
4919
+ * outright over this flag: with both present, the default view is never
4920
+ * applied and the active view id stays `null`.
4921
+ */
4727
4922
  isDefault: boolean;
4728
4923
  /** Supplied in `config.views.saved`: listed apart, and not renamable or deletable. */
4729
4924
  builtin: boolean;
@@ -5356,7 +5551,11 @@ export interface FindApi {
5356
5551
  export interface StateApi {
5357
5552
  get(): GridState;
5358
5553
  apply(state: GridState, opts?: { skip?: (keyof GridState)[] }): StateApplyReport;
5359
- /** The state the grid started in, captured once after `config.state`. */
5554
+ /**
5555
+ * The grid as configured, without `config.state` — captured once, before
5556
+ * that seed is applied, so a view opened through `config.state` is never
5557
+ * itself mistaken for the default `reset()` returns to.
5558
+ */
5360
5559
  baseline(): GridState | null;
5361
5560
  /** Put the grid back the way it started, as one undoable step. */
5362
5561
  reset(): StateApplyReport | null;
@@ -5520,13 +5719,21 @@ export interface PaginationApi {
5520
5719
  /** What a cell-menu builder and a host item's `action` are handed. */
5521
5720
  export interface CellMenuParams {
5522
5721
  key: string;
5523
- colId: string;
5722
+ /**
5723
+ * The column under the pointer, or `null` when the row belongs to no column:
5724
+ * a right-click in the empty tail of a row beyond the last column
5725
+ * (BACKLOG-0001153), or on a group row, pivot group row or full-width row.
5726
+ * The grid-level menu stands in that case (BACKLOG-0001068).
5727
+ */
5728
+ colId: string | null;
5729
+ /** The cell's value; `undefined` when there is no column. */
5524
5730
  value: unknown;
5525
5731
  /** The row wrapper. */
5526
5732
  row: Row;
5527
5733
  /** Your original row object. */
5528
5734
  data: unknown;
5529
- column: ResolvedColumn;
5735
+ /** The resolved column; `undefined` when `colId` is `null`. */
5736
+ column: ResolvedColumn | undefined;
5530
5737
  index: number;
5531
5738
  grid: Grid;
5532
5739
  }
@@ -7911,7 +8118,15 @@ declare module 'lattice-grid/modules/webcomponent' {
7911
8118
  * is disconnected.
7912
8119
  */
7913
8120
  export function defineLatticeGrid(tag?: string): void;
7914
- export function createLatticeGridElement(deps?: object): unknown;
8121
+ /**
8122
+ * Build the `<lattice-grid>` element class. The one argument is the grid
8123
+ * factory the element creates its grid with — `createGrid`-shaped, and
8124
+ * defaulting to it — injectable for tests. Returns the class, or `null`
8125
+ * where `HTMLElement` is undefined (a Node import, a server-side pass).
8126
+ */
8127
+ export function createLatticeGridElement(
8128
+ factory?: (element: Element, config: GridConfig) => Grid,
8129
+ ): typeof HTMLElement | null;
7915
8130
  export const TAG_NAME: string;
7916
8131
  export const EVENT_PREFIX: string;
7917
8132
  export const ATTRIBUTE_CONFIG: Readonly<Record<string, unknown>>;
@@ -7933,7 +8148,14 @@ declare module 'lattice-grid/modules/htmx' {
7933
8148
  */
7934
8149
  export function createGrid(element: Element, config: GridConfig): Grid;
7935
8150
  export function autoInit(root?: ParentNode): Grid[];
7936
- export function attach(element: Element, config?: GridConfig): Grid;
8151
+ /**
8152
+ * Wire the htmx lifecycle events on a document: grids are built in each
8153
+ * swapped-in fragment, released before htmx detaches one, and their view
8154
+ * state carried across history navigation. Called once on import against
8155
+ * the global `document`; call it again only for another document. Returns
8156
+ * the function that removes every listener it installed.
8157
+ */
8158
+ export function attach(doc?: Document): () => void;
7937
8159
  export function initWithin(root: ParentNode): Grid[];
7938
8160
  export function destroyWithin(root: ParentNode): void;
7939
8161
  export function gridElementsWithin(root: ParentNode): Element[];
@@ -7941,9 +8163,41 @@ declare module 'lattice-grid/modules/htmx' {
7941
8163
  export function readTable(table: Element): { columns: Column[]; rows: unknown[] };
7942
8164
  export function rowsFromFragment(fragment: ParentNode): unknown[];
7943
8165
  export function rowsFromJson(text: string): unknown[];
7944
- export function ingestResponse(grid: Grid, response: unknown): void;
7945
- export function driveServerMode(grid: Grid, opts?: object): () => void;
7946
- export function driveInfiniteScroll(grid: Grid, opts?: object): () => void;
8166
+ /**
8167
+ * Parse a response into rows by its content type: JSON through
8168
+ * `rowsFromJson`, anything else through `rowsFromFragment` against the
8169
+ * columns given. The fragment arrives already parsed; this never touches
8170
+ * `DOMParser` or `innerHTML`. Returns the rows and, when the body carried
8171
+ * one, the total.
8172
+ */
8173
+ export function ingestResponse(
8174
+ response: { contentType: string; text?: string; fragment?: ParentNode },
8175
+ columns: { field: string }[],
8176
+ ): { rows: unknown[]; total: number | undefined };
8177
+ /**
8178
+ * Drive server-side sort and filter through htmx. `trigger` is the element
8179
+ * carrying the htmx request attributes (`hx-get`, `hx-target`,
8180
+ * `hx-trigger="lattice:query-changed"`); the grid's query parameters are
8181
+ * merged into that element's request and its response ingested. Returns the
8182
+ * function that detaches everything this attached.
8183
+ */
8184
+ export function driveServerMode(
8185
+ grid: Grid,
8186
+ trigger: Element,
8187
+ opts?: { columns?: { field: string }[] },
8188
+ ): () => void;
8189
+ /**
8190
+ * Load rows in chunks as the user nears the end of what is loaded.
8191
+ * `sentinelEl` is the element carrying `hx-get` and
8192
+ * `hx-trigger="revealed, lattice:scroll-near-end"`; `threshold` is how many
8193
+ * rows from the end counts as near (default 20). Returns the function that
8194
+ * detaches everything this attached.
8195
+ */
8196
+ export function driveInfiniteScroll(
8197
+ grid: Grid,
8198
+ sentinelEl: Element,
8199
+ opts?: { columns?: { field: string }[]; threshold?: number },
8200
+ ): () => void;
7947
8201
  export function driveOobUpdates(grid: Grid, opts?: object): () => void;
7948
8202
  export function serialiseState(grid: Grid): string;
7949
8203
  export function restoreState(grid: Grid, state: string): void;
@@ -8007,7 +8261,12 @@ declare module 'lattice-grid/modules/devtools' {
8007
8261
  destroy(): void;
8008
8262
  };
8009
8263
  export function expose(grid: Grid, name?: string): void;
8010
- export const CONSOLE_ACTIVATION: string;
8264
+ /**
8265
+ * Whether the console entry point is compiled in. A build that replaces the
8266
+ * activation token with `false` removes the global entirely; in every other
8267
+ * build this is `true`.
8268
+ */
8269
+ export const CONSOLE_ACTIVATION: boolean;
8011
8270
  export default createDevtools;
8012
8271
  }
8013
8272
 
@@ -9560,11 +9819,12 @@ declare module 'lattice-grid/modules/layout' {
9560
9819
  *
9561
9820
  * **Nothing moves**: no compaction runs, no placement changes, and the
9562
9821
  * payload container is the same DOM node throughout. **Escape restores it**,
9563
- * from anywhere inside the layout, unless a payload has already claimed the
9564
- * key — a grid marks every Escape as handled, at two independent sites (a
9565
- * focused body cell and a focused header cell), so from inside a maximised
9566
- * grid the way back is the restore control. A minimised window is expanded first,
9567
- * and maximising a second window restores the first.
9822
+ * from anywhere inside the layout — a focused grid body cell or column
9823
+ * heading included — unless a payload has already claimed the key: an open
9824
+ * cell editor, filter menu or column menu closes first, and the next Escape
9825
+ * restores the window. Afterwards focus lands on the window's maximise
9826
+ * control. A minimised window is expanded first, and maximising a second
9827
+ * window restores the first.
9568
9828
  */
9569
9829
  maximise(id: string): boolean;
9570
9830
  /**