@ornery/ui-grid-react 0.1.9 → 1.0.0

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