@ornery/ui-grid-react 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/demo/main.tsx +1 -1
  2. package/demo/vite.config.ts +1 -1
  3. package/dist/UiGrid.d.ts +11 -0
  4. package/dist/UiGrid.d.ts.map +1 -0
  5. package/dist/gridStateMath.d.ts +8 -0
  6. package/dist/gridStateMath.d.ts.map +1 -0
  7. package/dist/index.d.ts +14 -155
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +699 -1063
  10. package/dist/index.mjs +594 -930
  11. package/dist/mountUiGrid.d.ts +4 -0
  12. package/dist/mountUiGrid.d.ts.map +1 -0
  13. package/dist/rustWasmGridEngine.d.ts +8 -0
  14. package/dist/rustWasmGridEngine.d.ts.map +1 -0
  15. package/dist/{index.d.mts → useGridState.d.ts} +6 -50
  16. package/dist/useGridState.d.ts.map +1 -0
  17. package/dist/useVirtualScroll.d.ts +20 -0
  18. package/dist/useVirtualScroll.d.ts.map +1 -0
  19. package/dist/vanillaAdapter.d.ts +14 -0
  20. package/dist/vanillaAdapter.d.ts.map +1 -0
  21. package/dist/virtualScrollMath.d.ts +17 -0
  22. package/dist/virtualScrollMath.d.ts.map +1 -0
  23. package/package.json +11 -11
  24. package/src/UiGrid.test.tsx +63 -25
  25. package/src/UiGrid.tsx +438 -187
  26. package/src/gridStateMath.test.ts +10 -8
  27. package/src/gridStateMath.ts +20 -7
  28. package/src/index.ts +21 -5
  29. package/src/mountUiGrid.tsx +10 -0
  30. package/src/rustWasmGridEngine.test.ts +4 -4
  31. package/src/rustWasmGridEngine.ts +7 -5
  32. package/src/ui-grid.css +200 -1
  33. package/src/useGridState.ts +56 -30
  34. package/src/useVirtualScroll.ts +2 -0
  35. package/src/vanillaAdapter.test.ts +33 -0
  36. package/src/vanillaAdapter.ts +36 -0
  37. package/tsconfig.build.json +6 -0
  38. package/tsconfig.dts.json +15 -0
  39. package/tsconfig.json +1 -1
  40. package/vitest.config.ts +1 -1
  41. package/CLAUDE.md +0 -283
package/dist/index.mjs CHANGED
@@ -1,8 +1,11 @@
1
+ // src/UiGrid.tsx
2
+ import React from "react";
3
+
1
4
  // src/useGridState.ts
2
5
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
6
 
4
7
  // src/gridStateMath.ts
5
- import { gridColumnWidth } from "@ornery/ui-grid";
8
+ import { gridColumnWidth } from "@ornery/ui-grid-core";
6
9
  function orderVisibleColumns(columns, order) {
7
10
  return [...columns].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
8
11
  }
@@ -28,9 +31,9 @@ function computeViewportRows(viewportHeight, rowHeight) {
28
31
  // src/useGridState.ts
29
32
  import {
30
33
  createGridApi,
31
- getCellValue as getCellValue2,
34
+ getCellValue,
32
35
  setPathValue,
33
- SORT_DIRECTIONS as SORT_DIRECTIONS2,
36
+ SORT_DIRECTIONS,
34
37
  defaultGridEngine,
35
38
  resolveGridLabels,
36
39
  gridColumnWidth as gridColumnWidth2,
@@ -86,679 +89,48 @@ import {
86
89
  FEATURE_COLUMN_MOVING,
87
90
  FEATURE_CSV_EXPORT,
88
91
  FEATURE_AUTO_RESIZE,
89
- FEATURE_PINNING
90
- } from "@ornery/ui-grid";
91
-
92
- // ../ui-grid/src/lib/grid/grid.core.pagination.ts
93
- function seekGridPage(page, totalPages) {
94
- return Math.min(Math.max(page, 1), Math.max(totalPages, 1));
95
- }
96
- function resolveGridPageSize(pageSize) {
97
- return Number.isFinite(pageSize) && pageSize > 0 ? pageSize : null;
98
- }
99
-
100
- // ../ui-grid/src/lib/grid/grid.constants.ts
101
- var SORT_DIRECTIONS = {
102
- asc: "asc",
103
- desc: "desc",
104
- none: "none"
105
- };
106
-
107
- // ../ui-grid/src/lib/grid/grid.utils.ts
108
- var PROTECTED_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
109
- function getPathValue(record, path) {
110
- return path.split(".").reduce((current, part) => {
111
- if (current === null || current === void 0 || typeof current !== "object") {
112
- return void 0;
113
- }
114
- if (PROTECTED_PATH_SEGMENTS.has(part)) {
115
- return void 0;
116
- }
117
- if (!Object.prototype.hasOwnProperty.call(current, part)) {
118
- return void 0;
119
- }
120
- return current[part];
121
- }, record);
122
- }
123
- function getCellValue(row, column) {
124
- if (column.valueGetter) {
125
- return column.valueGetter(row);
126
- }
127
- if (column.field) {
128
- return getPathValue(row, column.field);
129
- }
130
- return row[column.name];
131
- }
132
-
133
- // ../ui-grid/src/lib/grid/grid.core.identity.ts
134
- function buildGridSortState(columnName, direction) {
135
- return {
136
- columnName,
137
- direction: direction ?? SORT_DIRECTIONS.asc
138
- };
139
- }
140
-
141
- // ../ui-grid/src/lib/grid/grid.core.edit.ts
142
- function beginGridEditSession(rowId, columnName, editingValue) {
143
- const position = { rowId, columnName };
144
- return {
145
- focusedCell: position,
146
- editingCell: position,
147
- editingValue
148
- };
149
- }
150
- function clearGridEditSession() {
151
- return {
152
- editingCell: null,
153
- editingValue: ""
154
- };
155
- }
156
- function stringifyGridEditorValue(value) {
157
- if (value instanceof Date) {
158
- return value.toISOString().slice(0, 10);
159
- }
160
- return value === null || value === void 0 ? "" : String(value);
161
- }
162
-
163
- // ../ui-grid/src/lib/grid/grid.core.infinite-scroll.ts
164
- function maybeRequestInfiniteScrollData(context) {
165
- if (context.state.dataLoading) {
166
- return { request: null, nextState: context.state };
167
- }
168
- if (context.state.scrollUp && context.startIndex <= context.threshold) {
169
- return {
170
- request: "top",
171
- nextState: {
172
- ...context.state,
173
- dataLoading: true,
174
- previousVisibleRows: context.visibleRows
175
- }
176
- };
177
- }
178
- if (context.state.scrollDown && context.startIndex + context.viewportRows >= Math.max(context.visibleRows - context.threshold, 0)) {
179
- return {
180
- request: "bottom",
181
- nextState: {
182
- ...context.state,
183
- dataLoading: true,
184
- previousVisibleRows: context.visibleRows
185
- }
186
- };
187
- }
188
- return { request: null, nextState: context.state };
189
- }
190
- function completeInfiniteScrollDataLoad(state, scrollUp, scrollDown) {
191
- return {
192
- ...state,
193
- scrollUp,
194
- scrollDown,
195
- dataLoading: false
196
- };
197
- }
198
- function resetInfiniteScrollState(scrollUp, scrollDown) {
199
- return {
200
- scrollUp,
201
- scrollDown,
202
- dataLoading: false,
203
- previousVisibleRows: 0
204
- };
205
- }
206
- function saveInfiniteScrollPercentage(state, visibleRows) {
207
- return {
208
- ...state,
209
- previousVisibleRows: visibleRows
210
- };
211
- }
212
- function setInfiniteScrollDirectionsState(state, scrollUp, scrollDown) {
213
- return {
214
- ...state,
215
- scrollUp,
216
- scrollDown
217
- };
218
- }
219
-
220
- // ../ui-grid/src/lib/grid/grid.core.row-state.ts
221
- function toggleGridRowExpanded(expandedRows, rowId) {
222
- const expanded = !expandedRows[rowId];
223
- return {
224
- expanded,
225
- nextExpandedRows: {
226
- ...expandedRows,
227
- [rowId]: expanded
228
- }
229
- };
230
- }
231
- function expandAllGridRows(rows) {
232
- const nextExpandedRows = {};
233
- for (const row of rows) {
234
- nextExpandedRows[row.id] = true;
235
- }
236
- return nextExpandedRows;
237
- }
238
- function setGridTreeRowExpanded(expandedTreeRows, rowId, expanded) {
239
- return {
240
- ...expandedTreeRows,
241
- [rowId]: expanded
242
- };
243
- }
244
- function toggleGridTreeRowExpanded(expandedTreeRows, rowId) {
245
- const expanded = !expandedTreeRows[rowId];
246
- return {
247
- expanded,
248
- nextExpandedTreeRows: setGridTreeRowExpanded(expandedTreeRows, rowId, expanded)
249
- };
250
- }
251
- function expandAllGridTreeRows(rows) {
252
- const nextExpandedTreeRows = {};
253
- for (const row of rows) {
254
- if (row.hasChildren) {
255
- nextExpandedTreeRows[row.id] = true;
256
- }
257
- }
258
- return nextExpandedTreeRows;
259
- }
260
-
261
- // ../ui-grid/src/lib/grid/grid.core.state.ts
262
- function normalizeGridSavedState(state) {
263
- const normalized = {};
264
- if (Array.isArray(state.columnOrder)) {
265
- normalized.columnOrder = state.columnOrder.filter(
266
- (columnName) => typeof columnName === "string" && isSafeStateKey(columnName)
267
- );
268
- }
269
- if (state.filters && typeof state.filters === "object") {
270
- normalized.filters = Object.entries(state.filters).reduce(
271
- (accumulator, [key, value]) => {
272
- if (typeof key === "string" && isSafeStateKey(key) && typeof value === "string") {
273
- accumulator[key] = value;
274
- }
275
- return accumulator;
276
- },
277
- {}
278
- );
279
- }
280
- if (state.sort && typeof state.sort === "object") {
281
- normalized.sort = {
282
- columnName: typeof state.sort.columnName === "string" && isSafeStateKey(state.sort.columnName) ? state.sort.columnName : null,
283
- direction: state.sort.direction === SORT_DIRECTIONS.asc || state.sort.direction === SORT_DIRECTIONS.desc ? state.sort.direction : SORT_DIRECTIONS.none
284
- };
285
- }
286
- if (Array.isArray(state.grouping)) {
287
- normalized.grouping = state.grouping.filter(
288
- (columnName) => typeof columnName === "string" && isSafeStateKey(columnName)
289
- );
290
- }
291
- if (state.pagination && typeof state.pagination === "object") {
292
- const paginationCurrentPage = Number(state.pagination.paginationCurrentPage);
293
- const paginationPageSize = Number(state.pagination.paginationPageSize);
294
- normalized.pagination = {
295
- paginationCurrentPage: Number.isFinite(paginationCurrentPage) && paginationCurrentPage > 0 ? Math.floor(paginationCurrentPage) : 1,
296
- paginationPageSize: Number.isFinite(paginationPageSize) && paginationPageSize >= 0 ? Math.floor(paginationPageSize) : 0
297
- };
298
- }
299
- if (state.expandable && typeof state.expandable === "object") {
300
- normalized.expandable = normalizeBooleanMap(state.expandable);
301
- }
302
- if (state.treeView && typeof state.treeView === "object") {
303
- normalized.treeView = normalizeBooleanMap(state.treeView);
304
- }
305
- if (state.pinning && typeof state.pinning === "object") {
306
- normalized.pinning = Object.entries(state.pinning).reduce(
307
- (acc, [key, value]) => {
308
- if (typeof key === "string" && isSafeStateKey(key) && (value === "left" || value === "right")) {
309
- acc[key] = value;
310
- }
311
- return acc;
312
- },
313
- {}
314
- );
315
- }
316
- return normalized;
317
- }
318
- function normalizeBooleanMap(value) {
319
- return Object.entries(value).reduce((accumulator, [key, entry]) => {
320
- if (typeof key === "string" && isSafeStateKey(key) && typeof entry === "boolean") {
321
- accumulator[key] = entry;
322
- }
323
- return accumulator;
324
- }, {});
325
- }
326
- function isSafeStateKey(value) {
327
- return value !== "__proto__" && value !== "constructor" && value !== "prototype";
328
- }
329
-
330
- // ../ui-grid/src/lib/grid/grid.core.pinning.ts
331
- function isPinningEnabled(options) {
332
- return options.enablePinning === true;
333
- }
334
- function isColumnPinnable(options, column) {
335
- return isPinningEnabled(options) && column.enablePinning !== false;
336
- }
337
- function pinColumnState(current, columnName, direction) {
338
- const next = { ...current };
339
- if (direction === "none") {
340
- delete next[columnName];
341
- } else {
342
- next[columnName] = direction;
343
- }
344
- return next;
345
- }
346
- function buildInitialPinnedState(columns) {
347
- const state = {};
348
- for (const col of columns) {
349
- if (col.pinnedLeft) state[col.name] = "left";
350
- else if (col.pinnedRight) state[col.name] = "right";
351
- }
352
- return state;
353
- }
354
- function computePinnedOffset(visibleColumns, pinnedColumns, column) {
355
- const direction = pinnedColumns[column.name];
356
- if (!direction) return null;
357
- function resolveColumnWidthForOffset(column2) {
358
- const w = column2.width;
359
- if (!w) return "11rem";
360
- if (w.includes("fr") || w.includes("minmax")) return "11rem";
361
- return w;
362
- }
363
- if (direction === "left") {
364
- const offsetParts = [];
365
- for (const col of visibleColumns) {
366
- if (col.name === column.name) break;
367
- if (pinnedColumns[col.name] === "left") {
368
- offsetParts.push(resolveColumnWidthForOffset(col));
369
- }
370
- }
371
- return {
372
- side: "left",
373
- offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
374
- };
375
- }
376
- if (direction === "right") {
377
- const offsetParts = [];
378
- const reversed = [...visibleColumns].reverse();
379
- for (const col of reversed) {
380
- if (col.name === column.name) break;
381
- if (pinnedColumns[col.name] === "right") {
382
- offsetParts.push(resolveColumnWidthForOffset(col));
383
- }
384
- }
385
- return {
386
- side: "right",
387
- offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
388
- };
389
- }
390
- return null;
391
- }
392
-
393
- // ../ui-grid/src/lib/grid/ui-grid.events.ts
394
- function raiseGridRenderingComplete(gridApi) {
395
- gridApi.core.raise.renderingComplete(gridApi);
396
- }
397
- function raiseGridRowsRendered(gridApi, rows) {
398
- gridApi.core.raise.rowsRendered(rows);
399
- }
400
- function raiseGridRowsVisibleChanged(gridApi, rows) {
401
- gridApi.core.raise.rowsVisibleChanged(rows);
402
- }
403
- function raiseGridCanvasHeightChanged(gridApi, oldHeight, newHeight) {
404
- gridApi.core.raise.canvasHeightChanged(oldHeight, newHeight);
405
- }
406
- function raiseGridDimensionChanged(gridApi, oldHeight, oldWidth, newHeight, newWidth) {
407
- gridApi.core.raise.gridDimensionChanged(oldHeight, oldWidth, newHeight, newWidth);
408
- }
409
- function raiseGridScrollBegin(gridApi) {
410
- gridApi.core.raise.scrollBegin();
411
- }
412
- function raiseGridScrollEnd(gridApi) {
413
- gridApi.core.raise.scrollEnd();
414
- }
415
- function raiseGridSortChanged(gridApi, sortState) {
416
- gridApi.core.raise.sortChanged(sortState.columnName, sortState.direction);
417
- }
418
- function raiseGridFilterChanged(gridApi, filters) {
419
- gridApi.core.raise.filterChanged(filters);
420
- }
421
- function raiseGridGroupingChanged(gridApi, groupByColumns) {
422
- gridApi.core.raise.groupingChanged(groupByColumns);
423
- }
424
- function raiseGridColumnOrderChanged(gridApi, order) {
425
- gridApi.core.raise.columnOrderChanged(order);
426
- }
427
- function raiseGridBenchmarkComplete(gridApi, result) {
428
- gridApi.core.raise.benchmarkComplete(result);
429
- }
430
- function raiseGridPaginationChanged(gridApi, currentPage, pageSize) {
431
- gridApi.pagination.raise.paginationChanged(currentPage, pageSize);
432
- }
433
- function raiseGridExpandableRowStateChanged(gridApi, row, expanded) {
434
- gridApi.expandable.raise.rowExpandedStateChanged(row, expanded);
435
- }
436
- function raiseGridTreeRowStateChanged(gridApi, row, expanded) {
437
- if (expanded) {
438
- gridApi.treeBase.raise.rowExpanded(row);
439
- return;
440
- }
441
- gridApi.treeBase.raise.rowCollapsed(row);
442
- }
443
- function raiseGridNeedMoreData(gridApi, request) {
444
- if (request === "top") {
445
- gridApi.infiniteScroll.raise.needLoadMoreDataTop();
446
- return;
447
- }
448
- gridApi.infiniteScroll.raise.needLoadMoreData();
449
- }
450
- function raiseGridBeginCellEdit(gridApi, rowEntity, column, triggerEvent) {
451
- gridApi.edit.raise.beginCellEdit(rowEntity, column, triggerEvent);
452
- }
453
- function raiseGridAfterCellEdit(gridApi, rowEntity, column, newValue, oldValue) {
454
- gridApi.edit.raise.afterCellEdit(rowEntity, column, newValue, oldValue);
455
- }
456
- function raiseGridCancelCellEdit(gridApi, rowEntity, column) {
457
- gridApi.edit.raise.cancelCellEdit(rowEntity, column);
458
- }
459
- function raiseGridColumnPinned(gridApi, columnName, direction) {
460
- gridApi.pinning.raise.columnPinned(columnName, direction);
461
- }
462
-
463
- // ../ui-grid/src/lib/grid/ui-grid.state.ts
464
- function moveArrayItem(items, fromIndex, toIndex) {
465
- const next = [...items];
466
- const [item] = next.splice(fromIndex, 1);
467
- if (item === void 0) {
468
- return next;
469
- }
470
- next.splice(toIndex, 0, item);
471
- return next;
472
- }
473
- function moveGridColumnOrderState(current, fromIndex, toIndex) {
474
- return moveArrayItem(current, fromIndex, toIndex);
475
- }
476
- function createGridRestoreMutationPlan(state) {
477
- const normalizedState = normalizeGridSavedState(state);
478
- const plan = {};
479
- if (normalizedState.columnOrder) {
480
- plan.columnOrder = normalizedState.columnOrder;
481
- }
482
- if (normalizedState.filters) {
483
- plan.filters = normalizedState.filters;
484
- }
485
- if (normalizedState.sort) {
486
- plan.sort = normalizedState.sort;
487
- }
488
- if (normalizedState.grouping) {
489
- plan.grouping = normalizedState.grouping;
490
- }
491
- if (normalizedState.pagination) {
492
- plan.pagination = {
493
- currentPage: normalizedState.pagination.paginationCurrentPage,
494
- pageSize: normalizedState.pagination.paginationPageSize
495
- };
496
- }
497
- if (normalizedState.expandable) {
498
- plan.expandable = normalizedState.expandable;
499
- }
500
- if (normalizedState.treeView) {
501
- plan.treeView = normalizedState.treeView;
502
- }
503
- if (normalizedState.pinning) {
504
- plan.pinning = normalizedState.pinning;
505
- }
506
- return plan;
507
- }
508
-
509
- // ../ui-grid/src/lib/grid/ui-grid.commands.ts
510
- function applyGridSortStateCommand(gridApi, setSortState, sortState) {
511
- setSortState(sortState);
512
- raiseGridSortChanged(gridApi, sortState);
513
- }
514
- function sortGridColumnCommand(gridApi, setSortState, columnName, direction) {
515
- applyGridSortStateCommand(gridApi, setSortState, buildGridSortState(columnName, direction));
516
- }
517
- function updateGridFilterCommand(gridApi, updateFilters, getFilters, columnName, value) {
518
- updateFilters((current) => ({
519
- ...current,
520
- [columnName]: value
521
- }));
522
- raiseGridFilterChanged(gridApi, getFilters());
523
- }
524
- function clearGridFiltersCommand(gridApi, setFilters) {
525
- const nextFilters = {};
526
- setFilters(nextFilters);
527
- raiseGridFilterChanged(gridApi, nextFilters);
528
- }
529
- function clearGridGroupingCommand(gridApi, setGroupByColumns, shouldRaise = true) {
530
- const nextGrouping = [];
531
- setGroupByColumns(nextGrouping);
532
- if (shouldRaise) {
533
- raiseGridGroupingChanged(gridApi, nextGrouping);
534
- }
535
- }
536
- function moveGridColumnCommand(gridApi, canMoveColumns, updateColumnOrder, fromIndex, toIndex) {
537
- if (!canMoveColumns) {
538
- return;
539
- }
540
- updateColumnOrder((current) => {
541
- const next = moveGridColumnOrderState(current, fromIndex, toIndex);
542
- raiseGridColumnOrderChanged(gridApi, next);
543
- return next;
544
- });
545
- }
546
- function pinGridColumnCommand(gridApi, isPinningEnabled2, setPinnedColumns, getCurrentPinnedColumns, columnName, direction) {
547
- if (!isPinningEnabled2) return;
548
- const next = pinColumnState(getCurrentPinnedColumns(), columnName, direction);
549
- setPinnedColumns(next);
550
- raiseGridColumnPinned(gridApi, columnName, direction);
551
- }
552
- function seekGridPaginationCommand(gridApi, setCurrentPage, getTotalPages, getEffectivePageSize, page) {
553
- const nextPage = seekGridPage(page, getTotalPages());
554
- setCurrentPage(nextPage);
555
- raiseGridPaginationChanged(gridApi, nextPage, getEffectivePageSize());
556
- }
557
- function setGridPaginationPageSizeCommand(gridApi, setPageSize, setCurrentPage, pageSize) {
558
- const nextPageSize = resolveGridPageSize(pageSize);
559
- if (nextPageSize === null) {
560
- return;
561
- }
562
- setPageSize(nextPageSize);
563
- setCurrentPage(1);
564
- raiseGridPaginationChanged(gridApi, 1, nextPageSize);
565
- }
566
- function restoreGridStateCommand(gridApi, state, access) {
567
- const restorePlan = createGridRestoreMutationPlan(state);
568
- if (restorePlan.columnOrder) {
569
- access.setColumnOrder(restorePlan.columnOrder);
570
- }
571
- if (restorePlan.filters) {
572
- access.setActiveFilters(restorePlan.filters);
573
- raiseGridFilterChanged(gridApi, restorePlan.filters);
574
- }
575
- if (restorePlan.sort) {
576
- access.setSortState(restorePlan.sort);
577
- }
578
- if (restorePlan.grouping) {
579
- access.setGroupByColumns(restorePlan.grouping);
580
- raiseGridGroupingChanged(gridApi, restorePlan.grouping);
581
- }
582
- if (restorePlan.pagination) {
583
- access.setCurrentPage(restorePlan.pagination.currentPage);
584
- access.setPageSize(restorePlan.pagination.pageSize);
585
- raiseGridPaginationChanged(
586
- gridApi,
587
- restorePlan.pagination.currentPage,
588
- access.getEffectivePageSize()
589
- );
590
- }
591
- if (restorePlan.expandable) {
592
- access.setExpandedRows(restorePlan.expandable);
593
- }
594
- if (restorePlan.treeView) {
595
- access.setExpandedTreeRows(restorePlan.treeView);
596
- }
597
- if (restorePlan.pinning && typeof access.setPinnedColumns === "function") {
598
- access.setPinnedColumns(restorePlan.pinning);
599
- for (const [col, dir] of Object.entries(restorePlan.pinning)) {
600
- raiseGridColumnPinned(gridApi, col, dir);
601
- }
602
- }
603
- }
604
- function toggleGridRowExpansionCommand(gridApi, canExpandRows, currentExpandedRows, rowId, setExpandedRows, findRowById) {
605
- if (!canExpandRows) {
606
- return;
607
- }
608
- const { expanded, nextExpandedRows } = toggleGridRowExpanded(currentExpandedRows, rowId);
609
- setExpandedRows(nextExpandedRows);
610
- const gridRow = findRowById(rowId);
611
- if (!gridRow) {
612
- return;
613
- }
614
- gridRow.expanded = expanded;
615
- raiseGridExpandableRowStateChanged(gridApi, gridRow, expanded);
616
- }
617
- function expandAllGridRowsCommand(buildRows, data, setExpandedRows) {
618
- setExpandedRows(expandAllGridRows(buildRows(data)));
619
- }
620
- function collapseAllGridRowsCommand(setExpandedRows) {
621
- setExpandedRows({});
622
- }
623
- function toggleGridTreeRowCommand(gridApi, currentExpandedTreeRows, rowId, setExpandedTreeRows, findRowById) {
624
- const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(
625
- currentExpandedTreeRows,
626
- rowId
627
- );
628
- setExpandedTreeRows(nextExpandedTreeRows);
629
- const gridRow = findRowById(rowId);
630
- if (gridRow) {
631
- raiseGridTreeRowStateChanged(gridApi, gridRow, expanded);
632
- }
633
- }
634
- function setGridTreeRowExpandedCommand(gridApi, currentExpandedTreeRows, rowId, expanded, setExpandedTreeRows, findRowById) {
635
- setExpandedTreeRows(setGridTreeRowExpanded(currentExpandedTreeRows, rowId, expanded));
636
- const gridRow = findRowById(rowId);
637
- if (gridRow) {
638
- raiseGridTreeRowStateChanged(gridApi, gridRow, expanded);
639
- }
640
- }
641
- function expandAllGridTreeRowsCommand(buildRows, data, setExpandedTreeRows) {
642
- setExpandedTreeRows(expandAllGridTreeRows(buildRows(data)));
643
- }
644
- function collapseAllGridTreeRowsCommand(setExpandedTreeRows) {
645
- setExpandedTreeRows({});
646
- }
647
- function beginGridCellEditCommand(gridApi, access, row, column, currentValue, triggerEvent, initialValue) {
648
- const nextEditSession = beginGridEditSession(
649
- row.id,
650
- column.name,
651
- initialValue ?? stringifyGridEditorValue(currentValue)
652
- );
653
- access.setFocusedCell(nextEditSession.focusedCell);
654
- access.setEditingCell(nextEditSession.editingCell);
655
- access.setEditingValue(nextEditSession.editingValue);
656
- raiseGridBeginCellEdit(gridApi, row.entity, column, triggerEvent);
657
- return nextEditSession.editingCell;
658
- }
659
- function commitGridCellEditCommand(gridApi, access) {
660
- const editingCell = access.getEditingCell();
661
- if (!editingCell) {
662
- return { committed: false };
663
- }
664
- const row = access.findRowById(editingCell.rowId);
665
- const column = access.findColumnByName(editingCell.columnName);
666
- if (!row || !column) {
667
- access.setEditingCell(null);
668
- return { committed: false };
669
- }
670
- const oldValue = getCellValue(row.entity, column);
671
- const newValue = access.parseEditedValue(column, access.getEditingValue(), oldValue);
672
- access.setCellValue(row.entity, column, newValue);
673
- const clearedEditSession = clearGridEditSession();
674
- access.setEditingCell(clearedEditSession.editingCell);
675
- raiseGridAfterCellEdit(gridApi, row.entity, column, newValue, oldValue);
676
- access.setEditingValue(clearedEditSession.editingValue);
677
- return {
678
- committed: true,
679
- focusTarget: { rowId: row.id, columnName: column.name },
680
- row,
681
- column
682
- };
683
- }
684
- function cancelGridCellEditCommand(gridApi, access) {
685
- const editingCell = access.getEditingCell();
686
- if (!editingCell) {
687
- return {};
688
- }
689
- const row = access.findRowById(editingCell.rowId);
690
- const column = access.findColumnByName(editingCell.columnName);
691
- const clearedEditSession = clearGridEditSession();
692
- access.setEditingCell(clearedEditSession.editingCell);
693
- access.setEditingValue(clearedEditSession.editingValue);
694
- if (!row || !column) {
695
- return {};
696
- }
697
- raiseGridCancelCellEdit(gridApi, row.entity, column);
698
- return { focusTarget: editingCell };
699
- }
700
- function maybeRequestInfiniteScrollCommand(gridApi, access) {
701
- if (!access.enabled || !access.virtualizationEnabled) {
702
- return;
703
- }
704
- const { request, nextState } = maybeRequestInfiniteScrollData({
705
- state: access.state,
706
- startIndex: access.startIndex,
707
- visibleRows: access.visibleRows,
708
- viewportRows: access.viewportRows,
709
- threshold: access.threshold
710
- });
711
- if (request === "top" || request === "bottom") {
712
- access.setState(nextState);
713
- raiseGridNeedMoreData(gridApi, request);
714
- }
715
- }
716
- function completeGridInfiniteScrollDataLoadCommand(currentState, setState, scrollUp, scrollDown) {
717
- setState(completeInfiniteScrollDataLoad(currentState, scrollUp, scrollDown));
718
- return Promise.resolve();
719
- }
720
- function resetGridInfiniteScrollCommand(setState, scrollUp, scrollDown) {
721
- setState(resetInfiniteScrollState(scrollUp, scrollDown));
722
- }
723
- function saveGridInfiniteScrollPercentageCommand(currentState, visibleRows, setState) {
724
- setState(saveInfiniteScrollPercentage(currentState, visibleRows));
725
- }
726
- function setGridInfiniteScrollDirectionsCommand(currentState, setState, scrollUp, scrollDown) {
727
- setState(setInfiniteScrollDirectionsState(currentState, scrollUp, scrollDown));
728
- }
729
-
730
- // ../ui-grid/src/lib/grid/ui-grid.host.ts
731
- function observeGridHostSize(hostElement, onSizeChange) {
732
- if (typeof ResizeObserver === "undefined") {
733
- return null;
734
- }
735
- const observer = new ResizeObserver((entries) => {
736
- const entry = entries[0];
737
- if (!entry) {
738
- return;
739
- }
740
- onSizeChange({
741
- height: Math.round(entry.contentRect.height),
742
- width: Math.round(entry.contentRect.width)
743
- });
744
- });
745
- observer.observe(hostElement);
746
- return observer;
747
- }
748
- function downloadGridCsvFile(csv, filename) {
749
- if (typeof Blob === "undefined" || typeof URL === "undefined" || typeof document === "undefined") {
750
- return;
751
- }
752
- const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
753
- const url = URL.createObjectURL(blob);
754
- const link = document.createElement("a");
755
- link.href = url;
756
- link.download = filename;
757
- link.click();
758
- URL.revokeObjectURL(url);
759
- }
760
-
761
- // src/useGridState.ts
92
+ FEATURE_PINNING,
93
+ buildInitialPinnedState,
94
+ computePinnedOffset,
95
+ isColumnPinnable,
96
+ isPinningEnabled,
97
+ applyGridSortStateCommand,
98
+ updateGridFilterCommand,
99
+ clearGridFiltersCommand,
100
+ clearGridGroupingCommand,
101
+ moveGridColumnCommand,
102
+ moveGridVisibleColumnCommand,
103
+ seekGridPaginationCommand,
104
+ setGridPaginationPageSizeCommand,
105
+ sortGridColumnCommand,
106
+ toggleGridRowExpansionCommand,
107
+ expandAllGridRowsCommand,
108
+ collapseAllGridRowsCommand,
109
+ toggleGridTreeRowCommand,
110
+ setGridTreeRowExpandedCommand,
111
+ expandAllGridTreeRowsCommand,
112
+ collapseAllGridTreeRowsCommand,
113
+ beginGridCellEditCommand,
114
+ commitGridCellEditCommand,
115
+ cancelGridCellEditCommand,
116
+ maybeRequestInfiniteScrollCommand,
117
+ completeGridInfiniteScrollDataLoadCommand,
118
+ resetGridInfiniteScrollCommand,
119
+ saveGridInfiniteScrollPercentageCommand,
120
+ setGridInfiniteScrollDirectionsCommand,
121
+ restoreGridStateCommand,
122
+ pinGridColumnCommand,
123
+ raiseGridRenderingComplete,
124
+ raiseGridRowsRendered,
125
+ raiseGridRowsVisibleChanged,
126
+ raiseGridCanvasHeightChanged,
127
+ raiseGridDimensionChanged,
128
+ raiseGridScrollBegin,
129
+ raiseGridScrollEnd,
130
+ raiseGridBenchmarkComplete,
131
+ downloadGridCsvFile,
132
+ observeGridHostSize
133
+ } from "@ornery/ui-grid-core";
762
134
  function escapeCssSelectorValue(value) {
763
135
  const nativeEscape = globalThis.CSS?.escape;
764
136
  if (typeof nativeEscape === "function") {
@@ -796,7 +168,7 @@ function useGridState(options, onRegisterApi) {
796
168
  const [hiddenRowReasons, setHiddenRowReasons] = useState({});
797
169
  const [sortState, setSortState] = useState({
798
170
  columnName: null,
799
- direction: SORT_DIRECTIONS2.none
171
+ direction: SORT_DIRECTIONS.none
800
172
  });
801
173
  const [focusedCell, setFocusedCell] = useState(null);
802
174
  const [editingCell, setEditingCell] = useState(null);
@@ -857,8 +229,19 @@ function useGridState(options, onRegisterApi) {
857
229
  optionsRef.current = options;
858
230
  const rowSize = options.rowHeight ?? 44;
859
231
  const visibleColumns = useMemo(() => {
860
- return orderVisibleColumns(options.columnDefs, columnOrder);
861
- }, [options.columnDefs, columnOrder]);
232
+ const orderedColumns = orderVisibleColumns(options.columnDefs, columnOrder);
233
+ const pinnedEntries = Object.entries(pinnedColumns);
234
+ if (pinnedEntries.length === 0) {
235
+ return orderedColumns;
236
+ }
237
+ const columnByName = new Map(orderedColumns.map((column) => [column.name, column]));
238
+ const pinnedLeft = pinnedEntries.filter(([, direction]) => direction === "left").map(([columnName]) => columnByName.get(columnName)).filter((column) => column !== void 0);
239
+ const pinnedRight = pinnedEntries.filter(([, direction]) => direction === "right").map(([columnName]) => columnByName.get(columnName)).filter((column) => column !== void 0);
240
+ const centerColumns = orderedColumns.filter(
241
+ (column) => pinnedColumns[column.name] === void 0
242
+ );
243
+ return [...pinnedLeft, ...centerColumns, ...pinnedRight];
244
+ }, [options.columnDefs, columnOrder, pinnedColumns]);
862
245
  const visibleColumnsRef = useRef(visibleColumns);
863
246
  visibleColumnsRef.current = visibleColumns;
864
247
  const pipeline = useMemo(() => {
@@ -1321,7 +704,7 @@ function useGridState(options, onRegisterApi) {
1321
704
  );
1322
705
  const startCellEditFn = useCallback(
1323
706
  (row, column, triggerEvent, initialValue) => {
1324
- const currentValue = getCellValue2(row.entity, column);
707
+ const currentValue = getCellValue(row.entity, column);
1325
708
  const focusToken = ++editorFocusTokenRef.current;
1326
709
  const ec = beginGridCellEditCommand(
1327
710
  gridApiRef.current,
@@ -1481,7 +864,7 @@ function useGridState(options, onRegisterApi) {
1481
864
  );
1482
865
  setSortState({
1483
866
  columnName: initialSort?.name ?? null,
1484
- direction: initialSort?.sort?.direction ?? SORT_DIRECTIONS2.none
867
+ direction: initialSort?.sort?.direction ?? SORT_DIRECTIONS.none
1485
868
  });
1486
869
  onRegisterApi?.(gridApi);
1487
870
  raiseGridRenderingComplete(gridApi);
@@ -1542,7 +925,7 @@ function useGridState(options, onRegisterApi) {
1542
925
  []
1543
926
  );
1544
927
  const sortDirectionFn = useCallback((column) => {
1545
- return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : SORT_DIRECTIONS2.none;
928
+ return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : SORT_DIRECTIONS.none;
1546
929
  }, []);
1547
930
  const sortButtonLabelFn = useCallback(
1548
931
  (column) => {
@@ -1668,10 +1051,10 @@ function useGridState(options, onRegisterApi) {
1668
1051
  }, []);
1669
1052
  const toggleSortFn = useCallback((column) => {
1670
1053
  if (!FEATURE_SORTING || !isGridColumnSortable(optionsRef.current, column)) return;
1671
- const currentDirection = sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : SORT_DIRECTIONS2.none;
1672
- const nextDirection = currentDirection === SORT_DIRECTIONS2.none ? SORT_DIRECTIONS2.asc : currentDirection === SORT_DIRECTIONS2.asc ? SORT_DIRECTIONS2.desc : SORT_DIRECTIONS2.none;
1054
+ const currentDirection = sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : SORT_DIRECTIONS.none;
1055
+ const nextDirection = currentDirection === SORT_DIRECTIONS.none ? SORT_DIRECTIONS.asc : currentDirection === SORT_DIRECTIONS.asc ? SORT_DIRECTIONS.desc : SORT_DIRECTIONS.none;
1673
1056
  applyGridSortStateCommand(gridApiRef.current, (state) => setSortState(state), {
1674
- columnName: nextDirection === SORT_DIRECTIONS2.none ? null : column.name,
1057
+ columnName: nextDirection === SORT_DIRECTIONS.none ? null : column.name,
1675
1058
  direction: nextDirection
1676
1059
  });
1677
1060
  }, []);
@@ -1835,6 +1218,17 @@ function useGridState(options, onRegisterApi) {
1835
1218
  toIndex
1836
1219
  );
1837
1220
  }, []);
1221
+ const moveVisibleColumnFn = useCallback((columnName, targetColumnName) => {
1222
+ moveGridVisibleColumnCommand(
1223
+ gridApiRef.current,
1224
+ FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1225
+ columnOrderRef.current,
1226
+ visibleColumnsRef.current.map((column) => column.name),
1227
+ columnName,
1228
+ targetColumnName,
1229
+ (order) => setColumnOrder(order)
1230
+ );
1231
+ }, []);
1838
1232
  const nextPageFn = useCallback(() => {
1839
1233
  seekPageFn(getCurrentPageValueFn() + 1);
1840
1234
  }, [seekPageFn, getCurrentPageValueFn]);
@@ -1964,6 +1358,7 @@ function useGridState(options, onRegisterApi) {
1964
1358
  toggleRowExpansion: toggleRowExpansionFn,
1965
1359
  toggleTreeRow: toggleTreeRowFn,
1966
1360
  moveColumn: moveColumnFn,
1361
+ moveVisibleColumn: moveVisibleColumnFn,
1967
1362
  nextPage: nextPageFn,
1968
1363
  previousPage: previousPageFn,
1969
1364
  onPageSizeChange: onPageSizeChangeFn,
@@ -2024,6 +1419,7 @@ function useVirtualScroll(options) {
2024
1419
  totalHeight: virtualWindow.totalHeight,
2025
1420
  offsetY: virtualWindow.offsetY,
2026
1421
  onScroll,
1422
+ setScrollTop,
2027
1423
  viewportRef,
2028
1424
  scrollTop
2029
1425
  };
@@ -2062,20 +1458,161 @@ function UiGrid({
2062
1458
  expandableFeature,
2063
1459
  treeViewFeature,
2064
1460
  csvExportFeature,
1461
+ columnMovingFeature,
2065
1462
  paginationCurrentPage,
2066
1463
  paginationTotalPages,
2067
1464
  paginationSelectedPageSize
2068
1465
  } = state;
1466
+ const headerGridRef = React.useRef(null);
1467
+ const filterGridRef = React.useRef(null);
1468
+ const [headerStickyHeight, setHeaderStickyHeight] = React.useState(0);
1469
+ const [filterStickyHeight, setFilterStickyHeight] = React.useState(0);
1470
+ const stickyChromeHeight = headerStickyHeight + filterStickyHeight;
1471
+ const bodyViewportHeight = Math.max(
1472
+ rowSize,
1473
+ (options.viewportHeight ?? 560) - stickyChromeHeight
1474
+ );
2069
1475
  const virtualScroll = useVirtualScroll({
2070
1476
  itemCount: displayItems.length,
2071
1477
  itemSize: rowSize,
2072
- viewportHeight: options.viewportHeight ?? 560,
1478
+ viewportHeight: bodyViewportHeight,
2073
1479
  overscan: 3
2074
1480
  });
1481
+ const [openPinMenuColumn, setOpenPinMenuColumn] = React.useState(null);
1482
+ const [draggedColumnName, setDraggedColumnName] = React.useState(null);
1483
+ const [dropTargetColumnName, setDropTargetColumnName] = React.useState(null);
1484
+ const scrollContainerHeight = `${options.viewportHeight ?? 560}px`;
1485
+ const eventPathIncludesClass = React.useCallback((event, className2) => {
1486
+ const eventPath = typeof event.composedPath === "function" ? event.composedPath() : event.target ? [event.target] : [];
1487
+ return eventPath.some((target) => {
1488
+ if (!target || typeof target !== "object" || !("classList" in target)) {
1489
+ return false;
1490
+ }
1491
+ const classList = target.classList;
1492
+ return classList?.contains(className2) ?? false;
1493
+ });
1494
+ }, []);
1495
+ const isPinMenuOpen = React.useCallback(
1496
+ (column) => openPinMenuColumn === column.name,
1497
+ [openPinMenuColumn]
1498
+ );
1499
+ const pinButtonLabel = React.useCallback(
1500
+ (column) => state.isPinned(column) ? labels.unpin : labels.pinColumn,
1501
+ [labels, state]
1502
+ );
1503
+ const onPinTrigger = React.useCallback(
1504
+ (column, event) => {
1505
+ event?.stopPropagation();
1506
+ if (state.isPinned(column)) {
1507
+ setOpenPinMenuColumn(null);
1508
+ state.gridApi.pinning.pinColumn(column.name, "none");
1509
+ return;
1510
+ }
1511
+ setOpenPinMenuColumn((current) => current === column.name ? null : column.name);
1512
+ },
1513
+ [state]
1514
+ );
1515
+ const choosePinDirection = React.useCallback(
1516
+ (column, direction, event) => {
1517
+ event?.stopPropagation();
1518
+ setOpenPinMenuColumn(null);
1519
+ state.gridApi.pinning.pinColumn(column.name, direction);
1520
+ },
1521
+ [state]
1522
+ );
1523
+ const handleHeaderDragStart = React.useCallback(
1524
+ (column, event) => {
1525
+ if (!columnMovingFeature) {
1526
+ event.preventDefault();
1527
+ return;
1528
+ }
1529
+ setDraggedColumnName(column.name);
1530
+ setDropTargetColumnName(null);
1531
+ event.dataTransfer.effectAllowed = "move";
1532
+ event.dataTransfer.setData("text/plain", column.name);
1533
+ },
1534
+ [columnMovingFeature]
1535
+ );
1536
+ const handleHeaderDragOver = React.useCallback(
1537
+ (column, event) => {
1538
+ if (!columnMovingFeature || !draggedColumnName || draggedColumnName === column.name) {
1539
+ return;
1540
+ }
1541
+ event.preventDefault();
1542
+ event.dataTransfer.dropEffect = "move";
1543
+ setDropTargetColumnName(column.name);
1544
+ },
1545
+ [columnMovingFeature, draggedColumnName]
1546
+ );
1547
+ const handleHeaderDrop = React.useCallback(
1548
+ (column, event) => {
1549
+ event.preventDefault();
1550
+ if (!columnMovingFeature) {
1551
+ return;
1552
+ }
1553
+ const sourceColumnName = draggedColumnName ?? event.dataTransfer.getData("text/plain");
1554
+ setDraggedColumnName(null);
1555
+ setDropTargetColumnName(null);
1556
+ if (!sourceColumnName || sourceColumnName === column.name) {
1557
+ return;
1558
+ }
1559
+ state.moveVisibleColumn(sourceColumnName, column.name);
1560
+ },
1561
+ [columnMovingFeature, draggedColumnName, state]
1562
+ );
1563
+ const handleHeaderDragEnd = React.useCallback(() => {
1564
+ setDraggedColumnName(null);
1565
+ setDropTargetColumnName(null);
1566
+ }, []);
1567
+ React.useLayoutEffect(() => {
1568
+ setHeaderStickyHeight(headerGridRef.current?.offsetHeight ?? 0);
1569
+ setFilterStickyHeight(filterGridRef.current?.offsetHeight ?? 0);
1570
+ }, [visibleColumns, filteringFeature, options.enableFiltering]);
1571
+ React.useLayoutEffect(() => {
1572
+ const headerElement = headerGridRef.current;
1573
+ const filterElement = filterGridRef.current;
1574
+ if (typeof ResizeObserver === "undefined" || !headerElement && !filterElement) {
1575
+ return;
1576
+ }
1577
+ const observer = new ResizeObserver(() => {
1578
+ setHeaderStickyHeight(headerGridRef.current?.offsetHeight ?? 0);
1579
+ setFilterStickyHeight(filterGridRef.current?.offsetHeight ?? 0);
1580
+ });
1581
+ if (headerElement) {
1582
+ observer.observe(headerElement);
1583
+ }
1584
+ if (filterElement) {
1585
+ observer.observe(filterElement);
1586
+ }
1587
+ return () => observer.disconnect();
1588
+ }, []);
1589
+ React.useEffect(() => {
1590
+ if (!openPinMenuColumn) {
1591
+ return;
1592
+ }
1593
+ const handleDocumentClick = (event) => {
1594
+ if (eventPathIncludesClass(event, "pin-control")) {
1595
+ return;
1596
+ }
1597
+ setOpenPinMenuColumn(null);
1598
+ };
1599
+ const handleDocumentEscape = (event) => {
1600
+ if (event.key === "Escape") {
1601
+ setOpenPinMenuColumn(null);
1602
+ }
1603
+ };
1604
+ document.addEventListener("click", handleDocumentClick);
1605
+ document.addEventListener("keydown", handleDocumentEscape);
1606
+ return () => {
1607
+ document.removeEventListener("click", handleDocumentClick);
1608
+ document.removeEventListener("keydown", handleDocumentEscape);
1609
+ };
1610
+ }, [eventPathIncludesClass, openPinMenuColumn]);
2075
1611
  const itemsToRender = virtualizationEnabled ? displayItems.slice(virtualScroll.visibleRange.start, virtualScroll.visibleRange.end) : displayItems;
2076
- const onViewportScroll = (event) => {
2077
- virtualScroll.onScroll(event);
2078
- const startIndex = Math.floor(event.currentTarget.scrollTop / rowSize);
1612
+ const onGridTableScroll = (event) => {
1613
+ const bodyScrollTop = Math.max(0, event.currentTarget.scrollTop - stickyChromeHeight);
1614
+ virtualScroll.setScrollTop(bodyScrollTop);
1615
+ const startIndex = Math.floor(bodyScrollTop / rowSize);
2079
1616
  state.onViewportScroll(startIndex);
2080
1617
  };
2081
1618
  function renderDisplayItem(item) {
@@ -2169,12 +1706,21 @@ function UiGrid({
2169
1706
  "aria-label": state.treeToggleLabel(rowItem.row),
2170
1707
  "aria-expanded": state.isTreeRowExpanded(rowItem.row),
2171
1708
  onClick: (e) => state.toggleTreeRow(rowItem.row, e),
2172
- children: /* @__PURE__ */ jsx("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx(
2173
- "path",
1709
+ children: /* @__PURE__ */ jsx(
1710
+ "svg",
2174
1711
  {
2175
- d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z"
1712
+ className: "toggle-icon",
1713
+ viewBox: "0 0 24 24",
1714
+ "aria-hidden": "true",
1715
+ focusable: false,
1716
+ children: /* @__PURE__ */ jsx(
1717
+ "path",
1718
+ {
1719
+ d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z"
1720
+ }
1721
+ )
2176
1722
  }
2177
- ) })
1723
+ )
2178
1724
  }
2179
1725
  ),
2180
1726
  expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ jsx(
@@ -2186,7 +1732,16 @@ function UiGrid({
2186
1732
  "aria-label": state.expandToggleLabel(rowItem.row),
2187
1733
  "aria-expanded": rowItem.row.expanded,
2188
1734
  onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
2189
- children: /* @__PURE__ */ jsx("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
1735
+ children: /* @__PURE__ */ jsx(
1736
+ "svg",
1737
+ {
1738
+ className: "toggle-icon",
1739
+ viewBox: "0 0 24 24",
1740
+ "aria-hidden": "true",
1741
+ focusable: false,
1742
+ children: /* @__PURE__ */ jsx("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" })
1743
+ }
1744
+ )
2190
1745
  }
2191
1746
  ),
2192
1747
  /* @__PURE__ */ jsx("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ jsx(
@@ -2315,260 +1870,366 @@ function UiGrid({
2315
1870
  ] }),
2316
1871
  /* @__PURE__ */ jsx("p", { children: "`gridOptions` compatibility layer: sorting, filtering, grouping, column moving, templating, and virtualized rendering." })
2317
1872
  ] }),
2318
- /* @__PURE__ */ jsxs("div", { className: "grid-table ui-grid-contents-wrapper", "data-part": "grid-table", children: [
2319
- /* @__PURE__ */ jsx(
2320
- "div",
2321
- {
2322
- className: "header-grid ui-grid-header ui-grid-header-canvas",
2323
- "data-part": "header",
2324
- role: "row",
2325
- style: { gridTemplateColumns },
2326
- children: visibleColumns.map((column) => {
2327
- const pinned = state.isPinned(column);
2328
- const pinOffset = pinned ? state.pinnedOffset(column) : null;
2329
- return /* @__PURE__ */ jsxs(
2330
- "div",
2331
- {
2332
- className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}${pinned ? " is-pinned" : ""}`,
2333
- "data-part": "header-cell",
2334
- role: "columnheader",
2335
- "aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
2336
- style: {
2337
- position: pinned ? "sticky" : void 0,
2338
- left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2339
- right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2340
- zIndex: pinned ? 2 : void 0
2341
- },
2342
- children: [
2343
- /* @__PURE__ */ jsx("span", { className: "header-label", children: state.headerLabel(column) }),
2344
- /* @__PURE__ */ jsxs("div", { className: "header-actions", children: [
2345
- sortingFeature && /* @__PURE__ */ jsxs(
2346
- "button",
2347
- {
2348
- type: "button",
2349
- className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
2350
- disabled: !state.isColumnSortable(column),
2351
- "aria-label": state.sortButtonLabel(column),
2352
- title: state.sortButtonLabel(column),
2353
- onClick: () => state.toggleSort(column),
2354
- children: [
2355
- renderSortIcon(column),
2356
- /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
2357
- ]
2358
- }
2359
- ),
2360
- groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ jsxs(
2361
- "button",
2362
- {
2363
- type: "button",
2364
- className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
2365
- "data-part": "group-toggle",
2366
- "aria-label": state.groupingButtonLabel(column),
2367
- title: state.groupingButtonLabel(column),
2368
- onClick: (e) => state.toggleGrouping(column, e),
2369
- children: [
2370
- /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
2371
- /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
2372
- ]
2373
- }
2374
- ),
2375
- state.pinningFeature && state.isPinningEnabled() && state.isColumnPinnable(column) && /* @__PURE__ */ jsxs(
2376
- "button",
2377
- {
2378
- type: "button",
2379
- className: `chip-action${pinned ? " chip-action-active" : ""}`,
2380
- "data-part": "pin-toggle",
2381
- "aria-label": pinned ? labels.unpin : labels.pinLeft,
2382
- title: pinned ? labels.unpin : labels.pinLeft,
2383
- onClick: () => state.togglePin(column),
2384
- children: [
2385
- /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M16 12V4h1V2H7v2h1v8l-2 2v2h5v6l1 1 1-1v-6h5v-2l-2-2z" }) }),
2386
- /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: pinned ? labels.unpin : labels.pinLeft })
2387
- ]
1873
+ /* @__PURE__ */ jsxs(
1874
+ "div",
1875
+ {
1876
+ className: "grid-table ui-grid-contents-wrapper",
1877
+ "data-part": "grid-table",
1878
+ style: virtualizationEnabled ? { height: scrollContainerHeight, overflowY: "auto" } : void 0,
1879
+ onScroll: virtualizationEnabled ? onGridTableScroll : void 0,
1880
+ children: [
1881
+ /* @__PURE__ */ jsx(
1882
+ "div",
1883
+ {
1884
+ className: "header-grid ui-grid-header ui-grid-header-canvas",
1885
+ "data-part": "header",
1886
+ role: "row",
1887
+ ref: headerGridRef,
1888
+ style: { gridTemplateColumns },
1889
+ children: visibleColumns.map((column) => {
1890
+ const pinned = state.isPinned(column);
1891
+ const pinOffset = pinned ? state.pinnedOffset(column) : null;
1892
+ const pinMenuOpen = isPinMenuOpen(column);
1893
+ return /* @__PURE__ */ jsxs(
1894
+ "div",
1895
+ {
1896
+ 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" : ""}`,
1897
+ "data-part": "header-cell",
1898
+ role: "columnheader",
1899
+ "aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
1900
+ draggable: columnMovingFeature,
1901
+ onDragStart: (event) => handleHeaderDragStart(column, event),
1902
+ onDragOver: (event) => handleHeaderDragOver(column, event),
1903
+ onDrop: (event) => handleHeaderDrop(column, event),
1904
+ onDragEnd: handleHeaderDragEnd,
1905
+ onDragLeave: () => {
1906
+ if (dropTargetColumnName === column.name) {
1907
+ setDropTargetColumnName(null);
2388
1908
  }
2389
- )
2390
- ] })
2391
- ]
2392
- },
2393
- column.name
2394
- );
2395
- })
2396
- }
2397
- ),
2398
- filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ jsx(
2399
- "div",
2400
- {
2401
- className: "filter-grid ui-grid-header",
2402
- "data-part": "filters",
2403
- style: { gridTemplateColumns },
2404
- children: visibleColumns.map((column) => {
2405
- const pinned = state.isPinned(column);
2406
- const pinOffset = pinned ? state.pinnedOffset(column) : null;
2407
- return /* @__PURE__ */ jsxs(
2408
- "label",
2409
- {
2410
- className: `filter-cell ui-grid-filter-container${pinned ? " is-pinned" : ""}`,
2411
- "data-part": "filter-cell",
2412
- style: {
2413
- position: pinned ? "sticky" : void 0,
2414
- left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2415
- right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2416
- zIndex: pinned ? 2 : void 0
2417
- },
2418
- children: [
2419
- /* @__PURE__ */ jsxs("span", { className: "sr-only ui-grid-sr-only", children: [
2420
- labels.filterColumn,
2421
- " ",
2422
- state.headerLabel(column)
2423
- ] }),
2424
- /* @__PURE__ */ jsx(
2425
- "input",
2426
- {
2427
- className: "ui-grid-filter-input",
2428
- type: "text",
2429
- defaultValue: state.filterValue(column.name),
2430
- placeholder: state.filterPlaceholder(column),
2431
- disabled: state.isFilterInputDisabled(column),
2432
- onChange: (e) => state.updateFilter(column.name, e.target.value)
2433
- }
2434
- )
2435
- ]
2436
- },
2437
- column.name
2438
- );
2439
- })
2440
- }
2441
- ),
2442
- displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ jsx(
2443
- "div",
2444
- {
2445
- className: "grid-viewport ui-grid-viewport",
2446
- "data-part": "viewport",
2447
- ref: virtualScroll.viewportRef,
2448
- style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
2449
- onScroll: onViewportScroll,
2450
- children: /* @__PURE__ */ jsx("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ jsx(
1909
+ },
1910
+ style: {
1911
+ position: pinned ? "sticky" : void 0,
1912
+ left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
1913
+ right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
1914
+ zIndex: pinMenuOpen ? 8 : pinned ? 2 : void 0
1915
+ },
1916
+ children: [
1917
+ /* @__PURE__ */ jsx("span", { className: "header-label", children: state.headerLabel(column) }),
1918
+ /* @__PURE__ */ jsxs("div", { className: "header-actions", children: [
1919
+ sortingFeature && /* @__PURE__ */ jsxs(
1920
+ "button",
1921
+ {
1922
+ type: "button",
1923
+ className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
1924
+ disabled: !state.isColumnSortable(column),
1925
+ "aria-label": state.sortButtonLabel(column),
1926
+ title: state.sortButtonLabel(column),
1927
+ onClick: () => state.toggleSort(column),
1928
+ children: [
1929
+ renderSortIcon(column),
1930
+ /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
1931
+ ]
1932
+ }
1933
+ ),
1934
+ groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ jsxs(
1935
+ "button",
1936
+ {
1937
+ type: "button",
1938
+ className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
1939
+ "data-part": "group-toggle",
1940
+ "aria-label": state.groupingButtonLabel(column),
1941
+ title: state.groupingButtonLabel(column),
1942
+ onClick: (e) => state.toggleGrouping(column, e),
1943
+ children: [
1944
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
1945
+ /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
1946
+ ]
1947
+ }
1948
+ ),
1949
+ state.pinningFeature && state.isPinningEnabled() && state.isColumnPinnable(column) && /* @__PURE__ */ jsxs(
1950
+ "div",
1951
+ {
1952
+ className: `pin-control${pinMenuOpen ? " pin-control-open" : ""}`,
1953
+ onClick: (event) => event.stopPropagation(),
1954
+ children: [
1955
+ /* @__PURE__ */ jsxs(
1956
+ "button",
1957
+ {
1958
+ type: "button",
1959
+ className: `chip-action pin-trigger${pinned || pinMenuOpen ? " chip-action-active" : ""}`,
1960
+ "data-part": "pin-toggle",
1961
+ "aria-label": pinButtonLabel(column),
1962
+ title: pinButtonLabel(column),
1963
+ "aria-haspopup": pinned ? void 0 : "menu",
1964
+ "aria-expanded": pinned ? void 0 : pinMenuOpen,
1965
+ onClick: (event) => onPinTrigger(column, event),
1966
+ children: [
1967
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M16 12V4h1V2H7v2h1v8l-2 2v2h5v6l1 1 1-1v-6h5v-2l-2-2z" }) }),
1968
+ /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: pinButtonLabel(column) })
1969
+ ]
1970
+ }
1971
+ ),
1972
+ /* @__PURE__ */ jsxs(
1973
+ "div",
1974
+ {
1975
+ className: "pin-menu",
1976
+ "data-part": "pin-menu",
1977
+ role: "menu",
1978
+ "aria-label": "Pin options",
1979
+ "aria-hidden": !pinMenuOpen,
1980
+ children: [
1981
+ /* @__PURE__ */ jsxs(
1982
+ "button",
1983
+ {
1984
+ type: "button",
1985
+ className: "pin-menu-action",
1986
+ "data-part": "pin-left-action",
1987
+ role: "menuitem",
1988
+ "aria-label": labels.pinLeft,
1989
+ title: labels.pinLeft,
1990
+ tabIndex: pinMenuOpen ? 0 : -1,
1991
+ onClick: (event) => choosePinDirection(column, "left", event),
1992
+ children: [
1993
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M10 6 4 12l6 6v-4h10v-4H10V6z" }) }),
1994
+ /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: labels.pinLeft })
1995
+ ]
1996
+ }
1997
+ ),
1998
+ /* @__PURE__ */ jsxs(
1999
+ "button",
2000
+ {
2001
+ type: "button",
2002
+ className: "pin-menu-action",
2003
+ "data-part": "pin-right-action",
2004
+ role: "menuitem",
2005
+ "aria-label": labels.pinRight,
2006
+ title: labels.pinRight,
2007
+ tabIndex: pinMenuOpen ? 0 : -1,
2008
+ onClick: (event) => choosePinDirection(column, "right", event),
2009
+ children: [
2010
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M14 6v4H4v4h10v4l6-6-6-6z" }) }),
2011
+ /* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: labels.pinRight })
2012
+ ]
2013
+ }
2014
+ )
2015
+ ]
2016
+ }
2017
+ )
2018
+ ]
2019
+ }
2020
+ )
2021
+ ] })
2022
+ ]
2023
+ },
2024
+ column.name
2025
+ );
2026
+ })
2027
+ }
2028
+ ),
2029
+ filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ jsx(
2451
2030
  "div",
2452
2031
  {
2453
- className: "body-grid ui-grid-canvas",
2454
- "data-part": "body",
2455
- role: "rowgroup",
2032
+ className: "filter-grid ui-grid-header",
2033
+ "data-part": "filters",
2034
+ ref: filterGridRef,
2456
2035
  style: {
2457
2036
  gridTemplateColumns,
2458
- position: "absolute",
2459
- top: 0,
2460
- left: 0,
2461
- right: 0,
2462
- transform: `translateY(${virtualScroll.offsetY}px)`
2037
+ ["--ui-grid-header-sticky-top"]: `${headerStickyHeight}px`
2463
2038
  },
2464
- children: itemsToRender.map(renderDisplayItem)
2039
+ children: visibleColumns.map((column) => {
2040
+ const pinned = state.isPinned(column);
2041
+ const pinOffset = pinned ? state.pinnedOffset(column) : null;
2042
+ return /* @__PURE__ */ jsxs(
2043
+ "label",
2044
+ {
2045
+ className: `filter-cell ui-grid-filter-container${pinned ? " is-pinned" : ""}`,
2046
+ "data-part": "filter-cell",
2047
+ style: {
2048
+ position: pinned ? "sticky" : void 0,
2049
+ left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2050
+ right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2051
+ zIndex: pinned ? 2 : void 0
2052
+ },
2053
+ children: [
2054
+ /* @__PURE__ */ jsxs("span", { className: "sr-only ui-grid-sr-only", children: [
2055
+ labels.filterColumn,
2056
+ " ",
2057
+ state.headerLabel(column)
2058
+ ] }),
2059
+ /* @__PURE__ */ jsx(
2060
+ "input",
2061
+ {
2062
+ className: "ui-grid-filter-input",
2063
+ type: "text",
2064
+ defaultValue: state.filterValue(column.name),
2065
+ placeholder: state.filterPlaceholder(column),
2066
+ disabled: state.isFilterInputDisabled(column),
2067
+ onChange: (e) => state.updateFilter(column.name, e.target.value)
2068
+ }
2069
+ )
2070
+ ]
2071
+ },
2072
+ column.name
2073
+ );
2074
+ })
2465
2075
  }
2466
- ) })
2467
- }
2468
- ) : /* @__PURE__ */ jsx(
2469
- "div",
2470
- {
2471
- className: "body-grid ui-grid-canvas",
2472
- "data-part": "body",
2473
- role: "rowgroup",
2474
- style: { gridTemplateColumns },
2475
- children: displayItems.map(renderDisplayItem)
2476
- }
2477
- ) : /* @__PURE__ */ jsxs("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
2478
- /* @__PURE__ */ jsx("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
2479
- /* @__PURE__ */ jsx("p", { children: labels.emptyDescription })
2480
- ] }),
2481
- paginationFeature && state.showPaginationControls() && /* @__PURE__ */ jsxs(
2482
- "footer",
2483
- {
2484
- className: "pagination-bar ui-grid-pagination",
2485
- "data-part": "pagination",
2486
- role: "navigation",
2487
- "aria-label": labels.paginationPage,
2488
- children: [
2489
- /* @__PURE__ */ jsx("p", { children: state.paginationSummary() }),
2490
- /* @__PURE__ */ jsxs("div", { className: "pagination-controls", children: [
2491
- /* @__PURE__ */ jsxs(
2492
- "button",
2076
+ ),
2077
+ displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ jsx(
2078
+ "div",
2079
+ {
2080
+ className: "grid-virtual-spacer",
2081
+ style: { height: `${virtualScroll.totalHeight}px` },
2082
+ children: /* @__PURE__ */ jsx(
2083
+ "div",
2493
2084
  {
2494
- type: "button",
2495
- className: "action action-secondary pagination-button",
2496
- "aria-label": labels.paginationPrevious,
2497
- disabled: paginationCurrentPage <= 1,
2498
- onClick: () => state.previousPage(),
2499
- children: [
2500
- /* @__PURE__ */ jsx(
2501
- "svg",
2502
- {
2503
- className: "pagination-icon",
2504
- viewBox: "0 0 24 24",
2505
- "aria-hidden": "true",
2506
- focusable: false,
2507
- children: /* @__PURE__ */ jsx("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" })
2508
- }
2509
- ),
2510
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationPrevious })
2511
- ]
2085
+ className: "body-grid ui-grid-canvas grid-virtual-body",
2086
+ "data-part": "body",
2087
+ role: "rowgroup",
2088
+ style: {
2089
+ gridTemplateColumns,
2090
+ position: "absolute",
2091
+ top: `${virtualScroll.offsetY}px`,
2092
+ left: 0
2093
+ },
2094
+ children: itemsToRender.map(renderDisplayItem)
2512
2095
  }
2513
- ),
2514
- /* @__PURE__ */ jsxs("span", { children: [
2515
- labels.paginationPage,
2516
- " ",
2517
- paginationCurrentPage,
2518
- " ",
2519
- labels.paginationOf,
2520
- " ",
2521
- paginationTotalPages
2522
- ] }),
2523
- /* @__PURE__ */ jsxs(
2524
- "button",
2525
- {
2526
- type: "button",
2527
- className: "action action-secondary pagination-button",
2528
- "aria-label": labels.paginationNext,
2529
- disabled: paginationCurrentPage >= paginationTotalPages,
2530
- onClick: () => state.nextPage(),
2531
- children: [
2096
+ )
2097
+ }
2098
+ ) : /* @__PURE__ */ jsx(
2099
+ "div",
2100
+ {
2101
+ className: "body-grid ui-grid-canvas",
2102
+ "data-part": "body",
2103
+ role: "rowgroup",
2104
+ style: { gridTemplateColumns },
2105
+ children: displayItems.map(renderDisplayItem)
2106
+ }
2107
+ ) : /* @__PURE__ */ jsxs("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
2108
+ /* @__PURE__ */ jsx("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
2109
+ /* @__PURE__ */ jsx("p", { children: labels.emptyDescription })
2110
+ ] }),
2111
+ paginationFeature && state.showPaginationControls() && /* @__PURE__ */ jsxs(
2112
+ "footer",
2113
+ {
2114
+ className: "pagination-bar ui-grid-pagination",
2115
+ "data-part": "pagination",
2116
+ role: "navigation",
2117
+ "aria-label": labels.paginationPage,
2118
+ children: [
2119
+ /* @__PURE__ */ jsx("p", { children: state.paginationSummary() }),
2120
+ /* @__PURE__ */ jsxs("div", { className: "pagination-controls", children: [
2121
+ /* @__PURE__ */ jsxs(
2122
+ "button",
2123
+ {
2124
+ type: "button",
2125
+ className: "action action-secondary pagination-button",
2126
+ "aria-label": labels.paginationPrevious,
2127
+ disabled: paginationCurrentPage <= 1,
2128
+ onClick: () => state.previousPage(),
2129
+ children: [
2130
+ /* @__PURE__ */ jsx(
2131
+ "svg",
2132
+ {
2133
+ className: "pagination-icon",
2134
+ viewBox: "0 0 24 24",
2135
+ "aria-hidden": "true",
2136
+ focusable: false,
2137
+ children: /* @__PURE__ */ jsx("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" })
2138
+ }
2139
+ ),
2140
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationPrevious })
2141
+ ]
2142
+ }
2143
+ ),
2144
+ /* @__PURE__ */ jsxs("span", { children: [
2145
+ labels.paginationPage,
2146
+ " ",
2147
+ paginationCurrentPage,
2148
+ " ",
2149
+ labels.paginationOf,
2150
+ " ",
2151
+ paginationTotalPages
2152
+ ] }),
2153
+ /* @__PURE__ */ jsxs(
2154
+ "button",
2155
+ {
2156
+ type: "button",
2157
+ className: "action action-secondary pagination-button",
2158
+ "aria-label": labels.paginationNext,
2159
+ disabled: paginationCurrentPage >= paginationTotalPages,
2160
+ onClick: () => state.nextPage(),
2161
+ children: [
2162
+ /* @__PURE__ */ jsx(
2163
+ "svg",
2164
+ {
2165
+ className: "pagination-icon",
2166
+ viewBox: "0 0 24 24",
2167
+ "aria-hidden": "true",
2168
+ focusable: false,
2169
+ children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" })
2170
+ }
2171
+ ),
2172
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationNext })
2173
+ ]
2174
+ }
2175
+ ),
2176
+ state.pageSizeOptions().length > 0 && /* @__PURE__ */ jsxs("label", { className: "pagination-size", children: [
2177
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationRows }),
2532
2178
  /* @__PURE__ */ jsx(
2533
- "svg",
2179
+ "select",
2534
2180
  {
2535
- className: "pagination-icon",
2536
- viewBox: "0 0 24 24",
2537
- "aria-hidden": "true",
2538
- focusable: false,
2539
- children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" })
2181
+ "aria-label": labels.paginationRows,
2182
+ value: paginationSelectedPageSize,
2183
+ onChange: (e) => state.onPageSizeChange(e.target.value),
2184
+ children: state.pageSizeOptions().map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
2540
2185
  }
2541
- ),
2542
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationNext })
2543
- ]
2544
- }
2545
- ),
2546
- state.pageSizeOptions().length > 0 && /* @__PURE__ */ jsxs("label", { className: "pagination-size", children: [
2547
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationRows }),
2548
- /* @__PURE__ */ jsx(
2549
- "select",
2550
- {
2551
- "aria-label": labels.paginationRows,
2552
- value: paginationSelectedPageSize,
2553
- onChange: (e) => state.onPageSizeChange(e.target.value),
2554
- children: state.pageSizeOptions().map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
2555
- }
2556
- )
2557
- ] })
2558
- ] })
2559
- ]
2560
- }
2561
- )
2562
- ] })
2186
+ )
2187
+ ] })
2188
+ ] })
2189
+ ]
2190
+ }
2191
+ )
2192
+ ]
2193
+ }
2194
+ )
2563
2195
  ]
2564
2196
  }
2565
2197
  )
2566
2198
  ] }) });
2567
2199
  }
2568
2200
 
2201
+ // src/mountUiGrid.tsx
2202
+ import React2 from "react";
2203
+ import { createRoot } from "react-dom/client";
2204
+ function mountUiGrid(container, props) {
2205
+ const root = createRoot(container);
2206
+ root.render(React2.createElement(UiGrid, props));
2207
+ return root;
2208
+ }
2209
+
2210
+ // src/vanillaAdapter.ts
2211
+ async function mountUiGridCustomElement(container, mountOptions) {
2212
+ const tagName = mountOptions.tagName ?? "ui-grid-element";
2213
+ if (mountOptions.ensureDefined) {
2214
+ await mountOptions.ensureDefined(tagName);
2215
+ }
2216
+ const element = document.createElement(tagName);
2217
+ element.options = mountOptions.options;
2218
+ container.replaceChildren(element);
2219
+ return {
2220
+ element,
2221
+ unmount: () => {
2222
+ if (container.firstElementChild === element) {
2223
+ container.replaceChildren();
2224
+ }
2225
+ }
2226
+ };
2227
+ }
2228
+
2569
2229
  // src/rustWasmGridEngine.ts
2570
- import { registerRustWasmGridEngine } from "@ornery/ui-grid";
2571
- var uiGridWasmModulePath = "../../../dist/ui-grid-wasm/ui_grid_wasm.js";
2230
+ import { registerRustWasmGridEngine } from "@ornery/ui-grid-core";
2231
+ var uiGridWasmModulePath = "../../../dist/ui-grid-wasm-web/ui_grid_wasm.js";
2232
+ var uiGridWasmBinaryPath = "/dist/ui-grid-wasm-web/ui_grid_wasm_bg.wasm";
2572
2233
  function registerReactUiGridWasmEngineFromModule(module) {
2573
2234
  registerRustWasmGridEngine({
2574
2235
  buildPipeline(context) {
@@ -2581,11 +2242,12 @@ async function enableReactUiGridWasmEngine() {
2581
2242
  /* @vite-ignore */
2582
2243
  uiGridWasmModulePath
2583
2244
  );
2245
+ await module.default(uiGridWasmBinaryPath);
2584
2246
  registerReactUiGridWasmEngineFromModule(module);
2585
2247
  }
2586
2248
 
2587
2249
  // src/index.ts
2588
- import { DEFAULT_GRID_LABELS } from "@ornery/ui-grid";
2250
+ import { DEFAULT_GRID_LABELS } from "@ornery/ui-grid-core";
2589
2251
  export {
2590
2252
  DEFAULT_GRID_LABELS,
2591
2253
  UiGrid,
@@ -2594,6 +2256,8 @@ export {
2594
2256
  computeViewportRows,
2595
2257
  enableReactUiGridWasmEngine,
2596
2258
  formatPaginationSummary,
2259
+ mountUiGrid,
2260
+ mountUiGridCustomElement,
2597
2261
  orderVisibleColumns,
2598
2262
  registerReactUiGridWasmEngineFromModule,
2599
2263
  resolveBenchmarkIterations,