@alaarab/ogrid-js 2.0.0-beta

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.
Files changed (55) hide show
  1. package/dist/esm/OGrid.js +654 -0
  2. package/dist/esm/components/ColumnChooser.js +68 -0
  3. package/dist/esm/components/ContextMenu.js +122 -0
  4. package/dist/esm/components/HeaderFilter.js +281 -0
  5. package/dist/esm/components/InlineCellEditor.js +278 -0
  6. package/dist/esm/components/MarchingAntsOverlay.js +170 -0
  7. package/dist/esm/components/PaginationControls.js +85 -0
  8. package/dist/esm/components/SideBar.js +353 -0
  9. package/dist/esm/components/StatusBar.js +34 -0
  10. package/dist/esm/index.js +26 -0
  11. package/dist/esm/renderer/TableRenderer.js +414 -0
  12. package/dist/esm/state/ClipboardState.js +171 -0
  13. package/dist/esm/state/ColumnPinningState.js +78 -0
  14. package/dist/esm/state/ColumnResizeState.js +55 -0
  15. package/dist/esm/state/EventEmitter.js +27 -0
  16. package/dist/esm/state/FillHandleState.js +218 -0
  17. package/dist/esm/state/GridState.js +261 -0
  18. package/dist/esm/state/HeaderFilterState.js +205 -0
  19. package/dist/esm/state/KeyboardNavState.js +374 -0
  20. package/dist/esm/state/RowSelectionState.js +81 -0
  21. package/dist/esm/state/SelectionState.js +102 -0
  22. package/dist/esm/state/SideBarState.js +41 -0
  23. package/dist/esm/state/TableLayoutState.js +95 -0
  24. package/dist/esm/state/UndoRedoState.js +82 -0
  25. package/dist/esm/types/columnTypes.js +1 -0
  26. package/dist/esm/types/gridTypes.js +1 -0
  27. package/dist/esm/types/index.js +2 -0
  28. package/dist/types/OGrid.d.ts +60 -0
  29. package/dist/types/components/ColumnChooser.d.ts +14 -0
  30. package/dist/types/components/ContextMenu.d.ts +17 -0
  31. package/dist/types/components/HeaderFilter.d.ts +24 -0
  32. package/dist/types/components/InlineCellEditor.d.ts +24 -0
  33. package/dist/types/components/MarchingAntsOverlay.d.ts +25 -0
  34. package/dist/types/components/PaginationControls.d.ts +9 -0
  35. package/dist/types/components/SideBar.d.ts +35 -0
  36. package/dist/types/components/StatusBar.d.ts +8 -0
  37. package/dist/types/index.d.ts +26 -0
  38. package/dist/types/renderer/TableRenderer.d.ts +59 -0
  39. package/dist/types/state/ClipboardState.d.ts +35 -0
  40. package/dist/types/state/ColumnPinningState.d.ts +36 -0
  41. package/dist/types/state/ColumnResizeState.d.ts +23 -0
  42. package/dist/types/state/EventEmitter.d.ts +9 -0
  43. package/dist/types/state/FillHandleState.d.ts +51 -0
  44. package/dist/types/state/GridState.d.ts +68 -0
  45. package/dist/types/state/HeaderFilterState.d.ts +64 -0
  46. package/dist/types/state/KeyboardNavState.d.ts +29 -0
  47. package/dist/types/state/RowSelectionState.d.ts +23 -0
  48. package/dist/types/state/SelectionState.d.ts +37 -0
  49. package/dist/types/state/SideBarState.d.ts +19 -0
  50. package/dist/types/state/TableLayoutState.d.ts +33 -0
  51. package/dist/types/state/UndoRedoState.d.ts +28 -0
  52. package/dist/types/types/columnTypes.d.ts +28 -0
  53. package/dist/types/types/gridTypes.d.ts +69 -0
  54. package/dist/types/types/index.d.ts +2 -0
  55. package/package.json +29 -0
@@ -0,0 +1,55 @@
1
+ import { DEFAULT_MIN_COLUMN_WIDTH } from '@alaarab/ogrid-core';
2
+ import { EventEmitter } from './EventEmitter';
3
+ export class ColumnResizeState {
4
+ constructor() {
5
+ this.emitter = new EventEmitter();
6
+ this.columnWidths = new Map();
7
+ this.isResizing = false;
8
+ this.resizeColumnId = null;
9
+ this.resizeStartX = 0;
10
+ this.resizeStartWidth = 0;
11
+ }
12
+ get resizingColumnId() {
13
+ return this.resizeColumnId;
14
+ }
15
+ getColumnWidth(columnId) {
16
+ return this.columnWidths.get(columnId);
17
+ }
18
+ getAllColumnWidths() {
19
+ const result = {};
20
+ this.columnWidths.forEach((width, id) => {
21
+ result[id] = width;
22
+ });
23
+ return result;
24
+ }
25
+ startResize(columnId, clientX, currentWidth) {
26
+ this.isResizing = true;
27
+ this.resizeColumnId = columnId;
28
+ this.resizeStartX = clientX;
29
+ this.resizeStartWidth = currentWidth;
30
+ }
31
+ updateResize(clientX) {
32
+ if (!this.isResizing || !this.resizeColumnId)
33
+ return null;
34
+ const delta = clientX - this.resizeStartX;
35
+ const newWidth = Math.max(DEFAULT_MIN_COLUMN_WIDTH, this.resizeStartWidth + delta);
36
+ return newWidth;
37
+ }
38
+ endResize(clientX) {
39
+ if (!this.isResizing || !this.resizeColumnId)
40
+ return;
41
+ const delta = clientX - this.resizeStartX;
42
+ const newWidth = Math.max(DEFAULT_MIN_COLUMN_WIDTH, this.resizeStartWidth + delta);
43
+ this.columnWidths.set(this.resizeColumnId, newWidth);
44
+ this.emitter.emit('columnWidthChange', { columnId: this.resizeColumnId, widthPx: newWidth });
45
+ this.isResizing = false;
46
+ this.resizeColumnId = null;
47
+ }
48
+ onColumnWidthChange(handler) {
49
+ this.emitter.on('columnWidthChange', handler);
50
+ return () => this.emitter.off('columnWidthChange', handler);
51
+ }
52
+ destroy() {
53
+ this.emitter.removeAllListeners();
54
+ }
55
+ }
@@ -0,0 +1,27 @@
1
+ export class EventEmitter {
2
+ constructor() {
3
+ this.handlers = new Map();
4
+ }
5
+ on(event, handler) {
6
+ if (!this.handlers.has(event)) {
7
+ this.handlers.set(event, new Set());
8
+ }
9
+ this.handlers.get(event).add(handler);
10
+ }
11
+ off(event, handler) {
12
+ this.handlers.get(event)?.delete(handler);
13
+ }
14
+ emit(event, data) {
15
+ this.handlers.get(event)?.forEach(handler => {
16
+ handler(data);
17
+ });
18
+ }
19
+ removeAllListeners(event) {
20
+ if (event) {
21
+ this.handlers.delete(event);
22
+ }
23
+ else {
24
+ this.handlers.clear();
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,218 @@
1
+ import { normalizeSelectionRange, getCellValue, parseValue } from '@alaarab/ogrid-core';
2
+ import { EventEmitter } from './EventEmitter';
3
+ /**
4
+ * Manages Excel-style fill handle drag-to-fill for cell ranges (vanilla JS).
5
+ * Mirrors the React `useFillHandle` hook as a class-based state.
6
+ */
7
+ export class FillHandleState {
8
+ constructor(params, getSelectionRange, setSelectionRange, setActiveCell) {
9
+ this.emitter = new EventEmitter();
10
+ this.wrapperRef = null;
11
+ this._isFillDragging = false;
12
+ this.fillDragStart = null;
13
+ this.fillDragEnd = { endRow: 0, endCol: 0 };
14
+ this.rafHandle = 0;
15
+ this.liveFillRange = null;
16
+ this.lastMousePos = null;
17
+ this.params = params;
18
+ this.getSelectionRange = getSelectionRange;
19
+ this.setSelectionRange = setSelectionRange;
20
+ this.setActiveCell = setActiveCell;
21
+ this.onMoveBound = this.onMouseMove.bind(this);
22
+ this.onUpBound = this.onMouseUp.bind(this);
23
+ }
24
+ get isFillDragging() {
25
+ return this._isFillDragging;
26
+ }
27
+ get fillRange() {
28
+ return this.liveFillRange;
29
+ }
30
+ setWrapperRef(ref) {
31
+ this.wrapperRef = ref;
32
+ }
33
+ updateParams(params) {
34
+ this.params = params;
35
+ }
36
+ /** Called when the fill handle square is mousedown'd. */
37
+ startFillDrag(e) {
38
+ e.preventDefault();
39
+ e.stopPropagation();
40
+ const range = this.getSelectionRange();
41
+ if (!range)
42
+ return;
43
+ if (this.params.editable === false || !this.params.onCellValueChanged)
44
+ return;
45
+ this._isFillDragging = true;
46
+ this.fillDragStart = { startRow: range.startRow, startCol: range.startCol };
47
+ this.fillDragEnd = { endRow: range.startRow, endCol: range.startCol };
48
+ this.liveFillRange = null;
49
+ window.addEventListener('mousemove', this.onMoveBound, true);
50
+ window.addEventListener('mouseup', this.onUpBound, true);
51
+ }
52
+ onMouseMove(e) {
53
+ if (!this._isFillDragging || !this.fillDragStart)
54
+ return;
55
+ this.lastMousePos = { cx: e.clientX, cy: e.clientY };
56
+ if (this.rafHandle)
57
+ cancelAnimationFrame(this.rafHandle);
58
+ this.rafHandle = requestAnimationFrame(() => {
59
+ this.rafHandle = 0;
60
+ if (!this.lastMousePos)
61
+ return;
62
+ const newRange = this.resolveRange(this.lastMousePos.cx, this.lastMousePos.cy);
63
+ if (!newRange)
64
+ return;
65
+ // Skip if unchanged
66
+ const prev = this.liveFillRange;
67
+ if (prev &&
68
+ prev.startRow === newRange.startRow &&
69
+ prev.startCol === newRange.startCol &&
70
+ prev.endRow === newRange.endRow &&
71
+ prev.endCol === newRange.endCol) {
72
+ return;
73
+ }
74
+ this.liveFillRange = newRange;
75
+ this.fillDragEnd = { endRow: newRange.endRow, endCol: newRange.endCol };
76
+ this.applyDragAttrs(newRange);
77
+ });
78
+ }
79
+ onMouseUp() {
80
+ if (!this._isFillDragging || !this.fillDragStart)
81
+ return;
82
+ window.removeEventListener('mousemove', this.onMoveBound, true);
83
+ window.removeEventListener('mouseup', this.onUpBound, true);
84
+ if (this.rafHandle) {
85
+ cancelAnimationFrame(this.rafHandle);
86
+ this.rafHandle = 0;
87
+ }
88
+ // Flush: resolve final position
89
+ if (this.lastMousePos) {
90
+ const flushed = this.resolveRange(this.lastMousePos.cx, this.lastMousePos.cy);
91
+ if (flushed) {
92
+ this.liveFillRange = flushed;
93
+ this.fillDragEnd = { endRow: flushed.endRow, endCol: flushed.endCol };
94
+ }
95
+ }
96
+ this.clearDragAttrs();
97
+ const start = this.fillDragStart;
98
+ const end = this.fillDragEnd;
99
+ const norm = normalizeSelectionRange({
100
+ startRow: start.startRow,
101
+ startCol: start.startCol,
102
+ endRow: end.endRow,
103
+ endCol: end.endCol,
104
+ });
105
+ // Commit range
106
+ this.setSelectionRange(norm);
107
+ this.setActiveCell({ rowIndex: end.endRow, columnIndex: end.endCol + this.params.colOffset });
108
+ // Apply fill values
109
+ this.applyFillValues(norm, start);
110
+ this._isFillDragging = false;
111
+ this.fillDragStart = null;
112
+ this.liveFillRange = null;
113
+ this.lastMousePos = null;
114
+ this.emitter.emit('fillRangeChange', { fillRange: null });
115
+ }
116
+ applyFillValues(norm, start) {
117
+ const { items, visibleCols, onCellValueChanged, beginBatch, endBatch } = this.params;
118
+ if (!onCellValueChanged)
119
+ return;
120
+ const startItem = items[norm.startRow];
121
+ const startColDef = visibleCols[norm.startCol];
122
+ if (!startItem || !startColDef)
123
+ return;
124
+ const startValue = getCellValue(startItem, startColDef);
125
+ beginBatch?.();
126
+ for (let row = norm.startRow; row <= norm.endRow; row++) {
127
+ for (let col = norm.startCol; col <= norm.endCol; col++) {
128
+ if (row === start.startRow && col === start.startCol)
129
+ continue;
130
+ if (row >= items.length || col >= visibleCols.length)
131
+ continue;
132
+ const item = items[row];
133
+ const colDef = visibleCols[col];
134
+ const colEditable = colDef.editable === true ||
135
+ (typeof colDef.editable === 'function' && colDef.editable(item));
136
+ if (!colEditable)
137
+ continue;
138
+ const oldValue = getCellValue(item, colDef);
139
+ const result = parseValue(startValue, oldValue, item, colDef);
140
+ if (!result.valid)
141
+ continue;
142
+ onCellValueChanged({
143
+ item,
144
+ columnId: colDef.columnId,
145
+ oldValue,
146
+ newValue: result.value,
147
+ rowIndex: row,
148
+ });
149
+ }
150
+ }
151
+ endBatch?.();
152
+ }
153
+ resolveRange(cx, cy) {
154
+ if (!this.fillDragStart || !this.wrapperRef)
155
+ return null;
156
+ const target = document.elementFromPoint(cx, cy);
157
+ const cell = target?.closest?.('[data-row-index][data-col-index]');
158
+ if (!cell || !this.wrapperRef.contains(cell))
159
+ return null;
160
+ const r = parseInt(cell.getAttribute('data-row-index') ?? '', 10);
161
+ const c = parseInt(cell.getAttribute('data-col-index') ?? '', 10);
162
+ if (Number.isNaN(r) || Number.isNaN(c) || c < this.params.colOffset)
163
+ return null;
164
+ const dataCol = c - this.params.colOffset;
165
+ return normalizeSelectionRange({
166
+ startRow: this.fillDragStart.startRow,
167
+ startCol: this.fillDragStart.startCol,
168
+ endRow: r,
169
+ endCol: dataCol,
170
+ });
171
+ }
172
+ applyDragAttrs(range) {
173
+ const wrapper = this.wrapperRef;
174
+ if (!wrapper)
175
+ return;
176
+ const colOff = this.params.colOffset;
177
+ const minR = Math.min(range.startRow, range.endRow);
178
+ const maxR = Math.max(range.startRow, range.endRow);
179
+ const minC = Math.min(range.startCol, range.endCol);
180
+ const maxC = Math.max(range.startCol, range.endCol);
181
+ const cells = wrapper.querySelectorAll('[data-row-index][data-col-index]');
182
+ for (let i = 0; i < cells.length; i++) {
183
+ const el = cells[i];
184
+ const r = parseInt(el.getAttribute('data-row-index'), 10);
185
+ const c = parseInt(el.getAttribute('data-col-index'), 10) - colOff;
186
+ const inRange = r >= minR && r <= maxR && c >= minC && c <= maxC;
187
+ if (inRange) {
188
+ if (!el.hasAttribute('data-drag-range'))
189
+ el.setAttribute('data-drag-range', '');
190
+ }
191
+ else {
192
+ if (el.hasAttribute('data-drag-range'))
193
+ el.removeAttribute('data-drag-range');
194
+ }
195
+ }
196
+ }
197
+ clearDragAttrs() {
198
+ const wrapper = this.wrapperRef;
199
+ if (!wrapper)
200
+ return;
201
+ const marked = wrapper.querySelectorAll('[data-drag-range]');
202
+ for (let i = 0; i < marked.length; i++)
203
+ marked[i].removeAttribute('data-drag-range');
204
+ }
205
+ onFillRangeChange(handler) {
206
+ this.emitter.on('fillRangeChange', handler);
207
+ return () => this.emitter.off('fillRangeChange', handler);
208
+ }
209
+ destroy() {
210
+ if (this._isFillDragging) {
211
+ window.removeEventListener('mousemove', this.onMoveBound, true);
212
+ window.removeEventListener('mouseup', this.onUpBound, true);
213
+ }
214
+ if (this.rafHandle)
215
+ cancelAnimationFrame(this.rafHandle);
216
+ this.emitter.removeAllListeners();
217
+ }
218
+ }
@@ -0,0 +1,261 @@
1
+ import { flattenColumns, processClientSideData, exportToCsv as coreExportToCsv, getCellValue, deriveFilterOptionsFromData, mergeFilter, } from '@alaarab/ogrid-core';
2
+ import { EventEmitter } from './EventEmitter';
3
+ export class GridState {
4
+ constructor(options) {
5
+ this.emitter = new EventEmitter();
6
+ this._data = [];
7
+ this._filters = {};
8
+ this._isLoading = false;
9
+ this._serverItems = [];
10
+ this._serverTotalCount = 0;
11
+ this._fetchId = 0; // Guards against stale fetch responses
12
+ this._firstDataRendered = false;
13
+ // Filter options for client-side data (used by sidebar filters panel & header filter popovers)
14
+ this._filterOptions = {};
15
+ this._allColumns = options.columns;
16
+ this._columns = flattenColumns(options.columns);
17
+ this._getRowId = options.getRowId;
18
+ this._data = options.data ?? [];
19
+ this._dataSource = options.dataSource;
20
+ this._page = options.page ?? 1;
21
+ this._pageSize = options.pageSize ?? 20;
22
+ this._sort = options.sort;
23
+ this._filters = options.filters ?? {};
24
+ this._visibleColumns = options.visibleColumns ?? new Set(this._columns.map(c => c.columnId));
25
+ this._onError = options.onError;
26
+ this._onFirstDataRendered = options.onFirstDataRendered;
27
+ // Derive initial filter options for client-side data
28
+ if (!this._dataSource) {
29
+ this._filterOptions = deriveFilterOptionsFromData(this._data, this._columns);
30
+ }
31
+ // If server-side, trigger initial fetch
32
+ if (this._dataSource) {
33
+ this._isLoading = true;
34
+ this.fetchServerData();
35
+ }
36
+ }
37
+ // --- Getters ---
38
+ get data() { return this._data; }
39
+ get page() { return this._page; }
40
+ get pageSize() { return this._pageSize; }
41
+ get sort() { return this._sort; }
42
+ get filters() { return this._filters; }
43
+ get visibleColumns() { return this._visibleColumns; }
44
+ get isLoading() { return this._isLoading; }
45
+ get columns() { return this._columns; }
46
+ get allColumns() { return this._allColumns; }
47
+ get getRowId() { return this._getRowId; }
48
+ get isServerSide() { return this._dataSource != null; }
49
+ get filterOptions() { return this._filterOptions; }
50
+ /** Get the visible columns in display order. */
51
+ get visibleColumnDefs() {
52
+ return this._columns.filter(c => this._visibleColumns.has(c.columnId));
53
+ }
54
+ /** Get processed (sorted, filtered, paginated) items for current page. */
55
+ getProcessedItems() {
56
+ if (this.isServerSide) {
57
+ return { items: this._serverItems, totalCount: this._serverTotalCount };
58
+ }
59
+ const filtered = processClientSideData(this._data, this._columns, this._filters, this._sort?.field, this._sort?.direction);
60
+ const totalCount = filtered.length;
61
+ const startIdx = (this._page - 1) * this._pageSize;
62
+ const endIdx = startIdx + this._pageSize;
63
+ const items = filtered.slice(startIdx, endIdx);
64
+ return { items, totalCount };
65
+ }
66
+ // --- Server-side fetch ---
67
+ fetchServerData() {
68
+ if (!this._dataSource)
69
+ return;
70
+ const id = ++this._fetchId;
71
+ this._isLoading = true;
72
+ this.emitter.emit('stateChange', { type: 'loading' });
73
+ this._dataSource
74
+ .fetchPage({
75
+ page: this._page,
76
+ pageSize: this._pageSize,
77
+ sort: this._sort ? { field: this._sort.field, direction: this._sort.direction } : undefined,
78
+ filters: this._filters,
79
+ })
80
+ .then((res) => {
81
+ if (id !== this._fetchId)
82
+ return; // Stale response
83
+ this._serverItems = res.items;
84
+ this._serverTotalCount = res.totalCount;
85
+ this._isLoading = false;
86
+ if (!this._firstDataRendered && res.items.length > 0) {
87
+ this._firstDataRendered = true;
88
+ this._onFirstDataRendered?.();
89
+ }
90
+ this.emitter.emit('stateChange', { type: 'data' });
91
+ })
92
+ .catch((err) => {
93
+ if (id !== this._fetchId)
94
+ return;
95
+ this._onError?.(err);
96
+ this._serverItems = [];
97
+ this._serverTotalCount = 0;
98
+ this._isLoading = false;
99
+ this.emitter.emit('stateChange', { type: 'data' });
100
+ });
101
+ }
102
+ // --- Setters ---
103
+ setData(data) {
104
+ this._data = data;
105
+ if (!this.isServerSide) {
106
+ this._filterOptions = deriveFilterOptionsFromData(data, this._columns);
107
+ }
108
+ this.emitter.emit('stateChange', { type: 'data' });
109
+ }
110
+ setPage(page) {
111
+ this._page = page;
112
+ if (this.isServerSide) {
113
+ this.fetchServerData();
114
+ }
115
+ else {
116
+ this.emitter.emit('stateChange', { type: 'page' });
117
+ }
118
+ }
119
+ setPageSize(pageSize) {
120
+ this._pageSize = pageSize;
121
+ this._page = 1;
122
+ if (this.isServerSide) {
123
+ this.fetchServerData();
124
+ }
125
+ else {
126
+ this.emitter.emit('stateChange', { type: 'page' });
127
+ }
128
+ }
129
+ setSort(sort) {
130
+ this._sort = sort;
131
+ this._page = 1;
132
+ if (this.isServerSide) {
133
+ this.fetchServerData();
134
+ }
135
+ else {
136
+ this.emitter.emit('stateChange', { type: 'sort' });
137
+ }
138
+ }
139
+ toggleSort(field) {
140
+ if (this._sort?.field === field) {
141
+ this._sort = this._sort.direction === 'asc'
142
+ ? { field, direction: 'desc' }
143
+ : undefined;
144
+ }
145
+ else {
146
+ this._sort = { field, direction: 'asc' };
147
+ }
148
+ this._page = 1;
149
+ if (this.isServerSide) {
150
+ this.fetchServerData();
151
+ }
152
+ else {
153
+ this.emitter.emit('stateChange', { type: 'sort' });
154
+ }
155
+ }
156
+ setFilter(key, value) {
157
+ this._filters = mergeFilter(this._filters, key, value);
158
+ this._page = 1;
159
+ if (this.isServerSide) {
160
+ this.fetchServerData();
161
+ }
162
+ else {
163
+ this.emitter.emit('stateChange', { type: 'filter' });
164
+ }
165
+ }
166
+ clearFilters() {
167
+ this._filters = {};
168
+ this._page = 1;
169
+ if (this.isServerSide) {
170
+ this.fetchServerData();
171
+ }
172
+ else {
173
+ this.emitter.emit('stateChange', { type: 'filter' });
174
+ }
175
+ }
176
+ setVisibleColumns(columns) {
177
+ this._visibleColumns = columns;
178
+ this.emitter.emit('stateChange', { type: 'columns' });
179
+ }
180
+ setLoading(loading) {
181
+ this._isLoading = loading;
182
+ this.emitter.emit('stateChange', { type: 'loading' });
183
+ }
184
+ refreshData() {
185
+ if (this.isServerSide) {
186
+ this.fetchServerData();
187
+ }
188
+ }
189
+ // --- Event subscription ---
190
+ onStateChange(handler) {
191
+ this.emitter.on('stateChange', handler);
192
+ return () => this.emitter.off('stateChange', handler);
193
+ }
194
+ // --- API ---
195
+ getApi() {
196
+ return {
197
+ setRowData: (data) => {
198
+ if (!this.isServerSide)
199
+ this.setData(data);
200
+ },
201
+ setLoading: (loading) => this.setLoading(loading),
202
+ getColumnState: () => ({
203
+ visibleColumns: Array.from(this._visibleColumns),
204
+ sort: this._sort,
205
+ filters: Object.keys(this._filters).length > 0 ? this._filters : undefined,
206
+ }),
207
+ applyColumnState: (state) => {
208
+ if (state.visibleColumns)
209
+ this._visibleColumns = new Set(state.visibleColumns);
210
+ if (state.sort !== undefined)
211
+ this._sort = state.sort;
212
+ if (state.filters !== undefined)
213
+ this._filters = state.filters ?? {};
214
+ if (this.isServerSide) {
215
+ this.fetchServerData();
216
+ }
217
+ else {
218
+ this.emitter.emit('stateChange', { type: 'columns' });
219
+ }
220
+ },
221
+ setFilterModel: (filters) => {
222
+ this._filters = filters;
223
+ this._page = 1;
224
+ if (this.isServerSide) {
225
+ this.fetchServerData();
226
+ }
227
+ else {
228
+ this.emitter.emit('stateChange', { type: 'filter' });
229
+ }
230
+ },
231
+ getSelectedRows: () => [],
232
+ setSelectedRows: () => { },
233
+ selectAll: () => { },
234
+ deselectAll: () => { },
235
+ clearFilters: () => this.clearFilters(),
236
+ clearSort: () => this.setSort(undefined),
237
+ resetGridState: () => {
238
+ this.clearFilters();
239
+ this.setSort(undefined);
240
+ },
241
+ getDisplayedRows: () => this.getProcessedItems().items,
242
+ refreshData: () => this.refreshData(),
243
+ exportToCsv: (filename) => {
244
+ const { items } = this.getProcessedItems();
245
+ const cols = this.visibleColumnDefs.map(c => ({ columnId: c.columnId, name: c.name }));
246
+ coreExportToCsv(items, cols, (item, colId) => {
247
+ const col = this._columns.find(c => c.columnId === colId);
248
+ if (!col)
249
+ return '';
250
+ const val = getCellValue(item, col);
251
+ if (col.valueFormatter)
252
+ return col.valueFormatter(val, item);
253
+ return val != null ? String(val) : '';
254
+ }, filename);
255
+ },
256
+ };
257
+ }
258
+ destroy() {
259
+ this.emitter.removeAllListeners();
260
+ }
261
+ }