apex-grid 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +439 -0
- package/LICENSE.md +125 -0
- package/README.md +107 -14
- package/components/cell.d.ts +30 -4
- package/components/cell.js +199 -53
- package/components/cell.js.map +1 -1
- package/components/filter-row.d.ts +2 -0
- package/components/filter-row.js +82 -28
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +257 -20
- package/components/grid.js +463 -99
- package/components/grid.js.map +1 -1
- package/components/group-header-row.js +28 -25
- package/components/group-header-row.js.map +1 -1
- package/components/header-row.d.ts +7 -5
- package/components/header-row.js +19 -9
- package/components/header-row.js.map +1 -1
- package/components/header.js +36 -22
- package/components/header.js.map +1 -1
- package/components/row.d.ts +19 -3
- package/components/row.js +96 -22
- package/components/row.js.map +1 -1
- package/components/toolbar.js +2 -1
- package/components/toolbar.js.map +1 -1
- package/components/virtualizer.d.ts +45 -1
- package/components/virtualizer.js +184 -3
- package/components/virtualizer.js.map +1 -1
- package/controllers/dom.d.ts +4 -4
- package/controllers/dom.js +40 -22
- package/controllers/dom.js.map +1 -1
- package/controllers/editing.d.ts +104 -37
- package/controllers/editing.js +230 -78
- package/controllers/editing.js.map +1 -1
- package/controllers/expansion.d.ts +14 -5
- package/controllers/expansion.js +24 -1
- package/controllers/expansion.js.map +1 -1
- package/controllers/filter.d.ts +10 -2
- package/controllers/filter.js +62 -17
- package/controllers/filter.js.map +1 -1
- package/controllers/history.d.ts +45 -8
- package/controllers/history.js +58 -20
- package/controllers/history.js.map +1 -1
- package/controllers/navigation.d.ts +68 -13
- package/controllers/navigation.js +196 -51
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.d.ts +6 -0
- package/controllers/pagination.js +10 -2
- package/controllers/pagination.js.map +1 -1
- package/controllers/reorder.js +42 -24
- package/controllers/reorder.js.map +1 -1
- package/controllers/resize.d.ts +17 -2
- package/controllers/resize.js +16 -6
- package/controllers/resize.js.map +1 -1
- package/controllers/row-pin.d.ts +20 -2
- package/controllers/row-pin.js +16 -9
- package/controllers/row-pin.js.map +1 -1
- package/controllers/row-reorder.d.ts +31 -11
- package/controllers/row-reorder.js +117 -37
- package/controllers/row-reorder.js.map +1 -1
- package/controllers/selection.d.ts +11 -4
- package/controllers/selection.js +26 -11
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.d.ts +22 -2
- package/controllers/sort.js +29 -23
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +65 -10
- package/controllers/state.js +86 -6
- package/controllers/state.js.map +1 -1
- package/controllers/tree.d.ts +15 -10
- package/controllers/tree.js +0 -0
- package/controllers/tree.js.map +1 -1
- package/custom-elements.json +3589 -452
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +15 -8
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +660 -0
- package/docs/classes/ApexGridPaginator.html +36 -0
- package/docs/classes/ApexGridToolbar.html +67 -0
- package/docs/functions/localize.html +2 -2
- package/docs/functions/setup.html +1 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +105 -15
- package/docs/interfaces/ApexCellValidationFailedEvent.html +3 -2
- package/docs/interfaces/ApexCellValueChangedEvent.html +4 -2
- package/docs/interfaces/ApexCellValueChangingEvent.html +3 -2
- package/docs/interfaces/ApexColumnMovedEvent.html +2 -2
- package/docs/interfaces/ApexColumnMovingEvent.html +1 -1
- package/docs/interfaces/ApexDetailContext.html +2 -2
- package/docs/interfaces/ApexGridEventMap.html +9 -6
- package/docs/interfaces/ApexRowEditEndedEvent.html +2 -1
- package/docs/interfaces/ApexRowEditStartedEvent.html +2 -1
- package/docs/interfaces/ApexRowMovingEvent.html +9 -3
- package/docs/interfaces/ApexRowPinningEvent.html +1 -1
- package/docs/interfaces/ApexTreeRowExpandedEvent.html +4 -1
- package/docs/interfaces/ApexTreeRowExpandingEvent.html +4 -1
- package/docs/interfaces/BaseApexCellContext.html +1 -1
- package/docs/interfaces/BaseApexEditorContext.html +1 -1
- package/docs/interfaces/BaseColumnConfiguration.html +3 -3
- package/docs/interfaces/BaseFilterExpression.html +2 -2
- package/docs/interfaces/CSVExportOptions.html +13 -5
- package/docs/interfaces/DataPipelineConfiguration.html +2 -2
- package/docs/interfaces/EditingHistoryConfiguration.html +1 -1
- package/docs/interfaces/ExportFormat.html +2 -2
- package/docs/interfaces/ExportOptions.html +5 -3
- package/docs/interfaces/GridExpansionConfiguration.html +6 -2
- package/docs/interfaces/GridRowPinningConfiguration.html +1 -1
- package/docs/interfaces/GridRowReorderingConfiguration.html +2 -2
- package/docs/interfaces/PaginationConfiguration.html +1 -1
- package/docs/interfaces/PaginationState.html +1 -1
- package/docs/interfaces/SetStateResult.html +3 -2
- package/docs/interfaces/ValidatorContext.html +7 -2
- package/docs/media/_token-values.scss +118 -0
- package/docs/media/package.json +5 -5
- package/docs/media/state-persistence.html +0 -10
- package/docs/modules.html +1 -1
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/EditMode.html +2 -2
- package/docs/types/ExportSource.html +6 -4
- package/docs/types/GridLocaleText.html +1 -1
- package/docs/types/OperandKeys.html +9 -0
- package/docs/types/PaginationMode.html +1 -1
- package/docs/variables/EN_LOCALE.html +3 -3
- package/docs/variables/esLocale.html +1 -1
- package/i18n/en.d.ts +19 -0
- package/i18n/en.js +19 -0
- package/i18n/en.js.map +1 -1
- package/i18n/es.js +19 -0
- package/i18n/es.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/internal/column-types.d.ts +27 -1
- package/internal/column-types.js +75 -49
- package/internal/column-types.js.map +1 -1
- package/internal/constants.d.ts +1 -2
- package/internal/constants.js +0 -4
- package/internal/constants.js.map +1 -1
- package/internal/document-styles.d.ts +30 -0
- package/internal/document-styles.js +48 -0
- package/internal/document-styles.js.map +1 -0
- package/internal/export.d.ts +39 -7
- package/internal/export.js +35 -34
- package/internal/export.js.map +1 -1
- package/internal/feature-module.d.ts +82 -3
- package/internal/feature-module.js +11 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/index.d.ts +6 -4
- package/internal/index.js +5 -3
- package/internal/index.js.map +1 -1
- package/internal/normalize-case.d.ts +8 -1
- package/internal/normalize-case.js +3 -2
- package/internal/normalize-case.js.map +1 -1
- package/internal/state-snapshot.d.ts +60 -8
- package/internal/state-snapshot.js +87 -19
- package/internal/state-snapshot.js.map +1 -1
- package/internal/types.d.ts +17 -2
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +48 -6
- package/internal/utils.js +35 -21
- package/internal/utils.js.map +1 -1
- package/internal/validators.js +1 -0
- package/internal/validators.js.map +1 -1
- package/operations/filter/operands/number.js +9 -6
- package/operations/filter/operands/number.js.map +1 -1
- package/operations/filter/operands/string.js +2 -3
- package/operations/filter/operands/string.js.map +1 -1
- package/operations/filter/types.d.ts +13 -1
- package/operations/filter/types.js.map +1 -1
- package/operations/filter.d.ts +6 -0
- package/operations/filter.js +23 -7
- package/operations/filter.js.map +1 -1
- package/operations/quick-filter.js +2 -5
- package/operations/quick-filter.js.map +1 -1
- package/operations/sort.d.ts +21 -2
- package/operations/sort.js +41 -14
- package/operations/sort.js.map +1 -1
- package/package.json +8 -4
- package/setup.d.ts +23 -11
- package/setup.js +19 -21
- package/setup.js.map +1 -1
- package/styles/_common.css.js +1 -1
- package/styles/_common.css.js.map +1 -1
- package/styles/_token-values.css.d.ts +1 -0
- package/styles/_token-values.css.js +3 -0
- package/styles/_token-values.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.d.ts +1 -0
- package/styles/document-tokens.css.js +3 -0
- package/styles/document-tokens.css.js.map +1 -0
- package/styles/filter-row/filter-row.css.js +1 -1
- package/styles/filter-row/filter-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/tokens.css +78 -0
- package/LICENSE +0 -80
- package/docs/media/LICENSE +0 -80
- package/docs/media/_tokens.scss +0 -193
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,445 @@ 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
|
+
## [3.6.0] - 2026-10-21
|
|
8
|
+
|
|
9
|
+
A quality release built from a full code-quality audit, plus `--ag-*` tokens
|
|
10
|
+
that reach the grid from any ancestor (shadow roots included). No exported
|
|
11
|
+
symbol was removed or renamed. A few documented contracts now hold where they
|
|
12
|
+
did not: `sorted`, `filtered`, `pageChanged` and `quickFilterChanged` fire after
|
|
13
|
+
the pipeline run they caused, and a row move on a sorted grid clears the sort.
|
|
14
|
+
See Changed for what apps may notice.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **`--ag-*` tokens set on any ancestor now reach the grid**, including the
|
|
18
|
+
shadow host of a web component the grid renders in, however deep. Set a
|
|
19
|
+
theme once on your own host element and every grid inside follows it. See
|
|
20
|
+
"Changed" for how the defaults moved to make this work.
|
|
21
|
+
- **Dark-mode inputs `--ag-dark-*`** (`--ag-dark-surface`, `--ag-dark-text`,
|
|
22
|
+
`--ag-dark-hairline`, `--ag-dark-shadow-card`, …) for every colour
|
|
23
|
+
`theme="dark"` changes. Dark grids read these instead of the light inputs,
|
|
24
|
+
so a light palette set on a shared ancestor never puts a white surface under
|
|
25
|
+
the dark theme's light text. Sizing, typography, motion, the brand and the
|
|
26
|
+
base state colours stay shared by both modes.
|
|
27
|
+
- **`apex-grid/tokens.css`**: the token defaults as a plain stylesheet, for
|
|
28
|
+
server rendering or for apps that opt out of the adopted sheet.
|
|
29
|
+
- **`setup({ tokenStyles: false })`** skips adopting the token defaults into
|
|
30
|
+
the document.
|
|
31
|
+
- **`applyEdits()` entries can name their row by record**: `{ row, column,
|
|
32
|
+
value }` alongside the positional `{ rowIndex, column, value }`. A record
|
|
33
|
+
reaches rows on other pages, pinned rows and rows under a collapsed tree
|
|
34
|
+
parent, so `grid.selectedRows.map((row) => ({ row, column, value }))` now
|
|
35
|
+
edits the whole selection; with `rowIndex` such rows were skipped. Events
|
|
36
|
+
and validators for those rows see `rowIndex` -1.
|
|
37
|
+
- **`ApexGrid.ownsEvent(event)`** tells whether an event came from this grid
|
|
38
|
+
or from a grid nested in one of its master-detail panels. The grid uses it
|
|
39
|
+
so cells of a nested grid no longer drive the outer one (clicks, Space
|
|
40
|
+
selection, Ctrl+Z, pointer drags).
|
|
41
|
+
- `CSVExportOptions.escapeFormulas` (default `true`), see the change below.
|
|
42
|
+
- Locale keys `toolPanel.valueColumn` and `toolPanel.columnLabelColumn` for the
|
|
43
|
+
enterprise tool panel, in English and Spanish.
|
|
44
|
+
- Locale key `chart.mapCategoryNone` (English "None", Spanish "Ninguna") for
|
|
45
|
+
the enterprise chart panel's Category select.
|
|
46
|
+
- Locale key `setFilter.more` for the enterprise set filter's list cap, in
|
|
47
|
+
English and Spanish.
|
|
48
|
+
- `expansion.exportParts` lists parts inside your `detailTemplate` content
|
|
49
|
+
for the row to re-export, so `apex-grid::part(name)` can style them.
|
|
50
|
+
- Locale key `pivot.columnsTruncated` for the enterprise pivot column cap, in
|
|
51
|
+
English and Spanish.
|
|
52
|
+
- `rowMoving` and `rowMoved` carry `position` (`'before'` or `'after'`) and
|
|
53
|
+
`toIndex`, the view index the row lands at, next to `from`, `to` and
|
|
54
|
+
`data`.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
- **Token defaults moved from the grid host to the document root.** The grid
|
|
58
|
+
used to declare every `--ag-*` default on its own host, and a declaration on
|
|
59
|
+
an element always beats an inherited value, so tokens set on an ancestor
|
|
60
|
+
never reached it (only `--ig-primary-500` did, through the brand fallback).
|
|
61
|
+
The defaults now sit on `:where(:root)`, adopted into the document through
|
|
62
|
+
`adoptedStyleSheets` when the first grid connects (no `<style>` element, so
|
|
63
|
+
no CSP nonce), and the grid resolves them into private copies on its host.
|
|
64
|
+
Reading tokens keeps working: `var(--ag-surface)` resolves to the default
|
|
65
|
+
anywhere on the page, and `apex-grid { --ag-grid-shadow:
|
|
66
|
+
var(--ag-shadow-card); }` still gives the card shadow. Changes to look for:
|
|
67
|
+
- `var(--ag-brand)` and `var(--ag-brand-strong)` have no root default, so an
|
|
68
|
+
Ignite UI palette set on any ancestor keeps tinting the grid. Page CSS
|
|
69
|
+
reading them needs its own fallback.
|
|
70
|
+
- Derived tokens (`--ag-brand-soft`, `--ag-brand-softer`, `--ag-brand-line`,
|
|
71
|
+
`--ag-row-hover`, `--ag-surface-alt`) are mixed on the grid host so they
|
|
72
|
+
follow a brand set lower down. They still accept an override but have no
|
|
73
|
+
root default to read.
|
|
74
|
+
- A value set on an element above a dark grid (`--ag-surface`, …) no longer
|
|
75
|
+
applies to it; set `--ag-dark-surface` and the other `--ag-dark-*` inputs.
|
|
76
|
+
A value set on the dark grid element itself is now ignored the same way.
|
|
77
|
+
On a dark grid, use `--ag-grid-shadow: var(--ag-dark-shadow-card)` for the
|
|
78
|
+
card shadow recipe.
|
|
79
|
+
- `theme="tinted"` mixes the brand into the surface, gridline and
|
|
80
|
+
muted-text values in effect (yours, if you set them) instead of replacing
|
|
81
|
+
them. Its row separators stay the brand alone, so a tinted grid ignores
|
|
82
|
+
`--ag-border` and `--ag-dark-border`, including on the grid element itself.
|
|
83
|
+
The default tinted look is unchanged.
|
|
84
|
+
- **CSV export neutralises spreadsheet formulas.** A text cell or header that
|
|
85
|
+
starts with `=`, `+`, `-`, `@`, a tab or a carriage return is written with a
|
|
86
|
+
leading apostrophe, so a spreadsheet opening the file shows it as text
|
|
87
|
+
instead of running it. Numbers are untouched, and so is text that is a plain
|
|
88
|
+
signed decimal such as `-5` or `+1.5`. Other text with a leading sign gains
|
|
89
|
+
the apostrophe too: a lone `-`, a phone number such as `+44 20 7946 0958`,
|
|
90
|
+
`-1,234.50`, or formatter output such as `-$5.00`. Pass
|
|
91
|
+
`exportToCSV({ escapeFormulas: false })` for the old output.
|
|
92
|
+
- **An open editor stays on the record it was opened for** when the data,
|
|
93
|
+
sort, filter or page changes while editing; before, it could jump to another
|
|
94
|
+
row and Enter wrote into the wrong record. The edit is cancelled when its
|
|
95
|
+
record leaves the view (removed, filtered out or replaced by a copy).
|
|
96
|
+
`editingCell`, `editingRow` and the `rowIndex` of the edit events are -1 when
|
|
97
|
+
the edited record is in a pinned row or on another page.
|
|
98
|
+
- **Row mode edits the staged row.** Cells of the row in edit show their staged
|
|
99
|
+
values, validators receive the staged row as `ctx.data` (a copy of the
|
|
100
|
+
record with the staged values applied), and a row commit re-validates the
|
|
101
|
+
row's other editable cells. A checkbox click, or any `cellTemplate` calling
|
|
102
|
+
`ctx.commit`, joins the row edit instead of writing straight to the record,
|
|
103
|
+
so `cancelEdit()` rolls it back.
|
|
104
|
+
- **After tabbing into the grid body, the first arrow, Home or Page Up key
|
|
105
|
+
activates the first cell** instead of moving past it (ArrowDown lands on
|
|
106
|
+
row 0). Page Up and Page Down move by the rows that fit in the body instead
|
|
107
|
+
of a fixed 10.
|
|
108
|
+
- **Tree data under a filter shows the ancestors of a match as their own
|
|
109
|
+
rows** (selectable and exportable, not matching the filter themselves)
|
|
110
|
+
instead of blank placeholders, and matches under a non-matching parent are
|
|
111
|
+
no longer hidden.
|
|
112
|
+
- **Replacing `grid.data` prunes tree and detail expansion** of rows that left
|
|
113
|
+
the data, so `getState()` no longer lists rows that are gone.
|
|
114
|
+
- **Exports write booleans as the checkbox shows them**: true only for
|
|
115
|
+
`true`, so strings such as `'false'` or `'yes'` and the number 1 export as
|
|
116
|
+
false. **Currency and progress columns export as numbers**, like number and
|
|
117
|
+
rating columns; text that is not a number exports as an empty cell.
|
|
118
|
+
- **Replacing `grid.data` with new records clears the undo history** (and
|
|
119
|
+
fires `historyChanged`). Undo used to replay onto the old, detached records:
|
|
120
|
+
nothing changed on screen, yet `cellValueChanged` fired for a row the grid no
|
|
121
|
+
longer held. New data that keeps the edited records, such as an appended
|
|
122
|
+
row, keeps its history, and so do in-place edits. A subclass that keeps
|
|
123
|
+
records outside `data` (a row model that drops collapsed rows and restores
|
|
124
|
+
the same objects) overrides the protected `historyRecords()` to keep their
|
|
125
|
+
history too.
|
|
126
|
+
- **`cellValueChanged` from undo or redo reports `rowIndex` -1 when the
|
|
127
|
+
record is pinned or on another page**, instead of the index it had when
|
|
128
|
+
edited (which could name a different row). Listeners that read `rowIndex`
|
|
129
|
+
from a replayed change should identify the row by the event's `data`.
|
|
130
|
+
- `applyEdits()` skips an entry whose `rowIndex` is negative or fractional,
|
|
131
|
+
as it already skipped one past the end of the page. 3.5.0 counted a negative
|
|
132
|
+
index from the end of the page and rounded a fraction down.
|
|
133
|
+
- **`sortExpressions` and `filterExpressions` replace the current sort or filter
|
|
134
|
+
instead of merging into it**, as documented and as `setState` already did;
|
|
135
|
+
`[]`, `null` or `undefined` clears it. Apps that assigned one expression at a
|
|
136
|
+
time to build up a multi-column sort or filter should assign the full list (or
|
|
137
|
+
call `sort()` / `filter()`, which still add). The assigned list applies at the
|
|
138
|
+
next update, against the columns as they are then, so a template may bind it
|
|
139
|
+
before `columns`; reading it back before that returns what was assigned. Sort
|
|
140
|
+
entries for an unknown column or with an unknown direction are dropped with a
|
|
141
|
+
console warning (an omitted direction still sorts ascending).
|
|
142
|
+
- **`currency`, `rating` and `progress` columns filter as numbers**, as their
|
|
143
|
+
type docs already said. The filter panel offers the number conditions (Equals,
|
|
144
|
+
Greater than, Less than and so on) and reads the typed value as a number, and
|
|
145
|
+
`getSchema()` lists the number operands for these columns. A saved state or
|
|
146
|
+
`filter()` call that names a text condition such as `contains` on one of them
|
|
147
|
+
is now dropped with a console warning; in 3.5.0 those conditions threw inside
|
|
148
|
+
the pipeline and filtered nothing. Feature modules read the rule through
|
|
149
|
+
`StateController.isNumericColumn(column)`.
|
|
150
|
+
- Feature modules can reveal a cell, read the inline direction of an arrow key
|
|
151
|
+
under RTL and read the scroll insets through the grid's navigation
|
|
152
|
+
controller (`revealCell`, `towardsInlineEnd`, `scrollInsets`), so the
|
|
153
|
+
enterprise range selection follows core navigation instead of a copy.
|
|
154
|
+
- **Cell templates run again after each data pipeline run.** A column
|
|
155
|
+
`cellTemplate` is called for every visible row, body and pinned, after each
|
|
156
|
+
pipeline run (sort, filter, quick filter, edit, tree toggle), so a template
|
|
157
|
+
that reads other fields of its row stays current. Keep templates light;
|
|
158
|
+
plain and typed cells are not re-rendered by this.
|
|
159
|
+
- Start-pinned columns freeze after the leading checkbox, expansion, reorder
|
|
160
|
+
grip and row-number columns instead of at the grid edge. The grid sets
|
|
161
|
+
`--apex-chrome-offset-row-number`, `--apex-chrome-offset-reorder`,
|
|
162
|
+
`--apex-chrome-offset-selection` and `--apex-chrome-offset-expansion` on the
|
|
163
|
+
host and no longer writes `--scrollbar-offset` inline (the stylesheet
|
|
164
|
+
default stays).
|
|
165
|
+
- A decoration-only change (range selection, formula reference highlight)
|
|
166
|
+
updates cell attributes without re-rendering cell content. For feature
|
|
167
|
+
modules, `bumpDecoration` now only re-applies `CellDecorator` attributes;
|
|
168
|
+
request a pipeline run when content must change.
|
|
169
|
+
- Feature modules can attach a command to a cell edit and its undo step, and
|
|
170
|
+
read the header's sortable rule through `SortController.isSortable`.
|
|
171
|
+
- Pressing on interactive content in a `headerTemplate` (an input, select,
|
|
172
|
+
textarea, button, link or editable element) no longer starts a column drag.
|
|
173
|
+
- When a `columnMoving` listener cancels a live swap, the event is raised once
|
|
174
|
+
per target crossing instead of on every pointer move.
|
|
175
|
+
- The filter panel's `filtering` event carries a proposed copy of the
|
|
176
|
+
expression for panel edits, and the change is applied only after the event
|
|
177
|
+
is not cancelled. Escape pressed outside the panel is no longer swallowed.
|
|
178
|
+
- Switching an applied Empty or Not empty filter to a condition that needs a
|
|
179
|
+
value removes the filter (with a cancellable remove) until a value is typed.
|
|
180
|
+
- `getState()` and `setState()` copy array filter terms, and feature modules
|
|
181
|
+
can register a filter operand by name (`registerFilterOperand` on
|
|
182
|
+
`apex-grid/internal`) so a saved filter that uses it restores.
|
|
183
|
+
- **`sorted`, `filtered`, `pageChanged` and `quickFilterChanged` fire after
|
|
184
|
+
the pipeline run they caused.** With an asynchronous
|
|
185
|
+
`dataPipelineConfiguration` hook, listeners now read the new rows and
|
|
186
|
+
totals. With synchronous hooks they still fire in the same task, after the
|
|
187
|
+
re-render of the new rows. The server-side and infinite row models fetch
|
|
188
|
+
outside the pipeline, so with them these events can still fire before the
|
|
189
|
+
new block arrives.
|
|
190
|
+
- `setQuickFilter` (and the toolbar search box) fires `pageChanged` and
|
|
191
|
+
announces the page when it moves the grid back to the first page. Setting
|
|
192
|
+
the `quickFilter` property or calling `setState` stays silent.
|
|
193
|
+
- Every part a row renders can be styled with `apex-grid::part()`:
|
|
194
|
+
selection, expansion, detail panel, row number and reorder parts, and the
|
|
195
|
+
parts of rows a module renders. Before, only `cell` was reachable, so
|
|
196
|
+
existing `::part()` rules for these names now take effect.
|
|
197
|
+
- **Moving a row on a sorted grid clears the sort** and keeps the moved order,
|
|
198
|
+
so the sort indicator goes away on the first move and `getState` never
|
|
199
|
+
reports a sort and a row order together. Before, an `applyToData` move was
|
|
200
|
+
undone by the re-sort.
|
|
201
|
+
- A move that leaves the row where it is (`moveRow(0, 1, 'before')`, for
|
|
202
|
+
example) returns `false` and fires no `rowMoving` or `rowMoved`.
|
|
203
|
+
- Escape after keyboard grab steps restores the original order (and
|
|
204
|
+
`grid.data` with `applyToData`, and any sort) and fires `rowMoved` for the
|
|
205
|
+
way back, so a persisted order stays in sync.
|
|
206
|
+
|
|
207
|
+
### Fixed
|
|
208
|
+
- **`setup()` host sizing reaches grids inside a shadow root.** The
|
|
209
|
+
`min-height: 240px` default was adopted into the page only, which never
|
|
210
|
+
styles an element inside a shadow root. Each grid now adopts it into the
|
|
211
|
+
root it connects in, and for its own tag name, so `<apex-grid-enterprise>`
|
|
212
|
+
gets it too.
|
|
213
|
+
- **ArrowDown and ArrowUp in the toolbar's export menu move focus again.** The
|
|
214
|
+
menu looked up the focused item through `document.activeElement`, which is
|
|
215
|
+
the grid's host because the menu lives in the grid's shadow root, so focus
|
|
216
|
+
never moved past the first item.
|
|
217
|
+
- **Text filter conditions no longer throw on a cell that is not a string.**
|
|
218
|
+
Contains, Starts with, Equals and the rest read `null` and `undefined` as
|
|
219
|
+
empty text and match numbers, dates and other values on their text. In 3.5.0
|
|
220
|
+
one such cell (an optional field left empty, a Date in a date column) made
|
|
221
|
+
the filter apply nothing and stopped later sorts until it was removed.
|
|
222
|
+
- `OperandKeys` offers the text operand names for a field whose type is not
|
|
223
|
+
number, string or boolean (a `Date`, for example), matching what the grid
|
|
224
|
+
applies, instead of accepting the value type itself as a condition. A
|
|
225
|
+
nullable or optional field keeps the names of its type (`number | null`
|
|
226
|
+
still takes the number names only), and a field typed `unknown`, such as
|
|
227
|
+
every field of a `Record<string, unknown>` row, keeps every operand name.
|
|
228
|
+
- **Number range conditions no longer match an empty cell.** Greater than, Less
|
|
229
|
+
than and their or equal forms read `null`, and an empty string from CSV or
|
|
230
|
+
JSON data, as 0, so Less than 20 included rows with no value. Empty now
|
|
231
|
+
matches those cells instead.
|
|
232
|
+
- **OR filter criteria are evaluated per column.** An OR on one column no longer
|
|
233
|
+
cancels the OR conditions of other columns, so `(city is Paris OR Oslo) AND
|
|
234
|
+
(id is 3 OR 99)` keeps the matching rows instead of none, and a column left
|
|
235
|
+
with only OR conditions (after removing its first chip) filters again instead
|
|
236
|
+
of keeping every row.
|
|
237
|
+
- A filter entry without `caseSensitive` (from `setState`, `filter()` or an AI
|
|
238
|
+
patch) keeps the column's `filter.caseSensitive` instead of turning case
|
|
239
|
+
sensitivity off.
|
|
240
|
+
- Removing a filter that is not applied, such as typing `-` or `.` first into a
|
|
241
|
+
number filter, or clearing a column that has no filter, no longer fires
|
|
242
|
+
`filtering` and `filtered` or announces that the filter was cleared.
|
|
243
|
+
- When the filter changes (a condition or term is added, edited or removed, or
|
|
244
|
+
the filter is cleared), the grid scrolls back to its first row. The reset
|
|
245
|
+
targeted an element that does not scroll, so a deep scroll offset was clamped
|
|
246
|
+
to the end of the shorter result and the first matches sat above the fold.
|
|
247
|
+
Reapplying the same filter, such as `setState(getState())` or assigning an
|
|
248
|
+
equal `filterExpressions` list on every render, keeps the scroll position.
|
|
249
|
+
- **A batch of edits made inside another undoes as one step.** A
|
|
250
|
+
`cellValueChanged` listener that calls `applyEdits()` during a row commit,
|
|
251
|
+
a bulk edit or a paste no longer splits it, so one undo reverts all of it.
|
|
252
|
+
- Undoing or redoing a large batch reads the view once instead of once per
|
|
253
|
+
cell.
|
|
254
|
+
- `applyEdits()` shows the invalid state of its cells when every edit in the
|
|
255
|
+
batch is rejected by a validator, without waiting for another render.
|
|
256
|
+
- `pattern()` validators with a global (`g`) or sticky (`y`) RegExp give the
|
|
257
|
+
same result every time; repeated valid values no longer alternate between
|
|
258
|
+
passing and failing.
|
|
259
|
+
- Editing a pinned row edits the pinned record; a checkbox or double-click in
|
|
260
|
+
a pinned row used to act on a body row. In row mode a cancelled
|
|
261
|
+
`cellValueChanging` aborts the whole row before anything is written.
|
|
262
|
+
- Keyboard navigation keeps its position per grid: an arrow key in one grid no
|
|
263
|
+
longer continues from a cell clicked in another, and removing a grid no
|
|
264
|
+
longer resets the others. The active cell follows filters, sorting, paging,
|
|
265
|
+
data changes and hidden columns, so the body always keeps one tab stop.
|
|
266
|
+
- Ctrl+End and Ctrl+Home on large grids render the target rows and keep focus
|
|
267
|
+
on the target cell, and keyboard moves no longer leave the active cell
|
|
268
|
+
hidden behind the sticky header, pinned rows or pinned columns. Full-width
|
|
269
|
+
rows from feature modules (group headers, total rows) take keyboard focus.
|
|
270
|
+
- Tree data with `defaultExpanded` keeps a parent the user collapsed when
|
|
271
|
+
`grid.data` is reassigned. Two rows with the same path are both shown, and
|
|
272
|
+
`treeRowExpanding` and `treeRowExpanded` list parents that exist only as a
|
|
273
|
+
path segment.
|
|
274
|
+
- Exported dates stored as `'YYYY-MM-DD'` strings carry the calendar day the
|
|
275
|
+
grid shows; west of UTC they were written one day early. An invalid `Date`
|
|
276
|
+
exports as an empty cell instead of throwing (CSV) or writing a value the
|
|
277
|
+
spreadsheet app reports as corrupt (XLSX).
|
|
278
|
+
- Exporting with source `'selected'` writes rows in the order the grid shows
|
|
279
|
+
them, followed by selected rows the view hides.
|
|
280
|
+
- Date and currency cells reuse their `Intl` formatters, so re-renders and
|
|
281
|
+
large exports no longer build one per cell; a malformed locale, currency or
|
|
282
|
+
date format falls back to a default instead of failing every cell.
|
|
283
|
+
- Sparkline cells no longer show a misleading 0% delta when the series starts
|
|
284
|
+
at zero, and never print -0%.
|
|
285
|
+
- A `cellTemplate` that reads other fields of its row updates after an inline
|
|
286
|
+
edit, `applyEdits`, paste, fill or a data change, in body and pinned rows.
|
|
287
|
+
- The tree data chevron and `aria-expanded` follow every expand and collapse,
|
|
288
|
+
including `expandTreeRow` and `collapseTreeRow`.
|
|
289
|
+
- Range selection highlights stay on the selected positions after a sort,
|
|
290
|
+
filter or expand moves rows.
|
|
291
|
+
- With the row-number gutter, reorder grip, selection or expansion column
|
|
292
|
+
shown, a horizontal scroll no longer stacks those cells or a start-pinned
|
|
293
|
+
column on top of each other, in LTR and RTL.
|
|
294
|
+
- Column group headers sit over their member columns when the reorder grip or
|
|
295
|
+
the row-number gutter is shown, and the group row's cells over pinned and
|
|
296
|
+
leading columns stay frozen on horizontal scroll.
|
|
297
|
+
- Pinned columns inside a CSS-scaled container no longer overlap on
|
|
298
|
+
horizontal scroll.
|
|
299
|
+
- A header drag toward later columns (rightward, or leftward with
|
|
300
|
+
`dir="rtl"`) keeps following the pointer after the first swap and always
|
|
301
|
+
ends on release, including a release outside the header or a lost release.
|
|
302
|
+
- Column autosize no longer throws when group header, total or loading rows
|
|
303
|
+
are rendered.
|
|
304
|
+
- With `dir="rtl"` the column resize guide is drawn on the dragged edge.
|
|
305
|
+
- The filter panel: a cancelled change really leaves the filter unchanged, a
|
|
306
|
+
condition picked on a fresh panel is reported and announced as an add, the
|
|
307
|
+
filter icon of the open column closes it with a mouse, the panel stays under
|
|
308
|
+
its column on scroll, resize and keyboard column switches, and it no longer
|
|
309
|
+
runs off screen when the root font size is not 16px.
|
|
310
|
+
- `setState(getState())` keeps the scroll position when the filter holds an
|
|
311
|
+
array term, and the filter panel chip lists such a term's values.
|
|
312
|
+
- With an asynchronous pipeline hook, a slower earlier run no longer
|
|
313
|
+
overwrites the rows of a newer quick filter, filter or sort, and a run
|
|
314
|
+
replaced before it finishes no longer holds back the newer one's calls and
|
|
315
|
+
events.
|
|
316
|
+
- A `quickFilterChanging` listener that assigns `grid.quickFilter` (to trim
|
|
317
|
+
the input, for example) keeps its value, and `quickFilterChanged` reports
|
|
318
|
+
it. A substitute equal to the current filter changes nothing and
|
|
319
|
+
`setQuickFilter` returns `false`.
|
|
320
|
+
- Changing `grid.tree` after the first render (turning tree mode on or off,
|
|
321
|
+
or changing `getDataPath` or `defaultExpanded`) rebuilds the rows.
|
|
322
|
+
- `grid.data` set to `null` or `undefined` (a framework prop that is still
|
|
323
|
+
loading) shows an empty grid and reads back as `[]`, instead of throwing
|
|
324
|
+
and keeping the previous rows.
|
|
325
|
+
- `moveColumn` no longer fires `columnMoving` for a move that changes nothing.
|
|
326
|
+
- Shift+click and Ctrl or Cmd+click beside the checkbox in the selection cell
|
|
327
|
+
do the same range or additive selection as on the checkbox itself.
|
|
328
|
+
- When a `rowSelecting` listener cancels the change, the row and select-all
|
|
329
|
+
checkboxes show the real selection state instead of staying checked.
|
|
330
|
+
- Moving a row while a column filter or the quick filter is active keeps every
|
|
331
|
+
hidden row in its place, in the manual order and in `grid.data` with
|
|
332
|
+
`applyToData`. Before, hidden rows were pushed to the end.
|
|
333
|
+
- Replacing `grid.data` carries the manual row order and row pins onto the
|
|
334
|
+
new rows (by `rowId` when set, otherwise rows that left the data are
|
|
335
|
+
dropped). New rows can be move targets, a reload no longer disables
|
|
336
|
+
reordering and header sorting, and the pinned band no longer shows a stale
|
|
337
|
+
copy of a reloaded row.
|
|
338
|
+
- A row drag ends when the pointer is released or cancelled anywhere on the
|
|
339
|
+
page, or when a move arrives with no button held, and a grid removed
|
|
340
|
+
mid-drag drops its ghost.
|
|
341
|
+
- With `rowPinning.enabled` set to `false`, `pinnedRows` and the aria row
|
|
342
|
+
counts no longer report pinned rows and those rows get their reorder grip
|
|
343
|
+
back. The pins are kept for when pinning is turned back on.
|
|
344
|
+
|
|
345
|
+
## [3.5.0] - 2026-09-12
|
|
346
|
+
|
|
347
|
+
A feature and accessibility release. No exported symbol was removed or renamed.
|
|
348
|
+
Two consumer-visible changes are listed under Changed and Removed: the Ignite UI
|
|
349
|
+
dependencies are gone, and `setup({ theme })` is now inert.
|
|
350
|
+
|
|
351
|
+
### Added
|
|
352
|
+
- **Right-to-left support.** `dir="rtl"` on the grid or any ancestor mirrors it
|
|
353
|
+
completely. Direction is read from the computed style rather than the `dir`
|
|
354
|
+
attribute, so an inherited direction works. The stylesheets were already
|
|
355
|
+
written in logical properties; what changed is the code that reasoned in
|
|
356
|
+
physical pixels or physical key names: ArrowLeft / ArrowRight map onto
|
|
357
|
+
previous / next column by inline order, column resize takes width off the
|
|
358
|
+
inline-start edge, and column reorder flips its midpoint comparison. (The
|
|
359
|
+
enterprise range and chart-range handles had a matching fix; see that
|
|
360
|
+
package's 0.7.0 entry.)
|
|
361
|
+
- **`grid.applyEdits(edits)`**, a programmatic batch write. Previously the only
|
|
362
|
+
write path was `editCell` + `commitEdit`, which drives the editor, so a bulk
|
|
363
|
+
write meant a thousand undo entries and a thousand re-renders. Each write still
|
|
364
|
+
emits cancellable `cellValueChanging` then `cellValueChanged` and still runs
|
|
365
|
+
the column's validators, while the batch lands as one undo step and one
|
|
366
|
+
pipeline run. It returns a tally rather than a count, splitting `applied` from
|
|
367
|
+
`unchanged`, `invalid`, `cancelled` and `skipped`, since "nothing changed" and
|
|
368
|
+
"everything was rejected" are different answers. Out-of-range rows and
|
|
369
|
+
non-editable columns are skipped rather than thrown on, so a partially stale
|
|
370
|
+
batch still applies what it can.
|
|
371
|
+
- **Reduced-motion support.** Every transition now routes through one of the
|
|
372
|
+
`--ag-dur-*` tokens, and those zero under `prefers-reduced-motion: reduce`:
|
|
373
|
+
24 transitions across 9 stylesheets go instant with their end states
|
|
374
|
+
unchanged. The JS-driven row reorder and expansion animations already bailed
|
|
375
|
+
out.
|
|
376
|
+
- **Forced-colors support.** Forced colors paints no `box-shadow`, and the grid
|
|
377
|
+
leaned on inset shadows for exactly the indicators that matter most, so in
|
|
378
|
+
Windows High Contrast a keyboard user had no visible cursor and no visible
|
|
379
|
+
selection. The active-cell ring, invalid-cell ring, selected-row bar and every
|
|
380
|
+
toolbar and filter focus ring are restated as outlines, which forced colors
|
|
381
|
+
recolours rather than drops and which sit outside layout, so nothing shifts.
|
|
382
|
+
- **The Custom Elements Manifest is now authoritative for `<apex-grid>`.** The
|
|
383
|
+
element was missing from `custom-elements.json` entirely: no `tagName`, not
|
|
384
|
+
flagged `customElement`, and zero named events. It now resolves
|
|
385
|
+
`customElement`, `tagName`, all 29 `ApexGridEventMap` events, the `theme`
|
|
386
|
+
attribute and the public `@property` fields, and a build-time drift check
|
|
387
|
+
fails the build when any of them diverge. This is what the new
|
|
388
|
+
`react-apex-grid` wrapper package generates from, and what editor tooling
|
|
389
|
+
reads for completions.
|
|
390
|
+
|
|
391
|
+
### Changed
|
|
392
|
+
- **Target sizes meet WCAG 2.2 AA 2.5.8 (24x24).** The selection cell and the
|
|
393
|
+
select-all header cell forward clicks to their checkbox rather than growing a
|
|
394
|
+
deliberately small 14x14 mark. The header sort / filter / menu buttons reach
|
|
395
|
+
24x24 through the invisible chip that already expanded them, so the visible
|
|
396
|
+
16px box and the packed header layout are unchanged and nothing paints at
|
|
397
|
+
rest. **Paginator buttons grow from 22 to 24, which makes the paginator bar
|
|
398
|
+
2px taller.** The range fill handle stays a 10px grab band, now documented as
|
|
399
|
+
a criterion-permitted exception rather than a gap: it is reachable through
|
|
400
|
+
controls that do meet 24x24, and its position at the range corner is
|
|
401
|
+
essential to what it means.
|
|
402
|
+
- **`setup({ theme })` is inert and warns once.** It only ever forwarded to
|
|
403
|
+
Ignite UI's `configureTheme()`, which was already documented as not affecting
|
|
404
|
+
the grid's appearance. It still compiles, so no consumer code breaks; the
|
|
405
|
+
warning is there because silently dropping the forwarding would leave an
|
|
406
|
+
Ignite UI host app unthemed with no clue why.
|
|
407
|
+
|
|
408
|
+
### Removed
|
|
409
|
+
- **The `igniteui-webcomponents` and `igniteui-theming` dependencies.** Core
|
|
410
|
+
carried the first as a runtime dependency and enterprise as a peer, so every
|
|
411
|
+
consumer installed a whole component library (plus `@floating-ui`) for one
|
|
412
|
+
inert pass-through. The grid registers no Ignite UI element.
|
|
413
|
+
`igniteui-theming` was a Sass dependency for exactly one function, `rem()`,
|
|
414
|
+
now reimplemented locally with the same conversion, and it emitted 55 Sass
|
|
415
|
+
deprecation warnings per build. Five packages leave the lockfile, and the
|
|
416
|
+
compiled CSS is 3,718 bytes smaller with every `rem()` output byte-identical.
|
|
417
|
+
- **The `--igx-*` custom-property level.** Every colour rule resolved through
|
|
418
|
+
three levels and the first never fired: `--igx-*` is the igniteui-angular
|
|
419
|
+
naming convention, not the web-components one, so it was dead indirection in
|
|
420
|
+
front of the two levels that work. `--ag-*` overrides and the unprefixed
|
|
421
|
+
semantic variables behave exactly as before. The `--ig-primary-*` and
|
|
422
|
+
`--ig-font-family` hooks stay, since those are what an Ignite UI theme
|
|
423
|
+
actually sets and reading a variable with a default costs nothing when absent.
|
|
424
|
+
|
|
425
|
+
### Fixed
|
|
426
|
+
- **A grid could settle with zero rendered rows at first paint**, silently,
|
|
427
|
+
while reporting a correct `ariaRowCount` and a correctly sized scroll region
|
|
428
|
+
([#31](https://github.com/apexcharts/apex-grid/issues/31)). The virtualizer
|
|
429
|
+
derives its viewport from the intersection of the body, its clipping ancestors
|
|
430
|
+
and the window, and clears the rendered range when that intersection is
|
|
431
|
+
zero-height while still sizing the scroll extent from the full item count. It
|
|
432
|
+
could not recover, because the only invalidation signals it listens for are
|
|
433
|
+
size changes and scroll events: a body that moves into view, or a window that
|
|
434
|
+
resizes around a fixed-size host, fires neither. An iframe sized by its host
|
|
435
|
+
page after load hits this, as does content above the grid that is still
|
|
436
|
+
settling. The body now watches its own intersection with the window and
|
|
437
|
+
re-measures when it gains a visible slice with nothing rendered, bounded to
|
|
438
|
+
three attempts per geometry change and skipped entirely when there is no
|
|
439
|
+
visible slice.
|
|
440
|
+
- **A grid moved to another parent left its body permanently stale**, still
|
|
441
|
+
rendering the old rows after `data` was reassigned. The body awaited
|
|
442
|
+
virtualizer state before calling `super.connectedCallback()`, which deadlocks
|
|
443
|
+
on a reconnect: the promise waits on a layout that only runs once the update
|
|
444
|
+
cycle that call starts.
|
|
445
|
+
|
|
7
446
|
## [3.4.0] - 2026-07-17
|
|
8
447
|
|
|
9
448
|
An accessibility-focused release. The public module API is unchanged (no
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
## 📄 License Options for ApexGrid
|
|
2
|
+
|
|
3
|
+
ApexGrid is offered under a **dual-license model** to support individuals, startups, and commercial products of all sizes.
|
|
4
|
+
|
|
5
|
+
One license key works across every Apex product, so a customer of one does not buy a second for another.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
### 🔓 Community License (Free)
|
|
10
|
+
|
|
11
|
+
For individuals, non-profits, educators, and small businesses whose **annual revenue, operating budget, funding, or equivalent financial resources are less than $2 million USD**.
|
|
12
|
+
|
|
13
|
+
✅ What's allowed:
|
|
14
|
+
|
|
15
|
+
- Personal, educational, or non-profit use
|
|
16
|
+
- Commercial use by small orgs (under $2M in annual revenue, budget or funding)
|
|
17
|
+
- Modifications, and redistribution of the library itself (with attribution)
|
|
18
|
+
|
|
19
|
+
🚫 Not allowed:
|
|
20
|
+
|
|
21
|
+
- Use by companies or entities at or above $2M in annual revenue, budget or funding
|
|
22
|
+
- Use in competing data grid or charting products
|
|
23
|
+
- Sublicensing under different terms
|
|
24
|
+
- Embedding in a product or platform used by other people, which needs the OEM License below whatever your size
|
|
25
|
+
|
|
26
|
+
➡ By using ApexGrid under this license, you confirm that **you qualify as a Small Organization**.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### 💼 Commercial License (Paid)
|
|
31
|
+
|
|
32
|
+
The Commercial License applies to all paid SKUs (Pro, Premium and OEM).
|
|
33
|
+
|
|
34
|
+
The **Community License** is available at no cost **only** to organizations whose **annual revenue, operating budget, funding, or equivalent financial resources are under $2M USD**.
|
|
35
|
+
If you, your parent company, affiliates, or any entity under common control reach $2M USD or more on any of those measures, you must purchase one of our paid licenses.
|
|
36
|
+
|
|
37
|
+
Pro and Premium are priced per developer, and priced on the features you use rather than on your size.
|
|
38
|
+
|
|
39
|
+
✅ What's included:
|
|
40
|
+
|
|
41
|
+
- Use in internal tools and commercial applications
|
|
42
|
+
- Modifications and app-level distribution
|
|
43
|
+
- 12-month subscription with updates & support
|
|
44
|
+
|
|
45
|
+
🚫 Not allowed:
|
|
46
|
+
|
|
47
|
+
- Redistribution in toolkits, SDKs, or platforms
|
|
48
|
+
- Use by unlicensed developers
|
|
49
|
+
- Competing data grid or charting products
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### 🎚 What each plan includes for ApexGrid
|
|
54
|
+
|
|
55
|
+
- **Free, at Community and above:** ApexGrid itself.
|
|
56
|
+
- **Premium and above:** the ApexGrid Enterprise add-on, a separate package (`apex-grid-enterprise`) covering Row Grouping, Aggregations, Pivoting, the Server-Side Row Model, Advanced Filter Builder, Range Selection, Integrated Charts, Formula Engine, AI Toolkit and Companion Elements.
|
|
57
|
+
|
|
58
|
+
For the full comparison see [https://apexcharts.com/pricing](https://apexcharts.com/pricing).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 🏛 Non-Profit Tiers
|
|
63
|
+
|
|
64
|
+
Non-Profits are treated like commercial entities:
|
|
65
|
+
|
|
66
|
+
- Annual operating budget **less than $2 million USD**
|
|
67
|
+
- _Eligible for Community licenses_
|
|
68
|
+
|
|
69
|
+
or
|
|
70
|
+
|
|
71
|
+
- Annual operating budget **greater than $2 million USD**
|
|
72
|
+
- _Commercial license with possible discounts for Community, Pro, Premium and OEM products_
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 🔄 OEM / Redistribution License (Paid)
|
|
77
|
+
|
|
78
|
+
Required if you are **embedding ApexGrid into a product or platform used by other people**, such as:
|
|
79
|
+
|
|
80
|
+
- No-code dashboards
|
|
81
|
+
- Developer platforms
|
|
82
|
+
- Embedded BI tools
|
|
83
|
+
- SDKs
|
|
84
|
+
|
|
85
|
+
✅ What's included:
|
|
86
|
+
|
|
87
|
+
- Redistribution rights for **one application or product**
|
|
88
|
+
- **Unlimited developer seats** on that application, with no separate per-developer license to buy
|
|
89
|
+
- **Every licensed feature**, at the highest tier
|
|
90
|
+
- 12-month subscription with updates & support
|
|
91
|
+
|
|
92
|
+
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
|
+
✅ OEM **not required** if your app simply renders static grids and users **cannot** configure or interact with them.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### ⏳ When a subscription ends
|
|
99
|
+
|
|
100
|
+
Your license key expires, and **licensed features render with a trial watermark**. You no longer receive updates, new features, or technical support. Work built only from free features is unaffected, and your existing deployment keeps running.
|
|
101
|
+
|
|
102
|
+
For OEM licenses, continued redistribution requires an active subscription.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### ⚠️ License Acceptance
|
|
107
|
+
|
|
108
|
+
By installing ApexGrid (e.g., via `npm install apex-grid`), you are agreeing to the applicable license based on your usage:
|
|
109
|
+
|
|
110
|
+
- Community License (if under $2M in annual revenue, budget or funding)
|
|
111
|
+
- Commercial License (if at or above $2M in annual revenue, budget or funding)
|
|
112
|
+
- OEM License (if redistributing to third-party users)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 🛠 Need a License or Have Questions?
|
|
117
|
+
|
|
118
|
+
📧 Contact us at [sales@apexcharts.com](mailto:sales@apexcharts.com)
|
|
119
|
+
📚 Read full license agreements here: [https://apexcharts.com/license](https://apexcharts.com/license)
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
Copyright © 2026 ApexCharts. All rights reserved.
|
|
124
|
+
|
|
125
|
+
Thank you for supporting ApexGrid! Your licensing keeps the Community License available to individuals and small teams.
|