laif-ds 1.0.2-app-data-grid.87 → 1.0.2-app-data-grid.88
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.
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-09-23T10:
|
|
3
|
+
"generatedAt": "2026-09-23T10:54:10.419Z",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "laif-ds",
|
|
6
|
-
"version": "1.0.2-app-data-grid.
|
|
6
|
+
"version": "1.0.2-app-data-grid.88"
|
|
7
7
|
},
|
|
8
8
|
"summary": {
|
|
9
9
|
"scannedFiles": 491,
|
|
@@ -68,7 +68,7 @@ Three contracts are **copied from `DataTable`, never imported**, so that migrati
|
|
|
68
68
|
| `initialFullscreen` | `boolean` | `false` | **Fase 3, live.** Seeds the fullscreen state at the **first** render, so a call site that mounts with it finds `role="dialog"` immediately rather than after an effect. It is an `initial*`, not a controlled `fullscreen`: it seeds and then stops governing, so no consumer has to resynchronise a state it does not own. |
|
|
69
69
|
| `onColumnVisibilityChange` | `(columnVisibility: Readonly<Record<string, boolean>>) => void` | `undefined` | The missing half of `columnVisibility`, and the twin of `onDensityChange`. Until Fase 3 nothing **inside** the grid wrote that map — the panel was consumer-mounted and wrote it itself — so the controlled half existed without a callback. From Fase 3 the `toolbar.columns` slot lives inside the grid and dispatches `view/column-visibility` (the column menu's hide item did too, until the `⋮` menu was removed); but when `columnVisibility` arrives as a prop the engine **overrides** that reducer slice with the prop, so the dispatch would be invisible. With this callback the grid **asks** the owner of the map for the change instead of writing where nobody reads. Receives the already-applied map, in the slice's convention: an absent key means visible. ⚠️ **Omitting it while `columnVisibility` is passed switches the control off.** In that combination nobody can write the map — the dispatch is suppressed and the request has no recipient — so the «columns» trigger is **not rendered** at all, rather than accepting a click and snapping back in the same commit. Same rule the phase already applies to `toolbar.filters` without `onOpen`: a button that does nothing is worse than a button that is not there. Measured: with the prop and no callback `[data-grid-toolbar-columns]` is not in the DOM; adding the callback brings it back. (It used to switch off TWO controls, the second being the `⋮` menu's hide item, removed with the menu.) |
|
|
70
70
|
| `onColumnWidthsChange` | `(columnWidths: Readonly<Record<string, number>>) => void` | `undefined` | **The capture half of `columnWidths`, and until this prop there was none.** A width was always restorable through `preset.view.columnWidths`, and never readable: `view/column-width` lives in the reducer and no prop carried it back out, so a persistence consumer saved the widths frozen at their first value forever — which is written down as the literals `columnWidths: {}` / `columnOrder: []` in the phase's own reference harness. **Not an emission** — a width is view configuration, so it cannot refetch: `view/column-width` is a `GridViewAction`, `onQueryChange` does not appear in `applyView`, and `data-emissions` does not move. Receives the **already-applied, whole** map, in the slice's convention, exactly like `onColumnVisibilityChange`. ⚠️ **The map is PARTIAL, and the partiality is the value:** a column never dragged is **not a key**, and that absence is what `parts/grid-table.tsx` reads to decide which columns are elastic and take part in slack distribution. Completing it would switch slack distribution off at the first save AND emit a value different from what `preset.view.columnWidths` stores — the round trip would not come back. ⚠️ **One call per commit, not one per pixel:** between `pointerdown` and `pointerup` the width is written straight to the `<col>` and consolidated into state once, on release; `pointercancel` does not consolidate, so it does not notify. ⚠️ **Declared limit — the keyboard commits once per keypress**, so a held arrow key yields one notification per OS key-repeat. The grid does not smooth it: `serverDebounceTime` is declared for query _emission_, and a view action has no emitter to protect. Debounce on your side if you POST per notification. ⚠️ **Declared limit — a zero-delta gesture notifies too, and the notification is faithful.** `pointerup` commits the seeded start width whatever it is, so a still click on the handle (a mis-click, or the click that focuses the separator before using the arrows) dispatches the rendered width and the column leaves the elastic set from then on. This prop does not filter it: the dispatch is pre-existing P4 behavior, so suppressing only the notification would leave the consumer's copy diverging from the reducer slice — the one thing worse than an extra notification. ⚠️ **Declared limit — the width handed over is the RENDERED one**, i.e. post-`distributeGridColumnSlack`, so the first notification for a formerly elastic column carries a number nobody typed and nobody dragged to: well-defined but **viewport-dependent**, which means a view captured on a 1600px window and restored on a 1200px one pins a column at a width that window would never have given it. Restore itself is safe — `columnWidths[id] ?? header.width ?? gridColumnWidth.default`, then clamped. ⚠️ **Declared limit — it does NOT fire when a `preset` is applied**, deliberately: `applyPreset` dispatches `view/preset` straight to the reducer and never reaches this handler. Firing there would close a write-back loop (load the saved view → `preset` → callback → the consumer POSTs what it just GET-ed). Restoration is announced once and wholesale through `onPresetApplied`. The asymmetry with `onDensityChange`, which _does_ fire on a preset, is not a precedent — that one was rescued there because `adg-c12` removed its last caller. ⚠⚠ **And therefore the consumer MUST re-seed its captured copy from `onPresetApplied`.** `view/preset` replaces `columnWidths` wholesale and no capture callback announces it: drag `city` to 400, then restore an older view whose `columnWidths` is `{}` — the grid goes back to all-elastic while the consumer's copy still says `{city:400}`, and the next save, with nobody having touched anything, writes it back and undoes the restore in silence. One line in `onPresetApplied` fixes it. ⚠️ **No controlled half:** there is no `columnWidths` prop, because `preset.view` already imposes widths in one tick with one emission. Consequence: `preset` is guarded by object **identity**, so restoring the same saved view twice needs a new object. |
|
|
71
|
-
| `onColumnOrderChange` | `(columnOrder: string[]) => void` | `undefined` | **The capture half of the column order, and the twin of `onColumnWidthsChange`.** `view/column-order` has a single dispatch in the whole grid and had no way out; a `GridColumnRegistryPanel` you mount yourself has always had its own `onColumnOrderChange`, but an order decided there does not reach the grid — there is no `columnOrder` prop. **Not an emission** — column order changes nothing the server needs to know, and `view/column-order` is not a `GridQueryAction`. Receives the **new, whole** order, not the move. `string[]` and not `readonly string[]` on purpose: `GridViewPresetView.columnOrder` is `string[]`, so a readonly array is `TS4104` on assignment and would force `[...columnOrder]` in every consumer; the widths map stays `Readonly<Record<…>>` because TypeScript ignores the modifier there — the asymmetry is the language's, and it is the same one the panel already has. ⚠️ **Never fires on a non-event**, and not because this point guards: the panel already rejects a move past the end of the list, one that crosses a pinned block, and an identical order. ⚠⚠ **Declared limit — without the IN-GRID registry this prop can never be invoked
|
|
71
|
+
| `onColumnOrderChange` | `(columnOrder: string[]) => void` | `undefined` | **The capture half of the column order, and the twin of `onColumnWidthsChange`.** `view/column-order` has a single dispatch in the whole grid and had no way out; a `GridColumnRegistryPanel` you mount yourself has always had its own `onColumnOrderChange`, but an order decided there does not reach the grid — there is no `columnOrder` prop. **Not an emission** — column order changes nothing the server needs to know, and `view/column-order` is not a `GridQueryAction`. Receives the **new, whole** order, not the move. `string[]` and not `readonly string[]` on purpose: `GridViewPresetView.columnOrder` is `string[]`, so a readonly array is `TS4104` on assignment and would force `[...columnOrder]` in every consumer; the widths map stays `Readonly<Record<…>>` because TypeScript ignores the modifier there — the asymmetry is the language's, and it is the same one the panel already has. ⚠️ **Never fires on a non-event**, and not because this point guards: the panel already rejects a move past the end of the list, one that crosses a pinned block, and an identical order. ⚠⚠ **Declared limit — without the IN-GRID registry this prop can never be invoked.** The node that wires it renders unless `toolbar.columns` is `false` (from 2026-09-23 it is on by default, key omitted included), does **not** carry its own `render` (a consumer's panel wins the precondition, deliberately), **and** `canWriteVisibility` is true — i.e. `columnVisibility` is absent, or arrives together with `onColumnVisibilityChange`. The combination «controlled visibility without its callback» switches the trigger off entirely, and with it the reorder. Pass the three together, or this is a prop that cannot fire. ⚠️ **Declared limit — it does NOT fire when a `preset` is applied**, same reason, same loop, same restore channel as `onColumnWidthsChange`, and the same **obligation** to re-seed the captured copy from `onPresetApplied`, because `view/preset` replaces `columnOrder` wholesale too. ⚠️ **Declared limit — the order is a FLAT list that does not say whose an id is.** The engine sorts **siblings** inside their group, so a saved order whose move crosses a group boundary is a visible non-event. Pre-existing P7 behavior, true of the captured value as of the applied one. ⚠️ **No controlled half:** the order lives only in the reducer, and `preset.view.columnOrder` is the way to impose it. The panel tolerates a **partial** order — it appends the ids the saved order does not name — so a view saved before a column existed does not lose it. |
|
|
72
72
|
| `resultTotal` | `number` | `undefined` | **CLIENT BRANCH ONLY — Fase 4.** How many rows exist IN TOTAL, i.e. the figure the paginator prints after «of» («Rows 1-10 of 128») and the chip row's clause reads. NOT the number of rows rendered: in client mode `data` may already be a page, and `data.length` would say 10 where the scope is 128. The server-branch twin is `serverConfig.totalItems` — the two never merge, and which one you pass is decided by the branch. Omitted, the scope equals the rows actually rendered — **except on a grid that paginates itself**, where from `adg-m2` it is derived: see «The scope on a self-paginating grid». Passing it (or `pagination.pageSize`) is also what turns the paginator on on the client branch, where `paginated` is `never`. |
|
|
73
73
|
| `groupLabelPlacement` | `"grouping-column" \| "first-column"` | `"grouping-column"` | **CLIENT BRANCH ONLY — M5.** Where a group row's label, chevron and count land. They are ONE node and move together, so this prop picks the cell all three fall into. `"grouping-column"` (default) puts them in the cell of the column that groups **at that level**; `"first-column"` puts them in the **first rendered column**, which is the mockup's shape. ⚠️ **It places, it does not pin**: the identity sits in a frozen left band that does not scroll away ONLY if that first column declares `pinned: "left"`. On an unpinned first column the label scrolls away with the body — the play passes because the fixture's first column happens to be pinned. **The default reproduces today's behaviour on purpose:** flipping it would move the label in every consumer's grouped grid without anyone asking, so a grid that does not pass this prop renders exactly what it rendered before. **A closed union of two forms, never a column id** — a free id would be an unverifiable `string`, and pointing it at a column that does not exist (or is hidden) would do nothing and say nothing, leaving the grid on the default while the author believes they moved it. **It hides no column, and that is why the prop exists:** moving the label left used to require *hiding* the grouping column — a group row falls back to the first visible column when its own is gone — which drops the rendered leaves by one and makes the «fourteen columns» clause of the complete scene false. `"first-column"` unhooks PLACEMENT from VISIBILITY: every column stays, and the grouping column's cell goes back to the common rule — its own aggregate if it declares one, otherwise empty (R11: the grouping value appears once, and it is the label that says it). **Server variant: `never`**, next to `groupBy` and `initialOpenGroups` — a grid that does not group has no group label to place, and without the twin this prop would be a silent no-op instead of a type error. |
|
|
74
74
|
| `error` | `boolean` | `false` | **Fase 5.** The request FELL: the data exists and did not arrive. It is the PREDICATE, and `onRetry` is not one — without it a failed fetch and a filter that catches nothing are the same state for the grid (`loading={false}`, `data={[]}`), and the reader is told «no results» where they should be told to retry, so they change the filters instead. Lives on **BOTH branches** of the union. It **wins over the empty outcome** (a failed request has zero rows, so both predicates would be true) and, like the empty one, does **not** show while `loading`: an error from the previous attempt above the skeletons of the current one describes the past. |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.1.0",
|
|
3
|
-
"generatedAt": "2026-09-23T10:
|
|
3
|
+
"generatedAt": "2026-09-23T10:54:09.944Z",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "laif-ds",
|
|
6
|
-
"version": "1.0.2-app-data-grid.
|
|
6
|
+
"version": "1.0.2-app-data-grid.88"
|
|
7
7
|
},
|
|
8
8
|
"stats": {
|
|
9
9
|
"documentedComponentCount": 97,
|
|
@@ -6549,5 +6549,5 @@
|
|
|
6549
6549
|
]
|
|
6550
6550
|
}
|
|
6551
6551
|
],
|
|
6552
|
-
"checksum": "
|
|
6552
|
+
"checksum": "16268e4942256ecceb9cc962078a1687eb89049b0da3a1515f60c492c89bc52d"
|
|
6553
6553
|
}
|