@tipolox/litgrid-web 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,8 @@ LitGrid's `yc-grid` Web Component: a virtualized data grid for browser applicati
4
4
 
5
5
  ## Install
6
6
 
7
+ See [selection coordination](../../docs/selection-coordination.md) for typed notifications, stable row keys, restoration, and account/site scope resets.
8
+
7
9
  ```bash
8
10
  npm install @tipolox/litgrid-web
9
11
  ```
@@ -1,5 +1,5 @@
1
1
  import { LitElement } from 'lit';
2
- import { type GridConfig, type GridFilter, type GridSelection, type SelectionIntent } from '@tipolox/litgrid-core';
2
+ import { type GridConfig, type GridFilter, type GridSelection, type GridRowKey, type SelectionChangeDetail, type GridExternalState, type SortDirection, type SelectionIntent } from '@tipolox/litgrid-core';
3
3
  import type { GridColumn, GridTheme } from '../types.js';
4
4
  import { type GridColumnState } from '../columnState/columnState.js';
5
5
  export declare class DataGrid extends LitElement {
@@ -32,6 +32,7 @@ export declare class DataGrid extends LitElement {
32
32
  private previousBodyCursor;
33
33
  private previousBodyUserSelect;
34
34
  private activeHeaderMenu;
35
+ private headerMenuCapabilities;
35
36
  private columnChooserOpen;
36
37
  private columnChooserPosition;
37
38
  private quickSearchVisible;
@@ -58,6 +59,7 @@ export declare class DataGrid extends LitElement {
58
59
  private shouldRestoreHeaderMenuFocus;
59
60
  private screenReaderMessage;
60
61
  private lastScreenReaderAnnouncement;
62
+ private paginationFocusTarget;
61
63
  private maxScrollableHeight;
62
64
  private lastTotalSize;
63
65
  private lastDisplayTotal;
@@ -91,6 +93,7 @@ export declare class DataGrid extends LitElement {
91
93
  constructor();
92
94
  static styles: import("lit").CSSResult[];
93
95
  firstUpdated(): void;
96
+ willUpdate(): void;
94
97
  updated(): void;
95
98
  disconnectedCallback(): void;
96
99
  private updateVirtualizer;
@@ -136,6 +139,8 @@ export declare class DataGrid extends LitElement {
136
139
  private dispatchColumnStateChange;
137
140
  resetColumnVisibility(): void;
138
141
  private toggleHeaderMenu;
142
+ private getColumnCapabilities;
143
+ private reconcileHeaderMenuCapabilities;
139
144
  private closeHeaderMenu;
140
145
  private toggleColumnChooser;
141
146
  private closeColumnChooser;
@@ -174,14 +179,29 @@ export declare class DataGrid extends LitElement {
174
179
  setFilter(filter: GridFilter): void;
175
180
  clearFilter(columnKey?: string): void;
176
181
  getFilters(): GridFilter[];
182
+ sortBy(columnKey: string, direction: SortDirection): void;
183
+ clearSort(): void;
184
+ getQuery(): Readonly<{
185
+ requestId: number;
186
+ query: import("@tipolox/litgrid-core").GridQuery;
187
+ }>;
188
+ refreshQuery(): void;
189
+ get externalState(): GridExternalState | null;
190
+ set externalState(value: GridExternalState | null);
191
+ setExternalState(value: GridExternalState): boolean;
192
+ private getPageLabel;
177
193
  setPage(pageIndex: number): void;
178
194
  setPageSize(pageSize: number): void;
179
195
  getPagination(): import("@tipolox/litgrid-core").GridPaginationState;
196
+ private rememberPaginationFocus;
180
197
  getTotalRowCount(): number;
181
198
  selectRow(rowIndex: number, intent?: SelectionIntent): void;
199
+ private announceAllRowsSelected;
182
200
  selectAllRows(): void;
183
201
  clearSelection(): void;
184
202
  getSelection(): GridSelection;
203
+ getSelectionSnapshot(): SelectionChangeDetail;
204
+ selectRowByKey(key: GridRowKey, intent?: SelectionIntent): boolean;
185
205
  isRowSelected(rowIndex: number): boolean;
186
206
  isCellSelected(rowIndex: number, columnKey: string): boolean;
187
207
  private getSelectedCellsClipboardText;
@@ -1 +1 @@
1
- {"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../src/components/DataGrid.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../src/components/DataGrid.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,7 @@ export class DataGrid extends LitElement {
74
74
  this.previousBodyCursor = '';
75
75
  this.previousBodyUserSelect = '';
76
76
  this.activeHeaderMenu = null;
77
+ this.headerMenuCapabilities = { sortable: true, filterable: true };
77
78
  this.columnChooserOpen = false;
78
79
  this.columnChooserPosition = null;
79
80
  this.quickSearchVisible = false;
@@ -100,6 +101,7 @@ export class DataGrid extends LitElement {
100
101
  this.shouldRestoreHeaderMenuFocus = false;
101
102
  this.screenReaderMessage = '';
102
103
  this.lastScreenReaderAnnouncement = '';
104
+ this.paginationFocusTarget = null;
103
105
  // Use a larger cap (2^26) to avoid hitting browser element-height limits.
104
106
  this.maxScrollableHeight = 67108864;
105
107
  this.lastTotalSize = 0;
@@ -222,6 +224,21 @@ export class DataGrid extends LitElement {
222
224
  this.ariaLabel = 'Data grid';
223
225
  this.ariaDescription = '';
224
226
  this.screenReaderAnnouncements = true;
227
+ this.engine.onSelectionChange(detail => {
228
+ this.requestUpdate();
229
+ this.dispatchEvent(new CustomEvent('selection-change', {
230
+ detail, bubbles: true, composed: true
231
+ }));
232
+ });
233
+ this.engine.onQueryChange(detail => {
234
+ this.quickSearchDraft = detail.query.search;
235
+ this.clearBestFitWidths();
236
+ this.resetVerticalScroll();
237
+ this.requestUpdate();
238
+ this.dispatchEvent(new CustomEvent('query-change', {
239
+ detail, bubbles: true, composed: true
240
+ }));
241
+ });
225
242
  }
226
243
  static { this.styles = [lightThemeStyles, darkThemeStyles, css `
227
244
  :host {
@@ -241,11 +258,68 @@ export class DataGrid extends LitElement {
241
258
  overflow: hidden;
242
259
  }
243
260
 
261
+ .viewport-frame {
262
+ position: relative;
263
+ min-width: 0;
264
+ }
265
+
244
266
  .viewport {
245
267
  overflow: auto;
246
268
  height: var(--grid-height, 320px);
247
269
  }
248
270
 
271
+ /* The transient external status covers only the body and never enters the
272
+ normal layout flow. Header/search/footer positions remain unchanged. */
273
+ .external-status {
274
+ position: absolute;
275
+ inset: 0;
276
+ z-index: 2;
277
+ box-sizing: border-box;
278
+ display: flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ padding: 16px;
282
+ background: var(--litgrid-color-surface);
283
+ color: var(--litgrid-color-text-strong);
284
+ text-align: center;
285
+ pointer-events: none;
286
+ }
287
+
288
+ .external-status-label {
289
+ display: inline-flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ gap: 10px;
293
+ max-width: 100%;
294
+ border: 1px solid var(--litgrid-color-border);
295
+ border-radius: 8px;
296
+ padding: 10px 14px;
297
+ background: var(--litgrid-color-surface-subtle);
298
+ font-weight: 600;
299
+ }
300
+
301
+ .external-status.loading .external-status-label::before {
302
+ content: '';
303
+ box-sizing: border-box;
304
+ flex: none;
305
+ width: 16px;
306
+ height: 16px;
307
+ border: 2px solid var(--litgrid-color-border-strong);
308
+ border-top-color: var(--litgrid-color-accent);
309
+ border-radius: 50%;
310
+ animation: litgrid-external-loading-spin 0.8s linear infinite;
311
+ }
312
+
313
+ @keyframes litgrid-external-loading-spin {
314
+ to { transform: rotate(360deg); }
315
+ }
316
+
317
+ @media (prefers-reduced-motion: reduce) {
318
+ .external-status.loading .external-status-label::before {
319
+ animation: none;
320
+ }
321
+ }
322
+
249
323
  .screen-reader-only {
250
324
  position: absolute;
251
325
  width: 1px;
@@ -749,7 +823,16 @@ export class DataGrid extends LitElement {
749
823
  firstUpdated() {
750
824
  this.updateScrollbarWidth();
751
825
  }
826
+ willUpdate() {
827
+ // Reconcile after schema and persisted visibility settle, before triggers disappear.
828
+ this.reconcileHeaderMenuCapabilities();
829
+ }
752
830
  updated() {
831
+ const paginationTarget = this.paginationFocusTarget;
832
+ this.paginationFocusTarget = null;
833
+ if (paginationTarget?.isConnected && paginationTarget.disabled) {
834
+ this.renderRoot.querySelector('.pagination button:not([disabled]), .pagination select')?.focus();
835
+ }
753
836
  this.updateScrollbarWidth();
754
837
  if (this.shouldFocusViewport) {
755
838
  this.shouldFocusViewport = false;
@@ -1142,6 +1225,7 @@ export class DataGrid extends LitElement {
1142
1225
  });
1143
1226
  }
1144
1227
  const isOpening = this.activeHeaderMenu !== columnKey;
1228
+ this.headerMenuCapabilities = this.getColumnCapabilities(columnKey);
1145
1229
  this.activeHeaderMenu = isOpening ? columnKey : null;
1146
1230
  this.headerMenuTrigger = isOpening && event.currentTarget instanceof HTMLButtonElement
1147
1231
  ? event.currentTarget
@@ -1149,6 +1233,19 @@ export class DataGrid extends LitElement {
1149
1233
  this.shouldFocusHeaderMenu = isOpening;
1150
1234
  this.requestUpdate();
1151
1235
  }
1236
+ getColumnCapabilities(columnKey) {
1237
+ const column = this.getResolvedColumns().find(column => column.key === columnKey);
1238
+ return { sortable: !!column && column.sortable !== false, filterable: !!column && column.filterable !== false };
1239
+ }
1240
+ reconcileHeaderMenuCapabilities() {
1241
+ if (this.activeHeaderMenu === null)
1242
+ return;
1243
+ const next = this.getColumnCapabilities(this.activeHeaderMenu);
1244
+ if (!this.isColumnVisible(this.activeHeaderMenu)
1245
+ || next.sortable !== this.headerMenuCapabilities.sortable || next.filterable !== this.headerMenuCapabilities.filterable) {
1246
+ this.closeHeaderMenu(true);
1247
+ }
1248
+ }
1152
1249
  closeHeaderMenu(restoreFocus = false) {
1153
1250
  if (this.activeHeaderMenu === null && !this.columnChooserOpen)
1154
1251
  return;
@@ -1280,6 +1377,10 @@ export class DataGrid extends LitElement {
1280
1377
  }
1281
1378
  announceRowSelection(rowIndex, intent = 'replace') {
1282
1379
  const anchor = this.engine.getSelection().anchorRowIndex ?? rowIndex;
1380
+ if (intent === 'range' && this.engine.getConfig().selection.rowKey !== undefined) {
1381
+ this.announceScreenReader(`${this.getDisplayedSelectedRowCount()} displayed rows selected.`);
1382
+ return;
1383
+ }
1283
1384
  this.announceScreenReader(intent === 'range' && anchor !== rowIndex
1284
1385
  ? `Rows ${Math.min(anchor, rowIndex) + 1} through ${Math.max(anchor, rowIndex) + 1} selected.`
1285
1386
  : `Row ${rowIndex + 1} ${this.engine.isRowSelected(rowIndex) ? 'selected' : 'deselected'}.`);
@@ -1288,24 +1389,34 @@ export class DataGrid extends LitElement {
1288
1389
  this.announceScreenReader(`${this.getColumnLabel(columnKey)}, row ${rowIndex + 1} ${this.engine.isCellSelected(rowIndex, columnKey) ? 'selected' : 'deselected'}.`);
1289
1390
  }
1290
1391
  announceVisibleRowCount(context) {
1392
+ if (this.engine.getConfig().queryMode === 'external') {
1393
+ this.announceScreenReader(`${context}. Server query requested.`);
1394
+ return;
1395
+ }
1291
1396
  const rowCount = this.engine.getRowCount();
1292
1397
  this.announceScreenReader(rowCount === 0 ? `${context}. No matching rows.` : `${context}. ${rowCount} ${rowCount === 1 ? 'row' : 'rows'} shown.`);
1293
1398
  }
1294
1399
  handleSortAscending(columnKey) {
1400
+ if (!this.getColumnCapabilities(columnKey).sortable)
1401
+ return;
1295
1402
  this.engine.sortBy(columnKey, 'asc');
1296
- this.announceScreenReader(`${this.getColumnLabel(columnKey)} sorted ascending.`);
1403
+ this.announceScreenReader(`${this.getColumnLabel(columnKey)} ${this.engine.getConfig().queryMode === 'external' ? 'ascending sort requested' : 'sorted ascending'}.`);
1297
1404
  this.requestUpdate();
1298
1405
  this.closeHeaderMenu(true);
1299
1406
  }
1300
1407
  handleSortDescending(columnKey) {
1408
+ if (!this.getColumnCapabilities(columnKey).sortable)
1409
+ return;
1301
1410
  this.engine.sortBy(columnKey, 'desc');
1302
- this.announceScreenReader(`${this.getColumnLabel(columnKey)} sorted descending.`);
1411
+ this.announceScreenReader(`${this.getColumnLabel(columnKey)} ${this.engine.getConfig().queryMode === 'external' ? 'descending sort requested' : 'sorted descending'}.`);
1303
1412
  this.requestUpdate();
1304
1413
  this.closeHeaderMenu(true);
1305
1414
  }
1306
- handleClearSort() {
1415
+ handleClearSort(columnKey) {
1416
+ if (!this.getColumnCapabilities(columnKey).sortable)
1417
+ return;
1307
1418
  this.engine.clearSort();
1308
- this.announceScreenReader('Sorting cleared.');
1419
+ this.announceScreenReader(this.engine.getConfig().queryMode === 'external' ? 'Clear sorting requested.' : 'Sorting cleared.');
1309
1420
  this.requestUpdate();
1310
1421
  this.closeHeaderMenu(true);
1311
1422
  }
@@ -1478,7 +1589,8 @@ export class DataGrid extends LitElement {
1478
1589
  this.clearQuickSearchDebounce();
1479
1590
  const threshold = Math.max(0, Math.floor(this.quickSearchDebounceThreshold));
1480
1591
  const debounceMs = Math.max(0, Math.floor(this.quickSearchDebounceMs));
1481
- if (this.sourceRowCount < threshold || debounceMs === 0) {
1592
+ const external = this.engine.getConfig().queryMode === 'external';
1593
+ if (debounceMs === 0 || (!external && this.sourceRowCount < threshold)) {
1482
1594
  this.applyQuickSearch(query);
1483
1595
  return;
1484
1596
  }
@@ -1510,23 +1622,65 @@ export class DataGrid extends LitElement {
1510
1622
  getFilters() {
1511
1623
  return this.engine.getFilters();
1512
1624
  }
1625
+ sortBy(columnKey, direction) {
1626
+ this.engine.sortBy(columnKey, direction);
1627
+ this.resetVerticalScroll();
1628
+ this.requestUpdate();
1629
+ }
1630
+ clearSort() {
1631
+ this.engine.clearSort();
1632
+ this.resetVerticalScroll();
1633
+ this.requestUpdate();
1634
+ }
1635
+ getQuery() { return this.engine.getQuery(); }
1636
+ refreshQuery() { this.engine.refreshQuery(); }
1637
+ get externalState() { return this.engine.getExternalState(); }
1638
+ set externalState(value) {
1639
+ if (value)
1640
+ this.setExternalState(value);
1641
+ }
1642
+ setExternalState(value) {
1643
+ if (!this.engine.setExternalState(value))
1644
+ return false;
1645
+ this.clearQuickSearchDebounce();
1646
+ this.quickSearchDraft = this.engine.getQuickSearch();
1647
+ this.filterDrafts = new Map(this.engine.getFilters().map(filter => [filter.columnKey, filter]));
1648
+ this.sourceRowCount = this.engine.getRowCount();
1649
+ this.clearBestFitWidths();
1650
+ this.requestUpdate();
1651
+ return true;
1652
+ }
1653
+ getPageLabel() {
1654
+ const pagination = this.engine.getPagination();
1655
+ if (this.engine.getConfig().queryMode === 'external' && pagination.totalKnown && pagination.pageIndex > 0 && pagination.pageIndex >= pagination.pageCount)
1656
+ return `Page ${pagination.pageIndex + 1} (out of range)`;
1657
+ return pagination.totalKnown === false ? `Page ${pagination.pageIndex + 1}`
1658
+ : `Page ${pagination.pageCount === 0 ? 0 : pagination.pageIndex + 1} of ${pagination.pageCount}`;
1659
+ }
1513
1660
  setPage(pageIndex) {
1661
+ this.rememberPaginationFocus();
1514
1662
  this.engine.setPage(pageIndex);
1515
1663
  this.resetVerticalScroll();
1516
1664
  const pagination = this.engine.getPagination();
1517
- this.announceScreenReader(`Page ${pagination.pageCount === 0 ? 0 : pagination.pageIndex + 1} of ${pagination.pageCount}.`);
1665
+ this.announceScreenReader(`${this.getPageLabel()}.`);
1518
1666
  this.requestUpdate();
1519
1667
  }
1520
1668
  setPageSize(pageSize) {
1669
+ this.rememberPaginationFocus();
1521
1670
  this.engine.setPageSize(pageSize);
1522
1671
  this.resetVerticalScroll();
1523
1672
  const pagination = this.engine.getPagination();
1524
- this.announceScreenReader(`${pagination.pageSize} rows per page. Page ${pagination.pageCount === 0 ? 0 : pagination.pageIndex + 1} of ${pagination.pageCount}.`);
1673
+ this.announceScreenReader(`${pagination.pageSize} rows per page. ${this.getPageLabel()}.`);
1525
1674
  this.requestUpdate();
1526
1675
  }
1527
1676
  getPagination() {
1528
1677
  return this.engine.getPagination();
1529
1678
  }
1679
+ rememberPaginationFocus() {
1680
+ const active = this.shadowRoot?.activeElement;
1681
+ if (active instanceof HTMLButtonElement && active.closest('.pagination'))
1682
+ this.paginationFocusTarget = active;
1683
+ }
1530
1684
  getTotalRowCount() {
1531
1685
  return this.engine.getTotalRowCount();
1532
1686
  }
@@ -1545,13 +1699,18 @@ export class DataGrid extends LitElement {
1545
1699
  this.announceRowSelection(rowIndex, effectiveIntent);
1546
1700
  this.requestUpdate();
1547
1701
  }
1702
+ announceAllRowsSelected() {
1703
+ const count = this.engine.getSelectableRowCount();
1704
+ const qualifier = count === this.engine.getRowCount() ? '' : 'selectable ';
1705
+ this.announceScreenReader(`All ${count} ${qualifier}displayed rows selected.`);
1706
+ }
1548
1707
  selectAllRows() {
1549
- if (this.engine.getConfig().selection.mode !== 'multi-row' || this.engine.getRowCount() === 0)
1708
+ if (this.engine.getConfig().selection.mode !== 'multi-row' || this.engine.getSelectableRowCount() === 0)
1550
1709
  return;
1551
- const unchanged = this.engine.getSelection().rowIndexes.size === this.engine.getRowCount();
1710
+ const unchanged = this.engine.getSelection().rowIndexes.size === this.engine.getSelectableRowCount();
1552
1711
  this.engine.selectAllRows();
1553
1712
  if (!unchanged)
1554
- this.announceScreenReader(`All ${this.engine.getRowCount()} displayed rows selected.`);
1713
+ this.announceAllRowsSelected();
1555
1714
  this.requestUpdate();
1556
1715
  }
1557
1716
  clearSelection() {
@@ -1565,6 +1724,21 @@ export class DataGrid extends LitElement {
1565
1724
  getSelection() {
1566
1725
  return this.engine.getSelection();
1567
1726
  }
1727
+ getSelectionSnapshot() {
1728
+ return this.engine.getSelectionSnapshot();
1729
+ }
1730
+ selectRowByKey(key, intent) {
1731
+ const previous = this.engine.getSelectionSnapshot();
1732
+ const selected = this.engine.selectRowByKey(key, intent);
1733
+ const next = this.engine.getSelectionSnapshot();
1734
+ if (selected && next !== previous) {
1735
+ const index = next.rows.find(row => row.key === key)?.rowIndex
1736
+ ?? previous.rows.find(row => row.key === key)?.rowIndex;
1737
+ if (index !== undefined)
1738
+ this.announceRowSelection(index, intent);
1739
+ }
1740
+ return selected;
1741
+ }
1568
1742
  isRowSelected(rowIndex) {
1569
1743
  return this.engine.isRowSelected(rowIndex);
1570
1744
  }
@@ -1616,6 +1790,8 @@ export class DataGrid extends LitElement {
1616
1790
  }
1617
1791
  }
1618
1792
  applyHeaderFilter(columnKey) {
1793
+ if (!this.getColumnCapabilities(columnKey).filterable)
1794
+ return;
1619
1795
  const filter = this.getFilterDraft(columnKey);
1620
1796
  this.setFilter({
1621
1797
  ...filter,
@@ -1624,6 +1800,8 @@ export class DataGrid extends LitElement {
1624
1800
  this.closeHeaderMenu(true);
1625
1801
  }
1626
1802
  clearHeaderFilter(columnKey) {
1803
+ if (!this.getColumnCapabilities(columnKey).filterable)
1804
+ return;
1627
1805
  this.clearFilter(columnKey);
1628
1806
  this.closeHeaderMenu(true);
1629
1807
  }
@@ -2253,6 +2431,8 @@ export class DataGrid extends LitElement {
2253
2431
  `;
2254
2432
  }
2255
2433
  set data(value) {
2434
+ if (this.engine.getConfig().queryMode === 'external')
2435
+ return;
2256
2436
  this.clearQuickSearchDebounce();
2257
2437
  this.sourceRowCount = Array.isArray(value) ? value.length : 0;
2258
2438
  this.engine.setData(value ?? []);
@@ -2265,22 +2445,15 @@ export class DataGrid extends LitElement {
2265
2445
  this.selectRow(rowIndex, 'toggle');
2266
2446
  }
2267
2447
  getDisplayedSelectedRowCount() {
2268
- const rowCount = this.engine.getRowCount();
2269
- let selectedCount = 0;
2270
- for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
2271
- if (this.engine.isRowSelected(rowIndex)) {
2272
- selectedCount += 1;
2273
- }
2274
- }
2275
- return selectedCount;
2448
+ return this.engine.getSelectionSnapshot().rowIndexes.length;
2276
2449
  }
2277
2450
  areAllDisplayedRowsSelected() {
2278
- const rowCount = this.engine.getRowCount();
2451
+ const rowCount = this.engine.getSelectableRowCount();
2279
2452
  return rowCount > 0 && this.getDisplayedSelectedRowCount() === rowCount;
2280
2453
  }
2281
2454
  hasPartiallySelectedDisplayedRows() {
2282
2455
  const selectedCount = this.getDisplayedSelectedRowCount();
2283
- return selectedCount > 0 && selectedCount < this.engine.getRowCount();
2456
+ return selectedCount > 0 && selectedCount < this.engine.getSelectableRowCount();
2284
2457
  }
2285
2458
  handleSelectAllRows() {
2286
2459
  if (this.areAllDisplayedRowsSelected()) {
@@ -2289,7 +2462,7 @@ export class DataGrid extends LitElement {
2289
2462
  }
2290
2463
  else {
2291
2464
  this.engine.selectAllRows();
2292
- this.announceScreenReader(`All ${this.engine.getRowCount()} displayed rows selected.`);
2465
+ this.announceAllRowsSelected();
2293
2466
  }
2294
2467
  this.requestUpdate();
2295
2468
  }
@@ -2415,6 +2588,12 @@ export class DataGrid extends LitElement {
2415
2588
  render() {
2416
2589
  const count = this.engine.getRowCount();
2417
2590
  const pagination = this.engine.getPagination();
2591
+ const external = this.engine.getConfig().queryMode === 'external';
2592
+ const externalState = external ? this.engine.getExternalState() : null;
2593
+ const outOfRange = external && pagination.totalKnown && pagination.pageIndex > 0 && pagination.pageIndex >= pagination.pageCount;
2594
+ const externalStatus = externalState?.loading ? 'Loading results.' : externalState?.error
2595
+ ? externalState.error : outOfRange ? 'Requested page is out of range. Choose a previous page.'
2596
+ : count === 0 ? (pagination.totalRows === 0 ? 'No results.' : 'No rows on this page.') : '';
2418
2597
  const pageSizeOptions = [25, 50, 100].includes(pagination.pageSize)
2419
2598
  ? [25, 50, 100]
2420
2599
  : [pagination.pageSize, 25, 50, 100].sort((left, right) => left - right);
@@ -2530,6 +2709,7 @@ export class DataGrid extends LitElement {
2530
2709
  return html `
2531
2710
  <div
2532
2711
  class="shell"
2712
+ aria-busy=${external ? String(!!externalState?.loading) : nothing}
2533
2713
  style=${`--virtual-grid-template: ${gridTemplate}; --total-column-width: ${totalColumnWidth}px; --total-row-width: ${totalRowWidth}px; --row-header-width: ${rowHeaderWidth}px; --header-grid-template: ${headerGridTemplate}; --scrollbar-width: ${this.scrollbarWidth}px;`}
2534
2714
  @keydown=${this.handleShellKeyDown}
2535
2715
  >
@@ -2537,7 +2717,7 @@ export class DataGrid extends LitElement {
2537
2717
  ${this.screenReaderAnnouncements
2538
2718
  ? html `<div class="screen-reader-only" role="status" aria-live="polite" aria-atomic="true">${this.screenReaderMessage}</div>`
2539
2719
  : ''}
2540
- ${this.quickSearchVisible
2720
+ ${this.quickSearchVisible || external
2541
2721
  ? html `
2542
2722
  <div class="quick-search" role="search">
2543
2723
  <input
@@ -2583,7 +2763,7 @@ export class DataGrid extends LitElement {
2583
2763
  aria-label="Select all displayed rows"
2584
2764
  .checked=${this.areAllDisplayedRowsSelected()}
2585
2765
  .indeterminate=${this.hasPartiallySelectedDisplayedRows()}
2586
- ?disabled=${this.engine.getRowCount() === 0}
2766
+ ?disabled=${this.engine.getSelectableRowCount() === 0}
2587
2767
  @change=${() => this.handleSelectAllRows()}
2588
2768
  />`
2589
2769
  : html `<span>#</span>`}
@@ -2647,19 +2827,23 @@ export class DataGrid extends LitElement {
2647
2827
  ${this.quickSearchVisible ? 'Hide Quick Search' : 'Show Quick Search'}
2648
2828
  </button>
2649
2829
  <hr class="header-menu-divider" />
2650
- <button type="button" @click=${() => this.handleSortAscending(column.key)}>
2651
- Sort Asc
2652
- </button>
2653
- <button type="button" @click=${() => this.handleSortDescending(column.key)}>
2654
- Sort Desc
2655
- </button>
2656
- <button type="button" @click=${() => this.handleClearSort()}>
2657
- Clear Sort
2658
- </button>
2830
+ ${column.sortable === false ? '' : html `
2831
+ <button type="button" @click=${() => this.handleSortAscending(column.key)}>
2832
+ Sort Asc
2833
+ </button>
2834
+ <button type="button" @click=${() => this.handleSortDescending(column.key)}>
2835
+ Sort Desc
2836
+ </button>
2837
+ <button type="button" @click=${() => this.handleClearSort(column.key)}>
2838
+ Clear Sort
2839
+ </button>
2840
+ `}
2659
2841
  <button type="button" @click=${(event) => this.toggleColumnChooser(event)}>
2660
2842
  Columns
2661
2843
  </button>
2662
2844
  ${(() => {
2845
+ if (column.filterable === false)
2846
+ return '';
2663
2847
  const draft = this.getFilterDraft(column.key);
2664
2848
  const valueFree = this.isValueFreeFilter(draft.operator);
2665
2849
  return html `
@@ -2721,6 +2905,7 @@ export class DataGrid extends LitElement {
2721
2905
  <button class="columns-button" type="button" @click=${(event) => this.toggleColumnChooser(event)}>Columns</button>
2722
2906
  </div>`
2723
2907
  : ''}
2908
+ <div class="viewport-frame">
2724
2909
  <div
2725
2910
  class="viewport"
2726
2911
  role="grid"
@@ -2770,11 +2955,15 @@ export class DataGrid extends LitElement {
2770
2955
  </div>
2771
2956
  </div>
2772
2957
  </div>
2958
+ ${external && externalStatus
2959
+ ? html `<div class=${externalState?.loading ? 'external-status loading' : 'external-status'} role=${externalState?.error ? 'alert' : 'status'} aria-atomic="true"><span class="external-status-label">${externalStatus}</span></div>`
2960
+ : nothing}
2961
+ </div>
2773
2962
  ${pagination.enabled
2774
2963
  ? html `
2775
2964
  <div class="pagination" role="navigation" aria-label="Pagination">
2776
2965
  <div class="pagination-summary">
2777
- <span>${pagination.totalRows} rows</span>
2966
+ <span>${pagination.totalKnown === false ? 'Total unknown' : `${pagination.totalRows} rows`}</span>
2778
2967
  <label>
2779
2968
  Rows per page
2780
2969
  <select
@@ -2790,7 +2979,7 @@ export class DataGrid extends LitElement {
2790
2979
  </label>
2791
2980
  </div>
2792
2981
  <div class="pagination-navigation">
2793
- <span>Page ${pagination.pageCount === 0 ? 0 : pagination.pageIndex + 1} of ${pagination.pageCount}</span>
2982
+ <span>${this.getPageLabel()}</span>
2794
2983
  <button
2795
2984
  type="button"
2796
2985
  ?disabled=${pagination.pageIndex === 0}
@@ -2798,7 +2987,7 @@ export class DataGrid extends LitElement {
2798
2987
  >Previous</button>
2799
2988
  <button
2800
2989
  type="button"
2801
- ?disabled=${pagination.pageCount === 0 || pagination.pageIndex >= pagination.pageCount - 1}
2990
+ ?disabled=${pagination.totalKnown === false ? !pagination.hasMore : pagination.pageCount === 0 || pagination.pageIndex >= pagination.pageCount - 1}
2802
2991
  @click=${() => this.setPage(pagination.pageIndex + 1)}
2803
2992
  >Next</button>
2804
2993
  </div>