@cdx-ui/data-grid 0.3.11 → 0.3.13

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 (96) hide show
  1. package/README.md +3 -1
  2. package/coverage.svg +1 -1
  3. package/lib/commonjs/DataGrid.js +490 -81
  4. package/lib/commonjs/DataGrid.js.map +1 -1
  5. package/lib/commonjs/DataGridFilterPanel.js +547 -0
  6. package/lib/commonjs/DataGridFilterPanel.js.map +1 -0
  7. package/lib/commonjs/adapter/columnTypes.js +256 -0
  8. package/lib/commonjs/adapter/columnTypes.js.map +1 -0
  9. package/lib/commonjs/adapter/columns.js +140 -4
  10. package/lib/commonjs/adapter/columns.js.map +1 -1
  11. package/lib/commonjs/adapter/filterOperators.js +422 -0
  12. package/lib/commonjs/adapter/filterOperators.js.map +1 -0
  13. package/lib/commonjs/adapter/pinning.js +105 -0
  14. package/lib/commonjs/adapter/pinning.js.map +1 -0
  15. package/lib/commonjs/adapter/selectColumn.js +11 -0
  16. package/lib/commonjs/adapter/selectColumn.js.map +1 -1
  17. package/lib/commonjs/adapter/treeData.js +195 -0
  18. package/lib/commonjs/adapter/treeData.js.map +1 -0
  19. package/lib/commonjs/index.js +26 -0
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/numberCells.js +280 -0
  22. package/lib/commonjs/numberCells.js.map +1 -0
  23. package/lib/commonjs/styles.js +107 -1
  24. package/lib/commonjs/styles.js.map +1 -1
  25. package/lib/commonjs/types.js +39 -1
  26. package/lib/commonjs/types.js.map +1 -1
  27. package/lib/commonjs/useDataGridTable.js +234 -18
  28. package/lib/commonjs/useDataGridTable.js.map +1 -1
  29. package/lib/module/DataGrid.js +497 -88
  30. package/lib/module/DataGrid.js.map +1 -1
  31. package/lib/module/DataGridFilterPanel.js +540 -0
  32. package/lib/module/DataGridFilterPanel.js.map +1 -0
  33. package/lib/module/adapter/columnTypes.js +240 -0
  34. package/lib/module/adapter/columnTypes.js.map +1 -0
  35. package/lib/module/adapter/columns.js +137 -4
  36. package/lib/module/adapter/columns.js.map +1 -1
  37. package/lib/module/adapter/filterOperators.js +406 -0
  38. package/lib/module/adapter/filterOperators.js.map +1 -0
  39. package/lib/module/adapter/pinning.js +94 -0
  40. package/lib/module/adapter/pinning.js.map +1 -0
  41. package/lib/module/adapter/selectColumn.js +11 -1
  42. package/lib/module/adapter/selectColumn.js.map +1 -1
  43. package/lib/module/adapter/treeData.js +187 -0
  44. package/lib/module/adapter/treeData.js.map +1 -0
  45. package/lib/module/index.js +2 -0
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/numberCells.js +275 -0
  48. package/lib/module/numberCells.js.map +1 -0
  49. package/lib/module/styles.js +106 -0
  50. package/lib/module/styles.js.map +1 -1
  51. package/lib/module/types.js +38 -0
  52. package/lib/module/types.js.map +1 -1
  53. package/lib/module/useDataGridTable.js +238 -22
  54. package/lib/module/useDataGridTable.js.map +1 -1
  55. package/lib/typescript/DataGrid.d.ts.map +1 -1
  56. package/lib/typescript/DataGridFilterPanel.d.ts +52 -0
  57. package/lib/typescript/DataGridFilterPanel.d.ts.map +1 -0
  58. package/lib/typescript/adapter/columnTypes.d.ts +32 -0
  59. package/lib/typescript/adapter/columnTypes.d.ts.map +1 -0
  60. package/lib/typescript/adapter/columns.d.ts +14 -5
  61. package/lib/typescript/adapter/columns.d.ts.map +1 -1
  62. package/lib/typescript/adapter/filterOperators.d.ts +43 -0
  63. package/lib/typescript/adapter/filterOperators.d.ts.map +1 -0
  64. package/lib/typescript/adapter/pinning.d.ts +26 -0
  65. package/lib/typescript/adapter/pinning.d.ts.map +1 -0
  66. package/lib/typescript/adapter/selectColumn.d.ts +8 -0
  67. package/lib/typescript/adapter/selectColumn.d.ts.map +1 -1
  68. package/lib/typescript/adapter/treeData.d.ts +36 -0
  69. package/lib/typescript/adapter/treeData.d.ts.map +1 -0
  70. package/lib/typescript/index.d.ts +4 -1
  71. package/lib/typescript/index.d.ts.map +1 -1
  72. package/lib/typescript/numberCells.d.ts +46 -0
  73. package/lib/typescript/numberCells.d.ts.map +1 -0
  74. package/lib/typescript/styles.d.ts +32 -0
  75. package/lib/typescript/styles.d.ts.map +1 -1
  76. package/lib/typescript/types.d.ts +154 -7
  77. package/lib/typescript/types.d.ts.map +1 -1
  78. package/lib/typescript/useDataGridTable.d.ts +40 -4
  79. package/lib/typescript/useDataGridTable.d.ts.map +1 -1
  80. package/package.json +5 -5
  81. package/src/DataGrid.tsx +745 -95
  82. package/src/DataGridFilterPanel.tsx +648 -0
  83. package/src/adapter/columnTypes.ts +327 -0
  84. package/src/adapter/columns.test.ts +75 -1
  85. package/src/adapter/columns.ts +192 -3
  86. package/src/adapter/filterOperators.test.ts +292 -0
  87. package/src/adapter/filterOperators.ts +524 -0
  88. package/src/adapter/pinning.ts +134 -0
  89. package/src/adapter/selectColumn.ts +12 -1
  90. package/src/adapter/treeData.ts +228 -0
  91. package/src/index.ts +19 -0
  92. package/src/numberCells.tsx +379 -0
  93. package/src/styles.ts +131 -0
  94. package/src/types.ts +190 -7
  95. package/src/useDataGridTable.test.ts +69 -0
  96. package/src/useDataGridTable.ts +338 -17
@@ -11,16 +11,23 @@ var _icons = require("@cdx-ui/icons");
11
11
  var _primitives = require("@cdx-ui/primitives");
12
12
  var _utils = require("@cdx-ui/utils");
13
13
  var _columns = require("./adapter/columns");
14
+ var _pinning = require("./adapter/pinning");
15
+ var _columnTypes = require("./adapter/columnTypes");
16
+ var _DataGridFilterPanel = require("./DataGridFilterPanel");
14
17
  var _styles = require("./styles");
15
18
  var _types = require("./types");
16
19
  var _useDataGridTable = require("./useDataGridTable");
17
20
  var _jsxRuntime = require("react/jsx-runtime");
18
21
  const MAX_SKELETON_ROW_COUNT = 10;
22
+ /** Matches the detail panel cell's `px-4`. */
23
+ const DETAIL_PANEL_INSET = 16;
24
+ const TREE_INDENT = 24;
19
25
  const DEFAULT_WEB_COLUMN_WIDTH = 100;
20
- const SELECT_COLUMN_WIDTH = 56;
21
26
  const WEB_TABLE_CONTAINER_STYLE = {
22
27
  overflow: 'visible'
23
28
  };
29
+ // Same token as the pinned cells' `border-stroke-secondary` divider.
30
+ const PINNED_EDGE_COLOR = 'var(--color-stroke-secondary)';
24
31
  function cellStyle(col, webWidth) {
25
32
  if (!col) {
26
33
  return undefined;
@@ -43,36 +50,96 @@ function cellStyle(col, webWidth) {
43
50
  }
44
51
  return Object.keys(style).length > 0 ? style : undefined;
45
52
  }
46
- function webColumnWidths(columns, checkboxSelection) {
47
- const totalFlex = columns.reduce((total, column) => total + Math.max(column.flex ?? 0, 0), 0);
53
+ function effectiveFlex(column, pinned) {
54
+ if (pinned.has(column.field)) {
55
+ return 0;
56
+ }
57
+ return Math.max(column.flex ?? 0, 0);
58
+ }
59
+ function webColumnWidths(columns, leadingWidth, pinned = new Set()) {
60
+ const totalFlex = columns.reduce((total, column) => total + effectiveFlex(column, pinned), 0);
48
61
  const widths = new Map();
49
62
  if (totalFlex === 0) {
50
63
  for (const column of columns) {
51
- if (column.width !== undefined) {
64
+ if (pinned.has(column.field)) {
65
+ widths.set(column.field, Math.max(column.width ?? _pinning.DEFAULT_PINNED_COLUMN_WIDTH, column.minWidth ?? 0));
66
+ } else if (column.width !== undefined) {
52
67
  widths.set(column.field, column.width);
53
68
  }
54
69
  }
55
70
  return widths;
56
71
  }
57
- const fixedWidth = (checkboxSelection ? SELECT_COLUMN_WIDTH : 0) + columns.reduce((total, column) => {
58
- if ((column.flex ?? 0) > 0) {
72
+ const fixedWidth = leadingWidth + columns.reduce((total, column) => {
73
+ if (effectiveFlex(column, pinned) > 0) {
59
74
  return total;
60
75
  }
61
- return total + Math.max(column.width ?? DEFAULT_WEB_COLUMN_WIDTH, column.minWidth ?? 0);
76
+ const fallback = pinned.has(column.field) ? _pinning.DEFAULT_PINNED_COLUMN_WIDTH : DEFAULT_WEB_COLUMN_WIDTH;
77
+ return total + Math.max(column.width ?? fallback, column.minWidth ?? 0);
62
78
  }, 0);
63
79
  for (const column of columns) {
64
- if ((column.flex ?? 0) > 0) {
65
- const share = (column.flex ?? 0) / totalFlex;
80
+ const flex = effectiveFlex(column, pinned);
81
+ if (flex > 0) {
82
+ const share = flex / totalFlex;
66
83
  const percentage = share * 100;
67
84
  const fixedShare = fixedWidth * share;
68
85
  const width = `calc(${percentage.toString()}% - ${fixedShare.toString()}px)`;
69
86
  widths.set(column.field, column.minWidth === undefined ? width : `max(${column.minWidth.toString()}px, ${width})`);
70
87
  } else {
71
- widths.set(column.field, Math.max(column.width ?? DEFAULT_WEB_COLUMN_WIDTH, column.minWidth ?? 0));
88
+ const fallback = pinned.has(column.field) ? _pinning.DEFAULT_PINNED_COLUMN_WIDTH : DEFAULT_WEB_COLUMN_WIDTH;
89
+ widths.set(column.field, Math.max(column.width ?? fallback, column.minWidth ?? 0));
72
90
  }
73
91
  }
74
92
  return widths;
75
93
  }
94
+ function pinMetaFor(columnId, pinning) {
95
+ const startIndex = pinning.start.indexOf(columnId);
96
+ if (startIndex >= 0) {
97
+ return {
98
+ edge: 'start',
99
+ isEdgeDivider: startIndex === pinning.start.length - 1
100
+ };
101
+ }
102
+ const endIndex = pinning.end.indexOf(columnId);
103
+ if (endIndex >= 0) {
104
+ return {
105
+ edge: 'end',
106
+ isEdgeDivider: endIndex === 0
107
+ };
108
+ }
109
+ return {
110
+ edge: false,
111
+ isEdgeDivider: false
112
+ };
113
+ }
114
+ function mergePinnedStyle(base, pin, offsets, columnId, isHeader) {
115
+ if (!pin.edge || offsets == null) {
116
+ return base;
117
+ }
118
+ const offset = pin.edge === 'start' ? offsets.start.get(columnId) ?? 0 : offsets.end.get(columnId) ?? 0;
119
+ return {
120
+ ...base,
121
+ ...(0, _pinning.pinnedCellStyle)(pin.edge, offset, isHeader)
122
+ };
123
+ }
124
+ function pinnedClassName(pin, isHeader) {
125
+ if (!pin.edge) {
126
+ return undefined;
127
+ }
128
+ return (0, _utils.cn)((0, _styles.dataGridPinnedSurfaceVariants)({
129
+ header: isHeader
130
+ }), (0, _styles.dataGridPinnedEdgeVariants)({
131
+ edge: pin.isEdgeDivider ? pin.edge : 'none'
132
+ }));
133
+ }
134
+ function BooleanCell({
135
+ value
136
+ }) {
137
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Icon, {
138
+ as: value ? _icons.Check : _icons.Close,
139
+ accessibilityLabel: value ? 'Yes' : 'No',
140
+ className: "size-5"
141
+ });
142
+ }
76
143
  function defaultCellContent(value) {
77
144
  if (value == null) {
78
145
  return '';
@@ -92,30 +159,52 @@ function defaultCellContent(value) {
92
159
  }
93
160
  function DefaultLoadingRows({
94
161
  columns,
95
- checkboxSelection,
162
+ leadingColumnIds,
96
163
  rowCount,
97
- columnWidths
164
+ columnWidths,
165
+ orderedColumnIds,
166
+ pinning,
167
+ offsets
98
168
  }) {
169
+ const colByField = new Map(columns.map(column => [column.field, column]));
170
+ const ids = orderedColumnIds ?? [...leadingColumnIds, ...columns.map(column => column.field)];
99
171
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
100
172
  children: Array.from({
101
173
  length: rowCount
102
- }, (_, rowIndex) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Table.Row, {
174
+ }, (_, rowIndex) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
103
175
  className: "pointer-events-none web:hover:bg-surface-primary",
104
176
  testID: rowIndex === 0 ? 'data-grid-default-loading-rows' : undefined,
105
- children: [checkboxSelection ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
106
- align: "center",
107
- className: (0, _styles.dataGridSelectCellVariants)(),
108
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Skeleton, {
109
- className: "size-5"
110
- })
111
- }) : null, columns.map(column => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
112
- align: (0, _columns.normalizeGridAlignment)(column.align),
113
- className: (0, _styles.dataGridCellVariants)(),
114
- style: cellStyle(column, columnWidths.get(column.field)),
115
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Skeleton, {
116
- className: "h-4 w-3/5"
117
- })
118
- }, column.field))]
177
+ children: ids.map(columnId => {
178
+ const pin = pinMetaFor(columnId, pinning);
179
+ if (columnId === _types.SELECT_COLUMN_ID) {
180
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
181
+ align: "center",
182
+ className: (0, _utils.cn)((0, _styles.dataGridSelectCellVariants)(), pinnedClassName(pin, false)),
183
+ style: mergePinnedStyle(undefined, pin, offsets, columnId, false),
184
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Skeleton, {
185
+ className: "size-5"
186
+ })
187
+ }, columnId);
188
+ }
189
+ if (columnId === _types.DETAIL_PANEL_TOGGLE_ID) {
190
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
191
+ className: (0, _utils.cn)((0, _styles.dataGridDetailToggleCellVariants)(), pinnedClassName(pin, false)),
192
+ style: mergePinnedStyle(undefined, pin, offsets, columnId, false)
193
+ }, columnId);
194
+ }
195
+ const column = colByField.get(columnId);
196
+ if (!column) {
197
+ return null;
198
+ }
199
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
200
+ align: (0, _columns.resolveColumnAlign)(column),
201
+ className: (0, _utils.cn)((0, _styles.dataGridCellVariants)(), pinnedClassName(pin, false)),
202
+ style: mergePinnedStyle(cellStyle(column, columnWidths.get(column.field)), pin, offsets, column.field, false),
203
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Skeleton, {
204
+ className: "h-4 w-3/5"
205
+ })
206
+ }, column.field);
207
+ })
119
208
  }, rowIndex))
120
209
  });
121
210
  }
@@ -148,6 +237,8 @@ function DataGridInner(props) {
148
237
  rowCount,
149
238
  showToolbar = false,
150
239
  headerFilters = false,
240
+ pinnedColumns,
241
+ columnVisibilityModel,
151
242
  pageSizeOptions = _types.DEFAULT_PAGE_SIZE_OPTIONS,
152
243
  noRowsOverlay,
153
244
  loadingOverlay,
@@ -156,8 +247,49 @@ function DataGridInner(props) {
156
247
  style,
157
248
  label,
158
249
  'aria-label': ariaLabel,
159
- 'aria-labelledby': ariaLabelledBy
250
+ 'aria-labelledby': ariaLabelledBy,
251
+ treeData = false,
252
+ getTreeDataPath,
253
+ groupingColDef,
254
+ defaultGroupingExpansionDepth,
255
+ isGroupExpandedByDefault,
256
+ rowSelectionPropagation,
257
+ getDetailPanelContent
160
258
  } = props;
259
+ const treeActive = treeData && getTreeDataPath !== undefined;
260
+ const isColumnVisible = (0, _react.useCallback)(column => columnVisibilityModel?.[column.field] !== false, [columnVisibilityModel]);
261
+ const treeField = treeActive ? columns.find(isColumnVisible)?.field : undefined;
262
+ const gridColumns = (0, _react.useMemo)(() => {
263
+ if (treeField === undefined || groupingColDef === undefined) {
264
+ return columns;
265
+ }
266
+ return columns.map(column => column.field === treeField ? {
267
+ ...column,
268
+ ...groupingColDef,
269
+ field: column.field
270
+ } : column);
271
+ }, [columns, groupingColDef, treeField]);
272
+ const visibleColumns = (0, _react.useMemo)(() => gridColumns.filter(isColumnVisible), [gridColumns, isColumnVisible]);
273
+ const selectColumn = checkboxSelection && !treeActive;
274
+ const treeCheckbox = checkboxSelection && treeActive;
275
+ const detailPanel = getDetailPanelContent !== undefined;
276
+ const leadingColumnIds = (0, _react.useMemo)(() => [...(selectColumn ? [_types.SELECT_COLUMN_ID] : []), ...(detailPanel ? [_types.DETAIL_PANEL_TOGGLE_ID] : [])], [detailPanel, selectColumn]);
277
+ const leadingWidth = (selectColumn ? _pinning.SELECT_COLUMN_WIDTH : 0) + (detailPanel ? _pinning.DETAIL_PANEL_TOGGLE_WIDTH : 0);
278
+ const [detailPanelExpandedRowIds, setDetailPanelExpandedRowIds] = (0, _utils.useControllableState)({
279
+ prop: props.detailPanelExpandedRowIds,
280
+ defaultProp: props.defaultDetailPanelExpandedRowIds ?? _types.EMPTY_ROW_ID_SET,
281
+ onChange: ids => props.onDetailPanelExpandedRowIdsChange?.(new Set(ids))
282
+ });
283
+ const resolvedDetailIds = detailPanelExpandedRowIds ?? _types.EMPTY_ROW_ID_SET;
284
+ const toggleDetailPanel = id => {
285
+ const next = new Set(resolvedDetailIds);
286
+ if (next.has(id)) {
287
+ next.delete(id);
288
+ } else {
289
+ next.add(id);
290
+ }
291
+ setDetailPanelExpandedRowIds(next);
292
+ };
161
293
  const [sortModel, setSortModel] = (0, _utils.useControllableState)({
162
294
  prop: props.sortModel,
163
295
  defaultProp: props.defaultSortModel ?? [],
@@ -173,6 +305,11 @@ function DataGridInner(props) {
173
305
  defaultProp: props.defaultFilterModel ?? [],
174
306
  onChange: props.onFilterModelChange
175
307
  });
308
+ const [filterLogicOperator, setFilterLogicOperator] = (0, _utils.useControllableState)({
309
+ prop: props.filterLogicOperator,
310
+ defaultProp: props.defaultFilterLogicOperator ?? 'and',
311
+ onChange: props.onFilterLogicOperatorChange
312
+ });
176
313
  const [quickFilter, setQuickFilter] = (0, _utils.useControllableState)({
177
314
  prop: props.quickFilter,
178
315
  defaultProp: props.defaultQuickFilter ?? '',
@@ -186,16 +323,29 @@ function DataGridInner(props) {
186
323
  const resolvedSortModel = sortModel ?? [];
187
324
  const resolvedPagination = paginationModel ?? _types.DEFAULT_PAGINATION_MODEL;
188
325
  const resolvedFilterModel = filterModel ?? [];
326
+ const resolvedFilterLogicOperator = filterLogicOperator ?? 'and';
189
327
  const resolvedQuickFilter = quickFilter ?? '';
190
328
  const resolvedSelection = rowSelectionModel ?? _types.EMPTY_SELECTION;
329
+ const knownFields = (0, _react.useMemo)(() => new Set(columns.map(column => column.field)), [columns]);
330
+ const columnPinning = (0, _react.useMemo)(() => (0, _columns.normalizePinnedColumns)(pinnedColumns, knownFields, selectColumn, detailPanel), [pinnedColumns, knownFields, selectColumn, detailPanel]);
331
+ const pinningActive = (0, _pinning.isColumnPinningActive)(columnPinning);
332
+ const pinnedFields = (0, _react.useMemo)(() => (0, _pinning.pinnedFieldSet)(columnPinning), [columnPinning]);
191
333
  const {
192
334
  table,
193
335
  setQuickFilter: setQuickFilterWithPageReset,
194
- setColumnFilter
336
+ setColumnFilter,
337
+ setFilterModel: setFilterModelWithPageReset,
338
+ tree
195
339
  } = (0, _useDataGridTable.useDataGridTable)({
196
340
  rows,
197
- columns,
341
+ columns: gridColumns,
198
342
  getRowId,
343
+ detailPanel,
344
+ treeData: treeActive,
345
+ getTreeDataPath,
346
+ defaultGroupingExpansionDepth,
347
+ isGroupExpandedByDefault,
348
+ rowSelectionPropagation,
199
349
  checkboxSelection,
200
350
  disableColumnSorting,
201
351
  paginationMode,
@@ -208,25 +358,52 @@ function DataGridInner(props) {
208
358
  onPaginationModelChange: model => setPaginationModel(model),
209
359
  filterModel: resolvedFilterModel,
210
360
  onFilterModelChange: model => setFilterModel(model),
361
+ filterLogicOperator: resolvedFilterLogicOperator,
211
362
  quickFilter: resolvedQuickFilter,
212
363
  onQuickFilterChange: value => setQuickFilter(value),
213
364
  rowSelectionModel: resolvedSelection,
214
- onRowSelectionModelChange: model => setRowSelectionModel(model)
365
+ onRowSelectionModelChange: model => setRowSelectionModel(model),
366
+ columnPinning,
367
+ columnVisibility: columnVisibilityModel
215
368
  });
216
369
  const colByField = (0, _react.useMemo)(() => {
217
370
  const map = new Map();
218
- for (const col of columns) {
371
+ for (const col of gridColumns) {
219
372
  map.set(col.field, col);
220
373
  }
221
374
  return map;
222
- }, [columns]);
223
- const columnWidths = (0, _react.useMemo)(() => webColumnWidths(columns, checkboxSelection), [checkboxSelection, columns]);
224
- const hasFlexColumns = (0, _react.useMemo)(() => columns.some(column => (column.flex ?? 0) > 0), [columns]);
375
+ }, [gridColumns]);
376
+ (0, _pinning.warnPinnedFlexColumns)(visibleColumns, pinnedFields);
377
+ const columnWidths = (0, _react.useMemo)(() => webColumnWidths(visibleColumns, leadingWidth, pinnedFields), [leadingWidth, visibleColumns, pinnedFields]);
378
+ const hasFlexColumns = (0, _react.useMemo)(() => visibleColumns.some(column => effectiveFlex(column, pinnedFields) > 0), [visibleColumns, pinnedFields]);
379
+ const pinnedOffsets = (0, _react.useMemo)(() => pinningActive ? (0, _pinning.buildPinnedOffsets)(columnPinning, colByField) : null, [pinningActive, columnPinning, colByField]);
380
+ const orderedLeafColumnIds = (0, _react.useMemo)(() => {
381
+ if (!pinningActive) {
382
+ return undefined;
383
+ }
384
+ return [...table.getStartVisibleLeafColumns().map(column => column.id), ...table.getCenterVisibleLeafColumns().map(column => column.id), ...table.getEndVisibleLeafColumns().map(column => column.id)];
385
+ }, [pinningActive, table]);
386
+ const isEmpty = !loading && rows.length === 0;
387
+ const mainScrollStyle = (0, _react.useMemo)(() => {
388
+ if (!pinningActive || pinnedOffsets == null) {
389
+ return undefined;
390
+ }
391
+ const guides = _reactNative.Platform.OS === 'web' && !isEmpty ? (0, _pinning.pinnedEdgeGuidesImage)(pinnedOffsets, PINNED_EDGE_COLOR, _reactNative.I18nManager.isRTL) : undefined;
392
+ // Logical scroll-padding keeps focused cells out from under pinned edges (web).
393
+ return {
394
+ scrollPaddingInlineStart: pinnedOffsets.startTotal,
395
+ scrollPaddingInlineEnd: pinnedOffsets.endTotal,
396
+ ...(guides ? {
397
+ backgroundImage: guides,
398
+ backgroundRepeat: 'no-repeat'
399
+ } : {})
400
+ };
401
+ }, [pinningActive, pinnedOffsets, isEmpty]);
225
402
  const visibleRows = table.getRowModel().rows;
226
403
  const pageCount = Math.max(table.getPageCount(), 1);
227
404
  const selectedCount = table.getFilteredSelectedRowModel().rows.length;
228
405
  const filterableCount = table.getFilteredRowModel().rows.length;
229
- const headerSelectState = selectedCount === 0 ? {
406
+ const headerSelectState = tree?.headerSelection ?? (selectedCount === 0 ? {
230
407
  checked: false,
231
408
  indeterminate: false
232
409
  } : selectedCount === filterableCount ? {
@@ -235,16 +412,74 @@ function DataGridInner(props) {
235
412
  } : {
236
413
  checked: false,
237
414
  indeterminate: true
238
- };
415
+ });
416
+ const leafColumnCount = table.getVisibleLeafColumns().length;
239
417
  const accessibleName = ariaLabel ?? label;
240
- const isEmpty = !loading && rows.length === 0;
241
418
  const totalCount = paginationMode === 'server' ? rowCount ?? rows.length : filterableCount;
242
- const filterValueFor = field => resolvedFilterModel.find(item => item.field === field)?.value ?? '';
419
+ const filterValueFor = field => {
420
+ const value = resolvedFilterModel.find(item => item.field === field)?.value;
421
+ return typeof value === 'string' ? value : '';
422
+ };
243
423
  const showToolbarBar = showToolbar || toolbarActions != null;
424
+ const filterPanelColumns = (0, _react.useMemo)(() => gridColumns.filter(column => column.filterable !== false), [gridColumns]);
425
+ // Header filter cells and the column menu open the panel through `filterPanel.openForField`.
426
+ const filterPanel = (0, _DataGridFilterPanel.useDataGridFilterPanel)({
427
+ columns: filterPanelColumns,
428
+ filterModel: resolvedFilterModel,
429
+ onFilterModelChange: setFilterModel
430
+ });
431
+ const filterPanelOpen = filterPanel.opener !== null && filterPanelColumns.length > 0;
432
+ const filterPanelAnchored = filterPanel.opener?.field !== undefined;
433
+ const filterPanelButtonRef = (0, _react.useRef)(null);
434
+ const showFilterPanelButton = showToolbar && filterPanelColumns.length > 0;
435
+ const mainRef = (0, _react.useRef)(null);
436
+ const [viewportWidth, setViewportWidth] = (0, _react.useState)(undefined);
437
+ (0, _react.useEffect)(() => {
438
+ const main = mainRef.current;
439
+ if (_reactNative.Platform.OS !== 'web' || !detailPanel || main === null || typeof ResizeObserver === 'undefined') {
440
+ return undefined;
441
+ }
442
+ const observer = new ResizeObserver(() => setViewportWidth(main.clientWidth));
443
+ observer.observe(main);
444
+ return () => observer.disconnect();
445
+ }, [detailPanel]);
446
+ const detailPanelContentStyle = (0, _react.useMemo)(() => viewportWidth === undefined ? undefined : {
447
+ position: 'sticky',
448
+ insetInlineStart: DETAIL_PANEL_INSET,
449
+ width: viewportWidth - DETAIL_PANEL_INSET * 2
450
+ }, [viewportWidth]);
451
+ const rootRef = (0, _react.useRef)(null);
452
+ const searchRef = (0, _react.useRef)(null);
453
+ const bodyFocusRef = (0, _react.useRef)(null);
454
+ (0, _react.useEffect)(() => {
455
+ if (_reactNative.Platform.OS !== 'web') {
456
+ return undefined;
457
+ }
458
+ const root = rootRef.current;
459
+ const onFocusIn = event => {
460
+ const target = event.target instanceof Element ? event.target : null;
461
+ bodyFocusRef.current = target !== null && root?.contains(target.closest('tbody')) === true ? target : null;
462
+ };
463
+ document.addEventListener('focusin', onFocusIn);
464
+ return () => document.removeEventListener('focusin', onFocusIn);
465
+ }, []);
466
+ // Only when the focused row control was removed: focus that left the grid stays where it went.
467
+ (0, _react.useEffect)(() => {
468
+ const focused = bodyFocusRef.current;
469
+ if (_reactNative.Platform.OS !== 'web' || focused === null || focused.isConnected) {
470
+ return;
471
+ }
472
+ bodyFocusRef.current = null;
473
+ const active = document.activeElement;
474
+ if (active === null || active === document.body) {
475
+ searchRef.current?.focus();
476
+ }
477
+ }, [visibleRows]);
244
478
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
479
+ ref: rootRef,
245
480
  className: (0, _utils.cn)((0, _styles.dataGridRootVariants)({
246
481
  autoHeight
247
- }), className),
482
+ }), className, filterPanelOpen && !filterPanelAnchored && 'overflow-visible'),
248
483
  style: style,
249
484
  ...(0, _primitives.mergeDataAttributes)({}, (0, _primitives.dataAttributes)({
250
485
  slot: 'data-grid'
@@ -257,20 +492,50 @@ function DataGridInner(props) {
257
492
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Input.Icon, {
258
493
  as: _icons.Search
259
494
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Input.Field, {
495
+ ref: searchRef,
260
496
  value: resolvedQuickFilter,
261
497
  onChangeText: setQuickFilterWithPageReset,
262
498
  placeholder: "Search",
263
499
  accessibilityLabel: "Search"
264
500
  })]
501
+ }) : null, showFilterPanelButton ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
502
+ ref: filterPanelButtonRef,
503
+ as: _icons.FilterList,
504
+ variant: "ghost",
505
+ color: "neutral",
506
+ size: "small",
507
+ accessibilityLabel: "Filters",
508
+ accessibilityState: {
509
+ expanded: filterPanelOpen
510
+ },
511
+ onPress: () => filterPanel.toggle(filterPanelButtonRef)
265
512
  }) : null, toolbarActions ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
266
513
  className: (0, _styles.dataGridToolbarActionsVariants)(),
267
514
  children: toolbarActions
268
515
  }) : null]
516
+ }) : null, filterPanelOpen && filterPanel.opener ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataGridFilterPanel.DataGridFilterPanel, {
517
+ columns: filterPanelColumns,
518
+ filterModel: resolvedFilterModel,
519
+ onFilterModelChange: setFilterModelWithPageReset,
520
+ logicOperator: resolvedFilterLogicOperator,
521
+ onLogicOperatorChange: operator => {
522
+ setFilterLogicOperator(operator);
523
+ if (resolvedPagination.page !== 0) {
524
+ setPaginationModel({
525
+ ...resolvedPagination,
526
+ page: 0
527
+ });
528
+ }
529
+ },
530
+ onClose: filterPanel.close,
531
+ opener: filterPanel.opener
269
532
  }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
533
+ ref: mainRef,
270
534
  className: (0, _styles.dataGridMainVariants)({
271
535
  autoHeight,
272
536
  overlay: isEmpty || loading && loadingOverlay != null
273
537
  }),
538
+ style: mainScrollStyle,
274
539
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Table, {
275
540
  className: (0, _utils.cn)((0, _styles.dataGridTableVariants)(), _reactNative.Platform.OS === 'web' && hasFlexColumns ? 'table-fixed' : undefined),
276
541
  containerStyle: _reactNative.Platform.OS === 'web' ? WEB_TABLE_CONTAINER_STYLE : undefined,
@@ -282,25 +547,34 @@ function DataGridInner(props) {
282
547
  } : {}),
283
548
  children: [label ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Caption, {
284
549
  children: label
285
- }) : null, _reactNative.Platform.OS === 'web' && hasFlexColumns ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("colgroup", {
286
- children: [checkboxSelection ? /*#__PURE__*/(0, _jsxRuntime.jsx)("col", {
550
+ }) : null, _reactNative.Platform.OS === 'web' && hasFlexColumns ? /*#__PURE__*/(0, _jsxRuntime.jsx)("colgroup", {
551
+ children: (orderedLeafColumnIds ?? [...leadingColumnIds, ...visibleColumns.map(column => column.field)]).map(columnId => columnId === _types.SELECT_COLUMN_ID ? /*#__PURE__*/(0, _jsxRuntime.jsx)("col", {
552
+ style: {
553
+ width: _pinning.SELECT_COLUMN_WIDTH
554
+ }
555
+ }, columnId) : columnId === _types.DETAIL_PANEL_TOGGLE_ID ? /*#__PURE__*/(0, _jsxRuntime.jsx)("col", {
287
556
  style: {
288
- width: SELECT_COLUMN_WIDTH
557
+ width: _pinning.DETAIL_PANEL_TOGGLE_WIDTH
289
558
  }
290
- }) : null, columns.map(column => /*#__PURE__*/(0, _jsxRuntime.jsx)("col", {
559
+ }, columnId) : /*#__PURE__*/(0, _jsxRuntime.jsx)("col", {
291
560
  style: {
292
- width: columnWidths.get(column.field),
293
- minWidth: column.minWidth
561
+ width: columnWidths.get(columnId),
562
+ minWidth: colByField.get(columnId)?.minWidth
294
563
  }
295
- }, column.field))]
564
+ }, columnId))
296
565
  }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Table.Header, {
297
566
  className: (0, _styles.dataGridHeaderVariants)(),
298
- children: [table.getHeaderGroups().map(headerGroup => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
567
+ children: [(pinningActive ? [{
568
+ id: 'pinned',
569
+ headers: [...table.getStartLeafHeaders(), ...table.getCenterLeafHeaders(), ...table.getEndLeafHeaders()]
570
+ }] : table.getHeaderGroups()).map(headerGroup => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
299
571
  children: headerGroup.headers.map(header => {
572
+ const pin = pinMetaFor(header.column.id, columnPinning);
300
573
  if (header.id === _types.SELECT_COLUMN_ID) {
301
574
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Head, {
302
575
  align: "center",
303
- className: (0, _styles.dataGridSelectHeadVariants)(),
576
+ className: (0, _utils.cn)((0, _styles.dataGridSelectHeadVariants)(), pinnedClassName(pin, true)),
577
+ style: mergePinnedStyle(undefined, pin, pinnedOffsets, header.id, true),
304
578
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Checkbox, {
305
579
  value: "select-all",
306
580
  isChecked: headerSelectState.checked,
@@ -311,10 +585,17 @@ function DataGridInner(props) {
311
585
  })
312
586
  }, header.id);
313
587
  }
588
+ if (header.id === _types.DETAIL_PANEL_TOGGLE_ID) {
589
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
590
+ className: (0, _utils.cn)((0, _styles.dataGridHeadVariants)(), (0, _styles.dataGridDetailToggleCellVariants)(), pinnedClassName(pin, true)),
591
+ style: mergePinnedStyle(undefined, pin, pinnedOffsets, header.id, true)
592
+ }, header.id);
593
+ }
314
594
  const col = colByField.get(header.column.id);
595
+ const isTreeColumn = header.column.id === treeField;
315
596
  const sorted = header.column.getIsSorted();
316
597
  const canSort = !disableColumnSorting && header.column.getCanSort();
317
- const headerAlign = (0, _columns.normalizeGridAlignment)(col?.headerAlign ?? col?.align);
598
+ const headerAlign = (0, _columns.resolveColumnHeaderAlign)(col);
318
599
  const headerName = col?.headerName ?? header.column.id;
319
600
  const SortIcon = sorted === 'asc' ? _icons.KeyboardArrowUp : _icons.KeyboardArrowDown;
320
601
  const sortButton = canSort ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
@@ -332,50 +613,71 @@ function DataGridInner(props) {
332
613
  sorted: sorted !== false
333
614
  })
334
615
  }) : null;
616
+ const headerLabel = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
617
+ children: [headerAlign === 'end' ? sortButton : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Text, {
618
+ numberOfLines: 1,
619
+ className: (0, _styles.dataGridHeaderLabelVariants)(),
620
+ children: col?.renderHeader ? col.renderHeader() : headerName
621
+ }), headerAlign === 'end' ? null : sortButton]
622
+ });
335
623
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Head, {
336
624
  align: headerAlign,
337
- className: (0, _styles.dataGridHeadVariants)(),
338
- style: cellStyle(col, columnWidths.get(header.column.id)),
625
+ className: (0, _utils.cn)((0, _styles.dataGridHeadVariants)(), pinnedClassName(pin, true)),
626
+ style: mergePinnedStyle(cellStyle(col, columnWidths.get(header.column.id)), pin, pinnedOffsets, header.column.id, true),
339
627
  ...(_reactNative.Platform.OS === 'web' ? {
340
628
  title: col?.renderHeader ? undefined : headerName,
341
629
  ...(canSort ? {
342
630
  'aria-sort': sorted === 'asc' ? 'ascending' : sorted === 'desc' ? 'descending' : 'none'
343
631
  } : {})
344
632
  } : {}),
345
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
633
+ children: isTreeColumn ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
634
+ className: (0, _styles.dataGridTreeCellInnerVariants)(),
635
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
636
+ className: (0, _styles.dataGridTreeToggleSlotVariants)()
637
+ }), treeCheckbox ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Checkbox, {
638
+ value: "select-all",
639
+ isChecked: headerSelectState.checked,
640
+ isIndeterminate: headerSelectState.indeterminate,
641
+ onChange: () => tree?.toggleAllRowsSelected(),
642
+ accessibilityLabel: "Select all",
643
+ "aria-label": "Select all"
644
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
645
+ className: (0, _utils.cn)((0, _styles.dataGridHeaderCellInnerVariants)({
646
+ align: headerAlign
647
+ }), 'flex-1'),
648
+ children: headerLabel
649
+ })]
650
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
346
651
  className: (0, _styles.dataGridHeaderCellInnerVariants)({
347
652
  align: headerAlign,
348
653
  fitToColumn: _reactNative.Platform.OS === 'web' && columnWidths.has(header.column.id)
349
654
  }),
350
- children: [headerAlign === 'end' ? sortButton : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Text, {
351
- numberOfLines: 1,
352
- className: (0, _styles.dataGridHeaderLabelVariants)(),
353
- children: col?.renderHeader ? col.renderHeader() : headerName
354
- }), headerAlign === 'end' ? null : sortButton]
655
+ children: headerLabel
355
656
  })
356
657
  }, header.id);
357
658
  })
358
659
  }, headerGroup.id)), headerFilters ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
359
- children: table.getAllLeafColumns().map(column => {
360
- if (column.id === _types.SELECT_COLUMN_ID) {
660
+ children: (pinningActive ? [...table.getStartVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns(), ...table.getEndVisibleLeafColumns()] : table.getVisibleLeafColumns()).map(column => {
661
+ const pin = pinMetaFor(column.id, columnPinning);
662
+ if (column.id === _types.SELECT_COLUMN_ID || column.id === _types.DETAIL_PANEL_TOGGLE_ID) {
361
663
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
362
664
  align: "center",
363
- className: (0, _styles.dataGridSelectHeadVariants)()
665
+ className: (0, _utils.cn)((0, _styles.dataGridSelectHeadVariants)(), column.id === _types.DETAIL_PANEL_TOGGLE_ID && 'w-12 px-2', pinnedClassName(pin, true)),
666
+ style: mergePinnedStyle(undefined, pin, pinnedOffsets, column.id, true)
364
667
  }, column.id);
365
668
  }
366
669
  const col = colByField.get(column.id);
367
- const headerAlign = col?.headerAlign ?? col?.align;
368
670
  if (col?.filterable === false) {
369
671
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Head, {
370
- align: (0, _columns.normalizeGridAlignment)(headerAlign),
371
- className: (0, _styles.dataGridHeadVariants)(),
372
- style: cellStyle(col, columnWidths.get(column.id))
672
+ align: (0, _columns.resolveColumnHeaderAlign)(col),
673
+ className: (0, _utils.cn)((0, _styles.dataGridHeadVariants)(), pinnedClassName(pin, true)),
674
+ style: mergePinnedStyle(cellStyle(col, columnWidths.get(column.id)), pin, pinnedOffsets, column.id, true)
373
675
  }, column.id);
374
676
  }
375
677
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Head, {
376
- align: (0, _columns.normalizeGridAlignment)(headerAlign),
377
- className: (0, _styles.dataGridHeadVariants)(),
378
- style: cellStyle(col, columnWidths.get(column.id)),
678
+ align: (0, _columns.resolveColumnHeaderAlign)(col),
679
+ className: (0, _utils.cn)((0, _styles.dataGridHeadVariants)(), pinnedClassName(pin, true)),
680
+ style: mergePinnedStyle(cellStyle(col, columnWidths.get(column.id)), pin, pinnedOffsets, column.id, true),
379
681
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Input, {
380
682
  size: "small",
381
683
  className: (0, _styles.dataGridFilterInputVariants)(),
@@ -392,18 +694,52 @@ function DataGridInner(props) {
392
694
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Body, {
393
695
  className: (0, _styles.dataGridBodyVariants)(),
394
696
  children: loading && loadingOverlay == null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(DefaultLoadingRows, {
395
- columns: columns,
396
- checkboxSelection: checkboxSelection,
697
+ columns: visibleColumns,
698
+ leadingColumnIds: leadingColumnIds,
397
699
  rowCount: Math.min(resolvedPagination.pageSize, MAX_SKELETON_ROW_COUNT),
398
- columnWidths: columnWidths
399
- }) : isEmpty ? null : visibleRows.map(row => {
700
+ columnWidths: columnWidths,
701
+ orderedColumnIds: orderedLeafColumnIds,
702
+ pinning: columnPinning,
703
+ offsets: pinnedOffsets
704
+ }) : isEmpty ? null : visibleRows.flatMap(row => {
400
705
  const rowId = (0, _useDataGridTable.resolveRowId)(row.original, getRowId);
401
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
402
- children: row.getAllCells().map(cell => {
706
+ const cells = pinningActive ? [...row.getStartVisibleCells(), ...row.getCenterVisibleCells(), ...row.getEndVisibleCells()] : row.getVisibleCells();
707
+ const detailContent = getDetailPanelContent?.({
708
+ id: rowId,
709
+ row: row.original
710
+ });
711
+ const hasDetailPanel = detailContent != null;
712
+ const detailOpen = hasDetailPanel && resolvedDetailIds.has(rowId);
713
+ const treeLabel = treeActive ? [...getTreeDataPath(row.original)].reverse().join(', ') : '';
714
+ const dataRow = /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
715
+ className: detailOpen ? 'web:[&>*]:border-b-0' : undefined,
716
+ children: cells.map(cell => {
717
+ const pin = pinMetaFor(cell.column.id, columnPinning);
718
+ if (cell.column.id === _types.DETAIL_PANEL_TOGGLE_ID) {
719
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
720
+ align: "center",
721
+ className: (0, _utils.cn)((0, _styles.dataGridDetailToggleCellVariants)(), pinnedClassName(pin, false)),
722
+ style: mergePinnedStyle(undefined, pin, pinnedOffsets, cell.column.id, false),
723
+ children: hasDetailPanel ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
724
+ as: detailOpen ? _icons.KeyboardArrowDown : _icons.KeyboardArrowRight,
725
+ variant: "ghost",
726
+ color: "neutral",
727
+ size: "small",
728
+ iconClassName: detailOpen ? undefined : 'rtl:-scale-x-100',
729
+ accessibilityLabel: `${detailOpen ? 'Collapse' : 'Expand'} row ${String(rowId)}`,
730
+ accessibilityState: {
731
+ expanded: detailOpen
732
+ },
733
+ "aria-expanded": detailOpen,
734
+ onPress: () => toggleDetailPanel(rowId)
735
+ }) : null
736
+ }, cell.id);
737
+ }
403
738
  if (cell.column.id === _types.SELECT_COLUMN_ID) {
404
739
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
405
740
  align: "center",
406
- className: (0, _styles.dataGridSelectCellVariants)(),
741
+ className: (0, _utils.cn)((0, _styles.dataGridSelectCellVariants)(), pinnedClassName(pin, false)),
742
+ style: mergePinnedStyle(undefined, pin, pinnedOffsets, cell.column.id, false),
407
743
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Checkbox, {
408
744
  value: String(rowId),
409
745
  isChecked: row.getIsSelected(),
@@ -421,21 +757,94 @@ function DataGridInner(props) {
421
757
  value,
422
758
  row: row.original,
423
759
  field: col.field,
424
- id: rowId
760
+ id: rowId,
761
+ col
425
762
  });
426
763
  } else if (col?.valueFormatter) {
427
764
  content = col.valueFormatter(value, row.original, col);
765
+ } else if (col?.type === 'boolean' && typeof value === 'boolean') {
766
+ content = /*#__PURE__*/(0, _jsxRuntime.jsx)(BooleanCell, {
767
+ value: value
768
+ });
428
769
  } else {
429
- content = defaultCellContent(value);
770
+ const typedText = (0, _columnTypes.getTypedCellText)(col, value, row.original);
771
+ content = typedText !== undefined ? typedText : defaultCellContent(value);
772
+ }
773
+ if (tree && cell.column.id === treeField) {
774
+ const canExpand = row.subRows.length > 0;
775
+ const expanded = canExpand && tree.isRowExpanded(row.id);
776
+ const status = tree.selectionStatus(row.id);
777
+ content = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
778
+ className: (0, _styles.dataGridTreeCellInnerVariants)(),
779
+ style: {
780
+ paddingStart: row.depth * TREE_INDENT
781
+ },
782
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
783
+ className: (0, _styles.dataGridTreeToggleSlotVariants)(),
784
+ children: canExpand ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
785
+ as: expanded ? _icons.KeyboardArrowDown : _icons.KeyboardArrowRight,
786
+ variant: "ghost",
787
+ color: "neutral",
788
+ size: "small",
789
+ iconClassName: expanded ? undefined : 'rtl:-scale-x-100',
790
+ accessibilityLabel: `${expanded ? 'Collapse' : 'Expand'} ${treeLabel}`,
791
+ accessibilityState: {
792
+ expanded
793
+ },
794
+ "aria-expanded": expanded,
795
+ onPress: () => tree.toggleRowExpanded(row.id)
796
+ }) : null
797
+ }), treeCheckbox ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Checkbox, {
798
+ value: String(rowId),
799
+ isChecked: status === 'all',
800
+ isIndeterminate: status === 'some',
801
+ onChange: () => tree.toggleRowSelected(row),
802
+ accessibilityLabel: `Select ${treeLabel}`,
803
+ "aria-label": `Select ${treeLabel}`
804
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
805
+ className: (0, _styles.dataGridTreeContentVariants)(),
806
+ children: typeof content === 'string' || typeof content === 'number' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Text, {
807
+ numberOfLines: 1,
808
+ children: content
809
+ }) : content
810
+ })]
811
+ });
430
812
  }
813
+ const align = (0, _columns.resolveColumnAlign)(col);
814
+ const cellText = !col?.renderCell && (typeof content === 'string' || typeof content === 'number') ? String(content) : undefined;
431
815
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
432
- align: (0, _columns.normalizeGridAlignment)(col?.align),
433
- className: (0, _styles.dataGridCellVariants)(),
434
- style: cellStyle(col, columnWidths.get(cell.column.id)),
435
- children: content
816
+ align: align,
817
+ ...(_reactNative.Platform.OS === 'web' && cellText ? {
818
+ title: cellText
819
+ } : {}),
820
+ className: (0, _utils.cn)((0, _styles.dataGridCellVariants)(), pinnedClassName(pin, false)),
821
+ style: mergePinnedStyle(cellStyle(col, columnWidths.get(cell.column.id)), pin, pinnedOffsets, cell.column.id, false),
822
+ children: cellText !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Text, {
823
+ numberOfLines: 1,
824
+ className: (0, _styles.dataGridCellTextVariants)({
825
+ align,
826
+ fitToColumn: _reactNative.Platform.OS === 'web' && columnWidths.has(cell.column.id)
827
+ }),
828
+ children: cellText
829
+ }) : content
436
830
  }, cell.id);
437
831
  })
438
832
  }, row.id);
833
+ if (!detailOpen) {
834
+ return [dataRow];
835
+ }
836
+ return [dataRow, /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Row, {
837
+ className: "web:hover:bg-transparent",
838
+ testID: `data-grid-detail-panel-${String(rowId)}`,
839
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Table.Cell, {
840
+ colSpan: leafColumnCount,
841
+ className: (0, _styles.dataGridDetailPanelCellVariants)(),
842
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
843
+ style: detailPanelContentStyle,
844
+ children: detailContent
845
+ })
846
+ })
847
+ }, `${row.id}:detail`)];
439
848
  })
440
849
  })]
441
850
  }), isEmpty ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {