@ornery/ui-grid-react 0.1.4

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/dist/index.js ADDED
@@ -0,0 +1,2020 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_GRID_LABELS: () => import_ui_grid7.DEFAULT_GRID_LABELS,
24
+ UiGrid: () => UiGrid,
25
+ useGridState: () => useGridState,
26
+ useVirtualScroll: () => useVirtualScroll
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/useGridState.ts
31
+ var import_react = require("react");
32
+ var import_ui_grid3 = require("@ornery/ui-grid");
33
+
34
+ // ../ui-grid/src/lib/grid/grid.core.pagination.ts
35
+ function seekGridPage(page, totalPages) {
36
+ return Math.min(Math.max(page, 1), Math.max(totalPages, 1));
37
+ }
38
+ function resolveGridPageSize(pageSize) {
39
+ return Number.isFinite(pageSize) && pageSize > 0 ? pageSize : null;
40
+ }
41
+
42
+ // ../ui-grid/src/lib/grid/grid.constants.ts
43
+ var SORT_DIRECTIONS = {
44
+ asc: "asc",
45
+ desc: "desc",
46
+ none: "none"
47
+ };
48
+
49
+ // ../ui-grid/src/lib/grid/grid.utils.ts
50
+ var PROTECTED_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
51
+ function getPathValue(record, path) {
52
+ return path.split(".").reduce((current, part) => {
53
+ if (current === null || current === void 0 || typeof current !== "object") {
54
+ return void 0;
55
+ }
56
+ if (PROTECTED_PATH_SEGMENTS.has(part)) {
57
+ return void 0;
58
+ }
59
+ if (!Object.prototype.hasOwnProperty.call(current, part)) {
60
+ return void 0;
61
+ }
62
+ return current[part];
63
+ }, record);
64
+ }
65
+ function getCellValue(row, column) {
66
+ if (column.valueGetter) {
67
+ return column.valueGetter(row);
68
+ }
69
+ if (column.field) {
70
+ return getPathValue(row, column.field);
71
+ }
72
+ return row[column.name];
73
+ }
74
+
75
+ // ../ui-grid/src/lib/grid/grid.core.identity.ts
76
+ function buildGridSortState(columnName, direction) {
77
+ return {
78
+ columnName,
79
+ direction: direction ?? SORT_DIRECTIONS.asc
80
+ };
81
+ }
82
+
83
+ // ../ui-grid/src/lib/grid/grid.core.edit.ts
84
+ function beginGridEditSession(rowId, columnName, editingValue) {
85
+ const position = { rowId, columnName };
86
+ return {
87
+ focusedCell: position,
88
+ editingCell: position,
89
+ editingValue
90
+ };
91
+ }
92
+ function clearGridEditSession() {
93
+ return {
94
+ editingCell: null,
95
+ editingValue: ""
96
+ };
97
+ }
98
+ function stringifyGridEditorValue(value) {
99
+ if (value instanceof Date) {
100
+ return value.toISOString().slice(0, 10);
101
+ }
102
+ return value === null || value === void 0 ? "" : String(value);
103
+ }
104
+
105
+ // ../ui-grid/src/lib/grid/grid.core.infinite-scroll.ts
106
+ function maybeRequestInfiniteScrollData(context) {
107
+ if (context.state.dataLoading) {
108
+ return { request: null, nextState: context.state };
109
+ }
110
+ if (context.state.scrollUp && context.startIndex <= context.threshold) {
111
+ return {
112
+ request: "top",
113
+ nextState: {
114
+ ...context.state,
115
+ dataLoading: true,
116
+ previousVisibleRows: context.visibleRows
117
+ }
118
+ };
119
+ }
120
+ if (context.state.scrollDown && context.startIndex + context.viewportRows >= Math.max(context.visibleRows - context.threshold, 0)) {
121
+ return {
122
+ request: "bottom",
123
+ nextState: {
124
+ ...context.state,
125
+ dataLoading: true,
126
+ previousVisibleRows: context.visibleRows
127
+ }
128
+ };
129
+ }
130
+ return { request: null, nextState: context.state };
131
+ }
132
+ function completeInfiniteScrollDataLoad(state, scrollUp, scrollDown) {
133
+ return {
134
+ ...state,
135
+ scrollUp,
136
+ scrollDown,
137
+ dataLoading: false
138
+ };
139
+ }
140
+ function resetInfiniteScrollState(scrollUp, scrollDown) {
141
+ return {
142
+ scrollUp,
143
+ scrollDown,
144
+ dataLoading: false,
145
+ previousVisibleRows: 0
146
+ };
147
+ }
148
+ function saveInfiniteScrollPercentage(state, visibleRows) {
149
+ return {
150
+ ...state,
151
+ previousVisibleRows: visibleRows
152
+ };
153
+ }
154
+ function setInfiniteScrollDirectionsState(state, scrollUp, scrollDown) {
155
+ return {
156
+ ...state,
157
+ scrollUp,
158
+ scrollDown
159
+ };
160
+ }
161
+
162
+ // ../ui-grid/src/lib/grid/grid.core.row-state.ts
163
+ function toggleGridRowExpanded(expandedRows, rowId) {
164
+ const expanded = !expandedRows[rowId];
165
+ return {
166
+ expanded,
167
+ nextExpandedRows: {
168
+ ...expandedRows,
169
+ [rowId]: expanded
170
+ }
171
+ };
172
+ }
173
+ function expandAllGridRows(rows) {
174
+ const nextExpandedRows = {};
175
+ for (const row of rows) {
176
+ nextExpandedRows[row.id] = true;
177
+ }
178
+ return nextExpandedRows;
179
+ }
180
+ function setGridTreeRowExpanded(expandedTreeRows, rowId, expanded) {
181
+ return {
182
+ ...expandedTreeRows,
183
+ [rowId]: expanded
184
+ };
185
+ }
186
+ function toggleGridTreeRowExpanded(expandedTreeRows, rowId) {
187
+ const expanded = !expandedTreeRows[rowId];
188
+ return {
189
+ expanded,
190
+ nextExpandedTreeRows: setGridTreeRowExpanded(expandedTreeRows, rowId, expanded)
191
+ };
192
+ }
193
+ function expandAllGridTreeRows(rows) {
194
+ const nextExpandedTreeRows = {};
195
+ for (const row of rows) {
196
+ if (row.hasChildren) {
197
+ nextExpandedTreeRows[row.id] = true;
198
+ }
199
+ }
200
+ return nextExpandedTreeRows;
201
+ }
202
+
203
+ // ../ui-grid/src/lib/grid/grid.core.state.ts
204
+ function normalizeGridSavedState(state) {
205
+ const normalized = {};
206
+ if (Array.isArray(state.columnOrder)) {
207
+ normalized.columnOrder = state.columnOrder.filter(
208
+ (columnName) => typeof columnName === "string" && isSafeStateKey(columnName)
209
+ );
210
+ }
211
+ if (state.filters && typeof state.filters === "object") {
212
+ normalized.filters = Object.entries(state.filters).reduce((accumulator, [key, value]) => {
213
+ if (typeof key === "string" && isSafeStateKey(key) && typeof value === "string") {
214
+ accumulator[key] = value;
215
+ }
216
+ return accumulator;
217
+ }, {});
218
+ }
219
+ if (state.sort && typeof state.sort === "object") {
220
+ normalized.sort = {
221
+ columnName: typeof state.sort.columnName === "string" && isSafeStateKey(state.sort.columnName) ? state.sort.columnName : null,
222
+ direction: state.sort.direction === SORT_DIRECTIONS.asc || state.sort.direction === SORT_DIRECTIONS.desc ? state.sort.direction : SORT_DIRECTIONS.none
223
+ };
224
+ }
225
+ if (Array.isArray(state.grouping)) {
226
+ normalized.grouping = state.grouping.filter(
227
+ (columnName) => typeof columnName === "string" && isSafeStateKey(columnName)
228
+ );
229
+ }
230
+ if (state.pagination && typeof state.pagination === "object") {
231
+ const paginationCurrentPage = Number(state.pagination.paginationCurrentPage);
232
+ const paginationPageSize = Number(state.pagination.paginationPageSize);
233
+ normalized.pagination = {
234
+ paginationCurrentPage: Number.isFinite(paginationCurrentPage) && paginationCurrentPage > 0 ? Math.floor(paginationCurrentPage) : 1,
235
+ paginationPageSize: Number.isFinite(paginationPageSize) && paginationPageSize >= 0 ? Math.floor(paginationPageSize) : 0
236
+ };
237
+ }
238
+ if (state.expandable && typeof state.expandable === "object") {
239
+ normalized.expandable = normalizeBooleanMap(state.expandable);
240
+ }
241
+ if (state.treeView && typeof state.treeView === "object") {
242
+ normalized.treeView = normalizeBooleanMap(state.treeView);
243
+ }
244
+ return normalized;
245
+ }
246
+ function normalizeBooleanMap(value) {
247
+ return Object.entries(value).reduce((accumulator, [key, entry]) => {
248
+ if (typeof key === "string" && isSafeStateKey(key) && typeof entry === "boolean") {
249
+ accumulator[key] = entry;
250
+ }
251
+ return accumulator;
252
+ }, {});
253
+ }
254
+ function isSafeStateKey(value) {
255
+ return value !== "__proto__" && value !== "constructor" && value !== "prototype";
256
+ }
257
+
258
+ // ../ui-grid/src/lib/grid/ui-grid.events.ts
259
+ function raiseGridRenderingComplete(gridApi) {
260
+ gridApi.core.raise.renderingComplete(gridApi);
261
+ }
262
+ function raiseGridRowsRendered(gridApi, rows) {
263
+ gridApi.core.raise.rowsRendered(rows);
264
+ }
265
+ function raiseGridRowsVisibleChanged(gridApi, rows) {
266
+ gridApi.core.raise.rowsVisibleChanged(rows);
267
+ }
268
+ function raiseGridCanvasHeightChanged(gridApi, oldHeight, newHeight) {
269
+ gridApi.core.raise.canvasHeightChanged(oldHeight, newHeight);
270
+ }
271
+ function raiseGridDimensionChanged(gridApi, oldHeight, oldWidth, newHeight, newWidth) {
272
+ gridApi.core.raise.gridDimensionChanged(oldHeight, oldWidth, newHeight, newWidth);
273
+ }
274
+ function raiseGridScrollBegin(gridApi) {
275
+ gridApi.core.raise.scrollBegin();
276
+ }
277
+ function raiseGridScrollEnd(gridApi) {
278
+ gridApi.core.raise.scrollEnd();
279
+ }
280
+ function raiseGridSortChanged(gridApi, sortState) {
281
+ gridApi.core.raise.sortChanged(sortState.columnName, sortState.direction);
282
+ }
283
+ function raiseGridFilterChanged(gridApi, filters) {
284
+ gridApi.core.raise.filterChanged(filters);
285
+ }
286
+ function raiseGridGroupingChanged(gridApi, groupByColumns) {
287
+ gridApi.core.raise.groupingChanged(groupByColumns);
288
+ }
289
+ function raiseGridColumnOrderChanged(gridApi, order) {
290
+ gridApi.core.raise.columnOrderChanged(order);
291
+ }
292
+ function raiseGridBenchmarkComplete(gridApi, result) {
293
+ gridApi.core.raise.benchmarkComplete(result);
294
+ }
295
+ function raiseGridPaginationChanged(gridApi, currentPage, pageSize) {
296
+ gridApi.pagination.raise.paginationChanged(currentPage, pageSize);
297
+ }
298
+ function raiseGridExpandableRowStateChanged(gridApi, row, expanded) {
299
+ gridApi.expandable.raise.rowExpandedStateChanged(row, expanded);
300
+ }
301
+ function raiseGridTreeRowStateChanged(gridApi, row, expanded) {
302
+ if (expanded) {
303
+ gridApi.treeBase.raise.rowExpanded(row);
304
+ return;
305
+ }
306
+ gridApi.treeBase.raise.rowCollapsed(row);
307
+ }
308
+ function raiseGridNeedMoreData(gridApi, request) {
309
+ if (request === "top") {
310
+ gridApi.infiniteScroll.raise.needLoadMoreDataTop();
311
+ return;
312
+ }
313
+ gridApi.infiniteScroll.raise.needLoadMoreData();
314
+ }
315
+ function raiseGridBeginCellEdit(gridApi, rowEntity, column, triggerEvent) {
316
+ gridApi.edit.raise.beginCellEdit(rowEntity, column, triggerEvent);
317
+ }
318
+ function raiseGridAfterCellEdit(gridApi, rowEntity, column, newValue, oldValue) {
319
+ gridApi.edit.raise.afterCellEdit(rowEntity, column, newValue, oldValue);
320
+ }
321
+ function raiseGridCancelCellEdit(gridApi, rowEntity, column) {
322
+ gridApi.edit.raise.cancelCellEdit(rowEntity, column);
323
+ }
324
+
325
+ // ../ui-grid/src/lib/grid/ui-grid.state.ts
326
+ function moveArrayItem(items, fromIndex, toIndex) {
327
+ const next = [...items];
328
+ const [item] = next.splice(fromIndex, 1);
329
+ if (item === void 0) {
330
+ return next;
331
+ }
332
+ next.splice(toIndex, 0, item);
333
+ return next;
334
+ }
335
+ function moveGridColumnOrderState(current, fromIndex, toIndex) {
336
+ return moveArrayItem(current, fromIndex, toIndex);
337
+ }
338
+ function createGridRestoreMutationPlan(state) {
339
+ const normalizedState = normalizeGridSavedState(state);
340
+ const plan = {};
341
+ if (normalizedState.columnOrder) {
342
+ plan.columnOrder = normalizedState.columnOrder;
343
+ }
344
+ if (normalizedState.filters) {
345
+ plan.filters = normalizedState.filters;
346
+ }
347
+ if (normalizedState.sort) {
348
+ plan.sort = normalizedState.sort;
349
+ }
350
+ if (normalizedState.grouping) {
351
+ plan.grouping = normalizedState.grouping;
352
+ }
353
+ if (normalizedState.pagination) {
354
+ plan.pagination = {
355
+ currentPage: normalizedState.pagination.paginationCurrentPage,
356
+ pageSize: normalizedState.pagination.paginationPageSize
357
+ };
358
+ }
359
+ if (normalizedState.expandable) {
360
+ plan.expandable = normalizedState.expandable;
361
+ }
362
+ if (normalizedState.treeView) {
363
+ plan.treeView = normalizedState.treeView;
364
+ }
365
+ return plan;
366
+ }
367
+
368
+ // ../ui-grid/src/lib/grid/ui-grid.commands.ts
369
+ function applyGridSortStateCommand(gridApi, setSortState, sortState) {
370
+ setSortState(sortState);
371
+ raiseGridSortChanged(gridApi, sortState);
372
+ }
373
+ function sortGridColumnCommand(gridApi, setSortState, columnName, direction) {
374
+ applyGridSortStateCommand(gridApi, setSortState, buildGridSortState(columnName, direction));
375
+ }
376
+ function updateGridFilterCommand(gridApi, updateFilters, getFilters, columnName, value) {
377
+ updateFilters((current) => ({
378
+ ...current,
379
+ [columnName]: value
380
+ }));
381
+ raiseGridFilterChanged(gridApi, getFilters());
382
+ }
383
+ function clearGridFiltersCommand(gridApi, setFilters) {
384
+ const nextFilters = {};
385
+ setFilters(nextFilters);
386
+ raiseGridFilterChanged(gridApi, nextFilters);
387
+ }
388
+ function clearGridGroupingCommand(gridApi, setGroupByColumns, shouldRaise = true) {
389
+ const nextGrouping = [];
390
+ setGroupByColumns(nextGrouping);
391
+ if (shouldRaise) {
392
+ raiseGridGroupingChanged(gridApi, nextGrouping);
393
+ }
394
+ }
395
+ function moveGridColumnCommand(gridApi, canMoveColumns, updateColumnOrder, fromIndex, toIndex) {
396
+ if (!canMoveColumns) {
397
+ return;
398
+ }
399
+ updateColumnOrder((current) => {
400
+ const next = moveGridColumnOrderState(current, fromIndex, toIndex);
401
+ raiseGridColumnOrderChanged(gridApi, next);
402
+ return next;
403
+ });
404
+ }
405
+ function seekGridPaginationCommand(gridApi, setCurrentPage, getTotalPages, getEffectivePageSize, page) {
406
+ const nextPage = seekGridPage(page, getTotalPages());
407
+ setCurrentPage(nextPage);
408
+ raiseGridPaginationChanged(gridApi, nextPage, getEffectivePageSize());
409
+ }
410
+ function setGridPaginationPageSizeCommand(gridApi, setPageSize, setCurrentPage, pageSize) {
411
+ const nextPageSize = resolveGridPageSize(pageSize);
412
+ if (nextPageSize === null) {
413
+ return;
414
+ }
415
+ setPageSize(nextPageSize);
416
+ setCurrentPage(1);
417
+ raiseGridPaginationChanged(gridApi, 1, nextPageSize);
418
+ }
419
+ function restoreGridStateCommand(gridApi, state, access) {
420
+ const restorePlan = createGridRestoreMutationPlan(state);
421
+ if (restorePlan.columnOrder) {
422
+ access.setColumnOrder(restorePlan.columnOrder);
423
+ }
424
+ if (restorePlan.filters) {
425
+ access.setActiveFilters(restorePlan.filters);
426
+ raiseGridFilterChanged(gridApi, restorePlan.filters);
427
+ }
428
+ if (restorePlan.sort) {
429
+ access.setSortState(restorePlan.sort);
430
+ }
431
+ if (restorePlan.grouping) {
432
+ access.setGroupByColumns(restorePlan.grouping);
433
+ raiseGridGroupingChanged(gridApi, restorePlan.grouping);
434
+ }
435
+ if (restorePlan.pagination) {
436
+ access.setCurrentPage(restorePlan.pagination.currentPage);
437
+ access.setPageSize(restorePlan.pagination.pageSize);
438
+ raiseGridPaginationChanged(gridApi, restorePlan.pagination.currentPage, access.getEffectivePageSize());
439
+ }
440
+ if (restorePlan.expandable) {
441
+ access.setExpandedRows(restorePlan.expandable);
442
+ }
443
+ if (restorePlan.treeView) {
444
+ access.setExpandedTreeRows(restorePlan.treeView);
445
+ }
446
+ }
447
+ function toggleGridRowExpansionCommand(gridApi, canExpandRows, currentExpandedRows, rowId, setExpandedRows, findRowById) {
448
+ if (!canExpandRows) {
449
+ return;
450
+ }
451
+ const { expanded, nextExpandedRows } = toggleGridRowExpanded(currentExpandedRows, rowId);
452
+ setExpandedRows(nextExpandedRows);
453
+ const gridRow = findRowById(rowId);
454
+ if (!gridRow) {
455
+ return;
456
+ }
457
+ gridRow.expanded = expanded;
458
+ raiseGridExpandableRowStateChanged(gridApi, gridRow, expanded);
459
+ }
460
+ function expandAllGridRowsCommand(buildRows, data, setExpandedRows) {
461
+ setExpandedRows(expandAllGridRows(buildRows(data)));
462
+ }
463
+ function collapseAllGridRowsCommand(setExpandedRows) {
464
+ setExpandedRows({});
465
+ }
466
+ function toggleGridTreeRowCommand(gridApi, currentExpandedTreeRows, rowId, setExpandedTreeRows, findRowById) {
467
+ const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(currentExpandedTreeRows, rowId);
468
+ setExpandedTreeRows(nextExpandedTreeRows);
469
+ const gridRow = findRowById(rowId);
470
+ if (gridRow) {
471
+ raiseGridTreeRowStateChanged(gridApi, gridRow, expanded);
472
+ }
473
+ }
474
+ function setGridTreeRowExpandedCommand(gridApi, currentExpandedTreeRows, rowId, expanded, setExpandedTreeRows, findRowById) {
475
+ setExpandedTreeRows(setGridTreeRowExpanded(currentExpandedTreeRows, rowId, expanded));
476
+ const gridRow = findRowById(rowId);
477
+ if (gridRow) {
478
+ raiseGridTreeRowStateChanged(gridApi, gridRow, expanded);
479
+ }
480
+ }
481
+ function expandAllGridTreeRowsCommand(buildRows, data, setExpandedTreeRows) {
482
+ setExpandedTreeRows(expandAllGridTreeRows(buildRows(data)));
483
+ }
484
+ function collapseAllGridTreeRowsCommand(setExpandedTreeRows) {
485
+ setExpandedTreeRows({});
486
+ }
487
+ function beginGridCellEditCommand(gridApi, access, row, column, currentValue, triggerEvent, initialValue) {
488
+ const nextEditSession = beginGridEditSession(
489
+ row.id,
490
+ column.name,
491
+ initialValue ?? stringifyGridEditorValue(currentValue)
492
+ );
493
+ access.setFocusedCell(nextEditSession.focusedCell);
494
+ access.setEditingCell(nextEditSession.editingCell);
495
+ access.setEditingValue(nextEditSession.editingValue);
496
+ raiseGridBeginCellEdit(gridApi, row.entity, column, triggerEvent);
497
+ return nextEditSession.editingCell;
498
+ }
499
+ function commitGridCellEditCommand(gridApi, access) {
500
+ const editingCell = access.getEditingCell();
501
+ if (!editingCell) {
502
+ return { committed: false };
503
+ }
504
+ const row = access.findRowById(editingCell.rowId);
505
+ const column = access.findColumnByName(editingCell.columnName);
506
+ if (!row || !column) {
507
+ access.setEditingCell(null);
508
+ return { committed: false };
509
+ }
510
+ const oldValue = getCellValue(row.entity, column);
511
+ const newValue = access.parseEditedValue(column, access.getEditingValue(), oldValue);
512
+ access.setCellValue(row.entity, column, newValue);
513
+ const clearedEditSession = clearGridEditSession();
514
+ access.setEditingCell(clearedEditSession.editingCell);
515
+ raiseGridAfterCellEdit(gridApi, row.entity, column, newValue, oldValue);
516
+ access.setEditingValue(clearedEditSession.editingValue);
517
+ return {
518
+ committed: true,
519
+ focusTarget: { rowId: row.id, columnName: column.name },
520
+ row,
521
+ column
522
+ };
523
+ }
524
+ function cancelGridCellEditCommand(gridApi, access) {
525
+ const editingCell = access.getEditingCell();
526
+ if (!editingCell) {
527
+ return {};
528
+ }
529
+ const row = access.findRowById(editingCell.rowId);
530
+ const column = access.findColumnByName(editingCell.columnName);
531
+ const clearedEditSession = clearGridEditSession();
532
+ access.setEditingCell(clearedEditSession.editingCell);
533
+ access.setEditingValue(clearedEditSession.editingValue);
534
+ if (!row || !column) {
535
+ return {};
536
+ }
537
+ raiseGridCancelCellEdit(gridApi, row.entity, column);
538
+ return { focusTarget: editingCell };
539
+ }
540
+ function maybeRequestInfiniteScrollCommand(gridApi, access) {
541
+ if (!access.enabled || !access.virtualizationEnabled) {
542
+ return;
543
+ }
544
+ const { request, nextState } = maybeRequestInfiniteScrollData({
545
+ state: access.state,
546
+ startIndex: access.startIndex,
547
+ visibleRows: access.visibleRows,
548
+ viewportRows: access.viewportRows,
549
+ threshold: access.threshold
550
+ });
551
+ if (request === "top" || request === "bottom") {
552
+ access.setState(nextState);
553
+ raiseGridNeedMoreData(gridApi, request);
554
+ }
555
+ }
556
+ function completeGridInfiniteScrollDataLoadCommand(currentState, setState, scrollUp, scrollDown) {
557
+ setState(completeInfiniteScrollDataLoad(currentState, scrollUp, scrollDown));
558
+ return Promise.resolve();
559
+ }
560
+ function resetGridInfiniteScrollCommand(setState, scrollUp, scrollDown) {
561
+ setState(resetInfiniteScrollState(scrollUp, scrollDown));
562
+ }
563
+ function saveGridInfiniteScrollPercentageCommand(currentState, visibleRows, setState) {
564
+ setState(saveInfiniteScrollPercentage(currentState, visibleRows));
565
+ }
566
+ function setGridInfiniteScrollDirectionsCommand(currentState, setState, scrollUp, scrollDown) {
567
+ setState(setInfiniteScrollDirectionsState(currentState, scrollUp, scrollDown));
568
+ }
569
+
570
+ // ../ui-grid/src/lib/grid/ui-grid.host.ts
571
+ function observeGridHostSize(hostElement, onSizeChange) {
572
+ if (typeof ResizeObserver === "undefined") {
573
+ return null;
574
+ }
575
+ const observer = new ResizeObserver((entries) => {
576
+ const entry = entries[0];
577
+ if (!entry) {
578
+ return;
579
+ }
580
+ onSizeChange({
581
+ height: Math.round(entry.contentRect.height),
582
+ width: Math.round(entry.contentRect.width)
583
+ });
584
+ });
585
+ observer.observe(hostElement);
586
+ return observer;
587
+ }
588
+ function downloadGridCsvFile(csv, filename) {
589
+ if (typeof Blob === "undefined" || typeof URL === "undefined" || typeof document === "undefined") {
590
+ return;
591
+ }
592
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
593
+ const url = URL.createObjectURL(blob);
594
+ const link = document.createElement("a");
595
+ link.href = url;
596
+ link.download = filename;
597
+ link.click();
598
+ URL.revokeObjectURL(url);
599
+ }
600
+
601
+ // src/useGridState.ts
602
+ function useGridState(options, onRegisterApi) {
603
+ const [activeFilters, setActiveFilters] = (0, import_react.useState)({});
604
+ const [groupByColumns, setGroupByColumns] = (0, import_react.useState)([]);
605
+ const [collapsedGroups, setCollapsedGroups] = (0, import_react.useState)({});
606
+ const [columnOrder, setColumnOrder] = (0, import_react.useState)([]);
607
+ const [hiddenRowReasons, setHiddenRowReasons] = (0, import_react.useState)({});
608
+ const [sortState, setSortState] = (0, import_react.useState)({ columnName: null, direction: import_ui_grid3.SORT_DIRECTIONS.none });
609
+ const [focusedCell, setFocusedCell] = (0, import_react.useState)(null);
610
+ const [editingCell, setEditingCell] = (0, import_react.useState)(null);
611
+ const [editingValue, setEditingValue] = (0, import_react.useState)("");
612
+ const [expandedRows, setExpandedRows] = (0, import_react.useState)({});
613
+ const [expandedTreeRows, setExpandedTreeRows] = (0, import_react.useState)({});
614
+ const [currentPage, setCurrentPage] = (0, import_react.useState)(1);
615
+ const [pageSize, setPageSize] = (0, import_react.useState)(0);
616
+ const [benchmarkResult, setBenchmarkResult] = (0, import_react.useState)(null);
617
+ const [infiniteScrollState, setInfiniteScrollState] = (0, import_react.useState)({
618
+ scrollUp: false,
619
+ scrollDown: true,
620
+ dataLoading: false,
621
+ previousVisibleRows: 0
622
+ });
623
+ const [autoViewportHeight, setAutoViewportHeight] = (0, import_react.useState)(null);
624
+ const gridContainerRef = (0, import_react.useRef)(null);
625
+ const initializedGridIdRef = (0, import_react.useRef)(null);
626
+ const lastCanvasHeightRef = (0, import_react.useRef)(0);
627
+ const lastGridHeightRef = (0, import_react.useRef)(0);
628
+ const lastGridWidthRef = (0, import_react.useRef)(0);
629
+ const scrollEndHandleRef = (0, import_react.useRef)(void 0);
630
+ const scrollingRef = (0, import_react.useRef)(false);
631
+ const editorFocusTokenRef = (0, import_react.useRef)(0);
632
+ const renderedCellFocusTokenRef = (0, import_react.useRef)(0);
633
+ const activeFiltersRef = (0, import_react.useRef)(activeFilters);
634
+ activeFiltersRef.current = activeFilters;
635
+ const groupByColumnsRef = (0, import_react.useRef)(groupByColumns);
636
+ groupByColumnsRef.current = groupByColumns;
637
+ const collapsedGroupsRef = (0, import_react.useRef)(collapsedGroups);
638
+ collapsedGroupsRef.current = collapsedGroups;
639
+ const columnOrderRef = (0, import_react.useRef)(columnOrder);
640
+ columnOrderRef.current = columnOrder;
641
+ const hiddenRowReasonsRef = (0, import_react.useRef)(hiddenRowReasons);
642
+ hiddenRowReasonsRef.current = hiddenRowReasons;
643
+ const sortStateRef = (0, import_react.useRef)(sortState);
644
+ sortStateRef.current = sortState;
645
+ const focusedCellRef = (0, import_react.useRef)(focusedCell);
646
+ focusedCellRef.current = focusedCell;
647
+ const editingCellRef = (0, import_react.useRef)(editingCell);
648
+ editingCellRef.current = editingCell;
649
+ const editingValueRef = (0, import_react.useRef)(editingValue);
650
+ editingValueRef.current = editingValue;
651
+ const expandedRowsRef = (0, import_react.useRef)(expandedRows);
652
+ expandedRowsRef.current = expandedRows;
653
+ const expandedTreeRowsRef = (0, import_react.useRef)(expandedTreeRows);
654
+ expandedTreeRowsRef.current = expandedTreeRows;
655
+ const currentPageRef = (0, import_react.useRef)(currentPage);
656
+ currentPageRef.current = currentPage;
657
+ const pageSizeRef = (0, import_react.useRef)(pageSize);
658
+ pageSizeRef.current = pageSize;
659
+ const infiniteScrollStateRef = (0, import_react.useRef)(infiniteScrollState);
660
+ infiniteScrollStateRef.current = infiniteScrollState;
661
+ const optionsRef = (0, import_react.useRef)(options);
662
+ optionsRef.current = options;
663
+ const rowSize = options.rowHeight ?? 44;
664
+ const visibleColumns = (0, import_react.useMemo)(() => {
665
+ const order = columnOrder;
666
+ return [...options.columnDefs].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
667
+ }, [options.columnDefs, columnOrder]);
668
+ const visibleColumnsRef = (0, import_react.useRef)(visibleColumns);
669
+ visibleColumnsRef.current = visibleColumns;
670
+ const pipeline = (0, import_react.useMemo)(() => {
671
+ return (0, import_ui_grid3.buildGridPipeline)({
672
+ options,
673
+ columns: visibleColumns,
674
+ activeFilters,
675
+ sortState,
676
+ groupByColumns,
677
+ collapsedGroups,
678
+ hiddenRowReasons,
679
+ expandedRows,
680
+ expandedTreeRows,
681
+ currentPage,
682
+ pageSize,
683
+ rowSize
684
+ });
685
+ }, [options, visibleColumns, activeFilters, sortState, groupByColumns, collapsedGroups, hiddenRowReasons, expandedRows, expandedTreeRows, currentPage, pageSize, rowSize]);
686
+ const pipelineRef = (0, import_react.useRef)(pipeline);
687
+ pipelineRef.current = pipeline;
688
+ const labels = (0, import_react.useMemo)(() => (0, import_ui_grid3.resolveGridLabels)(options.labels), [options.labels]);
689
+ const gridTemplateColumns = (0, import_react.useMemo)(
690
+ () => visibleColumns.map((column) => (0, import_ui_grid3.gridColumnWidth)(column)).join(" "),
691
+ [visibleColumns]
692
+ );
693
+ const resolveRowId = (0, import_react.useCallback)((row) => {
694
+ return (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
695
+ }, []);
696
+ const buildRowsFromData = (0, import_react.useCallback)((data) => {
697
+ return (0, import_ui_grid3.buildGridRows)(
698
+ { ...optionsRef.current, data },
699
+ optionsRef.current.rowHeight ?? 44,
700
+ hiddenRowReasonsRef.current,
701
+ expandedRowsRef.current
702
+ );
703
+ }, []);
704
+ const findRowById = (0, import_react.useCallback)((rowId) => {
705
+ return (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
706
+ }, [buildRowsFromData]);
707
+ const canExpandRowsFn = (0, import_react.useCallback)(() => {
708
+ return import_ui_grid3.FEATURE_EXPANDABLE && (0, import_ui_grid3.canGridExpandRows)(optionsRef.current);
709
+ }, []);
710
+ const effectivePageSizeFn = (0, import_react.useCallback)((totalItems) => {
711
+ return (0, import_ui_grid3.getEffectivePageSize)(optionsRef.current, pageSizeRef.current, totalItems);
712
+ }, []);
713
+ const getCurrentPageValueFn = (0, import_react.useCallback)((totalItems) => {
714
+ const ti = totalItems ?? pipelineRef.current.totalItems;
715
+ return (0, import_ui_grid3.getCurrentPageValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
716
+ }, []);
717
+ const getTotalPagesValueFn = (0, import_react.useCallback)((totalItems) => {
718
+ const ti = totalItems ?? pipelineRef.current.totalItems;
719
+ return (0, import_ui_grid3.getTotalPagesValue)(optionsRef.current, ti, pageSizeRef.current);
720
+ }, []);
721
+ const getFirstRowIndexValueFn = (0, import_react.useCallback)((totalItems) => {
722
+ const ti = totalItems ?? pipelineRef.current.totalItems;
723
+ return (0, import_ui_grid3.getFirstRowIndexValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
724
+ }, []);
725
+ const getLastRowIndexValueFn = (0, import_react.useCallback)((totalItems) => {
726
+ const ti = totalItems ?? pipelineRef.current.totalItems;
727
+ return (0, import_ui_grid3.getLastRowIndexValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
728
+ }, []);
729
+ const isCellEditable = (0, import_react.useCallback)((row, column, triggerEvent) => {
730
+ if (!import_ui_grid3.FEATURE_CELL_EDIT) return false;
731
+ const editable = column.enableCellEdit ?? optionsRef.current.enableCellEdit ?? false;
732
+ if (!editable) return false;
733
+ const condition = column.cellEditableCondition ?? optionsRef.current.cellEditableCondition ?? true;
734
+ if (typeof condition === "boolean") return condition;
735
+ const context = {
736
+ row: row.entity,
737
+ column,
738
+ rowIndex: row.index,
739
+ triggerEvent
740
+ };
741
+ return condition(context);
742
+ }, []);
743
+ const shouldEditOnFocusFn = (0, import_react.useCallback)((column) => {
744
+ return column.enableCellEditOnFocus ?? optionsRef.current.enableCellEditOnFocus ?? false;
745
+ }, []);
746
+ const focusRenderedCell = (0, import_react.useCallback)((position) => {
747
+ const focusToken = ++renderedCellFocusTokenRef.current;
748
+ const selector = `.body-cell[data-row-id="${position.rowId}"][data-col-name="${position.columnName}"]`;
749
+ const doFocus = (retry = true) => {
750
+ if (focusToken !== renderedCellFocusTokenRef.current) return;
751
+ const container = gridContainerRef.current;
752
+ if (!container) return;
753
+ const target = container.querySelector(selector);
754
+ if (!target) {
755
+ if (retry) requestAnimationFrame(() => doFocus(false));
756
+ return;
757
+ }
758
+ target.focus();
759
+ if (retry && container.ownerDocument.activeElement !== target) {
760
+ requestAnimationFrame(() => doFocus(false));
761
+ }
762
+ };
763
+ queueMicrotask(() => doFocus(true));
764
+ }, []);
765
+ const focusEditorInput = (0, import_react.useCallback)((focusToken) => {
766
+ if (focusToken !== editorFocusTokenRef.current) return;
767
+ const ec = editingCellRef.current;
768
+ if (!ec) return;
769
+ const selector = `.cell-editor[data-row-id="${ec.rowId}"][data-col-name="${ec.columnName}"]`;
770
+ const doFocus = (retry = true) => {
771
+ if (focusToken !== editorFocusTokenRef.current) return;
772
+ const currentEc = editingCellRef.current;
773
+ if (!currentEc || currentEc.rowId !== ec.rowId || currentEc.columnName !== ec.columnName) return;
774
+ const container = gridContainerRef.current;
775
+ if (!container) return;
776
+ const input = container.querySelector(selector);
777
+ if (!input) {
778
+ if (retry) requestAnimationFrame(() => doFocus(false));
779
+ return;
780
+ }
781
+ input.focus();
782
+ input.select();
783
+ };
784
+ doFocus(true);
785
+ }, []);
786
+ const gridApiRef = (0, import_react.useRef)(null);
787
+ if (!gridApiRef.current) {
788
+ const bindings = {
789
+ refresh: () => setActiveFilters((current) => ({ ...current })),
790
+ getVisibleRows: () => pipelineRef.current.visibleRows,
791
+ setRowInvisible: (row, reason = "user") => {
792
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
793
+ setHiddenRowReasons((current) => (0, import_ui_grid3.addGridRowInvisibleReason)(current, rowId, reason));
794
+ },
795
+ clearRowInvisible: (row, reason = "user") => {
796
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
797
+ setHiddenRowReasons((current) => (0, import_ui_grid3.clearGridRowInvisibleReason)(current, rowId, reason));
798
+ },
799
+ setFilter: (columnName, value) => {
800
+ setActiveFilters((current) => {
801
+ const next = { ...current, [columnName]: value };
802
+ activeFiltersRef.current = next;
803
+ queueMicrotask(() => gridApiRef.current.core.raise.filterChanged(next));
804
+ return next;
805
+ });
806
+ },
807
+ clearAllFilters: () => {
808
+ const nextFilters = {};
809
+ activeFiltersRef.current = nextFilters;
810
+ setActiveFilters(nextFilters);
811
+ queueMicrotask(() => gridApiRef.current.core.raise.filterChanged(nextFilters));
812
+ },
813
+ sortColumn: (columnName, direction) => {
814
+ sortGridColumnCommand(gridApiRef.current, (s) => setSortState(s), columnName, direction);
815
+ },
816
+ moveColumn: (fromIndex, toIndex) => {
817
+ moveGridColumnCommand(
818
+ gridApiRef.current,
819
+ import_ui_grid3.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
820
+ (updater) => setColumnOrder((current) => updater(current)),
821
+ fromIndex,
822
+ toIndex
823
+ );
824
+ },
825
+ toggleGrouping: (columnName) => {
826
+ if (!(import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current))) return;
827
+ const current = groupByColumnsRef.current;
828
+ const next = current.includes(columnName) ? current.filter((n) => n !== columnName) : [...current, columnName];
829
+ groupByColumnsRef.current = next;
830
+ setGroupByColumns(next);
831
+ gridApiRef.current.core.raise.groupingChanged(next);
832
+ },
833
+ clearGrouping: () => {
834
+ clearGridGroupingCommand(gridApiRef.current, (grouping) => setGroupByColumns(grouping), false);
835
+ },
836
+ benchmark: (iterations) => {
837
+ return runBenchmarkFn(iterations);
838
+ },
839
+ exportCsv: () => {
840
+ exportCsvFn();
841
+ },
842
+ paginationGetPage: () => getCurrentPageValueFn(),
843
+ paginationGetTotalPages: () => getTotalPagesValueFn(),
844
+ paginationGetFirstRowIndex: () => getFirstRowIndexValueFn(),
845
+ paginationGetLastRowIndex: () => getLastRowIndexValueFn(),
846
+ paginationNextPage: () => seekPageFn(getCurrentPageValueFn() + 1),
847
+ paginationPreviousPage: () => seekPageFn(getCurrentPageValueFn() - 1),
848
+ paginationSeek: (page) => seekPageFn(page),
849
+ paginationSetPageSize: (ps) => setPaginationPageSizeFn(ps),
850
+ toggleRowExpansion: (row) => toggleRowExpansionByRefFn(row),
851
+ expandAllRows: () => expandAllRowsFn(),
852
+ collapseAllRows: () => {
853
+ collapseAllGridRowsCommand((e) => setExpandedRows(e));
854
+ },
855
+ toggleAllRows: () => toggleAllRowsFn(),
856
+ treeExpandAllRows: () => {
857
+ expandAllGridTreeRowsCommand(
858
+ (data) => buildRowsFromData(data),
859
+ optionsRef.current.data,
860
+ (e) => setExpandedTreeRows(e)
861
+ );
862
+ },
863
+ treeCollapseAllRows: () => {
864
+ collapseAllGridTreeRowsCommand((e) => setExpandedTreeRows(e));
865
+ },
866
+ treeToggleRow: (row) => toggleTreeRowByRefFn(row),
867
+ treeExpandRow: (row) => expandTreeRowByRefFn(row),
868
+ treeCollapseRow: (row) => collapseTreeRowByRefFn(row),
869
+ treeGetRowChildren: (row) => {
870
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
871
+ return buildRowsFromData(optionsRef.current.data).filter((r) => r.parentId === rowId);
872
+ },
873
+ treeGetState: () => expandedTreeRowsRef.current,
874
+ treeSetState: (state) => setExpandedTreeRows({ ...state }),
875
+ infiniteScrollDataLoaded: (scrollUp, scrollDown) => {
876
+ return completeGridInfiniteScrollDataLoadCommand(
877
+ infiniteScrollStateRef.current,
878
+ (s) => setInfiniteScrollState(s),
879
+ scrollUp ?? infiniteScrollStateRef.current.scrollUp,
880
+ scrollDown ?? infiniteScrollStateRef.current.scrollDown
881
+ );
882
+ },
883
+ infiniteScrollReset: (scrollUp, scrollDown) => {
884
+ resetGridInfiniteScrollCommand(
885
+ (s) => setInfiniteScrollState(s),
886
+ scrollUp ?? infiniteScrollStateRef.current.scrollUp,
887
+ scrollDown ?? infiniteScrollStateRef.current.scrollDown
888
+ );
889
+ },
890
+ infiniteScrollSaveScrollPercentage: () => {
891
+ saveGridInfiniteScrollPercentageCommand(
892
+ infiniteScrollStateRef.current,
893
+ pipelineRef.current.visibleRows.length,
894
+ (s) => setInfiniteScrollState(s)
895
+ );
896
+ },
897
+ infiniteScrollDataRemovedTop: (scrollUp, scrollDown) => {
898
+ resetGridInfiniteScrollCommand(
899
+ (s) => setInfiniteScrollState(s),
900
+ scrollUp ?? infiniteScrollStateRef.current.scrollUp,
901
+ scrollDown ?? infiniteScrollStateRef.current.scrollDown
902
+ );
903
+ },
904
+ infiniteScrollDataRemovedBottom: (scrollUp, scrollDown) => {
905
+ resetGridInfiniteScrollCommand(
906
+ (s) => setInfiniteScrollState(s),
907
+ scrollUp ?? infiniteScrollStateRef.current.scrollUp,
908
+ scrollDown ?? infiniteScrollStateRef.current.scrollDown
909
+ );
910
+ },
911
+ infiniteScrollSetDirections: (scrollUp, scrollDown) => {
912
+ setGridInfiniteScrollDirectionsCommand(
913
+ infiniteScrollStateRef.current,
914
+ (s) => setInfiniteScrollState(s),
915
+ scrollUp,
916
+ scrollDown
917
+ );
918
+ },
919
+ saveState: () => {
920
+ return (0, import_ui_grid3.buildGridSavedState)({
921
+ columnOrder: columnOrderRef.current,
922
+ activeFilters: activeFiltersRef.current,
923
+ sortState: sortStateRef.current,
924
+ groupByColumns: groupByColumnsRef.current,
925
+ currentPage: currentPageRef.current,
926
+ pageSize: pageSizeRef.current,
927
+ totalItems: pipelineRef.current.totalItems,
928
+ expandedRows: expandedRowsRef.current,
929
+ expandedTreeRows: expandedTreeRowsRef.current
930
+ });
931
+ },
932
+ restoreState: (state) => {
933
+ restoreGridStateCommand(gridApiRef.current, state, {
934
+ setColumnOrder: (order) => setColumnOrder(order),
935
+ setActiveFilters: (filters) => setActiveFilters(filters),
936
+ setSortState: (s) => setSortState(s),
937
+ setGroupByColumns: (grouping) => setGroupByColumns(grouping),
938
+ setCurrentPage: (page) => setCurrentPage(page),
939
+ setPageSize: (ps) => setPageSize(ps),
940
+ setExpandedRows: (e) => setExpandedRows(e),
941
+ setExpandedTreeRows: (e) => setExpandedTreeRows(e),
942
+ getEffectivePageSize: () => effectivePageSizeFn(pipelineRef.current.totalItems)
943
+ });
944
+ },
945
+ beginCellEdit: (row, columnName, triggerEvent) => {
946
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
947
+ const gridRow = (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
948
+ const column = visibleColumnsRef.current.find((c) => c.name === columnName);
949
+ if (!gridRow || !column || !isCellEditable(gridRow, column, triggerEvent)) return;
950
+ startCellEditFn(gridRow, column, triggerEvent);
951
+ },
952
+ endCellEdit: () => commitCellEditFn(),
953
+ cancelCellEdit: () => cancelCellEditFn(),
954
+ getEditingCell: () => editingCellRef.current
955
+ };
956
+ gridApiRef.current = (0, import_ui_grid3.createGridApi)(bindings);
957
+ }
958
+ const gridApi = gridApiRef.current;
959
+ const seekPageFn = (0, import_react.useCallback)((page) => {
960
+ seekGridPaginationCommand(
961
+ gridApiRef.current,
962
+ (nextPage) => setCurrentPage(nextPage),
963
+ () => getTotalPagesValueFn(),
964
+ () => effectivePageSizeFn(pipelineRef.current.totalItems),
965
+ page
966
+ );
967
+ }, [getTotalPagesValueFn, effectivePageSizeFn]);
968
+ const setPaginationPageSizeFn = (0, import_react.useCallback)((ps) => {
969
+ setGridPaginationPageSizeCommand(
970
+ gridApiRef.current,
971
+ (nextPageSize) => setPageSize(nextPageSize),
972
+ (nextPage) => setCurrentPage(nextPage),
973
+ ps
974
+ );
975
+ }, []);
976
+ const toggleRowExpansionByRefFn = (0, import_react.useCallback)((row) => {
977
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
978
+ toggleGridRowExpansionCommand(
979
+ gridApiRef.current,
980
+ import_ui_grid3.FEATURE_EXPANDABLE && (0, import_ui_grid3.canGridExpandRows)(optionsRef.current),
981
+ expandedRowsRef.current,
982
+ rowId,
983
+ (e) => setExpandedRows(e),
984
+ (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
985
+ );
986
+ }, [buildRowsFromData]);
987
+ const expandAllRowsFn = (0, import_react.useCallback)(() => {
988
+ if (!(0, import_ui_grid3.canGridExpandRows)(optionsRef.current)) return;
989
+ expandAllGridRowsCommand(
990
+ (data) => buildRowsFromData(data),
991
+ optionsRef.current.data,
992
+ (e) => setExpandedRows(e)
993
+ );
994
+ }, [buildRowsFromData]);
995
+ const toggleAllRowsFn = (0, import_react.useCallback)(() => {
996
+ const allExpanded = (0, import_ui_grid3.areAllGridRowsExpanded)(buildRowsFromData(optionsRef.current.data), expandedRowsRef.current);
997
+ if (allExpanded) {
998
+ collapseAllGridRowsCommand((e) => setExpandedRows(e));
999
+ } else {
1000
+ expandAllRowsFn();
1001
+ }
1002
+ }, [buildRowsFromData, expandAllRowsFn]);
1003
+ const toggleTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1004
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1005
+ toggleGridTreeRowCommand(
1006
+ gridApiRef.current,
1007
+ expandedTreeRowsRef.current,
1008
+ rowId,
1009
+ (e) => setExpandedTreeRows(e),
1010
+ (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1011
+ );
1012
+ }, [buildRowsFromData]);
1013
+ const expandTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1014
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1015
+ setGridTreeRowExpandedCommand(
1016
+ gridApiRef.current,
1017
+ expandedTreeRowsRef.current,
1018
+ rowId,
1019
+ true,
1020
+ (e) => setExpandedTreeRows(e),
1021
+ (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1022
+ );
1023
+ }, [buildRowsFromData]);
1024
+ const collapseTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1025
+ const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1026
+ setGridTreeRowExpandedCommand(
1027
+ gridApiRef.current,
1028
+ expandedTreeRowsRef.current,
1029
+ rowId,
1030
+ false,
1031
+ (e) => setExpandedTreeRows(e),
1032
+ (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1033
+ );
1034
+ }, [buildRowsFromData]);
1035
+ const startCellEditFn = (0, import_react.useCallback)((row, column, triggerEvent, initialValue) => {
1036
+ const currentValue = (0, import_ui_grid3.getCellValue)(row.entity, column);
1037
+ const focusToken = ++editorFocusTokenRef.current;
1038
+ const ec = beginGridCellEditCommand(
1039
+ gridApiRef.current,
1040
+ {
1041
+ setFocusedCell: (fc) => setFocusedCell(fc),
1042
+ setEditingCell: (ec2) => setEditingCell(ec2),
1043
+ setEditingValue: (ev) => setEditingValue(ev)
1044
+ },
1045
+ row,
1046
+ column,
1047
+ currentValue,
1048
+ triggerEvent,
1049
+ initialValue
1050
+ );
1051
+ if (ec) {
1052
+ queueMicrotask(() => focusEditorInput(focusToken));
1053
+ }
1054
+ }, [focusEditorInput]);
1055
+ const commitCellEditFn = (0, import_react.useCallback)((direction, restoreFocus = true) => {
1056
+ const result = commitGridCellEditCommand(gridApiRef.current, {
1057
+ getEditingCell: () => editingCellRef.current,
1058
+ getEditingValue: () => editingValueRef.current,
1059
+ setEditingCell: (ec) => setEditingCell(ec),
1060
+ setEditingValue: (ev) => setEditingValue(ev),
1061
+ findRowById: (rowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1062
+ findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName),
1063
+ parseEditedValue: (column, value, oldValue) => (0, import_ui_grid3.parseGridEditedValue)(column, value, oldValue),
1064
+ setCellValue: (rowEntity, column, value) => {
1065
+ const fieldPath = column.editModelField ?? column.field ?? column.name;
1066
+ (0, import_ui_grid3.setPathValue)(rowEntity, fieldPath, value);
1067
+ }
1068
+ });
1069
+ if (!result.committed || !result.row || !result.column || !result.focusTarget) return;
1070
+ editorFocusTokenRef.current += 1;
1071
+ if (direction) {
1072
+ const moved = moveFocusFn(result.row, result.column, direction);
1073
+ if (!moved) focusRenderedCell(result.focusTarget);
1074
+ } else if (restoreFocus) {
1075
+ focusRenderedCell(result.focusTarget);
1076
+ }
1077
+ }, [buildRowsFromData, focusRenderedCell]);
1078
+ const cancelCellEditFn = (0, import_react.useCallback)(() => {
1079
+ const hadEditingCell = editingCellRef.current !== null;
1080
+ const result = cancelGridCellEditCommand(gridApiRef.current, {
1081
+ getEditingCell: () => editingCellRef.current,
1082
+ setEditingCell: (ec) => setEditingCell(ec),
1083
+ setEditingValue: (ev) => setEditingValue(ev),
1084
+ findRowById: (rowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1085
+ findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName)
1086
+ });
1087
+ if (!hadEditingCell) return;
1088
+ editorFocusTokenRef.current += 1;
1089
+ if (result.focusTarget) focusRenderedCell(result.focusTarget);
1090
+ }, [buildRowsFromData, focusRenderedCell]);
1091
+ const moveFocusFn = (0, import_react.useCallback)((row, column, direction, triggerEvent) => {
1092
+ const nextCell = (0, import_ui_grid3.findNextGridCell)({
1093
+ rows: pipelineRef.current.visibleRows,
1094
+ columns: visibleColumnsRef.current,
1095
+ rowId: row.id,
1096
+ columnName: column.name,
1097
+ direction
1098
+ });
1099
+ if (!nextCell) return false;
1100
+ setFocusedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1101
+ focusRenderedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1102
+ if (shouldEditOnFocusFn(nextCell.column) && isCellEditable(nextCell.row, nextCell.column, triggerEvent)) {
1103
+ startCellEditFn(nextCell.row, nextCell.column, triggerEvent);
1104
+ }
1105
+ return true;
1106
+ }, [focusRenderedCell, isCellEditable, shouldEditOnFocusFn, startCellEditFn]);
1107
+ const runBenchmarkFn = (0, import_react.useCallback)((iterations) => {
1108
+ const safeIterations = Math.max(1, iterations ?? optionsRef.current.benchmark?.iterations ?? 25);
1109
+ const startedAt = performance.now();
1110
+ let lastResult = (0, import_ui_grid3.buildGridPipeline)({
1111
+ options: optionsRef.current,
1112
+ columns: visibleColumnsRef.current,
1113
+ activeFilters: activeFiltersRef.current,
1114
+ sortState: sortStateRef.current,
1115
+ groupByColumns: groupByColumnsRef.current,
1116
+ collapsedGroups: collapsedGroupsRef.current,
1117
+ hiddenRowReasons: hiddenRowReasonsRef.current,
1118
+ expandedRows: expandedRowsRef.current,
1119
+ expandedTreeRows: expandedTreeRowsRef.current,
1120
+ currentPage: currentPageRef.current,
1121
+ pageSize: pageSizeRef.current,
1122
+ rowSize: optionsRef.current.rowHeight ?? 44
1123
+ });
1124
+ for (let i = 1; i < safeIterations; i++) {
1125
+ lastResult = (0, import_ui_grid3.buildGridPipeline)({
1126
+ options: optionsRef.current,
1127
+ columns: visibleColumnsRef.current,
1128
+ activeFilters: activeFiltersRef.current,
1129
+ sortState: sortStateRef.current,
1130
+ groupByColumns: groupByColumnsRef.current,
1131
+ collapsedGroups: collapsedGroupsRef.current,
1132
+ hiddenRowReasons: hiddenRowReasonsRef.current,
1133
+ expandedRows: expandedRowsRef.current,
1134
+ expandedTreeRows: expandedTreeRowsRef.current,
1135
+ currentPage: currentPageRef.current,
1136
+ pageSize: pageSizeRef.current,
1137
+ rowSize: optionsRef.current.rowHeight ?? 44
1138
+ });
1139
+ }
1140
+ const totalMs = performance.now() - startedAt;
1141
+ const result = {
1142
+ iterations: safeIterations,
1143
+ totalMs,
1144
+ averageMs: totalMs / safeIterations,
1145
+ visibleRows: lastResult.visibleRows.length,
1146
+ renderedItems: lastResult.displayItems.length
1147
+ };
1148
+ setBenchmarkResult(result);
1149
+ raiseGridBenchmarkComplete(gridApiRef.current, result);
1150
+ return result;
1151
+ }, []);
1152
+ const exportCsvFn = (0, import_react.useCallback)(() => {
1153
+ if (!import_ui_grid3.FEATURE_CSV_EXPORT) return;
1154
+ const columns = visibleColumnsRef.current;
1155
+ const csv = (0, import_ui_grid3.exportCsvRows)(columns, pipelineRef.current.visibleRows);
1156
+ downloadGridCsvFile(csv, `${(0, import_ui_grid3.sanitizeDownloadFilename)(optionsRef.current.id)}.csv`);
1157
+ }, []);
1158
+ (0, import_react.useEffect)(() => {
1159
+ if (initializedGridIdRef.current === options.id) return;
1160
+ initializedGridIdRef.current = options.id;
1161
+ setActiveFilters({});
1162
+ setHiddenRowReasons({});
1163
+ setCollapsedGroups({});
1164
+ setFocusedCell(null);
1165
+ setEditingCell(null);
1166
+ setEditingValue("");
1167
+ setExpandedRows({});
1168
+ setExpandedTreeRows({});
1169
+ setColumnOrder(options.columnDefs.map((column) => column.name));
1170
+ setGroupByColumns(options.grouping?.groupBy ?? []);
1171
+ setCurrentPage(options.paginationCurrentPage ?? 1);
1172
+ setPageSize((0, import_ui_grid3.getEffectivePageSize)(options, 0, options.data.length));
1173
+ setInfiniteScrollState({
1174
+ scrollUp: options.infiniteScrollUp === true,
1175
+ scrollDown: options.infiniteScrollDown !== false,
1176
+ dataLoading: false,
1177
+ previousVisibleRows: 0
1178
+ });
1179
+ const initialSort = options.columnDefs.find(
1180
+ (column) => column.sort?.direction && !column.sort.ignoreSort
1181
+ );
1182
+ setSortState({
1183
+ columnName: initialSort?.name ?? null,
1184
+ direction: initialSort?.sort?.direction ?? import_ui_grid3.SORT_DIRECTIONS.none
1185
+ });
1186
+ onRegisterApi?.(gridApi);
1187
+ raiseGridRenderingComplete(gridApi);
1188
+ }, [options.id]);
1189
+ (0, import_react.useEffect)(() => {
1190
+ raiseGridRowsRendered(gridApi, pipeline.visibleRows);
1191
+ raiseGridRowsVisibleChanged(gridApi, pipeline.visibleRows);
1192
+ const newHeight = pipeline.displayItems.length * rowSize;
1193
+ if (newHeight !== lastCanvasHeightRef.current) {
1194
+ raiseGridCanvasHeightChanged(gridApi, lastCanvasHeightRef.current, newHeight);
1195
+ lastCanvasHeightRef.current = newHeight;
1196
+ }
1197
+ }, [pipeline, gridApi, rowSize]);
1198
+ (0, import_react.useEffect)(() => {
1199
+ if (!import_ui_grid3.FEATURE_AUTO_RESIZE || !options.enableAutoResize) return;
1200
+ const container = gridContainerRef.current;
1201
+ if (!container) return;
1202
+ const observer = observeGridHostSize(container, ({ height: nextHeight, width: nextWidth }) => {
1203
+ if (nextHeight === lastGridHeightRef.current && nextWidth === lastGridWidthRef.current) return;
1204
+ raiseGridDimensionChanged(gridApi, lastGridHeightRef.current, lastGridWidthRef.current, nextHeight, nextWidth);
1205
+ lastGridHeightRef.current = nextHeight;
1206
+ lastGridWidthRef.current = nextWidth;
1207
+ if (!options.viewportHeight && nextHeight > 0) {
1208
+ setAutoViewportHeight(nextHeight);
1209
+ }
1210
+ });
1211
+ if (!observer) return;
1212
+ return () => observer.disconnect();
1213
+ }, [options.enableAutoResize, options.viewportHeight, gridApi]);
1214
+ const totalRows = pipeline.totalItems;
1215
+ const visibleRowCount = pipeline.visibleRows.length;
1216
+ const displayItems = pipeline.displayItems;
1217
+ const virtualizationEnabled = pipeline.virtualizationEnabled;
1218
+ const pipelineMsVal = pipeline.pipelineMs;
1219
+ const paginationCurrentPage = getCurrentPageValueFn();
1220
+ const paginationTotalPages = getTotalPagesValueFn();
1221
+ const paginationSelectedPageSize = effectivePageSizeFn(pipeline.totalItems);
1222
+ const viewportHeightPx = `${options.viewportHeight ?? autoViewportHeight ?? 560}px`;
1223
+ const headerLabelFn = (0, import_react.useCallback)((column) => (0, import_ui_grid3.headerLabel)(column), []);
1224
+ const isGroupItemFn = (0, import_react.useCallback)((item) => item.kind === "group", []);
1225
+ const isExpandableItemFn = (0, import_react.useCallback)((item) => item.kind === "expandable", []);
1226
+ const isRowItemFn = (0, import_react.useCallback)((item) => item.kind === "row", []);
1227
+ const isOddStripedRowFn = (0, import_react.useCallback)((item) => item.kind === "row" && item.visibleIndex % 2 === 0, []);
1228
+ const sortDirectionFn = (0, import_react.useCallback)((column) => {
1229
+ return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid3.SORT_DIRECTIONS.none;
1230
+ }, []);
1231
+ const sortButtonLabelFn = (0, import_react.useCallback)((column) => {
1232
+ return (0, import_ui_grid3.gridSortButtonLabel)(sortDirectionFn(column), labels);
1233
+ }, [labels, sortDirectionFn]);
1234
+ const sortAriaSortFn = (0, import_react.useCallback)((column) => {
1235
+ return (0, import_ui_grid3.gridSortAriaSort)(sortDirectionFn(column));
1236
+ }, [sortDirectionFn]);
1237
+ const groupingButtonLabelFn = (0, import_react.useCallback)((column) => {
1238
+ return (0, import_ui_grid3.gridGroupingButtonLabel)((0, import_ui_grid3.isGridColumnGrouped)(groupByColumnsRef.current, column), labels);
1239
+ }, [labels]);
1240
+ const filterValueFn = (0, import_react.useCallback)((columnName) => {
1241
+ return activeFiltersRef.current[columnName] ?? "";
1242
+ }, []);
1243
+ const filterPlaceholderFn = (0, import_react.useCallback)((column) => {
1244
+ return (0, import_ui_grid3.gridFilterPlaceholder)((0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column), labels);
1245
+ }, [labels]);
1246
+ const isFilterInputDisabledFn = (0, import_react.useCallback)((column) => {
1247
+ return !(0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column);
1248
+ }, []);
1249
+ const groupDisclosureLabelFn = (0, import_react.useCallback)((item) => {
1250
+ return (0, import_ui_grid3.gridGroupDisclosureLabel)(item.collapsed, labels);
1251
+ }, [labels]);
1252
+ const cellContextFn = (0, import_react.useCallback)((row, column) => {
1253
+ return (0, import_ui_grid3.buildGridCellContext)(row, column);
1254
+ }, []);
1255
+ const displayValueFn = (0, import_react.useCallback)((row, column) => {
1256
+ return (0, import_ui_grid3.formatGridCellDisplayValue)(cellContextFn(row, column));
1257
+ }, [cellContextFn]);
1258
+ const isFocusedCellFn = (0, import_react.useCallback)((row, column) => {
1259
+ return (0, import_ui_grid3.isGridCellPosition)(focusedCellRef.current, row.id, column.name);
1260
+ }, []);
1261
+ const isEditingCellFn = (0, import_react.useCallback)((row, column) => {
1262
+ return (0, import_ui_grid3.isGridCellPosition)(editingCellRef.current, row.id, column.name);
1263
+ }, []);
1264
+ const editorInputTypeFn = (0, import_react.useCallback)((column) => {
1265
+ return (0, import_ui_grid3.gridEditorInputType)(column);
1266
+ }, []);
1267
+ const expandedContextFn = (0, import_react.useCallback)((row) => {
1268
+ return {
1269
+ $implicit: row.entity,
1270
+ row: row.entity,
1271
+ rowIndex: row.index,
1272
+ expanded: true,
1273
+ ...optionsRef.current.expandableRowScope ?? {}
1274
+ };
1275
+ }, []);
1276
+ const columnWidthFn = (0, import_react.useCallback)((column) => (0, import_ui_grid3.gridColumnWidth)(column), []);
1277
+ const isColumnSortableFn = (0, import_react.useCallback)((column) => {
1278
+ return (0, import_ui_grid3.isGridColumnSortable)(optionsRef.current, column);
1279
+ }, []);
1280
+ const isColumnFilterableFn = (0, import_react.useCallback)((column) => {
1281
+ return (0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column);
1282
+ }, []);
1283
+ const cellIndentFn = (0, import_react.useCallback)((row, column) => {
1284
+ return (0, import_ui_grid3.gridCellIndent)(optionsRef.current, visibleColumnsRef.current, row, column);
1285
+ }, []);
1286
+ const treeToggleLabelFn = (0, import_react.useCallback)((row) => {
1287
+ return (0, import_ui_grid3.gridTreeToggleLabelForRow)(expandedTreeRowsRef.current, row, labels);
1288
+ }, [labels]);
1289
+ const isTreeRowExpandedFn = (0, import_react.useCallback)((row) => {
1290
+ return (0, import_ui_grid3.isGridTreeRowExpanded)(expandedTreeRowsRef.current, row);
1291
+ }, []);
1292
+ const expandToggleLabelFn = (0, import_react.useCallback)((row) => {
1293
+ return (0, import_ui_grid3.gridExpandToggleLabelForRow)(row, labels);
1294
+ }, [labels]);
1295
+ const isGroupedFn = (0, import_react.useCallback)((column) => {
1296
+ return (0, import_ui_grid3.isGridColumnGrouped)(groupByColumnsRef.current, column);
1297
+ }, []);
1298
+ const showTreeToggleFn = (0, import_react.useCallback)((row, column) => {
1299
+ return (0, import_ui_grid3.shouldShowGridTreeToggle)(optionsRef.current, visibleColumnsRef.current, row, column);
1300
+ }, []);
1301
+ const showExpandToggleFn = (0, import_react.useCallback)((row, column) => {
1302
+ return (0, import_ui_grid3.shouldShowGridExpandToggle)(optionsRef.current, visibleColumnsRef.current, column);
1303
+ }, []);
1304
+ const showPaginationControlsFn = (0, import_react.useCallback)(() => {
1305
+ return import_ui_grid3.FEATURE_PAGINATION && (0, import_ui_grid3.shouldShowGridPaginationControls)(optionsRef.current);
1306
+ }, []);
1307
+ const paginationSummaryFn = (0, import_react.useCallback)(() => {
1308
+ const ti = pipelineRef.current.totalItems;
1309
+ if (ti === 0) return "0-0 of 0";
1310
+ return `${getFirstRowIndexValueFn(ti) + 1}-${getLastRowIndexValueFn(ti) + 1} of ${ti}`;
1311
+ }, [getFirstRowIndexValueFn, getLastRowIndexValueFn]);
1312
+ const pageSizeOptionsFn = (0, import_react.useCallback)(() => {
1313
+ return optionsRef.current.paginationPageSizes ?? [];
1314
+ }, []);
1315
+ const isGroupingEnabledFn = (0, import_react.useCallback)(() => {
1316
+ return import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current);
1317
+ }, []);
1318
+ const isFilteringEnabledFn = (0, import_react.useCallback)(() => {
1319
+ return import_ui_grid3.FEATURE_FILTERING && (0, import_ui_grid3.isGridFilteringEnabled)(optionsRef.current);
1320
+ }, []);
1321
+ const toggleSortFn = (0, import_react.useCallback)((column) => {
1322
+ if (!import_ui_grid3.FEATURE_SORTING || !(0, import_ui_grid3.isGridColumnSortable)(optionsRef.current, column)) return;
1323
+ const currentDirection = sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid3.SORT_DIRECTIONS.none;
1324
+ const nextDirection = currentDirection === import_ui_grid3.SORT_DIRECTIONS.none ? import_ui_grid3.SORT_DIRECTIONS.asc : currentDirection === import_ui_grid3.SORT_DIRECTIONS.asc ? import_ui_grid3.SORT_DIRECTIONS.desc : import_ui_grid3.SORT_DIRECTIONS.none;
1325
+ applyGridSortStateCommand(gridApiRef.current, (state) => setSortState(state), {
1326
+ columnName: nextDirection === import_ui_grid3.SORT_DIRECTIONS.none ? null : column.name,
1327
+ direction: nextDirection
1328
+ });
1329
+ }, []);
1330
+ const updateFilterFn = (0, import_react.useCallback)((columnName, value) => {
1331
+ updateGridFilterCommand(
1332
+ gridApiRef.current,
1333
+ (updater) => setActiveFilters((current) => updater(current)),
1334
+ () => activeFiltersRef.current,
1335
+ columnName,
1336
+ value
1337
+ );
1338
+ }, []);
1339
+ const clearAllFiltersFn = (0, import_react.useCallback)(() => {
1340
+ clearGridFiltersCommand(gridApiRef.current, (filters) => setActiveFilters(filters));
1341
+ }, []);
1342
+ const toggleGroupingFn = (0, import_react.useCallback)((column, event) => {
1343
+ event?.stopPropagation();
1344
+ if (!(import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current))) return;
1345
+ const current = groupByColumnsRef.current;
1346
+ const next = current.includes(column.name) ? current.filter((n) => n !== column.name) : [...current, column.name];
1347
+ groupByColumnsRef.current = next;
1348
+ setGroupByColumns(next);
1349
+ gridApiRef.current.core.raise.groupingChanged(next);
1350
+ }, []);
1351
+ const toggleGroupFn = (0, import_react.useCallback)((item) => {
1352
+ setCollapsedGroups((current) => ({
1353
+ ...current,
1354
+ [item.id]: !current[item.id]
1355
+ }));
1356
+ }, []);
1357
+ const focusCellFn = (0, import_react.useCallback)((row, column, triggerEvent) => {
1358
+ const nextFocusResult = (0, import_ui_grid3.buildGridFocusCellResult)({
1359
+ currentFocusedCell: focusedCellRef.current,
1360
+ currentEditingCell: editingCellRef.current,
1361
+ rowId: row.id,
1362
+ columnName: column.name,
1363
+ shouldEditOnFocus: shouldEditOnFocusFn(column),
1364
+ isCellEditable: isCellEditable(row, column, triggerEvent)
1365
+ });
1366
+ setFocusedCell(nextFocusResult.focusedCell);
1367
+ if (nextFocusResult.shouldBeginEdit) {
1368
+ startCellEditFn(row, column, triggerEvent);
1369
+ }
1370
+ }, [isCellEditable, shouldEditOnFocusFn, startCellEditFn]);
1371
+ const handleCellKeyDownFn = (0, import_react.useCallback)((row, column, event) => {
1372
+ focusCellFn(row, column, event.nativeEvent);
1373
+ switch (event.key) {
1374
+ case "ArrowLeft":
1375
+ event.preventDefault();
1376
+ moveFocusFn(row, column, "left", event.nativeEvent);
1377
+ return;
1378
+ case "ArrowRight":
1379
+ event.preventDefault();
1380
+ moveFocusFn(row, column, "right", event.nativeEvent);
1381
+ return;
1382
+ case "ArrowUp":
1383
+ event.preventDefault();
1384
+ moveFocusFn(row, column, "up", event.nativeEvent);
1385
+ return;
1386
+ case "ArrowDown":
1387
+ event.preventDefault();
1388
+ moveFocusFn(row, column, "down", event.nativeEvent);
1389
+ return;
1390
+ case "Tab":
1391
+ event.preventDefault();
1392
+ moveFocusFn(row, column, event.shiftKey ? "left" : "right", event.nativeEvent);
1393
+ return;
1394
+ case "Enter":
1395
+ event.preventDefault();
1396
+ moveFocusFn(row, column, event.shiftKey ? "up" : "down", event.nativeEvent);
1397
+ return;
1398
+ case "F2":
1399
+ event.preventDefault();
1400
+ if (isCellEditable(row, column, event.nativeEvent)) {
1401
+ startCellEditFn(row, column, event.nativeEvent);
1402
+ }
1403
+ return;
1404
+ case "Backspace":
1405
+ case "Delete":
1406
+ if (isCellEditable(row, column, event.nativeEvent)) {
1407
+ event.preventDefault();
1408
+ startCellEditFn(row, column, event.nativeEvent, "");
1409
+ }
1410
+ return;
1411
+ default:
1412
+ break;
1413
+ }
1414
+ if ((0, import_ui_grid3.isPrintableGridKey)(event.key, event.ctrlKey, event.metaKey, event.altKey) && isCellEditable(row, column, event.nativeEvent)) {
1415
+ event.preventDefault();
1416
+ startCellEditFn(row, column, event.nativeEvent, event.key);
1417
+ }
1418
+ }, [focusCellFn, moveFocusFn, isCellEditable, startCellEditFn]);
1419
+ const handleCellDoubleClickFn = (0, import_react.useCallback)((row, column, event) => {
1420
+ focusCellFn(row, column, event.nativeEvent);
1421
+ if (isCellEditable(row, column, event.nativeEvent)) {
1422
+ startCellEditFn(row, column, event.nativeEvent);
1423
+ }
1424
+ }, [focusCellFn, isCellEditable, startCellEditFn]);
1425
+ const updateEditingValueFn = (0, import_react.useCallback)((value) => {
1426
+ setEditingValue(value);
1427
+ }, []);
1428
+ const handleEditorKeyDownFn = (0, import_react.useCallback)((event) => {
1429
+ if (event.key === "Escape") {
1430
+ event.preventDefault();
1431
+ cancelCellEditFn();
1432
+ return;
1433
+ }
1434
+ if (event.key === "Enter") {
1435
+ event.preventDefault();
1436
+ commitCellEditFn(event.shiftKey ? "up" : "down");
1437
+ return;
1438
+ }
1439
+ if (event.key === "Tab") {
1440
+ event.preventDefault();
1441
+ commitCellEditFn(event.shiftKey ? "left" : "right");
1442
+ }
1443
+ }, [cancelCellEditFn, commitCellEditFn]);
1444
+ const handleEditorBlurFn = (0, import_react.useCallback)((event) => {
1445
+ const ec = editingCellRef.current;
1446
+ const target = event.target;
1447
+ if (!ec || !target) return;
1448
+ if (target.dataset["rowId"] !== ec.rowId || target.dataset["colName"] !== ec.columnName) return;
1449
+ commitCellEditFn(void 0, false);
1450
+ }, [commitCellEditFn]);
1451
+ const toggleRowExpansionFn = (0, import_react.useCallback)((row, event) => {
1452
+ event?.stopPropagation();
1453
+ toggleRowExpansionByRefFn(row);
1454
+ }, [toggleRowExpansionByRefFn]);
1455
+ const toggleTreeRowFn = (0, import_react.useCallback)((row, event) => {
1456
+ event?.stopPropagation();
1457
+ toggleTreeRowByRefFn(row);
1458
+ }, [toggleTreeRowByRefFn]);
1459
+ const moveColumnFn = (0, import_react.useCallback)((fromIndex, toIndex) => {
1460
+ moveGridColumnCommand(
1461
+ gridApiRef.current,
1462
+ import_ui_grid3.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1463
+ (updater) => setColumnOrder((current) => updater(current)),
1464
+ fromIndex,
1465
+ toIndex
1466
+ );
1467
+ }, []);
1468
+ const nextPageFn = (0, import_react.useCallback)(() => {
1469
+ seekPageFn(getCurrentPageValueFn() + 1);
1470
+ }, [seekPageFn, getCurrentPageValueFn]);
1471
+ const previousPageFn = (0, import_react.useCallback)(() => {
1472
+ seekPageFn(getCurrentPageValueFn() - 1);
1473
+ }, [seekPageFn, getCurrentPageValueFn]);
1474
+ const onPageSizeChangeFn = (0, import_react.useCallback)((value) => {
1475
+ setPaginationPageSizeFn(Number(value));
1476
+ }, [setPaginationPageSizeFn]);
1477
+ const onViewportScrollFn = (0, import_react.useCallback)((startIndex) => {
1478
+ if (!scrollingRef.current) {
1479
+ scrollingRef.current = true;
1480
+ raiseGridScrollBegin(gridApiRef.current);
1481
+ }
1482
+ if (scrollEndHandleRef.current) {
1483
+ window.clearTimeout(scrollEndHandleRef.current);
1484
+ }
1485
+ scrollEndHandleRef.current = window.setTimeout(() => {
1486
+ scrollingRef.current = false;
1487
+ raiseGridScrollEnd(gridApiRef.current);
1488
+ }, 120);
1489
+ const isInfiniteScrollEnabled = import_ui_grid3.FEATURE_INFINITE_SCROLL && (optionsRef.current.infiniteScrollRowsFromEnd !== void 0 || optionsRef.current.infiniteScrollUp === true || optionsRef.current.infiniteScrollDown !== void 0);
1490
+ maybeRequestInfiniteScrollCommand(gridApiRef.current, {
1491
+ enabled: isInfiniteScrollEnabled,
1492
+ virtualizationEnabled: pipelineRef.current.virtualizationEnabled,
1493
+ state: infiniteScrollStateRef.current,
1494
+ startIndex,
1495
+ visibleRows: pipelineRef.current.visibleRows.length,
1496
+ viewportRows: Math.max(1, Math.ceil((optionsRef.current.viewportHeight ?? 560) / (optionsRef.current.rowHeight ?? 44))),
1497
+ threshold: optionsRef.current.infiniteScrollRowsFromEnd ?? 20,
1498
+ setState: (state) => setInfiniteScrollState(state)
1499
+ });
1500
+ }, []);
1501
+ return {
1502
+ pipeline,
1503
+ visibleColumns,
1504
+ labels,
1505
+ gridTemplateColumns,
1506
+ gridApi,
1507
+ gridContainerRef,
1508
+ activeFilters,
1509
+ groupByColumns,
1510
+ collapsedGroups,
1511
+ sortState,
1512
+ focusedCell,
1513
+ editingCell,
1514
+ editingValue,
1515
+ expandedRows,
1516
+ expandedTreeRows,
1517
+ currentPage,
1518
+ pageSize,
1519
+ benchmarkResult,
1520
+ infiniteScrollState,
1521
+ totalRows,
1522
+ visibleRowCount,
1523
+ displayItems,
1524
+ virtualizationEnabled,
1525
+ pipelineMs: pipelineMsVal,
1526
+ paginationCurrentPage,
1527
+ paginationTotalPages,
1528
+ paginationSelectedPageSize,
1529
+ rowSize,
1530
+ viewportHeightPx,
1531
+ headerLabel: headerLabelFn,
1532
+ isGroupItem: isGroupItemFn,
1533
+ isExpandableItem: isExpandableItemFn,
1534
+ isRowItem: isRowItemFn,
1535
+ isOddStripedRow: isOddStripedRowFn,
1536
+ sortButtonLabel: sortButtonLabelFn,
1537
+ sortAriaSort: sortAriaSortFn,
1538
+ sortDirection: sortDirectionFn,
1539
+ groupingButtonLabel: groupingButtonLabelFn,
1540
+ filterValue: filterValueFn,
1541
+ filterPlaceholder: filterPlaceholderFn,
1542
+ isFilterInputDisabled: isFilterInputDisabledFn,
1543
+ groupDisclosureLabel: groupDisclosureLabelFn,
1544
+ displayValue: displayValueFn,
1545
+ isFocusedCell: isFocusedCellFn,
1546
+ isEditingCell: isEditingCellFn,
1547
+ editorInputType: editorInputTypeFn,
1548
+ cellContext: cellContextFn,
1549
+ expandedContext: expandedContextFn,
1550
+ columnWidth: columnWidthFn,
1551
+ isColumnSortable: isColumnSortableFn,
1552
+ isColumnFilterable: isColumnFilterableFn,
1553
+ cellIndent: cellIndentFn,
1554
+ treeToggleLabel: treeToggleLabelFn,
1555
+ isTreeRowExpanded: isTreeRowExpandedFn,
1556
+ expandToggleLabel: expandToggleLabelFn,
1557
+ isGrouped: isGroupedFn,
1558
+ showTreeToggle: showTreeToggleFn,
1559
+ showExpandToggle: showExpandToggleFn,
1560
+ showPaginationControls: showPaginationControlsFn,
1561
+ paginationSummary: paginationSummaryFn,
1562
+ pageSizeOptions: pageSizeOptionsFn,
1563
+ isCellEditable,
1564
+ shouldEditOnFocus: shouldEditOnFocusFn,
1565
+ sortingFeature: import_ui_grid3.FEATURE_SORTING,
1566
+ filteringFeature: import_ui_grid3.FEATURE_FILTERING,
1567
+ groupingFeature: import_ui_grid3.FEATURE_GROUPING,
1568
+ paginationFeature: import_ui_grid3.FEATURE_PAGINATION,
1569
+ cellEditFeature: import_ui_grid3.FEATURE_CELL_EDIT,
1570
+ expandableFeature: import_ui_grid3.FEATURE_EXPANDABLE,
1571
+ treeViewFeature: import_ui_grid3.FEATURE_TREE_VIEW,
1572
+ infiniteScrollFeature: import_ui_grid3.FEATURE_INFINITE_SCROLL,
1573
+ columnMovingFeature: import_ui_grid3.FEATURE_COLUMN_MOVING,
1574
+ csvExportFeature: import_ui_grid3.FEATURE_CSV_EXPORT,
1575
+ isGroupingEnabled: isGroupingEnabledFn,
1576
+ isFilteringEnabled: isFilteringEnabledFn,
1577
+ toggleSort: toggleSortFn,
1578
+ updateFilter: updateFilterFn,
1579
+ clearAllFilters: clearAllFiltersFn,
1580
+ toggleGrouping: toggleGroupingFn,
1581
+ toggleGroup: toggleGroupFn,
1582
+ focusCell: focusCellFn,
1583
+ handleCellKeyDown: handleCellKeyDownFn,
1584
+ handleCellDoubleClick: handleCellDoubleClickFn,
1585
+ updateEditingValue: updateEditingValueFn,
1586
+ handleEditorKeyDown: handleEditorKeyDownFn,
1587
+ handleEditorBlur: handleEditorBlurFn,
1588
+ toggleRowExpansion: toggleRowExpansionFn,
1589
+ toggleTreeRow: toggleTreeRowFn,
1590
+ moveColumn: moveColumnFn,
1591
+ nextPage: nextPageFn,
1592
+ previousPage: previousPageFn,
1593
+ onPageSizeChange: onPageSizeChangeFn,
1594
+ runBenchmark: runBenchmarkFn,
1595
+ exportCsv: exportCsvFn,
1596
+ onViewportScroll: onViewportScrollFn
1597
+ };
1598
+ }
1599
+
1600
+ // src/useVirtualScroll.ts
1601
+ var import_react2 = require("react");
1602
+ function useVirtualScroll(options) {
1603
+ const { itemCount, itemSize, viewportHeight, overscan = 3 } = options;
1604
+ const [scrollTop, setScrollTop] = (0, import_react2.useState)(0);
1605
+ const viewportRef = (0, import_react2.useRef)(null);
1606
+ const rawStart = Math.floor(scrollTop / itemSize) - overscan;
1607
+ const start = Math.max(0, rawStart);
1608
+ const rawEnd = rawStart + Math.ceil(viewportHeight / itemSize) + 2 * overscan;
1609
+ const end = Math.min(itemCount, rawEnd);
1610
+ const totalHeight = itemCount * itemSize;
1611
+ const offsetY = start * itemSize;
1612
+ const onScroll = (0, import_react2.useCallback)((event) => {
1613
+ setScrollTop(event.currentTarget.scrollTop);
1614
+ }, []);
1615
+ return {
1616
+ visibleRange: { start, end },
1617
+ totalHeight,
1618
+ offsetY,
1619
+ onScroll,
1620
+ viewportRef,
1621
+ scrollTop
1622
+ };
1623
+ }
1624
+
1625
+ // src/UiGrid.tsx
1626
+ var import_jsx_runtime = require("react/jsx-runtime");
1627
+ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, className }) {
1628
+ const state = useGridState(options, onRegisterApi);
1629
+ const {
1630
+ pipeline,
1631
+ visibleColumns,
1632
+ labels,
1633
+ gridTemplateColumns,
1634
+ gridContainerRef,
1635
+ displayItems,
1636
+ virtualizationEnabled,
1637
+ pipelineMs,
1638
+ visibleRowCount,
1639
+ totalRows,
1640
+ benchmarkResult,
1641
+ rowSize,
1642
+ viewportHeightPx,
1643
+ editingValue,
1644
+ sortingFeature,
1645
+ filteringFeature,
1646
+ groupingFeature,
1647
+ paginationFeature,
1648
+ cellEditFeature,
1649
+ expandableFeature,
1650
+ treeViewFeature,
1651
+ csvExportFeature,
1652
+ paginationCurrentPage,
1653
+ paginationTotalPages,
1654
+ paginationSelectedPageSize
1655
+ } = state;
1656
+ const virtualScroll = useVirtualScroll({
1657
+ itemCount: displayItems.length,
1658
+ itemSize: rowSize,
1659
+ viewportHeight: options.viewportHeight ?? 560,
1660
+ overscan: 3
1661
+ });
1662
+ const itemsToRender = virtualizationEnabled ? displayItems.slice(virtualScroll.visibleRange.start, virtualScroll.visibleRange.end) : displayItems;
1663
+ const onViewportScroll = (event) => {
1664
+ virtualScroll.onScroll(event);
1665
+ const startIndex = Math.floor(event.currentTarget.scrollTop / rowSize);
1666
+ state.onViewportScroll(startIndex);
1667
+ };
1668
+ function renderDisplayItem(item) {
1669
+ if (groupingFeature && state.isGroupItem(item)) {
1670
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1671
+ "button",
1672
+ {
1673
+ type: "button",
1674
+ className: "group-row ui-grid-row ui-grid-group-row",
1675
+ "data-part": "group-row",
1676
+ role: "row",
1677
+ "aria-expanded": !item.collapsed,
1678
+ style: { gridColumn: "1 / -1", paddingInlineStart: `${item.depth * 1.25 + 1}rem` },
1679
+ onClick: () => state.toggleGroup(item),
1680
+ children: [
1681
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
1682
+ item.field,
1683
+ ": ",
1684
+ item.label
1685
+ ] }),
1686
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1687
+ item.count,
1688
+ " ",
1689
+ labels.groupRowsSuffix
1690
+ ] }),
1691
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon group-disclosure-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: item.collapsed ? "M10 7l5 5-5 5z" : "M7 10l5 5 5-5z" }) }),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.groupDisclosureLabel(item) })
1693
+ ]
1694
+ },
1695
+ item.id
1696
+ );
1697
+ }
1698
+ if (expandableFeature && state.isExpandableItem(item)) {
1699
+ const ctx = state.expandedContext(item.row);
1700
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1701
+ "div",
1702
+ {
1703
+ className: "expandable-row ui-grid-row ui-grid-expandable-row",
1704
+ "data-part": "expandable-row",
1705
+ style: { gridColumn: "1 / -1", minHeight: `${item.row.expandedRowHeight}px` },
1706
+ children: expandableRenderer?.(ctx)
1707
+ },
1708
+ item.id
1709
+ );
1710
+ }
1711
+ if (item.kind !== "row") return null;
1712
+ const rowItem = item;
1713
+ return visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1714
+ "div",
1715
+ {
1716
+ className: cellClassName(rowItem, column),
1717
+ "data-part": "body-cell",
1718
+ role: "gridcell",
1719
+ tabIndex: 0,
1720
+ "data-row-id": rowItem.row.id,
1721
+ "data-col-name": column.name,
1722
+ onFocus: () => state.focusCell(rowItem.row, column),
1723
+ onClick: () => state.focusCell(rowItem.row, column),
1724
+ onDoubleClick: (e) => state.handleCellDoubleClick(rowItem.row, column, e),
1725
+ onKeyDown: (e) => state.handleCellKeyDown(rowItem.row, column, e),
1726
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cell-shell", style: { paddingInlineStart: state.cellIndent(rowItem.row, column) }, children: [
1727
+ treeViewFeature && state.showTreeToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1728
+ "button",
1729
+ {
1730
+ type: "button",
1731
+ className: "row-toggle row-toggle-tree",
1732
+ "data-part": "tree-toggle",
1733
+ "aria-label": state.treeToggleLabel(rowItem.row),
1734
+ "aria-expanded": state.isTreeRowExpanded(rowItem.row),
1735
+ onClick: (e) => state.toggleTreeRow(rowItem.row, e),
1736
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
1737
+ }
1738
+ ),
1739
+ expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1740
+ "button",
1741
+ {
1742
+ type: "button",
1743
+ className: "row-toggle row-toggle-expand",
1744
+ "data-part": "expand-toggle",
1745
+ "aria-label": state.expandToggleLabel(rowItem.row),
1746
+ "aria-expanded": rowItem.row.expanded,
1747
+ onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
1748
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
1749
+ }
1750
+ ),
1751
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1752
+ "input",
1753
+ {
1754
+ className: "cell-editor",
1755
+ "data-row-id": rowItem.row.id,
1756
+ "data-col-name": column.name,
1757
+ "aria-label": state.headerLabel(column),
1758
+ type: state.editorInputType(column),
1759
+ defaultValue: editingValue,
1760
+ onChange: (e) => state.updateEditingValue(e.target.value),
1761
+ onKeyDown: (e) => state.handleEditorKeyDown(e),
1762
+ onBlur: (e) => state.handleEditorBlur(e)
1763
+ }
1764
+ ) : cellRenderer ? cellRenderer(state.cellContext(rowItem.row, column)) ?? state.displayValue(rowItem.row, column) : state.displayValue(rowItem.row, column) })
1765
+ ] })
1766
+ },
1767
+ `${rowItem.row.id}-${column.name}`
1768
+ ));
1769
+ }
1770
+ function cellClassName(item, column) {
1771
+ const classes = ["body-cell", "ui-grid-cell"];
1772
+ if (state.isOddStripedRow(item)) classes.push("body-cell-odd");
1773
+ if (column.align === "center") classes.push("align-center");
1774
+ if (column.align === "end") classes.push("align-end");
1775
+ if (state.isFocusedCell(item.row, column)) classes.push("cell-focused");
1776
+ if (cellEditFeature && state.isEditingCell(item.row, column)) classes.push("cell-editing");
1777
+ return classes.join(" ");
1778
+ }
1779
+ function renderSortIcon(column) {
1780
+ const direction = state.sortDirection(column);
1781
+ switch (direction) {
1782
+ case "asc":
1783
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 5l-6 6h4v8h4v-8h4z" }) });
1784
+ case "desc":
1785
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 19l6-6h-4V5h-4v8H6z" }) });
1786
+ default:
1787
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 6h10v2H7V6Zm0 5h7v2H7v-2Zm0 5h4v2H7v-2Z" }) });
1788
+ }
1789
+ }
1790
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `ui-grid-host ${className ?? ""}`, ref: gridContainerRef, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "grid-shell ui-grid-shell", "data-part": "shell", children: [
1791
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "grid-hero ui-grid-toolbar-shell", "data-part": "hero", children: [
1792
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1793
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "eyebrow", children: "React wrapper for @ornery/ui-grid" }),
1794
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: options.title ?? "UI Grid" }),
1795
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "deck", children: "Familiar `gridOptions` and `onRegisterApi`, built with React hooks, virtualization, grouping, sorting, filtering, and column ordering." })
1796
+ ] }),
1797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hero-actions", children: [
1798
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "action action-secondary", "data-part": "action benchmark-action", onClick: () => state.runBenchmark(), children: "Benchmark" }),
1799
+ csvExportFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "action action-secondary", "data-part": "action export-action", onClick: () => state.exportCsv(), children: "Export CSV" }),
1800
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stats-card", "data-part": "stats-card", children: [
1801
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: visibleRowCount }),
1802
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: labels.statsVisibleRows })
1803
+ ] })
1804
+ ] })
1805
+ ] }),
1806
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "metrics-strip", "data-part": "metrics", "aria-label": "Grid performance metrics", children: [
1807
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
1809
+ pipelineMs.toFixed(2),
1810
+ " ms"
1811
+ ] }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "pipeline" })
1813
+ ] }),
1814
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1815
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: virtualizationEnabled ? "On" : "Off" }),
1816
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "virtualization" })
1817
+ ] }),
1818
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1819
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: state.groupByColumns.length }),
1820
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "group columns" })
1821
+ ] }),
1822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1823
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: benchmarkResult?.averageMs?.toFixed(2) || "\u2014" }),
1824
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "benchmark avg" })
1825
+ ] })
1826
+ ] }),
1827
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "grid-frame ui-grid", "data-part": "grid-frame", role: "grid", "aria-label": options.title ?? "Data grid", children: [
1828
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-toolbar", "data-part": "grid-toolbar", children: [
1829
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1830
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: visibleRowCount }),
1831
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1832
+ labels.toolbarOf,
1833
+ " ",
1834
+ totalRows,
1835
+ " ",
1836
+ labels.toolbarRows
1837
+ ] })
1838
+ ] }),
1839
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "`gridOptions` compatibility layer: sorting, filtering, grouping, column moving, templating, and virtualized rendering." })
1840
+ ] }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-table ui-grid-contents-wrapper", "data-part": "grid-table", children: [
1842
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1843
+ "div",
1844
+ {
1845
+ className: "header-grid ui-grid-header ui-grid-header-canvas",
1846
+ "data-part": "header",
1847
+ role: "row",
1848
+ style: { gridTemplateColumns },
1849
+ children: visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1850
+ "div",
1851
+ {
1852
+ className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}`,
1853
+ "data-part": "header-cell",
1854
+ role: "columnheader",
1855
+ "aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
1856
+ children: [
1857
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "header-label", children: state.headerLabel(column) }),
1858
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "header-actions", children: [
1859
+ sortingFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1860
+ "button",
1861
+ {
1862
+ type: "button",
1863
+ className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
1864
+ disabled: !state.isColumnSortable(column),
1865
+ "aria-label": state.sortButtonLabel(column),
1866
+ title: state.sortButtonLabel(column),
1867
+ onClick: () => state.toggleSort(column),
1868
+ children: [
1869
+ renderSortIcon(column),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
1871
+ ]
1872
+ }
1873
+ ),
1874
+ groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1875
+ "button",
1876
+ {
1877
+ type: "button",
1878
+ className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
1879
+ "data-part": "group-toggle",
1880
+ "aria-label": state.groupingButtonLabel(column),
1881
+ title: state.groupingButtonLabel(column),
1882
+ onClick: (e) => state.toggleGrouping(column, e),
1883
+ children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
1885
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
1886
+ ]
1887
+ }
1888
+ )
1889
+ ] })
1890
+ ]
1891
+ },
1892
+ column.name
1893
+ ))
1894
+ }
1895
+ ),
1896
+ filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "filter-grid ui-grid-header", "data-part": "filters", style: { gridTemplateColumns }, children: visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter-cell ui-grid-filter-container", "data-part": "filter-cell", children: [
1897
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sr-only ui-grid-sr-only", children: [
1898
+ labels.filterColumn,
1899
+ " ",
1900
+ state.headerLabel(column)
1901
+ ] }),
1902
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1903
+ "input",
1904
+ {
1905
+ className: "ui-grid-filter-input",
1906
+ type: "text",
1907
+ defaultValue: state.filterValue(column.name),
1908
+ placeholder: state.filterPlaceholder(column),
1909
+ disabled: state.isFilterInputDisabled(column),
1910
+ onChange: (e) => state.updateFilter(column.name, e.target.value)
1911
+ }
1912
+ )
1913
+ ] }, column.name)) }),
1914
+ displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1915
+ "div",
1916
+ {
1917
+ className: "grid-viewport ui-grid-viewport",
1918
+ "data-part": "viewport",
1919
+ ref: virtualScroll.viewportRef,
1920
+ style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
1921
+ onScroll: onViewportScroll,
1922
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1923
+ "div",
1924
+ {
1925
+ className: "body-grid ui-grid-canvas",
1926
+ "data-part": "body",
1927
+ role: "rowgroup",
1928
+ style: {
1929
+ gridTemplateColumns,
1930
+ position: "absolute",
1931
+ top: 0,
1932
+ left: 0,
1933
+ right: 0,
1934
+ transform: `translateY(${virtualScroll.offsetY}px)`
1935
+ },
1936
+ children: itemsToRender.map(renderDisplayItem)
1937
+ }
1938
+ ) })
1939
+ }
1940
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1941
+ "div",
1942
+ {
1943
+ className: "body-grid ui-grid-canvas",
1944
+ "data-part": "body",
1945
+ role: "rowgroup",
1946
+ style: { gridTemplateColumns },
1947
+ children: displayItems.map(renderDisplayItem)
1948
+ }
1949
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
1950
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
1951
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: labels.emptyDescription })
1952
+ ] }),
1953
+ paginationFeature && state.showPaginationControls() && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", { className: "pagination-bar ui-grid-pagination", "data-part": "pagination", role: "navigation", "aria-label": labels.paginationPage, children: [
1954
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: state.paginationSummary() }),
1955
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pagination-controls", children: [
1956
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1957
+ "button",
1958
+ {
1959
+ type: "button",
1960
+ className: "action action-secondary pagination-button",
1961
+ "aria-label": labels.paginationPrevious,
1962
+ disabled: paginationCurrentPage <= 1,
1963
+ onClick: () => state.previousPage(),
1964
+ children: [
1965
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" }) }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationPrevious })
1967
+ ]
1968
+ }
1969
+ ),
1970
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1971
+ labels.paginationPage,
1972
+ " ",
1973
+ paginationCurrentPage,
1974
+ " ",
1975
+ labels.paginationOf,
1976
+ " ",
1977
+ paginationTotalPages
1978
+ ] }),
1979
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1980
+ "button",
1981
+ {
1982
+ type: "button",
1983
+ className: "action action-secondary pagination-button",
1984
+ "aria-label": labels.paginationNext,
1985
+ disabled: paginationCurrentPage >= paginationTotalPages,
1986
+ onClick: () => state.nextPage(),
1987
+ children: [
1988
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" }) }),
1989
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationNext })
1990
+ ]
1991
+ }
1992
+ ),
1993
+ state.pageSizeOptions().length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "pagination-size", children: [
1994
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationRows }),
1995
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1996
+ "select",
1997
+ {
1998
+ "aria-label": labels.paginationRows,
1999
+ value: paginationSelectedPageSize,
2000
+ onChange: (e) => state.onPageSizeChange(e.target.value),
2001
+ children: state.pageSizeOptions().map((size) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: size, children: size }, size))
2002
+ }
2003
+ )
2004
+ ] })
2005
+ ] })
2006
+ ] })
2007
+ ] })
2008
+ ] })
2009
+ ] }) });
2010
+ }
2011
+
2012
+ // src/index.ts
2013
+ var import_ui_grid7 = require("@ornery/ui-grid");
2014
+ // Annotate the CommonJS export names for ESM import in node:
2015
+ 0 && (module.exports = {
2016
+ DEFAULT_GRID_LABELS,
2017
+ UiGrid,
2018
+ useGridState,
2019
+ useVirtualScroll
2020
+ });