apex-grid 3.6.0 → 4.0.0-beta.2
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 +301 -0
- package/LICENSE.md +2 -1
- package/README.md +117 -18
- 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 +175 -28
- package/components/grid.js +183 -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 -5
- package/controllers/state.js +53 -46
- package/controllers/state.js.map +1 -1
- package/custom-elements.json +1762 -339
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +166 -66
- 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 +123 -20
- 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/_token-values.scss +42 -16
- package/docs/media/package.json +12 -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/ignite-ui.d.ts +1 -0
- package/ignite-ui.js +4 -0
- package/ignite-ui.js.map +1 -0
- 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/design-system.d.ts +32 -0
- package/internal/design-system.js +66 -0
- package/internal/design-system.js.map +1 -0
- 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/icons.d.ts +2 -16
- package/internal/icons.js +0 -8
- package/internal/icons.js.map +1 -1
- package/internal/ignite-ui.d.ts +10 -0
- package/internal/ignite-ui.js +118 -0
- package/internal/ignite-ui.js.map +1 -0
- package/internal/index.d.ts +4 -2
- package/internal/index.js +3 -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 +7 -2
- package/styles/_token-blocks.css.d.ts +1 -0
- package/styles/_token-blocks.css.js +3 -0
- package/styles/_token-blocks.css.js.map +1 -0
- 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/document-tokens.css.js +1 -1
- package/styles/document-tokens.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/ignite-ui/ignite-ui-dark.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui-dark.css.js +3 -0
- package/styles/ignite-ui/ignite-ui-dark.css.js.map +1 -0
- package/styles/ignite-ui/ignite-ui-document.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui-document.css.js +3 -0
- package/styles/ignite-ui/ignite-ui-document.css.js.map +1 -0
- package/styles/ignite-ui/ignite-ui.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui.css.js +3 -0
- package/styles/ignite-ui/ignite-ui.css.js.map +1 -0
- 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/tokens.css +14 -15
- 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,307 @@ 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.2] - 2026-11-08
|
|
10
|
+
|
|
11
|
+
A second pre-release of 4.0.0, under the `next` npm tag. It adds opt-in
|
|
12
|
+
Ignite UI theming (`apex-grid/ignite-ui`) and the family `--apx-*` tokens.
|
|
13
|
+
Breaking against 4.0.0-beta.1 and 3.x: an Ignite UI stylesheet no longer
|
|
14
|
+
re-tints the brand or replaces the font until you import the add-on, and
|
|
15
|
+
`--ag-font` has no root default any more (see Changed and Fixed).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **`apex-grid/ignite-ui`, the Ignite UI add-on.** `import 'apex-grid/ignite-ui'`
|
|
19
|
+
once and every grid on the page follows the Ignite UI theme the page loads:
|
|
20
|
+
brand, text and muted text, gridlines and the pinned-column edge, the header
|
|
21
|
+
(`--ig-surface-raised`, Ignite UI 7.5 and later), state colours, font and the
|
|
22
|
+
enterprise popups (`--ig-surface-overlay` on 7.5 and later). A grid without
|
|
23
|
+
`theme="dark"` or `theme="light"` follows the Ignite UI variant, live, with
|
|
24
|
+
a JS fallback where the browser has no container style queries;
|
|
25
|
+
`theme="light"` keeps a grid light. Ranking: an `--ag-*` token you set, then
|
|
26
|
+
the family `--apx-*` tokens, then Ignite UI, then the built-in values. Per
|
|
27
|
+
grid, `design-system="off"` turns the Ignite UI colours and font off (the
|
|
28
|
+
variant still picks the mode) and `tokens="off"` turns off the family tokens
|
|
29
|
+
and Ignite UI, variant included (both also as the reflected `designSystem`
|
|
30
|
+
and `tokens` properties). It registers on a shared `globalThis` slot, so it
|
|
31
|
+
reaches the grids of a separately built bundle too. While the add-on is
|
|
32
|
+
loaded, the tokens that follow Ignite UI (text, lines, surfaces, header,
|
|
33
|
+
state colours, pinned edge) leave the root defaults, so page CSS that reads
|
|
34
|
+
one needs its own fallback. It adds about 2.5 KB gzip to an app, and only
|
|
35
|
+
where it is imported.
|
|
36
|
+
- **The family `--apx-*` tokens** shared by every Apex product: `--apx-accent`
|
|
37
|
+
(brand), `--apx-fore` (text), `--apx-grid` (gridlines, row borders, header
|
|
38
|
+
separator), `--apx-surface` (card and row background), `--apx-font-family`
|
|
39
|
+
and `--apx-radius-factor`, each ranked below the matching `--ag-*` token.
|
|
40
|
+
The text, line and surface root defaults are now written as their family
|
|
41
|
+
chain (`--ag-text: var(--apx-fore, #111827)` in `:where(:root)` and
|
|
42
|
+
`apex-grid/tokens.css`), so they follow a family token set on `:root`.
|
|
43
|
+
- `--apx-radius-factor` scales `--ag-radius`, `--ag-radius-sm` and
|
|
44
|
+
`--ag-radius-xs` while it is set. Unset or 1, every radius is unchanged
|
|
45
|
+
(a multi-value radius too, without a factor); the pill stays round.
|
|
46
|
+
- `tokens="off"` (or `grid.tokens = false`) keeps one grid, and the content it
|
|
47
|
+
renders, off the family tokens, with or without the add-on. Without the
|
|
48
|
+
add-on, an `--apx-fore`, `--apx-grid` or `--apx-surface` set on `:root` still
|
|
49
|
+
reaches that grid through the root defaults, which resolve there.
|
|
50
|
+
- `--ag-overlay` and `--ag-overlay-text` (dark grids: `--ag-dark-overlay`,
|
|
51
|
+
`--ag-dark-overlay-text`) colour the `apex-grid-enterprise` popups. They have
|
|
52
|
+
no default: unset, each popup keeps its built-in colours.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
- **Breaking: the grid no longer reads Ignite UI tokens by itself.** Before,
|
|
56
|
+
an Ignite UI theme on the page re-tinted the brand (`--ig-primary-500`,
|
|
57
|
+
`--ig-primary-700`) and replaced the font (`--ig-font-family`) with no
|
|
58
|
+
import. Now an Ignite UI stylesheet changes nothing until you import
|
|
59
|
+
`apex-grid/ignite-ui`, which brings the brand and font back along with the
|
|
60
|
+
rest of the theme.
|
|
61
|
+
- The grid now follows the family `--apx-*` tokens (above). A page that sets
|
|
62
|
+
them for its charts, on `:root` for example, sees the grid follow them too.
|
|
63
|
+
Set the matching `--ag-*` tokens to keep the grid as it was, or set the
|
|
64
|
+
family tokens on the elements they are meant for.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
- An explicit `--ag-font` now wins over the family and Ignite UI fonts, the
|
|
68
|
+
same order the brand tokens use. Before, an Ignite UI theme on the page
|
|
69
|
+
replaced the grid font even when `--ag-font` was set on the grid itself. The
|
|
70
|
+
default Inter stack is unchanged. To keep the family and Ignite UI fonts
|
|
71
|
+
reachable, `--ag-font` no longer has a root default (it is gone from
|
|
72
|
+
`:where(:root)` and `apex-grid/tokens.css`), so page CSS that reads
|
|
73
|
+
`var(--ag-font)` needs its own fallback, as with `--ag-brand`.
|
|
74
|
+
|
|
75
|
+
## [4.0.0-beta.1] - 2026-10-29
|
|
76
|
+
|
|
77
|
+
A pre-release of 4.0.0, published under the `next` npm tag for trying out
|
|
78
|
+
before it becomes `latest`. It is a major version because these changes can
|
|
79
|
+
break existing code:
|
|
80
|
+
|
|
81
|
+
- **Body rows are recycled by default** (`rowRecycling`). A row element and
|
|
82
|
+
its cells can show another record after a scroll, sort or filter, so a
|
|
83
|
+
template that keeps state in the elements it creates, or code that holds
|
|
84
|
+
`grid.rows` elements or `ctx.row` across an `await`, can see another
|
|
85
|
+
record. Set `rowRecycling = false` (or `row-recycling="false"`) to keep
|
|
86
|
+
record-keyed rows.
|
|
87
|
+
- **The grid role moved off the host.** `role`, `aria-rowcount`,
|
|
88
|
+
`aria-colcount`, `aria-multiselectable` and the accessible name are on the
|
|
89
|
+
inner `[part~="table"]` element.
|
|
90
|
+
- **Types removed:** `DataPipelineConfiguration.pagination` and the
|
|
91
|
+
`'pagination'` value of `DataPipelineParams.type`.
|
|
92
|
+
- **Pagination:** pinned rows no longer count toward `totalItems` and the
|
|
93
|
+
pages, and a local page change no longer calls custom sort and filter hooks.
|
|
94
|
+
- **Smaller type and DOM changes:** `ctx.data` is a required field of the cell
|
|
95
|
+
context, `ApexGridPaginator.pageSizeOptions` is `readonly number[]`, the
|
|
96
|
+
paginator's previous button id is `prev`, and the protected
|
|
97
|
+
`ApexGrid.headerRowCount` and `ApexGridHeaderRow.renderDragGhost` are gone.
|
|
98
|
+
|
|
99
|
+
See Changed and Removed for the details and for other changes apps may notice.
|
|
100
|
+
|
|
101
|
+
### Added
|
|
102
|
+
- The `ai.cancelled` locale key (English and Spanish), used by the enterprise
|
|
103
|
+
Ask AI panel.
|
|
104
|
+
- The `chart.rangeResized` locale key (English and Spanish), announced when an
|
|
105
|
+
enterprise charted range is resized from the keyboard.
|
|
106
|
+
- **`showHeader`** (attribute `show-header="false"`) leaves out the column
|
|
107
|
+
header row, the column group row and the filter panel, so a short grid such as
|
|
108
|
+
a dashboard tile gives that room to the data rows. Screen readers still
|
|
109
|
+
announce the column names, and sort, filter, column widths and the page come
|
|
110
|
+
back unchanged when the header returns. While it is hidden, resizing, the
|
|
111
|
+
column menu, drag reorder and the header filter button are unavailable.
|
|
112
|
+
([#35](https://github.com/apexcharts/apex-grid/issues/35))
|
|
113
|
+
- **`selection.isRowSelectable(row)`** keeps chosen rows out of selection,
|
|
114
|
+
such as a pinned total row. Such a row shows no checkbox, and clicks, Shift
|
|
115
|
+
and Ctrl clicks, Space, Select all, `selectRow` and `setState` all skip it;
|
|
116
|
+
the header checkbox counts only selectable rows. Rows stay selectable by
|
|
117
|
+
default, pinned rows included.
|
|
118
|
+
([#38](https://github.com/apexcharts/apex-grid/issues/38))
|
|
119
|
+
- `pagination.paginator: 'compact'` draws the small paginator: summary,
|
|
120
|
+
previous, page / count, next.
|
|
121
|
+
([#36](https://github.com/apexcharts/apex-grid/issues/36))
|
|
122
|
+
- `apex-grid::part()` reaches every paginator and toolbar part
|
|
123
|
+
(`paginator-host`, `paginator`, `paginator-size`, `paginator-info`,
|
|
124
|
+
`paginator-controls`, `paginator-page`, `paginator-button`, `toolbar-host`,
|
|
125
|
+
`toolbar`, `toolbar-search`, `search-input`, `toolbar-actions`, `export`,
|
|
126
|
+
`export-menu` and the rest), and each paginator button also carries its own
|
|
127
|
+
part: `paginator-first`, `paginator-prev`, `paginator-next` or
|
|
128
|
+
`paginator-last`. ([#37](https://github.com/apexcharts/apex-grid/issues/37))
|
|
129
|
+
- **`ctx.data` in cell and editor templates.** The context handed to a
|
|
130
|
+
`cellTemplate` or an `editorTemplate` carries `data`, the record the cell
|
|
131
|
+
was rendered for. It stays that record after an `await`, while `ctx.row`
|
|
132
|
+
and `ctx.parent` are elements that a pinned row band can later re-bind to
|
|
133
|
+
another record. A `cellTemplate`'s `ctx.commit` writes to `ctx.data`. An
|
|
134
|
+
editor's `ctx.commit` still commits the cell in edit when it is called.
|
|
135
|
+
|
|
136
|
+
### Changed
|
|
137
|
+
- **Body rows are now recycled by default** (new `rowRecycling` property,
|
|
138
|
+
default `true`). A scroll, sort or filter re-binds the rendered row elements
|
|
139
|
+
to the records now in view instead of building new rows, which makes long
|
|
140
|
+
jumps and sorts cheaper on large grids. A row element, and its cells, can
|
|
141
|
+
therefore show another record later. Cell and editor templates should
|
|
142
|
+
derive what they render from their context on each render, read
|
|
143
|
+
`ctx.data` for the record, and not hold `ctx.row` or `ctx.parent` across an
|
|
144
|
+
`await`; a template that keeps element state can wrap itself in
|
|
145
|
+
`keyed(ctx.data, ...)`. What you might notice: a template that keeps state
|
|
146
|
+
in the elements it creates (an input's typed value, a third-party widget)
|
|
147
|
+
can show it on another record after a scroll or a sort, and code that holds
|
|
148
|
+
`grid.rows` elements across a scroll or a sort finds them showing other
|
|
149
|
+
records. To keep record-keyed rows, set `grid.rowRecycling = false` (or the
|
|
150
|
+
`row-recycling="false"` attribute). Detail panel content follows its record
|
|
151
|
+
and keeps its DOM state across a scroll, a sort or a `moveRow`, so detail
|
|
152
|
+
templates need no change; a grid created inside a `detailTemplate` keeps its
|
|
153
|
+
own setting.
|
|
154
|
+
- **The grid role and its row counts moved from the `<apex-grid>` host to an
|
|
155
|
+
inner element** exposed as part `table`: `role` (`grid` or `treegrid`),
|
|
156
|
+
`aria-rowcount`, `aria-colcount`, `aria-multiselectable` and the accessible
|
|
157
|
+
name. It holds only the header rows and the body, so the toolbar, paginator,
|
|
158
|
+
filter panel and live region are no longer read as table content, and every
|
|
159
|
+
default grid passes the axe `aria-required-children` rule. Code or tests
|
|
160
|
+
that read these from the host should query
|
|
161
|
+
`grid.shadowRoot.querySelector('[part~="table"]')`. The layout is unchanged.
|
|
162
|
+
- An `aria-label` or `aria-labelledby` on the host still names the grid, and
|
|
163
|
+
`aria-describedby` becomes its description. References are resolved when the
|
|
164
|
+
grid renders: if the referenced element is added later, set the attribute
|
|
165
|
+
again.
|
|
166
|
+
- The grid uses the `treegrid` role whenever rows carry levels or expand: tree
|
|
167
|
+
data, master-detail with a detail template, and the enterprise row grouping,
|
|
168
|
+
expandable pivot and server-side grouping.
|
|
169
|
+
- `pageItems` keeps the same array between updates while nothing that shapes
|
|
170
|
+
it changes. Apps that compared it by identity now see a new array only when
|
|
171
|
+
the body rows change.
|
|
172
|
+
- The column header row is no longer a Tab stop.
|
|
173
|
+
- **The built-in column menu opens in the top layer** where the browser supports
|
|
174
|
+
the Popover API: pinned rows, the paginator and the grid's edge no longer
|
|
175
|
+
cover or clip it, it stays on its header cell through any scroll or layout
|
|
176
|
+
change, and it closes when its column scrolls out of the grid. It can now
|
|
177
|
+
extend outside the grid's box.
|
|
178
|
+
- The column drag ghost renders at the grid root, so it stays above the column
|
|
179
|
+
group header and pinned top rows, and `apex-grid::part(drag-ghost)` now
|
|
180
|
+
reaches it.
|
|
181
|
+
- `--filtering-header-background` applies to every filtered header, pinned and
|
|
182
|
+
dragged ones included, as a layer over the header's own background, and
|
|
183
|
+
filtered headers get the same hover highlight as other headers.
|
|
184
|
+
- The paginator follows `--header-background` and group header labels follow
|
|
185
|
+
`--header-text-color`, like the rest of the header area. The paginator text
|
|
186
|
+
size follows `--ag-fs-cell-secondary`, and the filter count badge uses
|
|
187
|
+
`--ag-text-on-brand` and `--ag-fw-semibold`. Default rendering is unchanged.
|
|
188
|
+
- Forced colors (Windows High Contrast): checkboxes are drawn by the browser in
|
|
189
|
+
system colours, so apps that styled them through parts see the native
|
|
190
|
+
checkbox in that mode only.
|
|
191
|
+
- With pagination, pinned rows no longer count toward the pages: `totalItems`,
|
|
192
|
+
`pageCount`, the paginator summary and the `pageChanged` detail count the
|
|
193
|
+
rows the pager pages through, and pinning a row on the last page moves to the
|
|
194
|
+
new last page. Without pagination `totalItems` still counts every row.
|
|
195
|
+
- A local page or page size change no longer reruns sorting, filtering and the
|
|
196
|
+
rest of the pipeline, so custom sort and filter hooks are no longer called on
|
|
197
|
+
a local page change. Remote mode still reruns it.
|
|
198
|
+
- `pageChanged` reports the change that was applied, so two quick
|
|
199
|
+
`nextPage()` calls report page 2 and then page 3.
|
|
200
|
+
- A page change is announced once ("Page X of N"); the paginator summary and
|
|
201
|
+
page label are no longer live regions.
|
|
202
|
+
- The first grid on a page adds one window `error` listener that cancels
|
|
203
|
+
"ResizeObserver loop" messages and hides them from listeners added after it.
|
|
204
|
+
Listeners registered before the first grid still receive them. Every other
|
|
205
|
+
error is untouched. ([#32](https://github.com/apexcharts/apex-grid/issues/32))
|
|
206
|
+
- `totalItems` is described one way everywhere: the post-filter, post-sort
|
|
207
|
+
row count, and in remote mode the `pagination.totalItems` you supply, the
|
|
208
|
+
number of rows the server holds for the current filter.
|
|
209
|
+
([#34](https://github.com/apexcharts/apex-grid/issues/34))
|
|
210
|
+
- Type and DOM details for code that builds on the grid's internals:
|
|
211
|
+
`BaseApexCellContext.data` is required, so code that builds a cell context
|
|
212
|
+
by hand must supply it; `ApexGridPaginator.pageSizeOptions` is typed
|
|
213
|
+
`readonly number[]`; the paginator's previous button has the id `prev`
|
|
214
|
+
(it was `previous`) inside its shadow root; and the protected
|
|
215
|
+
`ApexGrid.headerRowCount` and `ApexGridHeaderRow.renderDragGhost` were
|
|
216
|
+
removed, which affects subclasses only.
|
|
217
|
+
- The `@lit-labs/virtualizer` dependency is pinned to exactly `2.1.1` (it was
|
|
218
|
+
`~2.1.0`). The grid body builds on parts of that package that are not public
|
|
219
|
+
API, so a newer version arrives only with a grid release that has been
|
|
220
|
+
checked against it.
|
|
221
|
+
|
|
222
|
+
### Removed
|
|
223
|
+
- **Breaking (types):** `DataPipelineConfiguration.pagination` and the
|
|
224
|
+
`'pagination'` value of `DataPipelineParams.type`. The hook was documented
|
|
225
|
+
but never called, so no runtime behaviour changes; TypeScript code that sets
|
|
226
|
+
it stops compiling. For server paging use `pagination.mode: 'remote'`, fetch
|
|
227
|
+
the page on `pageChanged` and keep `pagination.totalItems` current.
|
|
228
|
+
([#33](https://github.com/apexcharts/apex-grid/issues/33))
|
|
229
|
+
|
|
230
|
+
### Fixed
|
|
231
|
+
- `aria-rowcount` no longer counts the floating filter panel as a row, and a
|
|
232
|
+
pinned top row no longer shares its `aria-rowindex` with the first body row.
|
|
233
|
+
- The master-detail panel sits in a full-width gridcell, and `aria-expanded` is
|
|
234
|
+
set only on rows and toggle buttons that can expand. Turning expansion off or
|
|
235
|
+
removing the detail template no longer leaves it on rows.
|
|
236
|
+
- Announcing the same message twice in a row (two identical `grid.announce()`
|
|
237
|
+
calls, for example) is read out again by screen readers.
|
|
238
|
+
- Invalid cells no longer set an `aria-errormessage` that pointed at an
|
|
239
|
+
unreachable id. The inline alert message is unchanged.
|
|
240
|
+
- Range and formula reference highlights on a pinned column no longer let
|
|
241
|
+
scrolled cells show through it.
|
|
242
|
+
- Alternating row stripes follow the row index, so they no longer flip or
|
|
243
|
+
flicker while you scroll.
|
|
244
|
+
- In the dark theme the default, muted and gold badges are readable and the
|
|
245
|
+
progress bar track is visible. The light theme is unchanged.
|
|
246
|
+
- The selected row accent bar sits on the leading edge in right to left
|
|
247
|
+
layouts, including a left to right grid nested in a right to left one.
|
|
248
|
+
- Forced colors: checked and indeterminate checkboxes no longer look unchecked;
|
|
249
|
+
in a selected row the cell text, row number, reorder grip and chevrons take
|
|
250
|
+
the selection text colour; an editor opened in a selected row uses the
|
|
251
|
+
system field colours; a keyboard-grabbed row shows an outline.
|
|
252
|
+
- The paginator no longer clips its controls in a narrow grid: it drops the
|
|
253
|
+
rows per page selector, then the first and last buttons, so previous and next
|
|
254
|
+
stay reachable. ([#36](https://github.com/apexcharts/apex-grid/issues/36))
|
|
255
|
+
- Grids whose cell text wraps no longer raise "ResizeObserver loop completed
|
|
256
|
+
with undelivered notifications" while they resize or scroll.
|
|
257
|
+
([#32](https://github.com/apexcharts/apex-grid/issues/32))
|
|
258
|
+
- With row pinning and pagination, no trailing page is left empty.
|
|
259
|
+
- A `pageSize` missing from `pageSizeOptions` now appears in the rows per
|
|
260
|
+
page selector and is selected.
|
|
261
|
+
- A page size change or quick filter cancelled through `pageChanging` or
|
|
262
|
+
`quickFilterChanging` no longer leaves the selector or search box showing
|
|
263
|
+
the refused value.
|
|
264
|
+
- **Pinned rows no longer show the previous row's state.** When a pinned row
|
|
265
|
+
element switches to another record (a row above it is unpinned, say), it no
|
|
266
|
+
longer keeps the previous record's staged row edit value, validation error,
|
|
267
|
+
expanded state, detail panel content or selection checkbox state, even when
|
|
268
|
+
both records hold the same cell value.
|
|
269
|
+
- A `cellTemplate` that calls `ctx.commit` after an `await` writes to the
|
|
270
|
+
record it was rendered for, even if the rows changed in the meantime.
|
|
271
|
+
- Moving a keyboard grabbed row with the arrow keys keeps focus on that row
|
|
272
|
+
instead of dropping it to the page, and Escape puts the active cell and
|
|
273
|
+
focus back on the row at its original position.
|
|
274
|
+
- The floating ghost of a row drag shows the row's cell text. It showed empty
|
|
275
|
+
cells before.
|
|
276
|
+
- An editor rendered again for an edit already in progress (its row scrolled
|
|
277
|
+
back into view, for example) no longer scrolls the grid or selects the typed
|
|
278
|
+
draft when it takes focus.
|
|
279
|
+
- With an async `dataPipelineConfiguration` hook, moving a row with
|
|
280
|
+
`moveRow`, a keyboard grab or a drag animates the rows into their new places.
|
|
281
|
+
They jumped there without the animation before.
|
|
282
|
+
- A jump to a row far outside the view that is still waiting for the body to
|
|
283
|
+
finish scrolling no longer runs after a newer jump, so two quick jumps end on
|
|
284
|
+
the second row instead of snapping back to the first.
|
|
285
|
+
- A pinned row that switches to another record no longer animates from the
|
|
286
|
+
previous record's look: its selected wash, expand chevron, checkbox and
|
|
287
|
+
progress bars show the new record's state at once.
|
|
288
|
+
- An image cell whose URL changes (a pinned row switching records, an edit of
|
|
289
|
+
the URL) renders a new `<img>`, so the previous picture no longer stays on
|
|
290
|
+
screen while the new one loads.
|
|
291
|
+
- Arrow and Page keys in a grid whose rows grew after they were first shown
|
|
292
|
+
(detail panels expanded, wrapped text) keep the active cell in view and
|
|
293
|
+
focused. A quick run of key presses could leave it unrendered, with focus on
|
|
294
|
+
the body or on a cell of another record, until the next click.
|
|
295
|
+
- When a sort, a filter or a data change moves the record of an open cell
|
|
296
|
+
edit to another row that is still in view, the active cell moves with it, so
|
|
297
|
+
the keyboard carries on from the edited cell once the edit closes. It used to
|
|
298
|
+
stay on the old row, which then showed another record.
|
|
299
|
+
|
|
300
|
+
### Performance
|
|
301
|
+
- Scrolling no longer re-renders the rows that stay in view; only the rows that
|
|
302
|
+
scroll in render.
|
|
303
|
+
- A grid with a pinned row or a page slice no longer rescans the whole view on
|
|
304
|
+
every key press or click.
|
|
305
|
+
- Grids without feature modules skip the per-cell decoration step, and grids
|
|
306
|
+
with modules no longer check every module on each row and cell render.
|
|
307
|
+
|
|
7
308
|
## [3.6.0] - 2026-10-21
|
|
8
309
|
|
|
9
310
|
A quality release built from a full code-quality audit, plus `--ag-*` tokens
|
package/LICENSE.md
CHANGED
|
@@ -85,10 +85,11 @@ Required if you are **embedding ApexGrid into a product or platform used by othe
|
|
|
85
85
|
✅ What's included:
|
|
86
86
|
|
|
87
87
|
- Redistribution rights for **one application or product**
|
|
88
|
-
- **Unlimited developer seats** on that application, with no separate per-developer license to buy
|
|
89
88
|
- **Every licensed feature**, at the highest tier
|
|
90
89
|
- 12-month subscription with updates & support
|
|
91
90
|
|
|
91
|
+
⚠️ **Developer licenses are purchased separately.** The OEM License grants redistribution rights and carries no developer seats. Each developer who works with ApexGrid in that application also needs a **Community + Commercial** license of their own. That is the tier whatever features your product uses, because the license key comes from the OEM License and already renders every licensed feature.
|
|
92
|
+
|
|
92
93
|
Your end users need no license of their own. A second application needs a second OEM license. White-label, resale, and affiliate arrangements are quoted separately.
|
|
93
94
|
|
|
94
95
|
✅ OEM **not required** if your app simply renders static grids and users **cannot** configure or interact with them.
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ A Lit-based, framework-agnostic web component data grid. Ships as a single custo
|
|
|
29
29
|
- **CSV export**: programmatic method plus an optional toolbar dropdown. (Excel/XLSX export is in `apex-grid-enterprise`.)
|
|
30
30
|
- **Toolbar**: opt-in `<apex-grid-toolbar>` with debounced quick filter and export menu.
|
|
31
31
|
- **Templating**: slot-based templates for cells, headers, editors, and detail panels.
|
|
32
|
-
- **Theming**: styled out-of-the-box; fully customizable through `--ag-*` CSS custom properties (no theme import or build step)
|
|
32
|
+
- **Theming**: styled out-of-the-box; fully customizable through `--ag-*` CSS custom properties (no theme import or build step), and follows the `--apx-*` tokens shared by every Apex product. One import (`apex-grid/ignite-ui`) makes it follow an Ignite UI theme, light or dark.
|
|
33
33
|
- **Accessibility**: WCAG 2.2 AA semantics (`role="grid"` / `role="treegrid"`, `aria-rowcount`, `aria-colcount`, focus + keyboard navigation).
|
|
34
34
|
- **Provenance-signed npm releases** with OIDC trusted publishing.
|
|
35
35
|
|
|
@@ -130,11 +130,15 @@ See [`src/styles/_token-values.scss`](src/styles/_token-values.scss) for the ful
|
|
|
130
130
|
import 'apex-grid/tokens.css';
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
The grid renders the same without the sheet; it carries the defaults as fallbacks.
|
|
133
|
+
The grid renders the same without the sheet; it carries the defaults as fallbacks. Four groups have no root default, so page CSS reading them needs its own fallback:
|
|
134
134
|
|
|
135
|
-
- `--ag-brand` and `--ag-brand-strong`, so an Ignite UI palette set on any ancestor
|
|
135
|
+
- `--ag-brand` and `--ag-brand-strong`, so a family `--apx-accent` (or, with the Ignite UI add-on, an Ignite UI palette) set on any ancestor still reaches the grid (see below).
|
|
136
|
+
- `--ag-font`, for the same reason (`--apx-font-family`, an Ignite UI font).
|
|
137
|
+
- `--ag-overlay` and `--ag-overlay-text` (and `--ag-dark-overlay`, `--ag-dark-overlay-text`): unset, the enterprise popups keep their own colours (see below).
|
|
136
138
|
- The derived washes `--ag-brand-soft`, `--ag-brand-softer`, `--ag-brand-line`, `--ag-row-hover` and `--ag-surface-alt`. The grid mixes them from the brand and surface in effect, so they follow a brand set on an ancestor. Set them only to override the mix.
|
|
137
139
|
|
|
140
|
+
The root defaults of the text, line and surface tokens are written as their family chain (`--ag-text: var(--apx-fore, #111827)`), so they follow a family token set on `:root` (see below).
|
|
141
|
+
|
|
138
142
|
**Dark mode.** `theme="dark"` reads its own colour inputs, `--ag-dark-*` (`--ag-dark-surface`, `--ag-dark-text`, `--ag-dark-hairline`, `--ag-dark-shadow-card`, and so on), so a light palette set on a shared ancestor never puts a white surface under the dark theme's light text. Sizing, typography, motion, the brand and the base state colours are shared by both modes. To theme both from one place, set both palettes:
|
|
139
143
|
|
|
140
144
|
```css
|
|
@@ -155,7 +159,34 @@ apex-grid[theme~='dark'] { --ag-grid-shadow: var(--ag-dark-shadow-card); } /* th
|
|
|
155
159
|
apex-grid { --ag-grid-shadow: none; } /* remove the edge entirely */
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
**Enterprise popups.** `--ag-overlay` and `--ag-overlay-text` colour the popups of `apex-grid-enterprise` (filter builder, set filter, AI panel, tool panel, status bar); dark grids read `--ag-dark-overlay` and `--ag-dark-overlay-text`. Set both: the popup lines, muted text and hover wash are mixed from the two. Unset, each popup keeps its built-in colours.
|
|
163
|
+
|
|
164
|
+
**Family tokens (`--apx-*`).** The grid also reads the tokens every Apex product shares, ranked below its own: `--apx-accent` (brand), `--apx-fore` (text), `--apx-grid` (gridlines, row borders, header separator), `--apx-surface` (card and row background), `--apx-font-family` and `--apx-radius-factor`. An `--ag-*` or `--ag-dark-*` token you set wins over them, and they apply to light and dark grids alike. The brand, font and radius factor reach the grid from any ancestor. Text, lines and surface have root defaults, which resolve on `:root`: they follow a family token set on `:root` (or, with the Ignite UI add-on, which lifts those defaults, on any ancestor). `--apx-radius-factor` scales `--ag-radius`, `--ag-radius-sm` and `--ag-radius-xs` while it is set; at 1 nothing changes, the pill shape stays round, and a multi-value radius (`--ag-radius: 12px 12px 0 0`) works only without a factor.
|
|
165
|
+
|
|
166
|
+
`tokens="off"` on a grid (or `grid.tokens = false`) keeps it off the family tokens and the content it renders too. One limit without the Ignite UI add-on: an `--apx-fore`, `--apx-grid` or `--apx-surface` set on `:root` has already resolved into the text, line and surface root defaults there, which every grid reads, so that grid still shows it; set the matching `--ag-*` tokens on it, or set the family tokens on the elements they are meant for.
|
|
167
|
+
|
|
168
|
+
```css
|
|
169
|
+
:root {
|
|
170
|
+
--apx-accent: #7c3aed;
|
|
171
|
+
--apx-font-family: 'Source Sans 3', sans-serif;
|
|
172
|
+
--apx-radius-factor: 0.5;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Ignite UI.** To follow an Ignite UI theme, import the add-on once:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import 'apex-grid/ignite-ui';
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Every grid on the page, in the document or in any shadow root, then follows the Ignite UI theme the page loads, including grids that connected before the import: the brand (`--ig-primary-*`), text and muted text, gridlines and the pinned-column edge (the gray ramp), the header (`--ig-surface-raised`, Ignite UI 7.5 and later), the state colours, the font, and the enterprise popups (`--ig-surface-overlay` on 7.5 and later, else the grid's own popup colours). The card and row surfaces keep the grid's own light or dark background. Without the add-on the grid reads no `--ig-*` token, and an Ignite UI stylesheet changes nothing.
|
|
183
|
+
|
|
184
|
+
- **Ranking:** an `--ag-*` token you set, then the family `--apx-*` tokens, then Ignite UI, then the built-in values.
|
|
185
|
+
- **Mode:** a grid without `theme="dark"` or `theme="light"` follows the Ignite UI variant (`--ig-theme-variant`) declared on `:root` or any ancestor (as Ignite UI themes do), and a theme swap live. `theme="light"` keeps a grid light (text and lines then keep the built-in values, since a dark theme's grays are light) and `theme="dark"` keeps it dark. Where the browser has no container style queries, grids follow the document's variant.
|
|
186
|
+
- **Per grid:** `design-system="off"` (the `designSystem` property set to `false`) turns the Ignite UI colours and font off (the variant still picks the mode); `tokens="off"` (`tokens = false`) turns off the family tokens and Ignite UI, the variant included, for the grid and the content it renders.
|
|
187
|
+
- **Root defaults:** while the add-on is loaded, the tokens that follow Ignite UI (text, lines, surfaces, header, state colours, pinned edge) leave the root defaults, as `--ag-brand` and `--ag-font` always have, so page CSS that reads one gives its own fallback: `var(--ag-text, #111827)`.
|
|
188
|
+
- **Other products:** each takes its own add-on. For the `apex-grid-enterprise` chart panel to read the theme itself, also import `apexcharts/features/ignite-ui` (ApexCharts releases that ship it); the grid never loads it, since it themes every chart on the page. Without it the panel chart takes the grid's colours, which follow the theme.
|
|
189
|
+
- **Bundles:** the add-on registers on a shared `globalThis` slot, so it reaches every grid even when the grid and the add-on come from separately built bundles.
|
|
159
190
|
|
|
160
191
|
### 4. Size the host
|
|
161
192
|
|
|
@@ -192,6 +223,9 @@ With the element registered and the host sized, you should see:
|
|
|
192
223
|
| `<apex-grid>` blank tag in DOM | Step 2: element not registered |
|
|
193
224
|
| 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
225
|
|
|
226
|
+
> [!NOTE]
|
|
227
|
+
> 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.
|
|
228
|
+
|
|
195
229
|
---
|
|
196
230
|
|
|
197
231
|
## Features in depth
|
|
@@ -255,7 +289,20 @@ await grid.setPageSize(50);
|
|
|
255
289
|
grid.nextPage(); grid.previousPage(); grid.firstPage(); grid.lastPage();
|
|
256
290
|
```
|
|
257
291
|
|
|
258
|
-
|
|
292
|
+
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:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
grid.pagination = { enabled: true, pageSize: 5, paginator: 'compact' };
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
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`:
|
|
299
|
+
|
|
300
|
+
```css
|
|
301
|
+
apex-grid::part(paginator-first),
|
|
302
|
+
apex-grid::part(paginator-last) { display: none; }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
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
306
|
|
|
260
307
|
```ts
|
|
261
308
|
grid.pagination = { enabled: true, mode: 'remote', pageSize: 25, totalItems: 1280 };
|
|
@@ -264,7 +311,7 @@ grid.addEventListener('pageChanged', async (e) => {
|
|
|
264
311
|
});
|
|
265
312
|
```
|
|
266
313
|
|
|
267
|
-
Properties: `page`, `pageSize`, `pageCount`, `totalItems`, `pageItems`. Events: `pageChanging` (cancellable), `pageChanged`.
|
|
314
|
+
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
315
|
|
|
269
316
|
### Column pinning
|
|
270
317
|
|
|
@@ -305,6 +352,16 @@ grid.columnSeparator = false; // hide the dividers
|
|
|
305
352
|
|
|
306
353
|
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
354
|
|
|
355
|
+
### Hiding the header
|
|
356
|
+
|
|
357
|
+
For a compact table, such as a short dashboard tile, leave out the header rows and give their room to the data rows:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
grid.showHeader = false; // or <apex-grid show-header="false">
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
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`.
|
|
364
|
+
|
|
308
365
|
### Column groups (spanning headers)
|
|
309
366
|
|
|
310
367
|
```ts
|
|
@@ -388,9 +445,21 @@ A keyboard-driven commit or cancel returns focus to the cell, so navigation
|
|
|
388
445
|
continues from where you were. Sorting, filtering, selection, paging, row
|
|
389
446
|
pinning, reorder, expansion, and undo / redo are announced through a polite
|
|
390
447
|
live region, and every announcement and control label is localizable (the
|
|
391
|
-
`announce.*` and `header.*` locale keys).
|
|
392
|
-
|
|
393
|
-
`
|
|
448
|
+
`announce.*` and `header.*` locale keys).
|
|
449
|
+
|
|
450
|
+
The `grid` role (`treegrid` for tree data, master-detail and other expandable
|
|
451
|
+
rows), `aria-rowcount`, `aria-colcount` and `aria-multiselectable` sit on the
|
|
452
|
+
element exposed as `part="table"` inside the shadow root, not on the
|
|
453
|
+
`<apex-grid>` host. It holds only the header rows and the body, so the toolbar,
|
|
454
|
+
paginator and live region around it are not read as table content. It gets a
|
|
455
|
+
localized `aria-label` ("Data grid") unless you put `aria-label` or
|
|
456
|
+
`aria-labelledby` on the host, which then names it. An `aria-describedby` on
|
|
457
|
+
the host becomes its description. The references are resolved when the grid
|
|
458
|
+
renders, so if you add the referenced element later (a heading shown
|
|
459
|
+
conditionally), set the attribute again afterwards to pick it up.
|
|
460
|
+
|
|
461
|
+
> Changed in 4.0.0: the role and the row and column counts used to be on the
|
|
462
|
+
> host. Query `grid.shadowRoot.querySelector('[part~="table"]')` instead.
|
|
394
463
|
|
|
395
464
|
> Changed in 3.4.0: Home / End used to jump to the first / last row; they now
|
|
396
465
|
> stay within the row. Use Ctrl/Cmd+Home / Ctrl/Cmd+End for the grid corners.
|
|
@@ -435,6 +504,8 @@ grid.selectedRows; // snapshot
|
|
|
435
504
|
grid.selectedRows = [data[2]]; // replace selection (goes through `rowSelecting`)
|
|
436
505
|
```
|
|
437
506
|
|
|
507
|
+
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.
|
|
508
|
+
|
|
438
509
|
Events: `rowSelecting` (cancellable), `rowSelected`.
|
|
439
510
|
|
|
440
511
|
### Row pinning (top / bottom)
|
|
@@ -503,7 +574,7 @@ await grid.toggleTreeRow(data[0]);
|
|
|
503
574
|
await grid.expandAllTreeRows();
|
|
504
575
|
```
|
|
505
576
|
|
|
506
|
-
Methods: `toggleTreeRow`, `expandTreeRow`, `collapseTreeRow`, `expandAllTreeRows`, `collapseAllTreeRows`, `isTreeRowExpanded`. Events: `treeRowExpanding` (cancellable), `treeRowExpanded`. When tree mode is active, the
|
|
577
|
+
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
578
|
|
|
508
579
|
### CSV export
|
|
509
580
|
|
|
@@ -529,16 +600,19 @@ Renders a download icon in the toolbar's trailing actions area; the menu has an
|
|
|
529
600
|
|
|
530
601
|
### Toolbar
|
|
531
602
|
|
|
532
|
-
Rendered automatically above the header row when at least one of `show-quick-filter` or `show-export` is on. CSS parts:
|
|
603
|
+
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
604
|
|
|
534
605
|
| Part | What |
|
|
535
606
|
|---|---|
|
|
607
|
+
| `toolbar-host` | The `<apex-grid-toolbar>` element |
|
|
536
608
|
| `toolbar` | Root container |
|
|
537
609
|
| `toolbar-search` | Quick-filter input wrapper |
|
|
538
610
|
| `search-field` | The bordered input field |
|
|
539
611
|
| `search-icon`, `search-input` | Leading icon, input element |
|
|
540
612
|
| `toolbar-actions` | Trailing actions area |
|
|
541
|
-
| `
|
|
613
|
+
| `toolbar-action` | A host-contributed action button |
|
|
614
|
+
| `export` | Export menu wrapper |
|
|
615
|
+
| `export-trigger`, `export-icon`, `export-caret` | Export menu button and its icons |
|
|
542
616
|
| `export-menu` | Dropdown panel |
|
|
543
617
|
| `export-menu-item` | Menu item |
|
|
544
618
|
|
|
@@ -546,13 +620,13 @@ Search input has a `debounce` attribute (default `200`ms).
|
|
|
546
620
|
|
|
547
621
|
### Theming
|
|
548
622
|
|
|
549
|
-
The grid styles itself through `--ag-*` CSS custom properties; override them on `apex-grid` or any ancestor (shadow hosts included) to rebrand, and use `--ag-dark-*` for dark grids. See [Customize the look](#3-optional-customize-the-look) and [`src/styles/_token-values.scss`](src/styles/_token-values.scss) for the full list.
|
|
623
|
+
The grid styles itself through `--ag-*` CSS custom properties; override them on `apex-grid` or any ancestor (shadow hosts included) to rebrand, and use `--ag-dark-*` for dark grids. See [Customize the look](#3-optional-customize-the-look) and [`src/styles/_token-values.scss`](src/styles/_token-values.scss) for the full list. The grid also follows the family `--apx-*` tokens, and an Ignite UI theme with the opt-in `apex-grid/ignite-ui` add-on (both under Customize the look).
|
|
550
624
|
|
|
551
625
|
Style with CSS parts on the grid, paginator, and toolbar:
|
|
552
626
|
|
|
553
627
|
```css
|
|
554
628
|
apex-grid::part(paginator) { background: var(--surface-2); }
|
|
555
|
-
apex-grid
|
|
629
|
+
apex-grid::part(search-input) { font-family: var(--font-mono); }
|
|
556
630
|
```
|
|
557
631
|
|
|
558
632
|
Body rows re-export these parts, so `apex-grid::part(name)` reaches them:
|
|
@@ -611,6 +685,27 @@ grid.coordinateHints = true;
|
|
|
611
685
|
|
|
612
686
|
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
687
|
|
|
688
|
+
### Row recycling
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
grid.rowRecycling = false; // opt out
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
```html
|
|
695
|
+
<apex-grid row-recycling="false"></apex-grid>
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
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:
|
|
699
|
+
|
|
700
|
+
- Derive everything a template renders from its context on each render, and keep no state in the elements it creates.
|
|
701
|
+
- 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`.
|
|
702
|
+
- 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`.
|
|
703
|
+
- 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.
|
|
704
|
+
|
|
705
|
+
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.
|
|
706
|
+
|
|
707
|
+
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.
|
|
708
|
+
|
|
614
709
|
### State & persistence
|
|
615
710
|
|
|
616
711
|
`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 +742,7 @@ See [`demo/state-persistence.html`](../../demo/state-persistence.html) for a sav
|
|
|
647
742
|
| `columns` | `ColumnConfiguration<T>[]` | `[]` | Column configuration (property only) |
|
|
648
743
|
| `autoGenerate` | `boolean` | `false` | Infer columns from `data[0]` keys. Attr `auto-generate` |
|
|
649
744
|
| `sortConfiguration` | `GridSortConfiguration` | `{ multiple, triState }` | |
|
|
650
|
-
| `dataPipelineConfiguration` | `DataPipelineConfiguration<T>` | | Custom sort
|
|
745
|
+
| `dataPipelineConfiguration` | `DataPipelineConfiguration<T>` | | Custom sort, filter and quick filter hooks |
|
|
651
746
|
| `pagination` | `PaginationConfiguration` | | |
|
|
652
747
|
| `quickFilter` | `string` | `''` | Attr `quick-filter` |
|
|
653
748
|
| `showQuickFilter` | `boolean` | `false` | Attr `show-quick-filter` |
|
|
@@ -662,6 +757,10 @@ See [`demo/state-persistence.html`](../../demo/state-persistence.html) for a sav
|
|
|
662
757
|
| `rowReordering` | `GridRowReorderingConfiguration` | | `{ enabled, applyToData?, handle? }` (`handle` default `true`: grip-only drag) |
|
|
663
758
|
| `coordinateHints` | `boolean` | `false` | Show a row-number gutter + A / B / C header chips (spreadsheet look). Attr `coordinate-hints` |
|
|
664
759
|
| `columnMenu` | `boolean` | `true` | Show the always-visible column-menu (kebab) button on headers; `false` hides it |
|
|
760
|
+
| `showHeader` | `boolean` | `true` | `false` hides the header rows (kept for screen readers). Attr `show-header="false"` |
|
|
761
|
+
| `designSystem` | `boolean` | `true` | With the `apex-grid/ignite-ui` add-on, `false` turns the Ignite UI colours and font off for this grid (the variant still picks the mode). Reflected as `design-system="off"` |
|
|
762
|
+
| `tokens` | `boolean` | `true` | `false` turns the family `--apx-*` tokens (and, with the add-on, Ignite UI) off for this grid and its content. Reflected as `tokens="off"` |
|
|
763
|
+
| `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
764
|
| `rowId` | `(row: T) => string \| number` | | Durable row identity for `getState` / `setState` |
|
|
666
765
|
| `localeText` | `GridLocaleText` | | Override map for built-in strings (e.g. `esLocale`) |
|
|
667
766
|
| `canUndo`, `canRedo` | `boolean` | | Get (history) |
|
|
@@ -751,14 +850,14 @@ Programmatic `sort()` / `filter()` calls are silent; only UI-initiated changes e
|
|
|
751
850
|
|
|
752
851
|
### Attributes
|
|
753
852
|
|
|
754
|
-
`auto-generate`, `quick-filter`, `show-quick-filter`, `show-export`, `column-reordering`, `coordinate-hints`.
|
|
853
|
+
`auto-generate`, `quick-filter`, `show-quick-filter`, `show-export`, `column-reordering`, `coordinate-hints`, `show-header`, `row-recycling`. Theming: `theme` (`dark`, `light`, `tinted`), `tokens="off"` and, with the `apex-grid/ignite-ui` add-on, `design-system="off"` (see [Customize the look](#3-optional-customize-the-look)).
|
|
755
854
|
|
|
756
855
|
### CSS parts
|
|
757
856
|
|
|
758
857
|
| Component | Parts |
|
|
759
858
|
|---|---|
|
|
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` |
|
|
859
|
+
| `<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`) |
|
|
860
|
+
| `<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
861
|
| `<apex-grid-cell>` | `cell`, `editor` |
|
|
763
862
|
|
|
764
863
|
---
|
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;
|