@ceed/cds 1.25.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2136,14 +2136,15 @@ function reorderColumnsByGroupingModel(columns, columnGroupingModel) {
2136
2136
  }
2137
2137
  return reorderedColumns;
2138
2138
  }
2139
- function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }) {
2139
+ function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }, visibleFields) {
2140
2140
  const result = [];
2141
2141
  for (const item of items) {
2142
2142
  if ("groupId" in item) {
2143
2143
  const newPath = [...groupPath, item.groupId];
2144
2144
  const children = Array.isArray(item.children) ? item.children : [item.children];
2145
- result.push(...flattenColumnGroups(children, newPath, columnIndex));
2145
+ result.push(...flattenColumnGroups(children, newPath, columnIndex, visibleFields));
2146
2146
  } else {
2147
+ if (visibleFields && !visibleFields.has(item.field)) continue;
2147
2148
  result.push({
2148
2149
  ...item,
2149
2150
  groupPath,
@@ -2153,9 +2154,9 @@ function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }
2153
2154
  }
2154
2155
  return result;
2155
2156
  }
2156
- function calculateColumnGroups(columnGroupingModel, columns) {
2157
+ function calculateColumnGroups(columnGroupingModel, columns, visibleFields) {
2157
2158
  const fieldsInGroupingModel = extractFieldsFromGroupingModel(columnGroupingModel);
2158
- const flattenedColumns = flattenColumnGroups(columnGroupingModel);
2159
+ const flattenedColumns = flattenColumnGroups(columnGroupingModel, [], { current: 0 }, visibleFields);
2159
2160
  const columnIndexMap = new Map(flattenedColumns.map((col) => [col.field, col.columnIndex]));
2160
2161
  const processedGroups = /* @__PURE__ */ new Map();
2161
2162
  const groupsByLevel = [];
@@ -2203,7 +2204,9 @@ function calculateColumnGroups(columnGroupingModel, columns) {
2203
2204
  groupsByLevel.forEach((level) => {
2204
2205
  level.sort((a, b) => a.startIndex - b.startIndex);
2205
2206
  });
2206
- return { groups: groupsByLevel, maxLevel, fieldsInGroupingModel };
2207
+ const filteredGroupsByLevel = groupsByLevel.map((level) => level.filter((g) => g.colspan > 0)).filter((level) => level.length > 0);
2208
+ const correctedMaxLevel = filteredGroupsByLevel.length > 0 ? filteredGroupsByLevel.length - 1 : -1;
2209
+ return { groups: filteredGroupsByLevel, maxLevel: correctedMaxLevel, fieldsInGroupingModel };
2207
2210
  }
2208
2211
  function getTextAlign(props) {
2209
2212
  return !props.editMode && ["number", "date", "currency"].includes(props.type || "") ? "end" : "start";
@@ -3367,7 +3370,9 @@ function useDataTableRenderer({
3367
3370
  getId: _getId,
3368
3371
  isTotalSelected: _isTotalSelected,
3369
3372
  isRowSelectable,
3370
- columnGroupingModel
3373
+ columnGroupingModel,
3374
+ columnVisibilityModel,
3375
+ onColumnVisibilityModelChange
3371
3376
  }) {
3372
3377
  if (pinnedColumns && columnGroupingModel) {
3373
3378
  throw new Error(
@@ -3383,12 +3388,35 @@ function useDataTableRenderer({
3383
3388
  initialState?.sorting?.sortModel ?? [],
3384
3389
  (0, import_react25.useCallback)((sortModel2) => onSortModelChange?.(sortModel2), [onSortModelChange])
3385
3390
  );
3391
+ const [visibilityModel] = useControlledState(
3392
+ columnVisibilityModel,
3393
+ initialState?.columns?.columnVisibilityModel ?? {},
3394
+ (0, import_react25.useCallback)(
3395
+ (model) => onColumnVisibilityModelChange?.(model),
3396
+ [onColumnVisibilityModelChange]
3397
+ )
3398
+ );
3386
3399
  const reorderedColumns = (0, import_react25.useMemo)(() => {
3387
3400
  if (!columnGroupingModel) return columnsProp;
3388
3401
  return reorderColumnsByGroupingModel(columnsProp, columnGroupingModel);
3389
3402
  }, [columnsProp, columnGroupingModel]);
3390
- const columnsByField = (0, import_react25.useMemo)(
3403
+ const visibleColumns = (0, import_react25.useMemo)(
3404
+ () => reorderedColumns.filter((col) => visibilityModel[col.field] !== false),
3405
+ [reorderedColumns, visibilityModel]
3406
+ );
3407
+ const visibleFieldSet = (0, import_react25.useMemo)(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3408
+ const allColumnsByField = (0, import_react25.useMemo)(
3391
3409
  () => reorderedColumns.reduce(
3410
+ (acc, curr) => ({
3411
+ ...acc,
3412
+ [curr.field]: curr
3413
+ }),
3414
+ {}
3415
+ ),
3416
+ [reorderedColumns]
3417
+ );
3418
+ const visibleColumnsByField = (0, import_react25.useMemo)(
3419
+ () => visibleColumns.reduce(
3392
3420
  (acc, curr) => ({
3393
3421
  ...acc,
3394
3422
  [curr.field]: {
@@ -3399,7 +3427,7 @@ function useDataTableRenderer({
3399
3427
  }),
3400
3428
  {}
3401
3429
  ),
3402
- [reorderedColumns]
3430
+ [visibleColumns]
3403
3431
  );
3404
3432
  const sortComparator = (0, import_react25.useCallback)(
3405
3433
  (rowA, rowB) => {
@@ -3407,7 +3435,8 @@ function useDataTableRenderer({
3407
3435
  const { field, sort: direction } = sort;
3408
3436
  const a = rowA[field];
3409
3437
  const b = rowB[field];
3410
- const column = columnsByField[field];
3438
+ const column = allColumnsByField[field];
3439
+ if (!column) continue;
3411
3440
  let comparison = 0;
3412
3441
  if (column.sortComparator) {
3413
3442
  comparison = column.sortComparator({
@@ -3427,7 +3456,7 @@ function useDataTableRenderer({
3427
3456
  }
3428
3457
  return 0;
3429
3458
  },
3430
- [sortModel, columnsByField]
3459
+ [sortModel, allColumnsByField]
3431
3460
  );
3432
3461
  const rows = (0, import_react25.useMemo)(
3433
3462
  () => sortModel.length ? [..._rows].sort(sortComparator) : _rows,
@@ -3491,44 +3520,54 @@ function useDataTableRenderer({
3491
3520
  () => _isTotalSelected ?? (selectableRowCount > 0 && (selectionModel?.length || 0) === selectableRowCount),
3492
3521
  [_isTotalSelected, selectionModel, selectableRowCount]
3493
3522
  );
3494
- const columnWidths = useColumnWidths(columnsByField);
3523
+ const columnWidths = useColumnWidths(visibleColumnsByField);
3495
3524
  const getWidth = (0, import_react25.useCallback)(
3496
- (f) => columnWidths[f] ?? columnsByField[f].width ?? // Column prop 으로 지정된 width
3497
- columnsByField[f].minWidth ?? 0,
3498
- [columnWidths, columnsByField]
3525
+ (f) => columnWidths[f] ?? allColumnsByField[f]?.width ?? // Column prop 으로 지정된 width
3526
+ allColumnsByField[f]?.minWidth ?? 0,
3527
+ [columnWidths, allColumnsByField]
3499
3528
  );
3500
3529
  const processedColumnGroups = (0, import_react25.useMemo)(() => {
3501
3530
  if (!columnGroupingModel) return null;
3502
- return calculateColumnGroups(columnGroupingModel, reorderedColumns);
3503
- }, [columnGroupingModel, reorderedColumns]);
3531
+ return calculateColumnGroups(columnGroupingModel, visibleColumns, visibleFieldSet);
3532
+ }, [columnGroupingModel, visibleColumns, visibleFieldSet]);
3533
+ const effectivePinnedLeft = (0, import_react25.useMemo)(
3534
+ () => pinnedColumns?.left?.filter((f) => visibleFieldSet.has(f)),
3535
+ [pinnedColumns?.left, visibleFieldSet]
3536
+ );
3537
+ const effectivePinnedRight = (0, import_react25.useMemo)(
3538
+ () => pinnedColumns?.right?.filter((f) => visibleFieldSet.has(f)),
3539
+ [pinnedColumns?.right, visibleFieldSet]
3540
+ );
3504
3541
  const columns = (0, import_react25.useMemo)(() => {
3505
- const baseColumns = reorderedColumns.length > 0 ? reorderedColumns : Object.keys(rows[0] || {}).map((key) => ({
3542
+ const baseColumns = visibleColumns.length > 0 ? visibleColumns : reorderedColumns.length > 0 ? [] : Object.keys(rows[0] || {}).map((key) => ({
3506
3543
  field: key
3507
3544
  }));
3508
3545
  return baseColumns.map((column) => {
3509
- const isLeftPinned = pinnedColumns?.left?.includes(column.field);
3510
- const isRightPinned = pinnedColumns?.right?.includes(column.field);
3546
+ const isLeftPinned = effectivePinnedLeft?.includes(column.field);
3547
+ const isRightPinned = effectivePinnedRight?.includes(column.field);
3511
3548
  const isPinned = isLeftPinned || isRightPinned;
3512
3549
  return {
3513
3550
  ...column,
3514
- headerRef: columnsByField[column.field].headerRef,
3515
- tableColRef: columnsByField[column.field].tableColRef,
3551
+ headerRef: visibleColumnsByField[column.field]?.headerRef,
3552
+ tableColRef: visibleColumnsByField[column.field]?.tableColRef,
3516
3553
  isCellEditable: editMode && (typeof column.isCellEditable === "function" ? column.isCellEditable : column.isCellEditable ?? true),
3517
3554
  sort: sortModel.find((sort) => sort.field === column.field)?.sort,
3518
- sortOrder: columnsByField[column.field]?.sortOrder || sortOrder,
3555
+ sortOrder: allColumnsByField[column.field]?.sortOrder || sortOrder,
3519
3556
  isPinned,
3520
- isLastStartPinnedColumn: isLeftPinned && [...pinnedColumns?.left || []].pop() === column.field,
3521
- isLastEndPinnedColumn: isRightPinned && (pinnedColumns?.right?.[0] ?? null) === column.field,
3522
- pinnedStartPosition: pinnedColumns?.left?.slice(0, isLeftPinned ? pinnedColumns.left.indexOf(column.field) : pinnedColumns.left.length).reduce((acc, curr) => acc + getWidth(curr), 0),
3523
- pinnedEndPosition: pinnedColumns?.right?.slice(isRightPinned ? pinnedColumns.right.indexOf(column.field) + 1 : 0).reduce((acc, curr) => acc + getWidth(curr), 0)
3557
+ isLastStartPinnedColumn: isLeftPinned && [...effectivePinnedLeft || []].pop() === column.field,
3558
+ isLastEndPinnedColumn: isRightPinned && (effectivePinnedRight?.[0] ?? null) === column.field,
3559
+ pinnedStartPosition: effectivePinnedLeft?.slice(0, isLeftPinned ? effectivePinnedLeft.indexOf(column.field) : effectivePinnedLeft.length).reduce((acc, curr) => acc + getWidth(curr), 0),
3560
+ pinnedEndPosition: effectivePinnedRight?.slice(isRightPinned ? effectivePinnedRight.indexOf(column.field) + 1 : 0).reduce((acc, curr) => acc + getWidth(curr), 0)
3524
3561
  };
3525
3562
  });
3526
3563
  }, [
3564
+ visibleColumns,
3527
3565
  reorderedColumns,
3528
3566
  rows,
3529
- pinnedColumns?.left,
3530
- pinnedColumns?.right,
3531
- columnsByField,
3567
+ effectivePinnedLeft,
3568
+ effectivePinnedRight,
3569
+ visibleColumnsByField,
3570
+ allColumnsByField,
3532
3571
  editMode,
3533
3572
  sortModel,
3534
3573
  sortOrder,
@@ -3544,8 +3583,8 @@ function useDataTableRenderer({
3544
3583
  const handleSortChange = (0, import_react25.useCallback)(
3545
3584
  (props) => {
3546
3585
  const { field, currentSort, multiple } = props;
3547
- const column = columnsByField[field];
3548
- const columnSortOrder = column.sortOrder || sortOrder;
3586
+ const column = allColumnsByField[field];
3587
+ const columnSortOrder = column?.sortOrder || sortOrder;
3549
3588
  if (currentSort !== void 0) {
3550
3589
  const currentOrderIndex = columnSortOrder.indexOf(currentSort);
3551
3590
  const nextSortOrderIndex = (currentOrderIndex + 1) % columnSortOrder.length;
@@ -3562,7 +3601,7 @@ function useDataTableRenderer({
3562
3601
  setSortModel(newSortModel);
3563
3602
  }
3564
3603
  },
3565
- [sortOrder, columnsByField, sortModel, setSortModel]
3604
+ [sortOrder, allColumnsByField, sortModel, setSortModel]
3566
3605
  );
3567
3606
  (0, import_react25.useEffect)(() => {
3568
3607
  if (!paginationModel) {
@@ -3988,6 +4027,10 @@ function Component(props, apiRef) {
3988
4027
  loading,
3989
4028
  columnGroupingModel: _________________,
3990
4029
  // columnGroupingModel is used in useDataTableRenderer
4030
+ columnVisibilityModel: __________________,
4031
+ // columnVisibilityModel is used in useDataTableRenderer
4032
+ onColumnVisibilityModelChange: ___________________,
4033
+ // onColumnVisibilityModelChange is used in useDataTableRenderer
3991
4034
  slots: {
3992
4035
  checkbox: RenderCheckbox = Checkbox_default,
3993
4036
  toolbar: Toolbar,
@@ -4227,7 +4270,7 @@ function Component(props, apiRef) {
4227
4270
  width: c.width
4228
4271
  }
4229
4272
  }
4230
- ))), /* @__PURE__ */ import_react28.default.createElement("thead", null, processedColumnGroups && processedColumnGroups.groups.map((levelGroups, level) => /* @__PURE__ */ import_react28.default.createElement("tr", { key: `group-level-${level}` }, checkboxSelection && level === 0 && /* @__PURE__ */ import_react28.default.createElement(
4273
+ ))), /* @__PURE__ */ import_react28.default.createElement("thead", null, processedColumnGroups && processedColumnGroups.groups.length > 0 && processedColumnGroups.groups.map((levelGroups, level) => /* @__PURE__ */ import_react28.default.createElement("tr", { key: `group-level-${level}` }, checkboxSelection && level === 0 && /* @__PURE__ */ import_react28.default.createElement(
4231
4274
  "th",
4232
4275
  {
4233
4276
  rowSpan: processedColumnGroups.maxLevel + 2,
@@ -4247,7 +4290,7 @@ function Component(props, apiRef) {
4247
4290
  ...checkboxProps
4248
4291
  }
4249
4292
  )
4250
- ), level > 0 && Array.from({ length: levelGroups[0]?.startIndex || 0 }).map((_2, i) => /* @__PURE__ */ import_react28.default.createElement("th", { key: `empty-${level}-${i}` })), levelGroups.map((group, groupIndex) => {
4293
+ ), level > 0 && Array.from({ length: levelGroups[0]?.startIndex || 0 }).map((_2, i) => /* @__PURE__ */ import_react28.default.createElement("th", { key: `empty-${level}-${i}` })), levelGroups.filter((g) => g.colspan > 0).map((group, groupIndex) => {
4251
4294
  const nextGroup = levelGroups[groupIndex + 1];
4252
4295
  const emptyCells = nextGroup ? nextGroup.startIndex - (group.startIndex + group.colspan) : columns.length - (group.startIndex + group.colspan);
4253
4296
  const params = { groupId: group.groupId };
@@ -4265,7 +4308,7 @@ function Component(props, apiRef) {
4265
4308
  },
4266
4309
  group.headerName ?? group.groupId
4267
4310
  ), emptyCells > 0 && Array.from({ length: emptyCells }).map((_2, i) => /* @__PURE__ */ import_react28.default.createElement("th", { key: `empty-between-${level}-${groupIndex}-${i}`, colSpan: 1 })));
4268
- }))), /* @__PURE__ */ import_react28.default.createElement("tr", null, !processedColumnGroups && checkboxSelection && /* @__PURE__ */ import_react28.default.createElement(
4311
+ }))), /* @__PURE__ */ import_react28.default.createElement("tr", null, (!processedColumnGroups || processedColumnGroups.groups.length === 0) && checkboxSelection && /* @__PURE__ */ import_react28.default.createElement(
4269
4312
  "th",
4270
4313
  {
4271
4314
  style: {
package/dist/index.js CHANGED
@@ -2010,14 +2010,15 @@ function reorderColumnsByGroupingModel(columns, columnGroupingModel) {
2010
2010
  }
2011
2011
  return reorderedColumns;
2012
2012
  }
2013
- function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }) {
2013
+ function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }, visibleFields) {
2014
2014
  const result = [];
2015
2015
  for (const item of items) {
2016
2016
  if ("groupId" in item) {
2017
2017
  const newPath = [...groupPath, item.groupId];
2018
2018
  const children = Array.isArray(item.children) ? item.children : [item.children];
2019
- result.push(...flattenColumnGroups(children, newPath, columnIndex));
2019
+ result.push(...flattenColumnGroups(children, newPath, columnIndex, visibleFields));
2020
2020
  } else {
2021
+ if (visibleFields && !visibleFields.has(item.field)) continue;
2021
2022
  result.push({
2022
2023
  ...item,
2023
2024
  groupPath,
@@ -2027,9 +2028,9 @@ function flattenColumnGroups(items, groupPath = [], columnIndex = { current: 0 }
2027
2028
  }
2028
2029
  return result;
2029
2030
  }
2030
- function calculateColumnGroups(columnGroupingModel, columns) {
2031
+ function calculateColumnGroups(columnGroupingModel, columns, visibleFields) {
2031
2032
  const fieldsInGroupingModel = extractFieldsFromGroupingModel(columnGroupingModel);
2032
- const flattenedColumns = flattenColumnGroups(columnGroupingModel);
2033
+ const flattenedColumns = flattenColumnGroups(columnGroupingModel, [], { current: 0 }, visibleFields);
2033
2034
  const columnIndexMap = new Map(flattenedColumns.map((col) => [col.field, col.columnIndex]));
2034
2035
  const processedGroups = /* @__PURE__ */ new Map();
2035
2036
  const groupsByLevel = [];
@@ -2077,7 +2078,9 @@ function calculateColumnGroups(columnGroupingModel, columns) {
2077
2078
  groupsByLevel.forEach((level) => {
2078
2079
  level.sort((a, b) => a.startIndex - b.startIndex);
2079
2080
  });
2080
- return { groups: groupsByLevel, maxLevel, fieldsInGroupingModel };
2081
+ const filteredGroupsByLevel = groupsByLevel.map((level) => level.filter((g) => g.colspan > 0)).filter((level) => level.length > 0);
2082
+ const correctedMaxLevel = filteredGroupsByLevel.length > 0 ? filteredGroupsByLevel.length - 1 : -1;
2083
+ return { groups: filteredGroupsByLevel, maxLevel: correctedMaxLevel, fieldsInGroupingModel };
2081
2084
  }
2082
2085
  function getTextAlign(props) {
2083
2086
  return !props.editMode && ["number", "date", "currency"].includes(props.type || "") ? "end" : "start";
@@ -3250,7 +3253,9 @@ function useDataTableRenderer({
3250
3253
  getId: _getId,
3251
3254
  isTotalSelected: _isTotalSelected,
3252
3255
  isRowSelectable,
3253
- columnGroupingModel
3256
+ columnGroupingModel,
3257
+ columnVisibilityModel,
3258
+ onColumnVisibilityModelChange
3254
3259
  }) {
3255
3260
  if (pinnedColumns && columnGroupingModel) {
3256
3261
  throw new Error(
@@ -3266,12 +3271,35 @@ function useDataTableRenderer({
3266
3271
  initialState?.sorting?.sortModel ?? [],
3267
3272
  useCallback10((sortModel2) => onSortModelChange?.(sortModel2), [onSortModelChange])
3268
3273
  );
3274
+ const [visibilityModel] = useControlledState(
3275
+ columnVisibilityModel,
3276
+ initialState?.columns?.columnVisibilityModel ?? {},
3277
+ useCallback10(
3278
+ (model) => onColumnVisibilityModelChange?.(model),
3279
+ [onColumnVisibilityModelChange]
3280
+ )
3281
+ );
3269
3282
  const reorderedColumns = useMemo9(() => {
3270
3283
  if (!columnGroupingModel) return columnsProp;
3271
3284
  return reorderColumnsByGroupingModel(columnsProp, columnGroupingModel);
3272
3285
  }, [columnsProp, columnGroupingModel]);
3273
- const columnsByField = useMemo9(
3286
+ const visibleColumns = useMemo9(
3287
+ () => reorderedColumns.filter((col) => visibilityModel[col.field] !== false),
3288
+ [reorderedColumns, visibilityModel]
3289
+ );
3290
+ const visibleFieldSet = useMemo9(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3291
+ const allColumnsByField = useMemo9(
3274
3292
  () => reorderedColumns.reduce(
3293
+ (acc, curr) => ({
3294
+ ...acc,
3295
+ [curr.field]: curr
3296
+ }),
3297
+ {}
3298
+ ),
3299
+ [reorderedColumns]
3300
+ );
3301
+ const visibleColumnsByField = useMemo9(
3302
+ () => visibleColumns.reduce(
3275
3303
  (acc, curr) => ({
3276
3304
  ...acc,
3277
3305
  [curr.field]: {
@@ -3282,7 +3310,7 @@ function useDataTableRenderer({
3282
3310
  }),
3283
3311
  {}
3284
3312
  ),
3285
- [reorderedColumns]
3313
+ [visibleColumns]
3286
3314
  );
3287
3315
  const sortComparator = useCallback10(
3288
3316
  (rowA, rowB) => {
@@ -3290,7 +3318,8 @@ function useDataTableRenderer({
3290
3318
  const { field, sort: direction } = sort;
3291
3319
  const a = rowA[field];
3292
3320
  const b = rowB[field];
3293
- const column = columnsByField[field];
3321
+ const column = allColumnsByField[field];
3322
+ if (!column) continue;
3294
3323
  let comparison = 0;
3295
3324
  if (column.sortComparator) {
3296
3325
  comparison = column.sortComparator({
@@ -3310,7 +3339,7 @@ function useDataTableRenderer({
3310
3339
  }
3311
3340
  return 0;
3312
3341
  },
3313
- [sortModel, columnsByField]
3342
+ [sortModel, allColumnsByField]
3314
3343
  );
3315
3344
  const rows = useMemo9(
3316
3345
  () => sortModel.length ? [..._rows].sort(sortComparator) : _rows,
@@ -3374,44 +3403,54 @@ function useDataTableRenderer({
3374
3403
  () => _isTotalSelected ?? (selectableRowCount > 0 && (selectionModel?.length || 0) === selectableRowCount),
3375
3404
  [_isTotalSelected, selectionModel, selectableRowCount]
3376
3405
  );
3377
- const columnWidths = useColumnWidths(columnsByField);
3406
+ const columnWidths = useColumnWidths(visibleColumnsByField);
3378
3407
  const getWidth = useCallback10(
3379
- (f) => columnWidths[f] ?? columnsByField[f].width ?? // Column prop 으로 지정된 width
3380
- columnsByField[f].minWidth ?? 0,
3381
- [columnWidths, columnsByField]
3408
+ (f) => columnWidths[f] ?? allColumnsByField[f]?.width ?? // Column prop 으로 지정된 width
3409
+ allColumnsByField[f]?.minWidth ?? 0,
3410
+ [columnWidths, allColumnsByField]
3382
3411
  );
3383
3412
  const processedColumnGroups = useMemo9(() => {
3384
3413
  if (!columnGroupingModel) return null;
3385
- return calculateColumnGroups(columnGroupingModel, reorderedColumns);
3386
- }, [columnGroupingModel, reorderedColumns]);
3414
+ return calculateColumnGroups(columnGroupingModel, visibleColumns, visibleFieldSet);
3415
+ }, [columnGroupingModel, visibleColumns, visibleFieldSet]);
3416
+ const effectivePinnedLeft = useMemo9(
3417
+ () => pinnedColumns?.left?.filter((f) => visibleFieldSet.has(f)),
3418
+ [pinnedColumns?.left, visibleFieldSet]
3419
+ );
3420
+ const effectivePinnedRight = useMemo9(
3421
+ () => pinnedColumns?.right?.filter((f) => visibleFieldSet.has(f)),
3422
+ [pinnedColumns?.right, visibleFieldSet]
3423
+ );
3387
3424
  const columns = useMemo9(() => {
3388
- const baseColumns = reorderedColumns.length > 0 ? reorderedColumns : Object.keys(rows[0] || {}).map((key) => ({
3425
+ const baseColumns = visibleColumns.length > 0 ? visibleColumns : reorderedColumns.length > 0 ? [] : Object.keys(rows[0] || {}).map((key) => ({
3389
3426
  field: key
3390
3427
  }));
3391
3428
  return baseColumns.map((column) => {
3392
- const isLeftPinned = pinnedColumns?.left?.includes(column.field);
3393
- const isRightPinned = pinnedColumns?.right?.includes(column.field);
3429
+ const isLeftPinned = effectivePinnedLeft?.includes(column.field);
3430
+ const isRightPinned = effectivePinnedRight?.includes(column.field);
3394
3431
  const isPinned = isLeftPinned || isRightPinned;
3395
3432
  return {
3396
3433
  ...column,
3397
- headerRef: columnsByField[column.field].headerRef,
3398
- tableColRef: columnsByField[column.field].tableColRef,
3434
+ headerRef: visibleColumnsByField[column.field]?.headerRef,
3435
+ tableColRef: visibleColumnsByField[column.field]?.tableColRef,
3399
3436
  isCellEditable: editMode && (typeof column.isCellEditable === "function" ? column.isCellEditable : column.isCellEditable ?? true),
3400
3437
  sort: sortModel.find((sort) => sort.field === column.field)?.sort,
3401
- sortOrder: columnsByField[column.field]?.sortOrder || sortOrder,
3438
+ sortOrder: allColumnsByField[column.field]?.sortOrder || sortOrder,
3402
3439
  isPinned,
3403
- isLastStartPinnedColumn: isLeftPinned && [...pinnedColumns?.left || []].pop() === column.field,
3404
- isLastEndPinnedColumn: isRightPinned && (pinnedColumns?.right?.[0] ?? null) === column.field,
3405
- pinnedStartPosition: pinnedColumns?.left?.slice(0, isLeftPinned ? pinnedColumns.left.indexOf(column.field) : pinnedColumns.left.length).reduce((acc, curr) => acc + getWidth(curr), 0),
3406
- pinnedEndPosition: pinnedColumns?.right?.slice(isRightPinned ? pinnedColumns.right.indexOf(column.field) + 1 : 0).reduce((acc, curr) => acc + getWidth(curr), 0)
3440
+ isLastStartPinnedColumn: isLeftPinned && [...effectivePinnedLeft || []].pop() === column.field,
3441
+ isLastEndPinnedColumn: isRightPinned && (effectivePinnedRight?.[0] ?? null) === column.field,
3442
+ pinnedStartPosition: effectivePinnedLeft?.slice(0, isLeftPinned ? effectivePinnedLeft.indexOf(column.field) : effectivePinnedLeft.length).reduce((acc, curr) => acc + getWidth(curr), 0),
3443
+ pinnedEndPosition: effectivePinnedRight?.slice(isRightPinned ? effectivePinnedRight.indexOf(column.field) + 1 : 0).reduce((acc, curr) => acc + getWidth(curr), 0)
3407
3444
  };
3408
3445
  });
3409
3446
  }, [
3447
+ visibleColumns,
3410
3448
  reorderedColumns,
3411
3449
  rows,
3412
- pinnedColumns?.left,
3413
- pinnedColumns?.right,
3414
- columnsByField,
3450
+ effectivePinnedLeft,
3451
+ effectivePinnedRight,
3452
+ visibleColumnsByField,
3453
+ allColumnsByField,
3415
3454
  editMode,
3416
3455
  sortModel,
3417
3456
  sortOrder,
@@ -3427,8 +3466,8 @@ function useDataTableRenderer({
3427
3466
  const handleSortChange = useCallback10(
3428
3467
  (props) => {
3429
3468
  const { field, currentSort, multiple } = props;
3430
- const column = columnsByField[field];
3431
- const columnSortOrder = column.sortOrder || sortOrder;
3469
+ const column = allColumnsByField[field];
3470
+ const columnSortOrder = column?.sortOrder || sortOrder;
3432
3471
  if (currentSort !== void 0) {
3433
3472
  const currentOrderIndex = columnSortOrder.indexOf(currentSort);
3434
3473
  const nextSortOrderIndex = (currentOrderIndex + 1) % columnSortOrder.length;
@@ -3445,7 +3484,7 @@ function useDataTableRenderer({
3445
3484
  setSortModel(newSortModel);
3446
3485
  }
3447
3486
  },
3448
- [sortOrder, columnsByField, sortModel, setSortModel]
3487
+ [sortOrder, allColumnsByField, sortModel, setSortModel]
3449
3488
  );
3450
3489
  useEffect6(() => {
3451
3490
  if (!paginationModel) {
@@ -3871,6 +3910,10 @@ function Component(props, apiRef) {
3871
3910
  loading,
3872
3911
  columnGroupingModel: _________________,
3873
3912
  // columnGroupingModel is used in useDataTableRenderer
3913
+ columnVisibilityModel: __________________,
3914
+ // columnVisibilityModel is used in useDataTableRenderer
3915
+ onColumnVisibilityModelChange: ___________________,
3916
+ // onColumnVisibilityModelChange is used in useDataTableRenderer
3874
3917
  slots: {
3875
3918
  checkbox: RenderCheckbox = Checkbox_default,
3876
3919
  toolbar: Toolbar,
@@ -4110,7 +4153,7 @@ function Component(props, apiRef) {
4110
4153
  width: c.width
4111
4154
  }
4112
4155
  }
4113
- ))), /* @__PURE__ */ React25.createElement("thead", null, processedColumnGroups && processedColumnGroups.groups.map((levelGroups, level) => /* @__PURE__ */ React25.createElement("tr", { key: `group-level-${level}` }, checkboxSelection && level === 0 && /* @__PURE__ */ React25.createElement(
4156
+ ))), /* @__PURE__ */ React25.createElement("thead", null, processedColumnGroups && processedColumnGroups.groups.length > 0 && processedColumnGroups.groups.map((levelGroups, level) => /* @__PURE__ */ React25.createElement("tr", { key: `group-level-${level}` }, checkboxSelection && level === 0 && /* @__PURE__ */ React25.createElement(
4114
4157
  "th",
4115
4158
  {
4116
4159
  rowSpan: processedColumnGroups.maxLevel + 2,
@@ -4130,7 +4173,7 @@ function Component(props, apiRef) {
4130
4173
  ...checkboxProps
4131
4174
  }
4132
4175
  )
4133
- ), level > 0 && Array.from({ length: levelGroups[0]?.startIndex || 0 }).map((_2, i) => /* @__PURE__ */ React25.createElement("th", { key: `empty-${level}-${i}` })), levelGroups.map((group, groupIndex) => {
4176
+ ), level > 0 && Array.from({ length: levelGroups[0]?.startIndex || 0 }).map((_2, i) => /* @__PURE__ */ React25.createElement("th", { key: `empty-${level}-${i}` })), levelGroups.filter((g) => g.colspan > 0).map((group, groupIndex) => {
4134
4177
  const nextGroup = levelGroups[groupIndex + 1];
4135
4178
  const emptyCells = nextGroup ? nextGroup.startIndex - (group.startIndex + group.colspan) : columns.length - (group.startIndex + group.colspan);
4136
4179
  const params = { groupId: group.groupId };
@@ -4148,7 +4191,7 @@ function Component(props, apiRef) {
4148
4191
  },
4149
4192
  group.headerName ?? group.groupId
4150
4193
  ), emptyCells > 0 && Array.from({ length: emptyCells }).map((_2, i) => /* @__PURE__ */ React25.createElement("th", { key: `empty-between-${level}-${groupIndex}-${i}`, colSpan: 1 })));
4151
- }))), /* @__PURE__ */ React25.createElement("tr", null, !processedColumnGroups && checkboxSelection && /* @__PURE__ */ React25.createElement(
4194
+ }))), /* @__PURE__ */ React25.createElement("tr", null, (!processedColumnGroups || processedColumnGroups.groups.length === 0) && checkboxSelection && /* @__PURE__ */ React25.createElement(
4152
4195
  "th",
4153
4196
  {
4154
4197
  style: {