apex-grid 3.6.0 → 4.0.0-beta.1
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.
- package/CHANGELOG.md +235 -0
- package/README.md +79 -13
- package/components/cell.d.ts +13 -1
- package/components/cell.js +28 -13
- package/components/cell.js.map +1 -1
- package/components/grid.d.ts +135 -13
- package/components/grid.js +165 -63
- package/components/grid.js.map +1 -1
- package/components/header-row.d.ts +0 -6
- package/components/header-row.js +1 -19
- package/components/header-row.js.map +1 -1
- package/components/header.js +39 -2
- package/components/header.js.map +1 -1
- package/components/paginator.d.ts +20 -5
- package/components/paginator.js +54 -17
- package/components/paginator.js.map +1 -1
- package/components/row.js +149 -40
- package/components/row.js.map +1 -1
- package/components/toolbar.d.ts +5 -1
- package/components/toolbar.js +4 -1
- package/components/toolbar.js.map +1 -1
- package/components/virtualize-rows.d.ts +38 -0
- package/components/virtualize-rows.js +286 -0
- package/components/virtualize-rows.js.map +1 -0
- package/components/virtualizer.d.ts +71 -1
- package/components/virtualizer.js +105 -29
- package/components/virtualizer.js.map +1 -1
- package/controllers/dom.d.ts +10 -3
- package/controllers/dom.js +5 -5
- package/controllers/dom.js.map +1 -1
- package/controllers/navigation.d.ts +63 -0
- package/controllers/navigation.js +295 -21
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.d.ts +7 -6
- package/controllers/pagination.js +27 -28
- package/controllers/pagination.js.map +1 -1
- package/controllers/row-pin.d.ts +6 -0
- package/controllers/row-pin.js +8 -2
- package/controllers/row-pin.js.map +1 -1
- package/controllers/row-reorder.d.ts +12 -4
- package/controllers/row-reorder.js +20 -6
- package/controllers/row-reorder.js.map +1 -1
- package/controllers/selection.d.ts +32 -10
- package/controllers/selection.js +33 -10
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.js +2 -3
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +18 -0
- package/controllers/state.js +53 -42
- package/controllers/state.js.map +1 -1
- package/custom-elements.json +1404 -215
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +119 -47
- package/docs/classes/ApexGridPaginator.html +39 -8
- package/docs/classes/ApexGridToolbar.html +9 -5
- package/docs/functions/localize.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +85 -15
- package/docs/interfaces/ApexPageChangedEvent.html +3 -1
- package/docs/interfaces/BaseApexCellContext.html +18 -5
- package/docs/interfaces/BaseApexEditorContext.html +20 -5
- package/docs/interfaces/BaseFilterExpression.html +1 -1
- package/docs/interfaces/CSVExportOptions.html +1 -1
- package/docs/interfaces/DataPipelineConfiguration.html +4 -9
- package/docs/interfaces/ExportOptions.html +1 -1
- package/docs/interfaces/GridSelectionConfiguration.html +19 -4
- package/docs/interfaces/PaginationConfiguration.html +11 -4
- package/docs/interfaces/PaginationState.html +4 -2
- package/docs/media/package.json +7 -4
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/PaginationMode.html +5 -4
- package/docs/variables/EN_LOCALE.html +2 -2
- package/i18n/en.d.ts +2 -0
- package/i18n/en.js +2 -0
- package/i18n/en.js.map +1 -1
- package/i18n/es.js +2 -0
- package/i18n/es.js.map +1 -1
- package/internal/column-types.d.ts +11 -1
- package/internal/column-types.js +8 -6
- package/internal/column-types.js.map +1 -1
- package/internal/export.d.ts +6 -0
- package/internal/export.js +4 -0
- package/internal/export.js.map +1 -1
- package/internal/feature-module.d.ts +7 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/flip.d.ts +28 -16
- package/internal/flip.js +42 -10
- package/internal/flip.js.map +1 -1
- package/internal/index.d.ts +2 -2
- package/internal/index.js +2 -2
- package/internal/index.js.map +1 -1
- package/internal/types.d.ts +75 -19
- package/internal/types.js.map +1 -1
- package/operations/filter/types.d.ts +1 -1
- package/operations/filter/types.js.map +1 -1
- package/package.json +2 -2
- package/styles/_tokens.css.js +1 -1
- package/styles/_tokens.css.js.map +1 -1
- package/styles/body-cell/body-cell.css.js +1 -1
- package/styles/body-cell/body-cell.css.js.map +1 -1
- package/styles/body-cell/cell-renderers.css.js +1 -1
- package/styles/body-cell/cell-renderers.css.js.map +1 -1
- package/styles/body-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- package/styles/grid/_grid.base.css.js +1 -1
- package/styles/grid/_grid.base.css.js.map +1 -1
- package/styles/grid/grid.css.js +1 -1
- package/styles/grid/grid.css.js.map +1 -1
- package/styles/group-header-row/group-header-row.css.js +1 -1
- package/styles/group-header-row/group-header-row.css.js.map +1 -1
- package/styles/header-cell/header-cell.css.js +1 -1
- package/styles/header-cell/header-cell.css.js.map +1 -1
- package/styles/header-row/header-row.base.css.js +1 -1
- package/styles/header-row/header-row.base.css.js.map +1 -1
- package/styles/paginator/paginator.css.js +1 -1
- package/styles/paginator/paginator.css.js.map +1 -1
- package/styles/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/operations/pagination.d.ts +0 -19
- package/operations/pagination.js +0 -12
- package/operations/pagination.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,241 @@ All notable changes to the `apex-grid` (community) package are documented here.
|
|
|
4
4
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
5
5
|
and the format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [4.0.0-beta.1] - 2026-10-29
|
|
10
|
+
|
|
11
|
+
A pre-release of 4.0.0, published under the `next` npm tag for trying out
|
|
12
|
+
before it becomes `latest`. It is a major version because these changes can
|
|
13
|
+
break existing code:
|
|
14
|
+
|
|
15
|
+
- **Body rows are recycled by default** (`rowRecycling`). A row element and
|
|
16
|
+
its cells can show another record after a scroll, sort or filter, so a
|
|
17
|
+
template that keeps state in the elements it creates, or code that holds
|
|
18
|
+
`grid.rows` elements or `ctx.row` across an `await`, can see another
|
|
19
|
+
record. Set `rowRecycling = false` (or `row-recycling="false"`) to keep
|
|
20
|
+
record-keyed rows.
|
|
21
|
+
- **The grid role moved off the host.** `role`, `aria-rowcount`,
|
|
22
|
+
`aria-colcount`, `aria-multiselectable` and the accessible name are on the
|
|
23
|
+
inner `[part~="table"]` element.
|
|
24
|
+
- **Types removed:** `DataPipelineConfiguration.pagination` and the
|
|
25
|
+
`'pagination'` value of `DataPipelineParams.type`.
|
|
26
|
+
- **Pagination:** pinned rows no longer count toward `totalItems` and the
|
|
27
|
+
pages, and a local page change no longer calls custom sort and filter hooks.
|
|
28
|
+
- **Smaller type and DOM changes:** `ctx.data` is a required field of the cell
|
|
29
|
+
context, `ApexGridPaginator.pageSizeOptions` is `readonly number[]`, the
|
|
30
|
+
paginator's previous button id is `prev`, and the protected
|
|
31
|
+
`ApexGrid.headerRowCount` and `ApexGridHeaderRow.renderDragGhost` are gone.
|
|
32
|
+
|
|
33
|
+
See Changed and Removed for the details and for other changes apps may notice.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- The `ai.cancelled` locale key (English and Spanish), used by the enterprise
|
|
37
|
+
Ask AI panel.
|
|
38
|
+
- The `chart.rangeResized` locale key (English and Spanish), announced when an
|
|
39
|
+
enterprise charted range is resized from the keyboard.
|
|
40
|
+
- **`showHeader`** (attribute `show-header="false"`) leaves out the column
|
|
41
|
+
header row, the column group row and the filter panel, so a short grid such as
|
|
42
|
+
a dashboard tile gives that room to the data rows. Screen readers still
|
|
43
|
+
announce the column names, and sort, filter, column widths and the page come
|
|
44
|
+
back unchanged when the header returns. While it is hidden, resizing, the
|
|
45
|
+
column menu, drag reorder and the header filter button are unavailable.
|
|
46
|
+
([#35](https://github.com/apexcharts/apex-grid/issues/35))
|
|
47
|
+
- **`selection.isRowSelectable(row)`** keeps chosen rows out of selection,
|
|
48
|
+
such as a pinned total row. Such a row shows no checkbox, and clicks, Shift
|
|
49
|
+
and Ctrl clicks, Space, Select all, `selectRow` and `setState` all skip it;
|
|
50
|
+
the header checkbox counts only selectable rows. Rows stay selectable by
|
|
51
|
+
default, pinned rows included.
|
|
52
|
+
([#38](https://github.com/apexcharts/apex-grid/issues/38))
|
|
53
|
+
- `pagination.paginator: 'compact'` draws the small paginator: summary,
|
|
54
|
+
previous, page / count, next.
|
|
55
|
+
([#36](https://github.com/apexcharts/apex-grid/issues/36))
|
|
56
|
+
- `apex-grid::part()` reaches every paginator and toolbar part
|
|
57
|
+
(`paginator-host`, `paginator`, `paginator-size`, `paginator-info`,
|
|
58
|
+
`paginator-controls`, `paginator-page`, `paginator-button`, `toolbar-host`,
|
|
59
|
+
`toolbar`, `toolbar-search`, `search-input`, `toolbar-actions`, `export`,
|
|
60
|
+
`export-menu` and the rest), and each paginator button also carries its own
|
|
61
|
+
part: `paginator-first`, `paginator-prev`, `paginator-next` or
|
|
62
|
+
`paginator-last`. ([#37](https://github.com/apexcharts/apex-grid/issues/37))
|
|
63
|
+
- **`ctx.data` in cell and editor templates.** The context handed to a
|
|
64
|
+
`cellTemplate` or an `editorTemplate` carries `data`, the record the cell
|
|
65
|
+
was rendered for. It stays that record after an `await`, while `ctx.row`
|
|
66
|
+
and `ctx.parent` are elements that a pinned row band can later re-bind to
|
|
67
|
+
another record. A `cellTemplate`'s `ctx.commit` writes to `ctx.data`. An
|
|
68
|
+
editor's `ctx.commit` still commits the cell in edit when it is called.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
- **Body rows are now recycled by default** (new `rowRecycling` property,
|
|
72
|
+
default `true`). A scroll, sort or filter re-binds the rendered row elements
|
|
73
|
+
to the records now in view instead of building new rows, which makes long
|
|
74
|
+
jumps and sorts cheaper on large grids. A row element, and its cells, can
|
|
75
|
+
therefore show another record later. Cell and editor templates should
|
|
76
|
+
derive what they render from their context on each render, read
|
|
77
|
+
`ctx.data` for the record, and not hold `ctx.row` or `ctx.parent` across an
|
|
78
|
+
`await`; a template that keeps element state can wrap itself in
|
|
79
|
+
`keyed(ctx.data, ...)`. What you might notice: a template that keeps state
|
|
80
|
+
in the elements it creates (an input's typed value, a third-party widget)
|
|
81
|
+
can show it on another record after a scroll or a sort, and code that holds
|
|
82
|
+
`grid.rows` elements across a scroll or a sort finds them showing other
|
|
83
|
+
records. To keep record-keyed rows, set `grid.rowRecycling = false` (or the
|
|
84
|
+
`row-recycling="false"` attribute). Detail panel content follows its record
|
|
85
|
+
and keeps its DOM state across a scroll, a sort or a `moveRow`, so detail
|
|
86
|
+
templates need no change; a grid created inside a `detailTemplate` keeps its
|
|
87
|
+
own setting.
|
|
88
|
+
- **The grid role and its row counts moved from the `<apex-grid>` host to an
|
|
89
|
+
inner element** exposed as part `table`: `role` (`grid` or `treegrid`),
|
|
90
|
+
`aria-rowcount`, `aria-colcount`, `aria-multiselectable` and the accessible
|
|
91
|
+
name. It holds only the header rows and the body, so the toolbar, paginator,
|
|
92
|
+
filter panel and live region are no longer read as table content, and every
|
|
93
|
+
default grid passes the axe `aria-required-children` rule. Code or tests
|
|
94
|
+
that read these from the host should query
|
|
95
|
+
`grid.shadowRoot.querySelector('[part~="table"]')`. The layout is unchanged.
|
|
96
|
+
- An `aria-label` or `aria-labelledby` on the host still names the grid, and
|
|
97
|
+
`aria-describedby` becomes its description. References are resolved when the
|
|
98
|
+
grid renders: if the referenced element is added later, set the attribute
|
|
99
|
+
again.
|
|
100
|
+
- The grid uses the `treegrid` role whenever rows carry levels or expand: tree
|
|
101
|
+
data, master-detail with a detail template, and the enterprise row grouping,
|
|
102
|
+
expandable pivot and server-side grouping.
|
|
103
|
+
- `pageItems` keeps the same array between updates while nothing that shapes
|
|
104
|
+
it changes. Apps that compared it by identity now see a new array only when
|
|
105
|
+
the body rows change.
|
|
106
|
+
- The column header row is no longer a Tab stop.
|
|
107
|
+
- **The built-in column menu opens in the top layer** where the browser supports
|
|
108
|
+
the Popover API: pinned rows, the paginator and the grid's edge no longer
|
|
109
|
+
cover or clip it, it stays on its header cell through any scroll or layout
|
|
110
|
+
change, and it closes when its column scrolls out of the grid. It can now
|
|
111
|
+
extend outside the grid's box.
|
|
112
|
+
- The column drag ghost renders at the grid root, so it stays above the column
|
|
113
|
+
group header and pinned top rows, and `apex-grid::part(drag-ghost)` now
|
|
114
|
+
reaches it.
|
|
115
|
+
- `--filtering-header-background` applies to every filtered header, pinned and
|
|
116
|
+
dragged ones included, as a layer over the header's own background, and
|
|
117
|
+
filtered headers get the same hover highlight as other headers.
|
|
118
|
+
- The paginator follows `--header-background` and group header labels follow
|
|
119
|
+
`--header-text-color`, like the rest of the header area. The paginator text
|
|
120
|
+
size follows `--ag-fs-cell-secondary`, and the filter count badge uses
|
|
121
|
+
`--ag-text-on-brand` and `--ag-fw-semibold`. Default rendering is unchanged.
|
|
122
|
+
- Forced colors (Windows High Contrast): checkboxes are drawn by the browser in
|
|
123
|
+
system colours, so apps that styled them through parts see the native
|
|
124
|
+
checkbox in that mode only.
|
|
125
|
+
- With pagination, pinned rows no longer count toward the pages: `totalItems`,
|
|
126
|
+
`pageCount`, the paginator summary and the `pageChanged` detail count the
|
|
127
|
+
rows the pager pages through, and pinning a row on the last page moves to the
|
|
128
|
+
new last page. Without pagination `totalItems` still counts every row.
|
|
129
|
+
- A local page or page size change no longer reruns sorting, filtering and the
|
|
130
|
+
rest of the pipeline, so custom sort and filter hooks are no longer called on
|
|
131
|
+
a local page change. Remote mode still reruns it.
|
|
132
|
+
- `pageChanged` reports the change that was applied, so two quick
|
|
133
|
+
`nextPage()` calls report page 2 and then page 3.
|
|
134
|
+
- A page change is announced once ("Page X of N"); the paginator summary and
|
|
135
|
+
page label are no longer live regions.
|
|
136
|
+
- The first grid on a page adds one window `error` listener that cancels
|
|
137
|
+
"ResizeObserver loop" messages and hides them from listeners added after it.
|
|
138
|
+
Listeners registered before the first grid still receive them. Every other
|
|
139
|
+
error is untouched. ([#32](https://github.com/apexcharts/apex-grid/issues/32))
|
|
140
|
+
- `totalItems` is described one way everywhere: the post-filter, post-sort
|
|
141
|
+
row count, and in remote mode the `pagination.totalItems` you supply, the
|
|
142
|
+
number of rows the server holds for the current filter.
|
|
143
|
+
([#34](https://github.com/apexcharts/apex-grid/issues/34))
|
|
144
|
+
- Type and DOM details for code that builds on the grid's internals:
|
|
145
|
+
`BaseApexCellContext.data` is required, so code that builds a cell context
|
|
146
|
+
by hand must supply it; `ApexGridPaginator.pageSizeOptions` is typed
|
|
147
|
+
`readonly number[]`; the paginator's previous button has the id `prev`
|
|
148
|
+
(it was `previous`) inside its shadow root; and the protected
|
|
149
|
+
`ApexGrid.headerRowCount` and `ApexGridHeaderRow.renderDragGhost` were
|
|
150
|
+
removed, which affects subclasses only.
|
|
151
|
+
- The `@lit-labs/virtualizer` dependency is pinned to exactly `2.1.1` (it was
|
|
152
|
+
`~2.1.0`). The grid body builds on parts of that package that are not public
|
|
153
|
+
API, so a newer version arrives only with a grid release that has been
|
|
154
|
+
checked against it.
|
|
155
|
+
|
|
156
|
+
### Removed
|
|
157
|
+
- **Breaking (types):** `DataPipelineConfiguration.pagination` and the
|
|
158
|
+
`'pagination'` value of `DataPipelineParams.type`. The hook was documented
|
|
159
|
+
but never called, so no runtime behaviour changes; TypeScript code that sets
|
|
160
|
+
it stops compiling. For server paging use `pagination.mode: 'remote'`, fetch
|
|
161
|
+
the page on `pageChanged` and keep `pagination.totalItems` current.
|
|
162
|
+
([#33](https://github.com/apexcharts/apex-grid/issues/33))
|
|
163
|
+
|
|
164
|
+
### Fixed
|
|
165
|
+
- `aria-rowcount` no longer counts the floating filter panel as a row, and a
|
|
166
|
+
pinned top row no longer shares its `aria-rowindex` with the first body row.
|
|
167
|
+
- The master-detail panel sits in a full-width gridcell, and `aria-expanded` is
|
|
168
|
+
set only on rows and toggle buttons that can expand. Turning expansion off or
|
|
169
|
+
removing the detail template no longer leaves it on rows.
|
|
170
|
+
- Announcing the same message twice in a row (two identical `grid.announce()`
|
|
171
|
+
calls, for example) is read out again by screen readers.
|
|
172
|
+
- Invalid cells no longer set an `aria-errormessage` that pointed at an
|
|
173
|
+
unreachable id. The inline alert message is unchanged.
|
|
174
|
+
- Range and formula reference highlights on a pinned column no longer let
|
|
175
|
+
scrolled cells show through it.
|
|
176
|
+
- Alternating row stripes follow the row index, so they no longer flip or
|
|
177
|
+
flicker while you scroll.
|
|
178
|
+
- In the dark theme the default, muted and gold badges are readable and the
|
|
179
|
+
progress bar track is visible. The light theme is unchanged.
|
|
180
|
+
- The selected row accent bar sits on the leading edge in right to left
|
|
181
|
+
layouts, including a left to right grid nested in a right to left one.
|
|
182
|
+
- Forced colors: checked and indeterminate checkboxes no longer look unchecked;
|
|
183
|
+
in a selected row the cell text, row number, reorder grip and chevrons take
|
|
184
|
+
the selection text colour; an editor opened in a selected row uses the
|
|
185
|
+
system field colours; a keyboard-grabbed row shows an outline.
|
|
186
|
+
- The paginator no longer clips its controls in a narrow grid: it drops the
|
|
187
|
+
rows per page selector, then the first and last buttons, so previous and next
|
|
188
|
+
stay reachable. ([#36](https://github.com/apexcharts/apex-grid/issues/36))
|
|
189
|
+
- Grids whose cell text wraps no longer raise "ResizeObserver loop completed
|
|
190
|
+
with undelivered notifications" while they resize or scroll.
|
|
191
|
+
([#32](https://github.com/apexcharts/apex-grid/issues/32))
|
|
192
|
+
- With row pinning and pagination, no trailing page is left empty.
|
|
193
|
+
- A `pageSize` missing from `pageSizeOptions` now appears in the rows per
|
|
194
|
+
page selector and is selected.
|
|
195
|
+
- A page size change or quick filter cancelled through `pageChanging` or
|
|
196
|
+
`quickFilterChanging` no longer leaves the selector or search box showing
|
|
197
|
+
the refused value.
|
|
198
|
+
- **Pinned rows no longer show the previous row's state.** When a pinned row
|
|
199
|
+
element switches to another record (a row above it is unpinned, say), it no
|
|
200
|
+
longer keeps the previous record's staged row edit value, validation error,
|
|
201
|
+
expanded state, detail panel content or selection checkbox state, even when
|
|
202
|
+
both records hold the same cell value.
|
|
203
|
+
- A `cellTemplate` that calls `ctx.commit` after an `await` writes to the
|
|
204
|
+
record it was rendered for, even if the rows changed in the meantime.
|
|
205
|
+
- Moving a keyboard grabbed row with the arrow keys keeps focus on that row
|
|
206
|
+
instead of dropping it to the page, and Escape puts the active cell and
|
|
207
|
+
focus back on the row at its original position.
|
|
208
|
+
- The floating ghost of a row drag shows the row's cell text. It showed empty
|
|
209
|
+
cells before.
|
|
210
|
+
- An editor rendered again for an edit already in progress (its row scrolled
|
|
211
|
+
back into view, for example) no longer scrolls the grid or selects the typed
|
|
212
|
+
draft when it takes focus.
|
|
213
|
+
- With an async `dataPipelineConfiguration` hook, moving a row with
|
|
214
|
+
`moveRow`, a keyboard grab or a drag animates the rows into their new places.
|
|
215
|
+
They jumped there without the animation before.
|
|
216
|
+
- A jump to a row far outside the view that is still waiting for the body to
|
|
217
|
+
finish scrolling no longer runs after a newer jump, so two quick jumps end on
|
|
218
|
+
the second row instead of snapping back to the first.
|
|
219
|
+
- A pinned row that switches to another record no longer animates from the
|
|
220
|
+
previous record's look: its selected wash, expand chevron, checkbox and
|
|
221
|
+
progress bars show the new record's state at once.
|
|
222
|
+
- An image cell whose URL changes (a pinned row switching records, an edit of
|
|
223
|
+
the URL) renders a new `<img>`, so the previous picture no longer stays on
|
|
224
|
+
screen while the new one loads.
|
|
225
|
+
- Arrow and Page keys in a grid whose rows grew after they were first shown
|
|
226
|
+
(detail panels expanded, wrapped text) keep the active cell in view and
|
|
227
|
+
focused. A quick run of key presses could leave it unrendered, with focus on
|
|
228
|
+
the body or on a cell of another record, until the next click.
|
|
229
|
+
- When a sort, a filter or a data change moves the record of an open cell
|
|
230
|
+
edit to another row that is still in view, the active cell moves with it, so
|
|
231
|
+
the keyboard carries on from the edited cell once the edit closes. It used to
|
|
232
|
+
stay on the old row, which then showed another record.
|
|
233
|
+
|
|
234
|
+
### Performance
|
|
235
|
+
- Scrolling no longer re-renders the rows that stay in view; only the rows that
|
|
236
|
+
scroll in render.
|
|
237
|
+
- A grid with a pinned row or a page slice no longer rescans the whole view on
|
|
238
|
+
every key press or click.
|
|
239
|
+
- Grids without feature modules skip the per-cell decoration step, and grids
|
|
240
|
+
with modules no longer check every module on each row and cell render.
|
|
241
|
+
|
|
7
242
|
## [3.6.0] - 2026-10-21
|
|
8
243
|
|
|
9
244
|
A quality release built from a full code-quality audit, plus `--ag-*` tokens
|
package/README.md
CHANGED
|
@@ -192,6 +192,9 @@ With the element registered and the host sized, you should see:
|
|
|
192
192
|
| `<apex-grid>` blank tag in DOM | Step 2: element not registered |
|
|
193
193
|
| Columns shown as literal `[object Object]` | `columns=` used as an attribute; must be a **property** (`.columns=${...}` in Lit, `[columns]=` in Angular, `:columns.prop=` in Vue, `el.columns = ...` in vanilla JS) |
|
|
194
194
|
|
|
195
|
+
> [!NOTE]
|
|
196
|
+
> Rows whose text wraps change height while the grid resizes or scrolls, and the browser can defer the resulting row layout by one frame. It reports each deferral as a window `error` event with the message "ResizeObserver loop completed with undelivered notifications" (older browsers say "ResizeObserver loop limit exceeded"). The event is benign, so the first grid to connect adds one window `error` listener that cancels any message containing "ResizeObserver loop" (Safari then stops logging it) and stops the listeners added after it from seeing it. Every other error passes through untouched. Listeners added before the first grid connects, such as error monitoring set up at page start, still receive it, and the same message raised by your own code is quieted as well, since the browser does not say which observer raised it.
|
|
197
|
+
|
|
195
198
|
---
|
|
196
199
|
|
|
197
200
|
## Features in depth
|
|
@@ -255,7 +258,20 @@ await grid.setPageSize(50);
|
|
|
255
258
|
grid.nextPage(); grid.previousPage(); grid.firstPage(); grid.lastPage();
|
|
256
259
|
```
|
|
257
260
|
|
|
258
|
-
|
|
261
|
+
The paginator never clips its controls: on a narrow grid it drops the page size select first, then the first and last buttons, so previous and next stay reachable. `paginator: 'compact'` always uses that narrow layout ("start-end of total", previous, "page / count", next), for example in a small dashboard tile:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
grid.pagination = { enabled: true, pageSize: 5, paginator: 'compact' };
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Style it through the grid with `apex-grid::part(...)`: `paginator-host` (the element), `paginator`, `paginator-size`, `paginator-info`, `paginator-controls`, `paginator-page`, and `paginator-button` on each button, which also carries `paginator-first`, `paginator-prev`, `paginator-next` or `paginator-last`:
|
|
268
|
+
|
|
269
|
+
```css
|
|
270
|
+
apex-grid::part(paginator-first),
|
|
271
|
+
apex-grid::part(paginator-last) { display: none; }
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Remote mode: the grid does not slice `data`, it renders whatever `data` holds as the current page. Fetch the page on `pageChanged`, and keep `pagination.totalItems` at the number of rows the server holds for the current filter (update it when a server side filter changes that number), so the paginator can count the pages:
|
|
259
275
|
|
|
260
276
|
```ts
|
|
261
277
|
grid.pagination = { enabled: true, mode: 'remote', pageSize: 25, totalItems: 1280 };
|
|
@@ -264,7 +280,7 @@ grid.addEventListener('pageChanged', async (e) => {
|
|
|
264
280
|
});
|
|
265
281
|
```
|
|
266
282
|
|
|
267
|
-
Properties: `page`, `pageSize`, `pageCount`, `totalItems`, `pageItems`. Events: `pageChanging` (cancellable), `pageChanged`.
|
|
283
|
+
Properties: `page`, `pageSize`, `pageCount`, `totalItems`, `pageItems`. `totalItems` is the post-filter, post-sort row count; with pagination enabled it counts the rows paged through, without pinned rows, which show on every page (in remote mode, the `pagination.totalItems` you supplied), and `pageChanged` carries the same number in `detail.totalItems`. Events: `pageChanging` (cancellable), `pageChanged`.
|
|
268
284
|
|
|
269
285
|
### Column pinning
|
|
270
286
|
|
|
@@ -305,6 +321,16 @@ grid.columnSeparator = false; // hide the dividers
|
|
|
305
321
|
|
|
306
322
|
Theme the line with `--ag-header-separator` (or the `--header-separator-color` override hook) and set its vertical inset with `--apex-header-separator-inset`. Because the default is `true`, disable it through the property rather than markup (a default-on boolean attribute cannot be turned off by attribute alone). Attribute: `column-separator`.
|
|
307
323
|
|
|
324
|
+
### Hiding the header
|
|
325
|
+
|
|
326
|
+
For a compact table, such as a short dashboard tile, leave out the header rows and give their room to the data rows:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
grid.showHeader = false; // or <apex-grid show-header="false">
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The column header row, the column group row and the filter panel take no space, paint nothing and take no pointer, and the built-in header controls leave the tab order, so resizing, the column menu and drag reorder are unavailable while the header is hidden (an open column menu closes). A focusable control you render in a `headerTemplate` stays in the tab order: give it `tabindex="-1"` while the header is hidden. The column header row stays in the accessibility tree, so screen readers still announce the column names, and `aria-rowcount` and `aria-rowindex` do not change. Sort, filter, column widths and the current page are kept and come back unchanged with `grid.showHeader = true`. Attribute: `show-header`.
|
|
333
|
+
|
|
308
334
|
### Column groups (spanning headers)
|
|
309
335
|
|
|
310
336
|
```ts
|
|
@@ -388,9 +414,21 @@ A keyboard-driven commit or cancel returns focus to the cell, so navigation
|
|
|
388
414
|
continues from where you were. Sorting, filtering, selection, paging, row
|
|
389
415
|
pinning, reorder, expansion, and undo / redo are announced through a polite
|
|
390
416
|
live region, and every announcement and control label is localizable (the
|
|
391
|
-
`announce.*` and `header.*` locale keys).
|
|
392
|
-
|
|
393
|
-
`
|
|
417
|
+
`announce.*` and `header.*` locale keys).
|
|
418
|
+
|
|
419
|
+
The `grid` role (`treegrid` for tree data, master-detail and other expandable
|
|
420
|
+
rows), `aria-rowcount`, `aria-colcount` and `aria-multiselectable` sit on the
|
|
421
|
+
element exposed as `part="table"` inside the shadow root, not on the
|
|
422
|
+
`<apex-grid>` host. It holds only the header rows and the body, so the toolbar,
|
|
423
|
+
paginator and live region around it are not read as table content. It gets a
|
|
424
|
+
localized `aria-label` ("Data grid") unless you put `aria-label` or
|
|
425
|
+
`aria-labelledby` on the host, which then names it. An `aria-describedby` on
|
|
426
|
+
the host becomes its description. The references are resolved when the grid
|
|
427
|
+
renders, so if you add the referenced element later (a heading shown
|
|
428
|
+
conditionally), set the attribute again afterwards to pick it up.
|
|
429
|
+
|
|
430
|
+
> Changed in 4.0.0: the role and the row and column counts used to be on the
|
|
431
|
+
> host. Query `grid.shadowRoot.querySelector('[part~="table"]')` instead.
|
|
394
432
|
|
|
395
433
|
> Changed in 3.4.0: Home / End used to jump to the first / last row; they now
|
|
396
434
|
> stay within the row. Use Ctrl/Cmd+Home / Ctrl/Cmd+End for the grid corners.
|
|
@@ -435,6 +473,8 @@ grid.selectedRows; // snapshot
|
|
|
435
473
|
grid.selectedRows = [data[2]]; // replace selection (goes through `rowSelecting`)
|
|
436
474
|
```
|
|
437
475
|
|
|
476
|
+
Every row is selectable by default, pinned rows included. `selection.isRowSelectable: (row) => boolean` keeps rows out of the selection (a pinned total row, for example): such a row renders no checkbox and no `aria-selected`, every selection path skips it (clicks, Space, Select all, `selectRow`, `selectedRows = ...`, `setState`), and the header checkbox counts only selectable rows. Reassigning `selection` or `data` drops selected rows the predicate now rejects; a selected row it comes to reject otherwise (pinned or edited in place) keeps its checkbox until deselected.
|
|
477
|
+
|
|
438
478
|
Events: `rowSelecting` (cancellable), `rowSelected`.
|
|
439
479
|
|
|
440
480
|
### Row pinning (top / bottom)
|
|
@@ -503,7 +543,7 @@ await grid.toggleTreeRow(data[0]);
|
|
|
503
543
|
await grid.expandAllTreeRows();
|
|
504
544
|
```
|
|
505
545
|
|
|
506
|
-
Methods: `toggleTreeRow`, `expandTreeRow`, `collapseTreeRow`, `expandAllTreeRows`, `collapseAllTreeRows`, `isTreeRowExpanded`. Events: `treeRowExpanding` (cancellable), `treeRowExpanded`. When tree mode is active, the
|
|
546
|
+
Methods: `toggleTreeRow`, `expandTreeRow`, `collapseTreeRow`, `expandAllTreeRows`, `collapseAllTreeRows`, `isTreeRowExpanded`. Events: `treeRowExpanding` (cancellable), `treeRowExpanded`. When tree mode is active, the grid's `part="table"` element advertises `role="treegrid"`.
|
|
507
547
|
|
|
508
548
|
### CSV export
|
|
509
549
|
|
|
@@ -529,16 +569,19 @@ Renders a download icon in the toolbar's trailing actions area; the menu has an
|
|
|
529
569
|
|
|
530
570
|
### Toolbar
|
|
531
571
|
|
|
532
|
-
Rendered automatically above the header row when at least one of `show-quick-filter` or `show-export` is on. CSS parts:
|
|
572
|
+
Rendered automatically above the header row when at least one of `show-quick-filter` or `show-export` is on. The grid re-exports its CSS parts, so `apex-grid::part(name)` reaches them:
|
|
533
573
|
|
|
534
574
|
| Part | What |
|
|
535
575
|
|---|---|
|
|
576
|
+
| `toolbar-host` | The `<apex-grid-toolbar>` element |
|
|
536
577
|
| `toolbar` | Root container |
|
|
537
578
|
| `toolbar-search` | Quick-filter input wrapper |
|
|
538
579
|
| `search-field` | The bordered input field |
|
|
539
580
|
| `search-icon`, `search-input` | Leading icon, input element |
|
|
540
581
|
| `toolbar-actions` | Trailing actions area |
|
|
541
|
-
| `
|
|
582
|
+
| `toolbar-action` | A host-contributed action button |
|
|
583
|
+
| `export` | Export menu wrapper |
|
|
584
|
+
| `export-trigger`, `export-icon`, `export-caret` | Export menu button and its icons |
|
|
542
585
|
| `export-menu` | Dropdown panel |
|
|
543
586
|
| `export-menu-item` | Menu item |
|
|
544
587
|
|
|
@@ -552,7 +595,7 @@ Style with CSS parts on the grid, paginator, and toolbar:
|
|
|
552
595
|
|
|
553
596
|
```css
|
|
554
597
|
apex-grid::part(paginator) { background: var(--surface-2); }
|
|
555
|
-
apex-grid
|
|
598
|
+
apex-grid::part(search-input) { font-family: var(--font-mono); }
|
|
556
599
|
```
|
|
557
600
|
|
|
558
601
|
Body rows re-export these parts, so `apex-grid::part(name)` reaches them:
|
|
@@ -611,6 +654,27 @@ grid.coordinateHints = true;
|
|
|
611
654
|
|
|
612
655
|
When `coordinateHints` is on, the grid shows a leading row-number gutter (1, 2, 3, and so on) and A / B / C column-letter chips in the headers, so cell references are discoverable (a spreadsheet-style look). Set it directly for a persistent spreadsheet look. `apex-grid-enterprise` turns it on by default for any grid that has an `allowFormula` column, so the gutter is reserved up front and entering a formula never shifts the layout. Reflected to the `coordinate-hints` attribute (default `false`).
|
|
613
656
|
|
|
657
|
+
### Row recycling
|
|
658
|
+
|
|
659
|
+
```ts
|
|
660
|
+
grid.rowRecycling = false; // opt out
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
```html
|
|
664
|
+
<apex-grid row-recycling="false"></apex-grid>
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
On by default. A scroll, sort or filter re-binds the rendered body rows to the records now in view instead of building new rows, which makes long jumps and sorts cheaper on large grids. A row element, and its cells, then shows another record later, so cell and editor templates follow these rules:
|
|
668
|
+
|
|
669
|
+
- Derive everything a template renders from its context on each render, and keep no state in the elements it creates.
|
|
670
|
+
- Read `ctx.data` for the record, also after an `await`. `ctx.row` and `ctx.parent` are row and cell elements that may show another record by then, so do not hold them across an `await`.
|
|
671
|
+
- Wrap a template that has to keep element state in `keyed(ctx.data, ...)` from `lit/directives/keyed.js`. The state then never shows on the wrong record, but it is rebuilt every time the row shows another record, including after a sort or `moveRow`.
|
|
672
|
+
- Code that holds `grid.rows` elements across a scroll or a sort should read each element's `data` again rather than assume it still shows the same record.
|
|
673
|
+
|
|
674
|
+
Set `rowRecycling` to `false` (or the `row-recycling="false"` attribute) to restore record-keyed rows, where each row element stays with its record. Do that for templates that must keep element state across a sort or a move, such as some third-party widgets.
|
|
675
|
+
|
|
676
|
+
Detail templates are different: their content follows its record into whichever row shows it, and keeps its DOM state (typed text, a nested grid's sort) across a scroll within the rendered rows, a sort or a `moveRow`, so it needs neither `keyed()` nor the opt-out. It is rebuilt when the record leaves the rendered rows or is collapsed, as before. `ctx.parent` in a detail context is the grid itself. A grid created inside a `detailTemplate` has its own `rowRecycling` setting, so set it there too when you opt out.
|
|
677
|
+
|
|
614
678
|
### State & persistence
|
|
615
679
|
|
|
616
680
|
`getState()` returns a JSON-safe snapshot of the grid's restorable view and `setState()` applies one back. The snapshot covers column layout (order, width, pinning, visibility), sort, filter, quick filter, pagination, selection, expansion, tree expansion, pinned rows, the manual drag-reorder order, and any feature-module state (enterprise grouping / pivot / aggregation / ranges). Functions and templates are never serialized: sort comparers, filter condition functions, and cell/header/editor templates re-bind from the live `columns` config on restore (filter conditions are captured by operand name).
|
|
@@ -647,7 +711,7 @@ See [`demo/state-persistence.html`](../../demo/state-persistence.html) for a sav
|
|
|
647
711
|
| `columns` | `ColumnConfiguration<T>[]` | `[]` | Column configuration (property only) |
|
|
648
712
|
| `autoGenerate` | `boolean` | `false` | Infer columns from `data[0]` keys. Attr `auto-generate` |
|
|
649
713
|
| `sortConfiguration` | `GridSortConfiguration` | `{ multiple, triState }` | |
|
|
650
|
-
| `dataPipelineConfiguration` | `DataPipelineConfiguration<T>` | | Custom sort
|
|
714
|
+
| `dataPipelineConfiguration` | `DataPipelineConfiguration<T>` | | Custom sort, filter and quick filter hooks |
|
|
651
715
|
| `pagination` | `PaginationConfiguration` | | |
|
|
652
716
|
| `quickFilter` | `string` | `''` | Attr `quick-filter` |
|
|
653
717
|
| `showQuickFilter` | `boolean` | `false` | Attr `show-quick-filter` |
|
|
@@ -662,6 +726,8 @@ See [`demo/state-persistence.html`](../../demo/state-persistence.html) for a sav
|
|
|
662
726
|
| `rowReordering` | `GridRowReorderingConfiguration` | | `{ enabled, applyToData?, handle? }` (`handle` default `true`: grip-only drag) |
|
|
663
727
|
| `coordinateHints` | `boolean` | `false` | Show a row-number gutter + A / B / C header chips (spreadsheet look). Attr `coordinate-hints` |
|
|
664
728
|
| `columnMenu` | `boolean` | `true` | Show the always-visible column-menu (kebab) button on headers; `false` hides it |
|
|
729
|
+
| `showHeader` | `boolean` | `true` | `false` hides the header rows (kept for screen readers). Attr `show-header="false"` |
|
|
730
|
+
| `rowRecycling` | `boolean` | `true` | Re-binds body row elements across records on scroll, sort and filter; `false` restores record-keyed rows. See [Row recycling](#row-recycling). Attr `row-recycling="false"` |
|
|
665
731
|
| `rowId` | `(row: T) => string \| number` | | Durable row identity for `getState` / `setState` |
|
|
666
732
|
| `localeText` | `GridLocaleText` | | Override map for built-in strings (e.g. `esLocale`) |
|
|
667
733
|
| `canUndo`, `canRedo` | `boolean` | | Get (history) |
|
|
@@ -751,14 +817,14 @@ Programmatic `sort()` / `filter()` calls are silent; only UI-initiated changes e
|
|
|
751
817
|
|
|
752
818
|
### Attributes
|
|
753
819
|
|
|
754
|
-
`auto-generate`, `quick-filter`, `show-quick-filter`, `show-export`, `column-reordering`, `coordinate-hints`.
|
|
820
|
+
`auto-generate`, `quick-filter`, `show-quick-filter`, `show-export`, `column-reordering`, `coordinate-hints`, `show-header`, `row-recycling`.
|
|
755
821
|
|
|
756
822
|
### CSS parts
|
|
757
823
|
|
|
758
824
|
| Component | Parts |
|
|
759
825
|
|---|---|
|
|
760
|
-
| `<apex-grid-toolbar>` | `toolbar`, `toolbar-search`, `search-field`, `search-icon`, `search-input`, `toolbar-actions`, `export-trigger`, `export-menu`, `export-menu-item` |
|
|
761
|
-
| `<apex-grid-paginator>` | `paginator`, `paginator-size`, `paginator-info`, `paginator-controls`, `paginator-page` |
|
|
826
|
+
| `<apex-grid-toolbar>` | `toolbar`, `toolbar-search`, `search-field`, `search-icon`, `search-input`, `toolbar-actions`, `toolbar-action`, `export`, `export-trigger`, `export-icon`, `export-caret`, `export-menu`, `export-menu-item` (re-exported by the grid, which names the element `toolbar-host`) |
|
|
827
|
+
| `<apex-grid-paginator>` | `paginator`, `paginator-size`, `paginator-info`, `paginator-controls`, `paginator-page`, `paginator-button`, `paginator-first`, `paginator-prev`, `paginator-next`, `paginator-last` (re-exported by the grid, which names the element `paginator-host`) |
|
|
762
828
|
| `<apex-grid-cell>` | `cell`, `editor` |
|
|
763
829
|
|
|
764
830
|
---
|
package/components/cell.d.ts
CHANGED
|
@@ -17,6 +17,16 @@ export default class ApexGridCell<T extends object> extends LitElement {
|
|
|
17
17
|
* The value which will be rendered by the component.
|
|
18
18
|
*/
|
|
19
19
|
value: PropertyType<T>;
|
|
20
|
+
/**
|
|
21
|
+
* The record (row data object) the cell shows, set by the row next to
|
|
22
|
+
* {@link value}. A row element can be re-bound to another record without
|
|
23
|
+
* being rebuilt (a pinned band does when a row above it is unpinned), and
|
|
24
|
+
* `value` alone cannot tell: two records may hold the same value. A change
|
|
25
|
+
* here is a full update that drops every per-record state of the cell.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
record: T;
|
|
20
30
|
/**
|
|
21
31
|
* A reference to the column configuration object.
|
|
22
32
|
*/
|
|
@@ -86,13 +96,15 @@ export default class ApexGridCell<T extends object> extends LitElement {
|
|
|
86
96
|
* its row beyond {@link value} (a `cellTemplate`, which may read other fields
|
|
87
97
|
* or the row index, or the tree group cell, whose chevron shows the row's
|
|
88
98
|
* expansion) still renders when the row index or the data token moves.
|
|
99
|
+
* A {@link record} change is never a token: the cell renders in full.
|
|
89
100
|
*/
|
|
90
101
|
protected shouldUpdate(changed: PropertyValues<this>): boolean;
|
|
91
102
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
92
103
|
/**
|
|
93
104
|
* The inline error node surfaced when the cell is invalid. `role="alert"`
|
|
94
105
|
* announces the message when it appears, covering the cross-shadow gap where
|
|
95
|
-
* an `aria-errormessage` IDREF on the host can't reach this node
|
|
106
|
+
* an `aria-errormessage` IDREF on the host can't reach this node, so the
|
|
107
|
+
* host sets none (it would dangle).
|
|
96
108
|
*/
|
|
97
109
|
protected renderError(): import("lit-html").TemplateResult<1> | null;
|
|
98
110
|
protected updated(changed: PropertyValues<this>): void;
|
package/components/cell.js
CHANGED
|
@@ -4,7 +4,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
var _a;
|
|
8
7
|
import { consume } from '@lit/context';
|
|
9
8
|
import { html, LitElement } from 'lit';
|
|
10
9
|
import { property, query } from 'lit/decorators.js';
|
|
@@ -62,7 +61,7 @@ function scrollRowIntoRange(scroller, body, index) {
|
|
|
62
61
|
const rowCentre = top + (index - first.index + 0.5) * height;
|
|
63
62
|
scroller.scrollTop += rowCentre - (view.top + scroller.clientHeight / 2);
|
|
64
63
|
}
|
|
65
|
-
class ApexGridCell extends LitElement {
|
|
64
|
+
export default class ApexGridCell extends LitElement {
|
|
66
65
|
constructor() {
|
|
67
66
|
super(...arguments);
|
|
68
67
|
this.active = false;
|
|
@@ -77,6 +76,7 @@ class ApexGridCell extends LitElement {
|
|
|
77
76
|
this.#staged = false;
|
|
78
77
|
this.#resumed = null;
|
|
79
78
|
this.#reconnected = false;
|
|
79
|
+
this.#rebound = false;
|
|
80
80
|
this.#handleClick = (event) => {
|
|
81
81
|
if (this.isEditing) {
|
|
82
82
|
event.stopPropagation();
|
|
@@ -170,17 +170,20 @@ class ApexGridCell extends LitElement {
|
|
|
170
170
|
}
|
|
171
171
|
static { this.styles = styles; }
|
|
172
172
|
static register() {
|
|
173
|
-
registerComponent(
|
|
173
|
+
registerComponent(ApexGridCell);
|
|
174
174
|
}
|
|
175
175
|
get context() {
|
|
176
|
+
const data = this.row.data;
|
|
177
|
+
const key = this.column.key;
|
|
176
178
|
const ctx = {
|
|
177
179
|
parent: this,
|
|
178
180
|
row: this.row,
|
|
179
181
|
column: this.column,
|
|
180
182
|
value: this.value,
|
|
183
|
+
data,
|
|
181
184
|
};
|
|
182
185
|
if (this.isEditable) {
|
|
183
|
-
ctx.commit = (next) => this.editingController.commitImmediate(
|
|
186
|
+
ctx.commit = (next) => this.editingController.commitImmediate(data, key, next);
|
|
184
187
|
}
|
|
185
188
|
return ctx;
|
|
186
189
|
}
|
|
@@ -199,12 +202,15 @@ class ApexGridCell extends LitElement {
|
|
|
199
202
|
const pin = this.state.rowPin;
|
|
200
203
|
return pin.hasPinnedRows && pin.enabled && pin.isPinned(this.row.data);
|
|
201
204
|
}
|
|
205
|
+
get #recycledBody() {
|
|
206
|
+
return Boolean(this.state.host.rowRecycling) && !this.#inPinnedBand;
|
|
207
|
+
}
|
|
202
208
|
#decoratedKeys;
|
|
203
|
-
static #ERROR_ID = 'apex-cell-error';
|
|
204
209
|
#errors;
|
|
205
210
|
#staged;
|
|
206
211
|
#resumed;
|
|
207
212
|
#reconnected;
|
|
213
|
+
#rebound;
|
|
208
214
|
connectedCallback() {
|
|
209
215
|
this.#reconnected = this.hasUpdated && !this.isUpdatePending;
|
|
210
216
|
super.connectedCallback();
|
|
@@ -238,8 +244,9 @@ class ApexGridCell extends LitElement {
|
|
|
238
244
|
return false;
|
|
239
245
|
}
|
|
240
246
|
willUpdate(changed) {
|
|
247
|
+
this.#rebound = this.hasUpdated && changed.has('record');
|
|
241
248
|
this.#applyStaged();
|
|
242
|
-
if (changed.has('editing')) {
|
|
249
|
+
if (changed.has('editing') || this.#rebound) {
|
|
243
250
|
this.#resumed = this.editing
|
|
244
251
|
? this.editingController.heldDraft(this.row.data, this.column.key)
|
|
245
252
|
: null;
|
|
@@ -289,13 +296,11 @@ class ApexGridCell extends LitElement {
|
|
|
289
296
|
this.#errors = errors && errors.length > 0 ? errors : null;
|
|
290
297
|
if (this.#errors) {
|
|
291
298
|
this.setAttribute('aria-invalid', 'true');
|
|
292
|
-
this.setAttribute('aria-errormessage', _a.#ERROR_ID);
|
|
293
299
|
this.setAttribute('data-invalid', '');
|
|
294
300
|
this.setAttribute('title', this.#errors.join('; '));
|
|
295
301
|
}
|
|
296
302
|
else {
|
|
297
303
|
this.removeAttribute('aria-invalid');
|
|
298
|
-
this.removeAttribute('aria-errormessage');
|
|
299
304
|
this.removeAttribute('data-invalid');
|
|
300
305
|
this.removeAttribute('title');
|
|
301
306
|
}
|
|
@@ -305,12 +310,13 @@ class ApexGridCell extends LitElement {
|
|
|
305
310
|
return null;
|
|
306
311
|
return html `<span
|
|
307
312
|
part="cell-error"
|
|
308
|
-
id=${_a.#ERROR_ID}
|
|
309
313
|
role="alert"
|
|
310
314
|
>${this.#errors.join('; ')}</span
|
|
311
315
|
>`;
|
|
312
316
|
}
|
|
313
317
|
#applyDecoration() {
|
|
318
|
+
if (!this.state?.hasCellDecorators && !this.#decoratedKeys.length)
|
|
319
|
+
return;
|
|
314
320
|
const decoration = this.state && this.row
|
|
315
321
|
? this.state.decorateCell({
|
|
316
322
|
row: this.row.data,
|
|
@@ -341,8 +347,13 @@ class ApexGridCell extends LitElement {
|
|
|
341
347
|
if (!changed.has('editing'))
|
|
342
348
|
return;
|
|
343
349
|
const editor = this.editorElement;
|
|
344
|
-
|
|
345
|
-
if (
|
|
350
|
+
const resumed = this.#resumed !== null || this.#rebound;
|
|
351
|
+
if (resumed && this.#recycledBody && !this.state.navigation.ownsFocus)
|
|
352
|
+
return;
|
|
353
|
+
if (resumed)
|
|
354
|
+
editor?.getBoundingClientRect();
|
|
355
|
+
editor?.focus(resumed ? { preventScroll: true } : undefined);
|
|
356
|
+
if (!resumed && editor instanceof HTMLInputElement) {
|
|
346
357
|
if (editor.type === 'text' || editor.type === 'number') {
|
|
347
358
|
editor.select();
|
|
348
359
|
}
|
|
@@ -351,6 +362,8 @@ class ApexGridCell extends LitElement {
|
|
|
351
362
|
}
|
|
352
363
|
if (changed.get('editing') === true && this.#refocusAfterEdit) {
|
|
353
364
|
this.#refocusAfterEdit = false;
|
|
365
|
+
if (this.#rebound && this.editingController.activeCell)
|
|
366
|
+
return;
|
|
354
367
|
this.focus();
|
|
355
368
|
}
|
|
356
369
|
}
|
|
@@ -482,6 +495,7 @@ class ApexGridCell extends LitElement {
|
|
|
482
495
|
row: this.row,
|
|
483
496
|
column: this.column,
|
|
484
497
|
value: this.#editorValue,
|
|
498
|
+
data: this.row.data,
|
|
485
499
|
commit: (next) => this.editingController.commitCell(next),
|
|
486
500
|
cancel: () => this.editingController.cancelCell(),
|
|
487
501
|
setDraft: (next) => this.editingController.setDraft(next),
|
|
@@ -586,11 +600,12 @@ class ApexGridCell extends LitElement {
|
|
|
586
600
|
return html `${this.renderCellBody()}${error}`;
|
|
587
601
|
}
|
|
588
602
|
}
|
|
589
|
-
_a = ApexGridCell;
|
|
590
|
-
export default ApexGridCell;
|
|
591
603
|
__decorate([
|
|
592
604
|
property({ attribute: false })
|
|
593
605
|
], ApexGridCell.prototype, "value", void 0);
|
|
606
|
+
__decorate([
|
|
607
|
+
property({ attribute: false })
|
|
608
|
+
], ApexGridCell.prototype, "record", void 0);
|
|
594
609
|
__decorate([
|
|
595
610
|
property({ attribute: false })
|
|
596
611
|
], ApexGridCell.prototype, "column", void 0);
|