apex-grid 3.2.0 → 3.4.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 +120 -0
- package/README.md +229 -52
- package/components/cell.d.ts +16 -3
- package/components/cell.js +78 -8
- package/components/cell.js.map +1 -1
- package/components/filter-row.d.ts +3 -6
- package/components/filter-row.js +144 -115
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +421 -77
- package/components/grid.js +432 -13
- package/components/grid.js.map +1 -1
- package/components/group-header-row.d.ts +34 -0
- package/components/group-header-row.js +125 -0
- package/components/group-header-row.js.map +1 -0
- package/components/header-row.d.ts +13 -2
- package/components/header-row.js +33 -18
- package/components/header-row.js.map +1 -1
- package/components/header.d.ts +11 -0
- package/components/header.js +209 -8
- package/components/header.js.map +1 -1
- package/components/paginator.d.ts +6 -1
- package/components/paginator.js +17 -11
- package/components/paginator.js.map +1 -1
- package/components/row.d.ts +28 -0
- package/components/row.js +100 -3
- package/components/row.js.map +1 -1
- package/components/toolbar.d.ts +8 -1
- package/components/toolbar.js +25 -7
- package/components/toolbar.js.map +1 -1
- package/controllers/data-operation.js +1 -0
- package/controllers/data-operation.js.map +1 -1
- package/controllers/dom.d.ts +24 -6
- package/controllers/dom.js +62 -5
- package/controllers/dom.js.map +1 -1
- package/controllers/editing.d.ts +68 -1
- package/controllers/editing.js +129 -44
- package/controllers/editing.js.map +1 -1
- package/controllers/expansion.js +4 -4
- package/controllers/expansion.js.map +1 -1
- package/controllers/filter.d.ts +1 -1
- package/controllers/filter.js +27 -5
- package/controllers/filter.js.map +1 -1
- package/controllers/history.d.ts +86 -0
- package/controllers/history.js +125 -0
- package/controllers/history.js.map +1 -0
- package/controllers/navigation.d.ts +49 -2
- package/controllers/navigation.js +145 -3
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.js +1 -1
- package/controllers/pagination.js.map +1 -1
- package/controllers/reorder.js +3 -1
- package/controllers/reorder.js.map +1 -1
- package/controllers/row-pin.d.ts +59 -0
- package/controllers/row-pin.js +75 -0
- package/controllers/row-pin.js.map +1 -0
- package/controllers/row-reorder.d.ts +161 -0
- package/controllers/row-reorder.js +332 -0
- package/controllers/row-reorder.js.map +1 -0
- package/controllers/selection.js +3 -3
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.js +13 -3
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +33 -0
- package/controllers/state.js +37 -2
- package/controllers/state.js.map +1 -1
- package/controllers/tree.d.ts +8 -0
- package/controllers/tree.js +0 -0
- package/controllers/tree.js.map +1 -1
- package/custom-elements.json +4667 -926
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +28 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/functions/custom.html +3 -0
- package/docs/functions/interpolate.html +4 -0
- package/docs/functions/localize.html +8 -0
- package/docs/functions/max.html +3 -0
- package/docs/functions/min.html +3 -0
- package/docs/functions/pattern.html +3 -0
- package/docs/functions/required.html +3 -0
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +245 -54
- package/docs/interfaces/ApexCellValidationFailedEvent.html +13 -0
- package/docs/interfaces/ApexCellValueChangedEvent.html +1 -1
- package/docs/interfaces/ApexCellValueChangingEvent.html +2 -2
- package/docs/interfaces/ApexColumnGroupContext.html +6 -0
- 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 +37 -9
- package/docs/interfaces/ApexHistoryChangedEvent.html +6 -0
- package/docs/interfaces/ApexPageChangedEvent.html +1 -1
- package/docs/interfaces/ApexRowMovingEvent.html +9 -0
- package/docs/interfaces/ApexRowPinningEvent.html +8 -0
- package/docs/interfaces/ApexStateChangedEvent.html +4 -0
- package/docs/interfaces/BaseApexCellContext.html +1 -1
- package/docs/interfaces/BaseApexEditorContext.html +1 -1
- package/docs/interfaces/BaseColumnConfiguration.html +42 -17
- package/docs/interfaces/CSVExportOptions.html +2 -2
- package/docs/interfaces/ColumnGroupConfiguration.html +12 -0
- package/docs/interfaces/ColumnLayoutState.html +2 -0
- package/docs/interfaces/ColumnSchema.html +22 -0
- package/docs/interfaces/DataPipelineConfiguration.html +2 -2
- package/docs/interfaces/EditingHistoryConfiguration.html +10 -0
- package/docs/interfaces/ExportFormat.html +2 -2
- package/docs/interfaces/ExportOptions.html +1 -1
- package/docs/interfaces/FilterStateSnapshot.html +4 -0
- package/docs/interfaces/GetStateOptions.html +4 -0
- package/docs/interfaces/GridCapabilities.html +8 -0
- package/docs/interfaces/GridEditingConfiguration.html +4 -2
- package/docs/interfaces/GridRowPinningConfiguration.html +5 -0
- package/docs/interfaces/GridRowReorderingConfiguration.html +22 -0
- package/docs/interfaces/GridSchema.html +19 -0
- package/docs/interfaces/GridState.html +41 -0
- package/docs/interfaces/GridTreeConfiguration.html +2 -2
- package/docs/interfaces/PaginationConfiguration.html +1 -1
- package/docs/interfaces/PaginationState.html +1 -1
- package/docs/interfaces/SetStateOptions.html +9 -0
- package/docs/interfaces/SetStateResult.html +11 -0
- package/docs/interfaces/SortStateSnapshot.html +2 -0
- package/docs/interfaces/ValidatorContext.html +8 -0
- package/docs/media/_tokens.scss +70 -81
- package/docs/media/package.json +2 -2
- package/docs/media/state-persistence.html +189 -0
- package/docs/modules.html +1 -1
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/EditMode.html +2 -2
- package/docs/types/GridLocaleKey.html +3 -0
- package/docs/types/GridLocaleText.html +5 -0
- package/docs/types/LocaleParams.html +2 -0
- package/docs/types/PaginationMode.html +1 -1
- package/docs/types/RowDropPosition.html +2 -0
- package/docs/types/RowPinPosition.html +2 -0
- package/docs/types/RowRef.html +3 -0
- package/docs/types/Validator.html +4 -0
- package/docs/variables/EN_LOCALE.html +9 -0
- package/docs/variables/esLocale.html +8 -0
- package/i18n/en.d.ts +245 -0
- package/i18n/en.js +219 -0
- package/i18n/en.js.map +1 -0
- package/i18n/es.d.ts +18 -0
- package/i18n/es.js +219 -0
- package/i18n/es.js.map +1 -0
- package/i18n/index.d.ts +3 -0
- package/i18n/index.js +4 -0
- package/i18n/index.js.map +1 -0
- package/i18n/localize.d.ts +23 -0
- package/i18n/localize.js +15 -0
- package/i18n/localize.js.map +1 -0
- package/index.d.ts +8 -2
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/internal/column-types.js +1 -1
- package/internal/column-types.js.map +1 -1
- package/internal/feature-module.d.ts +46 -0
- package/internal/feature-module.js +11 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/flip.js +1 -1
- package/internal/flip.js.map +1 -1
- package/internal/icons.d.ts +9 -7
- package/internal/icons.js +75 -35
- package/internal/icons.js.map +1 -1
- package/internal/index.d.ts +5 -3
- package/internal/index.js +2 -1
- package/internal/index.js.map +1 -1
- package/internal/state-schema.d.ts +85 -0
- package/internal/state-schema.js +27 -0
- package/internal/state-schema.js.map +1 -0
- package/internal/state-snapshot.d.ts +152 -0
- package/internal/state-snapshot.js +115 -0
- package/internal/state-snapshot.js.map +1 -0
- package/internal/tags.d.ts +1 -0
- package/internal/tags.js +1 -0
- package/internal/tags.js.map +1 -1
- package/internal/types.d.ts +162 -2
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +12 -0
- package/internal/utils.js +17 -0
- package/internal/utils.js.map +1 -1
- package/internal/validators.d.ts +31 -0
- package/internal/validators.js +44 -0
- package/internal/validators.js.map +1 -0
- package/package.json +1 -1
- 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-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- 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.d.ts +1 -0
- package/styles/group-header-row/group-header-row.css.js +3 -0
- package/styles/group-header-row/group-header-row.css.js.map +1 -0
- 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/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/docs/classes/ApexGrid.html +0 -399
package/controllers/dom.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
2
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
3
|
+
import { SENTINEL_NODE } from '../internal/constants.js';
|
|
3
4
|
import { applyColumnWidths, getDisplayColumns } from '../internal/utils.js';
|
|
4
5
|
export class GridDOMController {
|
|
5
6
|
constructor(host, state) {
|
|
@@ -21,8 +22,7 @@ export class GridDOMController {
|
|
|
21
22
|
this.rowRenderer = (data, index) => {
|
|
22
23
|
const editingCell = this.state.editing.activeCell;
|
|
23
24
|
const editingKey = editingCell?.rowIndex === index ? editingCell.columnKey : null;
|
|
24
|
-
const
|
|
25
|
-
const ariaRowOffset = hasFilter ? 2 : 1;
|
|
25
|
+
const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;
|
|
26
26
|
return html `
|
|
27
27
|
<apex-grid-row
|
|
28
28
|
part="row"
|
|
@@ -35,12 +35,19 @@ export class GridDOMController {
|
|
|
35
35
|
.editingKey=${editingKey}
|
|
36
36
|
.ariaRowOffset=${ariaRowOffset}
|
|
37
37
|
.decorationVersion=${this.state.decorationVersion}
|
|
38
|
+
.validationVersion=${this.state.editing.validationVersion}
|
|
39
|
+
.dragging=${this.state.rowReorder.dragging === data}
|
|
40
|
+
.grabbed=${this.state.rowReorder.grabbed === data}
|
|
41
|
+
.coordinateHints=${Boolean(this.host.coordinateHints)}
|
|
38
42
|
>
|
|
39
43
|
</apex-grid-row>
|
|
40
44
|
`;
|
|
41
45
|
};
|
|
46
|
+
this.#lastGroupTop = -1;
|
|
42
47
|
this.#lastHeaderTop = -1;
|
|
43
48
|
this.#lastFilterTop = -1;
|
|
49
|
+
this.#lastPinnedTop = -1;
|
|
50
|
+
this.#lastPinnedBottom = -1;
|
|
44
51
|
this.#lastHostWidth = -1;
|
|
45
52
|
this.#hostWidthObserver = null;
|
|
46
53
|
this.host.addController(this);
|
|
@@ -56,6 +63,28 @@ export class GridDOMController {
|
|
|
56
63
|
get displayColumns() {
|
|
57
64
|
return getDisplayColumns(this.host.columns);
|
|
58
65
|
}
|
|
66
|
+
get headerRowCount() {
|
|
67
|
+
return this.host.columnGroupDepth + 1;
|
|
68
|
+
}
|
|
69
|
+
pinnedRowRenderer(data, localIndex, ariaRowOffset) {
|
|
70
|
+
return html `
|
|
71
|
+
<apex-grid-row
|
|
72
|
+
part="row pinned-row"
|
|
73
|
+
style=${styleMap(this.columnSizes)}
|
|
74
|
+
.index=${localIndex}
|
|
75
|
+
.activeNode=${SENTINEL_NODE}
|
|
76
|
+
.data=${data}
|
|
77
|
+
.columns=${this.displayColumns}
|
|
78
|
+
.pinOffsets=${this.pinOffsets}
|
|
79
|
+
.editingKey=${null}
|
|
80
|
+
.ariaRowOffset=${ariaRowOffset}
|
|
81
|
+
.decorationVersion=${this.state.decorationVersion}
|
|
82
|
+
.validationVersion=${this.state.editing.validationVersion}
|
|
83
|
+
.coordinateHints=${Boolean(this.host.coordinateHints)}
|
|
84
|
+
>
|
|
85
|
+
</apex-grid-row>
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
59
88
|
async hostConnected() {
|
|
60
89
|
this.setGridColumnSizes();
|
|
61
90
|
await this.host.updateComplete;
|
|
@@ -103,6 +132,8 @@ export class GridDOMController {
|
|
|
103
132
|
this.columnSizes = applyColumnWidths(this.displayColumns, {
|
|
104
133
|
showSelectionColumn: this.state.selection.showCheckboxColumn,
|
|
105
134
|
showExpansionColumn: this.state.expansion.showToggleColumn,
|
|
135
|
+
showReorderHandle: this.state.rowReorder.showHandleColumn,
|
|
136
|
+
showRowNumbers: Boolean(this.host.coordinateHints),
|
|
106
137
|
});
|
|
107
138
|
}
|
|
108
139
|
getActiveRowStyles(index) {
|
|
@@ -164,8 +195,11 @@ export class GridDOMController {
|
|
|
164
195
|
}
|
|
165
196
|
this.#observedHeaders = next;
|
|
166
197
|
}
|
|
198
|
+
#lastGroupTop;
|
|
167
199
|
#lastHeaderTop;
|
|
168
200
|
#lastFilterTop;
|
|
201
|
+
#lastPinnedTop;
|
|
202
|
+
#lastPinnedBottom;
|
|
169
203
|
#lastHostWidth;
|
|
170
204
|
#hostWidthObserver;
|
|
171
205
|
recomputeStickyRowOffsets() {
|
|
@@ -173,11 +207,23 @@ export class GridDOMController {
|
|
|
173
207
|
if (!root)
|
|
174
208
|
return;
|
|
175
209
|
const toolbar = root.querySelector('apex-grid-toolbar');
|
|
210
|
+
const groupHeader = root.querySelector('apex-grid-group-header-row');
|
|
176
211
|
const header = root.querySelector('apex-grid-header-row');
|
|
212
|
+
const filter = root.querySelector('apex-filter-row');
|
|
213
|
+
const paginator = root.querySelector('apex-grid-paginator');
|
|
177
214
|
const toolbarH = toolbar?.offsetHeight ?? 0;
|
|
215
|
+
const groupH = groupHeader?.offsetHeight ?? 0;
|
|
178
216
|
const headerH = header?.offsetHeight ?? 0;
|
|
179
|
-
const
|
|
180
|
-
const
|
|
217
|
+
const filterH = filter?.offsetHeight ?? 0;
|
|
218
|
+
const paginatorH = paginator?.offsetHeight ?? 0;
|
|
219
|
+
const groupTop = toolbarH;
|
|
220
|
+
const headerTop = toolbarH + groupH;
|
|
221
|
+
const filterTop = toolbarH + groupH + headerH;
|
|
222
|
+
const pinnedTop = toolbarH + groupH + headerH + filterH;
|
|
223
|
+
if (groupTop !== this.#lastGroupTop) {
|
|
224
|
+
this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);
|
|
225
|
+
this.#lastGroupTop = groupTop;
|
|
226
|
+
}
|
|
181
227
|
if (headerTop !== this.#lastHeaderTop) {
|
|
182
228
|
this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);
|
|
183
229
|
this.#lastHeaderTop = headerTop;
|
|
@@ -186,19 +232,30 @@ export class GridDOMController {
|
|
|
186
232
|
this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);
|
|
187
233
|
this.#lastFilterTop = filterTop;
|
|
188
234
|
}
|
|
235
|
+
if (pinnedTop !== this.#lastPinnedTop) {
|
|
236
|
+
this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);
|
|
237
|
+
this.#lastPinnedTop = pinnedTop;
|
|
238
|
+
}
|
|
239
|
+
if (paginatorH !== this.#lastPinnedBottom) {
|
|
240
|
+
this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);
|
|
241
|
+
this.#lastPinnedBottom = paginatorH;
|
|
242
|
+
}
|
|
189
243
|
}
|
|
190
244
|
observeStickyRows() {
|
|
191
245
|
const root = this.host.shadowRoot;
|
|
192
246
|
if (!root)
|
|
193
247
|
return;
|
|
194
248
|
const toolbar = root.querySelector('apex-grid-toolbar');
|
|
249
|
+
const groupHeader = root.querySelector('apex-grid-group-header-row');
|
|
195
250
|
const header = root.querySelector('apex-grid-header-row');
|
|
251
|
+
const filter = root.querySelector('apex-filter-row');
|
|
252
|
+
const paginator = root.querySelector('apex-grid-paginator');
|
|
196
253
|
if (!this.#stickyRowObserver) {
|
|
197
254
|
this.#stickyRowObserver = new ResizeObserver(() => {
|
|
198
255
|
requestAnimationFrame(() => this.recomputeStickyRowOffsets());
|
|
199
256
|
});
|
|
200
257
|
}
|
|
201
|
-
const next = new Set([toolbar, header].filter((el) => !!el));
|
|
258
|
+
const next = new Set([toolbar, groupHeader, header, filter, paginator].filter((el) => !!el));
|
|
202
259
|
for (const element of this.#observedStickyRows) {
|
|
203
260
|
if (!next.has(element))
|
|
204
261
|
this.#stickyRowObserver.unobserve(element);
|
package/controllers/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport type { ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { applyColumnWidths, getDisplayColumns } from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.setScrollOffset();\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n */\n public get displayColumns(): Array<ColumnConfiguration<T>> {\n return getDisplayColumns(this.host.columns);\n }\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingCell = this.state.editing.activeCell;\n const editingKey = editingCell?.rowIndex === index ? editingCell.columnKey : null;\n // aria-rowindex offset: header row is always row 1; filter row (when\n // any column has a filter configured) sits at row 2; body rows start\n // immediately after.\n const hasFilter = this.host.columns.some((column) => column.filter);\n const ariaRowOffset = hasFilter ? 2 : 1;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n >\n </apex-grid-row>\n `;\n };\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer and recalculate the scrollbar offset\n // for the next one\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setScrollOffset();\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n public setScrollOffset() {\n // The grid host now owns vertical scrolling, so the historic per-row\n // padding-inline-end compensation is no longer needed. Keep the CSS var\n // set to `0` for forward compatibility with consumer themes that read it.\n this.host.style.setProperty('--scrollbar-offset', '0px');\n }\n\n protected setGridColumnSizes() {\n this.columnSizes = applyColumnWidths(this.displayColumns, {\n showSelectionColumn: this.state.selection.showCheckboxColumn,\n showExpansionColumn: this.state.expansion.showToggleColumn,\n });\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const headersByKey = new Map<Keys<T>, DOMRect>();\n for (const header of headerRow.headers) {\n headersByKey.set(header.column.key as Keys<T>, header.getBoundingClientRect());\n }\n\n let leftAccum = 0;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n leftAccum += rect?.width ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n rightAccum += rect?.width ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative height of the sticky top rows into CSS custom\n * properties used by the header/filter rows for their `inset-block-start`\n * offsets. The toolbar is always at `top: 0`; the header sits below it\n * (`--apex-row-top-header`) and the filter sits below the header\n * (`--apex-row-top-filter`). Writes are skipped when the values haven't\n * changed so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n const headerH = header?.offsetHeight ?? 0;\n const headerTop = toolbarH;\n const filterTop = toolbarH + headerH;\n\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>([toolbar, header].filter((el): el is HTMLElement => !!el));\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { applyColumnWidths, getDisplayColumns } from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.setScrollOffset();\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n */\n public get displayColumns(): Array<ColumnConfiguration<T>> {\n return getDisplayColumns(this.host.columns);\n }\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n /**\n * Number of chrome rows above the body for `aria-rowindex`: an optional group\n * header row and the column header (always present). The filter panel is a\n * floating overlay rather than a table row, so it is not counted here.\n */\n protected get headerRowCount(): number {\n return this.host.columnGroupDepth + 1;\n }\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingCell = this.state.editing.activeCell;\n const editingKey = editingCell?.rowIndex === index ? editingCell.columnKey : null;\n // Body rows follow the chrome rows and any pinned-top rows in the\n // aria-rowindex sequence.\n const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .dragging=${this.state.rowReorder.dragging === data}\n .grabbed=${this.state.rowReorder.grabbed === data}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n };\n\n /**\n * Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}\n * so selection / expansion / decoration all work by data reference, but pins a\n * sentinel {@link ActiveNode} (pinned rows are presentation + selection\n * surfaces in v1, never the active/edited cell) and renders no editor.\n *\n * @param localIndex - position within the band (drives the active sentinel id).\n * @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.\n */\n public pinnedRowRenderer(data: T, localIndex: number, ariaRowOffset: number) {\n return html`\n <apex-grid-row\n part=\"row pinned-row\"\n style=${styleMap(this.columnSizes)}\n .index=${localIndex}\n .activeNode=${SENTINEL_NODE as ActiveNode<T>}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${null}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n }\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer and recalculate the scrollbar offset\n // for the next one\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setScrollOffset();\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n public setScrollOffset() {\n // The grid host now owns vertical scrolling, so the historic per-row\n // padding-inline-end compensation is no longer needed. Keep the CSS var\n // set to `0` for forward compatibility with consumer themes that read it.\n this.host.style.setProperty('--scrollbar-offset', '0px');\n }\n\n protected setGridColumnSizes() {\n this.columnSizes = applyColumnWidths(this.displayColumns, {\n showSelectionColumn: this.state.selection.showCheckboxColumn,\n showExpansionColumn: this.state.expansion.showToggleColumn,\n showReorderHandle: this.state.rowReorder.showHandleColumn,\n showRowNumbers: Boolean(this.host.coordinateHints),\n });\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const headersByKey = new Map<Keys<T>, DOMRect>();\n for (const header of headerRow.headers) {\n headersByKey.set(header.column.key as Keys<T>, header.getBoundingClientRect());\n }\n\n let leftAccum = 0;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n leftAccum += rect?.width ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n rightAccum += rect?.width ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastGroupTop = -1;\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastPinnedTop = -1;\n #lastPinnedBottom = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative heights of the sticky chrome rows into CSS custom\n * properties used for their `inset-block-start` / `inset-block-end` offsets.\n * The toolbar is at `top: 0`; the header sits below it\n * (`--apex-row-top-header`), the filter below the header\n * (`--apex-row-top-filter`), and the pinned-top band below the filter\n * (`--apex-row-top-pinned`). The pinned-bottom band sticks above the\n * paginator (`--apex-row-bottom-pinned`). Writes are skipped when values are\n * unchanged so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n const groupH = groupHeader?.offsetHeight ?? 0;\n const headerH = header?.offsetHeight ?? 0;\n const filterH = filter?.offsetHeight ?? 0;\n const paginatorH = paginator?.offsetHeight ?? 0;\n // The group header (when present) sits below the toolbar; the column header\n // sits below the group header; filter below header; pinned-top below filter.\n const groupTop = toolbarH;\n const headerTop = toolbarH + groupH;\n const filterTop = toolbarH + groupH + headerH;\n const pinnedTop = toolbarH + groupH + headerH + filterH;\n\n if (groupTop !== this.#lastGroupTop) {\n this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);\n this.#lastGroupTop = groupTop;\n }\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n if (pinnedTop !== this.#lastPinnedTop) {\n this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);\n this.#lastPinnedTop = pinnedTop;\n }\n if (paginatorH !== this.#lastPinnedBottom) {\n this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);\n this.#lastPinnedBottom = paginatorH;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>(\n [toolbar, groupHeader, header, filter, paginator].filter((el): el is HTMLElement => !!el)\n );\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|
package/controllers/editing.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactiveController } from 'lit';
|
|
2
2
|
import type { ColumnConfiguration, EditMode, EditTrigger, GridHost, Keys } from '../internal/types.js';
|
|
3
|
+
import type { HistoryController } from './history.js';
|
|
3
4
|
/**
|
|
4
5
|
* The default editing configuration used when the grid has none set.
|
|
5
6
|
*/
|
|
@@ -17,6 +18,28 @@ interface ActiveCell<T> {
|
|
|
17
18
|
*/
|
|
18
19
|
data: T;
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Outcome of a single committed cell edit routed through
|
|
23
|
+
* {@link EditingController.applyCellEdit}.
|
|
24
|
+
*
|
|
25
|
+
* - `'unchanged'` - the candidate equalled the current value; nothing happened.
|
|
26
|
+
* - `'invalid'` - a column validator rejected the candidate; the value was not
|
|
27
|
+
* written and `cellValidationFailed` fired.
|
|
28
|
+
* - `'cancelled'` - a `cellValueChanging` listener called `preventDefault()`.
|
|
29
|
+
* - `'applied'` - the value was written and `cellValueChanged` fired.
|
|
30
|
+
*/
|
|
31
|
+
export type CellEditResult = 'unchanged' | 'invalid' | 'cancelled' | 'applied';
|
|
32
|
+
/**
|
|
33
|
+
* Options for {@link EditingController.applyCellEdit}.
|
|
34
|
+
*/
|
|
35
|
+
export interface ApplyCellEditOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Run the column's declarative validators before writing. Defaults to `true`.
|
|
38
|
+
* Set to `false` for writes that must not be re-validated (e.g. reverting a
|
|
39
|
+
* previously valid value during undo/redo).
|
|
40
|
+
*/
|
|
41
|
+
validate?: boolean;
|
|
42
|
+
}
|
|
20
43
|
/**
|
|
21
44
|
* Reactive controller backing inline cell + row editing.
|
|
22
45
|
*
|
|
@@ -28,7 +51,9 @@ interface ActiveCell<T> {
|
|
|
28
51
|
* propagate to consumers that own the source array.
|
|
29
52
|
*/
|
|
30
53
|
export declare class EditingController<T extends object> implements ReactiveController {
|
|
54
|
+
#private;
|
|
31
55
|
protected host: GridHost<T>;
|
|
56
|
+
protected history?: HistoryController<T> | undefined;
|
|
32
57
|
/** The cell currently in edit mode, or `null`. */
|
|
33
58
|
activeCell: ActiveCell<T> | null;
|
|
34
59
|
/** The row currently in edit mode (row mode only), or `null`. */
|
|
@@ -42,7 +67,14 @@ export declare class EditingController<T extends object> implements ReactiveCont
|
|
|
42
67
|
* {@link commitRow}.
|
|
43
68
|
*/
|
|
44
69
|
pending: Map<Keys<T>, unknown>;
|
|
45
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Monotonic token bumped whenever the validation-error set changes. Forwarded
|
|
72
|
+
* down to each cell as a reactive property so a validation-only change
|
|
73
|
+
* re-renders the affected cells (toggling `aria-invalid` and the error node)
|
|
74
|
+
* without re-running the data pipeline. Stays `0` until the first failure.
|
|
75
|
+
*/
|
|
76
|
+
get validationVersion(): number;
|
|
77
|
+
constructor(host: GridHost<T>, history?: HistoryController<T> | undefined);
|
|
46
78
|
hostConnected(): void;
|
|
47
79
|
/**
|
|
48
80
|
* Whether editing is enabled at the grid level.
|
|
@@ -82,6 +114,41 @@ export declare class EditingController<T extends object> implements ReactiveCont
|
|
|
82
114
|
* success. No-op in cell mode.
|
|
83
115
|
*/
|
|
84
116
|
editRow(rowIndex: number): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* The single choke point for committing a cell value to the backing record.
|
|
119
|
+
* Short-circuits no-op writes, runs the cancellable `cellValueChanging` gate,
|
|
120
|
+
* writes the value through to {@link ApexGrid.data}, and emits
|
|
121
|
+
* `cellValueChanged`. Returns the {@link CellEditResult} so callers can manage
|
|
122
|
+
* their own UI state (active cell) and batch the render.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* Does **not** request a render — callers refresh (once per edit, or once per
|
|
126
|
+
* batch) so row-mode and bulk edits coalesce into a single pipeline pass.
|
|
127
|
+
* Every committed edit (single-cell, row-mode, and enterprise paste/fill)
|
|
128
|
+
* funnels through here so cross-cutting concerns (validation, undo/redo) have
|
|
129
|
+
* one place to hook the old/new values and the write.
|
|
130
|
+
*/
|
|
131
|
+
applyCellEdit(rowIndex: number, columnKey: Keys<T>, data: T, value: unknown, options?: ApplyCellEditOptions): CellEditResult;
|
|
132
|
+
/**
|
|
133
|
+
* Runs the column's declarative validators against a candidate value and
|
|
134
|
+
* returns the collected error messages (empty when the value passes or the
|
|
135
|
+
* column has no validators).
|
|
136
|
+
*/
|
|
137
|
+
validateCell(rowIndex: number, columnKey: Keys<T>, data: T, value: unknown): string[];
|
|
138
|
+
/**
|
|
139
|
+
* The current validation errors for `(data, columnKey)`, or `null` when the
|
|
140
|
+
* cell is valid. Read by {@link ApexGridCell} to drive `aria-invalid` and the
|
|
141
|
+
* inline error node.
|
|
142
|
+
*/
|
|
143
|
+
getCellErrors(data: T, columnKey: Keys<T>): readonly string[] | null;
|
|
144
|
+
/**
|
|
145
|
+
* Clears any validation error recorded for `(data, columnKey)`.
|
|
146
|
+
*/
|
|
147
|
+
clearCellErrors(data: T, columnKey: Keys<T>): void;
|
|
148
|
+
/**
|
|
149
|
+
* Clears every validation error recorded for a record (all columns).
|
|
150
|
+
*/
|
|
151
|
+
clearRecordErrors(data: T): void;
|
|
85
152
|
/**
|
|
86
153
|
* Commits a candidate value for the currently editing cell. In cell mode the
|
|
87
154
|
* value is written through to {@link ApexGrid.data}; in row mode it is staged
|
package/controllers/editing.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { PIPELINE } from '../internal/constants.js';
|
|
2
|
+
import { runValidators } from '../internal/validators.js';
|
|
2
3
|
export const DEFAULT_EDITING_CONFIG = Object.freeze({
|
|
3
4
|
enabled: false,
|
|
4
5
|
mode: 'cell',
|
|
5
6
|
trigger: 'doubleClick',
|
|
6
7
|
});
|
|
7
8
|
export class EditingController {
|
|
8
|
-
|
|
9
|
+
#invalid;
|
|
10
|
+
#validationVersion;
|
|
11
|
+
get validationVersion() {
|
|
12
|
+
return this.#validationVersion;
|
|
13
|
+
}
|
|
14
|
+
constructor(host, history) {
|
|
9
15
|
this.host = host;
|
|
16
|
+
this.history = history;
|
|
10
17
|
this.activeCell = null;
|
|
11
18
|
this.activeRow = null;
|
|
12
19
|
this.pending = new Map();
|
|
20
|
+
this.#invalid = new Map();
|
|
21
|
+
this.#validationVersion = 0;
|
|
13
22
|
this.host.addController(this);
|
|
14
23
|
}
|
|
15
24
|
hostConnected() { }
|
|
@@ -77,6 +86,74 @@ export class EditingController {
|
|
|
77
86
|
this.host.emitEvent('rowEditStarted', { detail: { rowIndex } });
|
|
78
87
|
return true;
|
|
79
88
|
}
|
|
89
|
+
applyCellEdit(rowIndex, columnKey, data, value, options) {
|
|
90
|
+
const record = data;
|
|
91
|
+
const oldValue = record[columnKey];
|
|
92
|
+
if (Object.is(value, oldValue)) {
|
|
93
|
+
this.clearCellErrors(data, columnKey);
|
|
94
|
+
return 'unchanged';
|
|
95
|
+
}
|
|
96
|
+
if (options?.validate !== false) {
|
|
97
|
+
const errors = this.validateCell(rowIndex, columnKey, data, value);
|
|
98
|
+
if (errors.length > 0) {
|
|
99
|
+
this.#setCellErrors(data, columnKey, errors);
|
|
100
|
+
this.host.emitEvent('cellValidationFailed', {
|
|
101
|
+
detail: { key: columnKey, rowIndex, data, value, errors },
|
|
102
|
+
});
|
|
103
|
+
return 'invalid';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const proceed = this.host.emitEvent('cellValueChanging', {
|
|
107
|
+
detail: { key: columnKey, rowIndex, data, oldValue, newValue: value },
|
|
108
|
+
cancelable: true,
|
|
109
|
+
});
|
|
110
|
+
if (!proceed)
|
|
111
|
+
return 'cancelled';
|
|
112
|
+
record[columnKey] = value;
|
|
113
|
+
this.clearCellErrors(data, columnKey);
|
|
114
|
+
this.history?.record({ record: data, key: columnKey, rowIndex, oldValue, newValue: value });
|
|
115
|
+
this.host.emitEvent('cellValueChanged', {
|
|
116
|
+
detail: { key: columnKey, rowIndex, data, value },
|
|
117
|
+
});
|
|
118
|
+
return 'applied';
|
|
119
|
+
}
|
|
120
|
+
validateCell(rowIndex, columnKey, data, value) {
|
|
121
|
+
const column = this.host.getColumn(columnKey);
|
|
122
|
+
if (!column?.validators?.length)
|
|
123
|
+
return [];
|
|
124
|
+
return runValidators(column.validators, value, {
|
|
125
|
+
column,
|
|
126
|
+
data,
|
|
127
|
+
rowIndex,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
getCellErrors(data, columnKey) {
|
|
131
|
+
return this.#invalid.get(data)?.get(columnKey) ?? null;
|
|
132
|
+
}
|
|
133
|
+
clearCellErrors(data, columnKey) {
|
|
134
|
+
const perColumn = this.#invalid.get(data);
|
|
135
|
+
if (!perColumn)
|
|
136
|
+
return;
|
|
137
|
+
if (perColumn.delete(columnKey)) {
|
|
138
|
+
if (perColumn.size === 0)
|
|
139
|
+
this.#invalid.delete(data);
|
|
140
|
+
this.#validationVersion += 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
clearRecordErrors(data) {
|
|
144
|
+
if (this.#invalid.delete(data)) {
|
|
145
|
+
this.#validationVersion += 1;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
#setCellErrors(data, columnKey, errors) {
|
|
149
|
+
let perColumn = this.#invalid.get(data);
|
|
150
|
+
if (!perColumn) {
|
|
151
|
+
perColumn = new Map();
|
|
152
|
+
this.#invalid.set(data, perColumn);
|
|
153
|
+
}
|
|
154
|
+
perColumn.set(columnKey, errors);
|
|
155
|
+
this.#validationVersion += 1;
|
|
156
|
+
}
|
|
80
157
|
async commitCell(value) {
|
|
81
158
|
const active = this.activeCell;
|
|
82
159
|
if (!active)
|
|
@@ -85,24 +162,21 @@ export class EditingController {
|
|
|
85
162
|
const oldValue = data[columnKey];
|
|
86
163
|
const candidate = value === undefined ? oldValue : value;
|
|
87
164
|
if (this.mode === 'cell') {
|
|
88
|
-
|
|
89
|
-
|
|
165
|
+
const result = this.applyCellEdit(rowIndex, columnKey, data, candidate);
|
|
166
|
+
if (result === 'cancelled')
|
|
167
|
+
return false;
|
|
168
|
+
if (result === 'invalid') {
|
|
90
169
|
this.host.requestUpdate();
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
const proceed = this.host.emitEvent('cellValueChanging', {
|
|
94
|
-
detail: { key: columnKey, rowIndex, data, oldValue, newValue: candidate },
|
|
95
|
-
cancelable: true,
|
|
96
|
-
});
|
|
97
|
-
if (!proceed)
|
|
98
170
|
return false;
|
|
99
|
-
|
|
171
|
+
}
|
|
100
172
|
this.activeCell = null;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
173
|
+
if (result === 'applied') {
|
|
174
|
+
this.host.requestUpdate(PIPELINE);
|
|
175
|
+
await this.host.updateComplete;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
this.host.requestUpdate();
|
|
179
|
+
}
|
|
106
180
|
return true;
|
|
107
181
|
}
|
|
108
182
|
if (!Object.is(candidate, oldValue)) {
|
|
@@ -121,27 +195,25 @@ export class EditingController {
|
|
|
121
195
|
const data = this.host.pageItems[rowIndex];
|
|
122
196
|
if (!data)
|
|
123
197
|
return false;
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
126
|
-
return true;
|
|
127
|
-
const proceed = this.host.emitEvent('cellValueChanging', {
|
|
128
|
-
detail: { key: columnKey, rowIndex, data, oldValue, newValue: value },
|
|
129
|
-
cancelable: true,
|
|
130
|
-
});
|
|
131
|
-
if (!proceed)
|
|
198
|
+
const result = this.applyCellEdit(rowIndex, columnKey, data, value);
|
|
199
|
+
if (result === 'cancelled')
|
|
132
200
|
return false;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
201
|
+
if (result === 'invalid') {
|
|
202
|
+
this.host.requestUpdate();
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
if (result === 'applied') {
|
|
206
|
+
this.host.requestUpdate(PIPELINE);
|
|
207
|
+
await this.host.updateComplete;
|
|
208
|
+
}
|
|
139
209
|
return true;
|
|
140
210
|
}
|
|
141
211
|
cancelCell() {
|
|
142
212
|
if (!this.activeCell)
|
|
143
213
|
return;
|
|
214
|
+
const { data, columnKey } = this.activeCell;
|
|
144
215
|
this.activeCell = null;
|
|
216
|
+
this.clearCellErrors(data, columnKey);
|
|
145
217
|
this.host.requestUpdate();
|
|
146
218
|
}
|
|
147
219
|
async commitRow() {
|
|
@@ -152,20 +224,32 @@ export class EditingController {
|
|
|
152
224
|
if (this.activeCell?.rowIndex === rowIndex) {
|
|
153
225
|
await this.commitCell();
|
|
154
226
|
}
|
|
227
|
+
let hasInvalid = false;
|
|
155
228
|
for (const [columnKey, candidate] of this.pending) {
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.host.
|
|
167
|
-
|
|
168
|
-
|
|
229
|
+
const errors = this.validateCell(rowIndex, columnKey, data, candidate);
|
|
230
|
+
if (errors.length > 0) {
|
|
231
|
+
this.#setCellErrors(data, columnKey, errors);
|
|
232
|
+
this.host.emitEvent('cellValidationFailed', {
|
|
233
|
+
detail: { key: columnKey, rowIndex, data, value: candidate, errors },
|
|
234
|
+
});
|
|
235
|
+
hasInvalid = true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (hasInvalid) {
|
|
239
|
+
this.host.requestUpdate();
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
this.history?.beginBatch();
|
|
243
|
+
try {
|
|
244
|
+
for (const [columnKey, candidate] of this.pending) {
|
|
245
|
+
if (this.applyCellEdit(rowIndex, columnKey, data, candidate, { validate: false }) ===
|
|
246
|
+
'cancelled') {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
this.history?.endBatch();
|
|
169
253
|
}
|
|
170
254
|
this.pending.clear();
|
|
171
255
|
this.activeRow = null;
|
|
@@ -177,10 +261,11 @@ export class EditingController {
|
|
|
177
261
|
cancelRow() {
|
|
178
262
|
if (!this.activeRow)
|
|
179
263
|
return;
|
|
180
|
-
const { rowIndex } = this.activeRow;
|
|
264
|
+
const { rowIndex, data } = this.activeRow;
|
|
181
265
|
this.activeCell = null;
|
|
182
266
|
this.activeRow = null;
|
|
183
267
|
this.pending.clear();
|
|
268
|
+
this.clearRecordErrors(data);
|
|
184
269
|
this.host.requestUpdate();
|
|
185
270
|
this.host.emitEvent('rowEditEnded', { detail: { rowIndex, committed: false } });
|
|
186
271
|
}
|