@jielga/tmdatagrid 2.0.1 → 2.1.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.
@@ -12,6 +12,7 @@ import {
12
12
  columnGroupingFeature,
13
13
  columnOrderingFeature,
14
14
  columnPinningFeature,
15
+ type ColumnPinningState,
15
16
  columnResizingFeature,
16
17
  columnSizingFeature,
17
18
  columnVisibilityFeature,
@@ -77,7 +78,11 @@ import {
77
78
  type TMDataGridColumnType,
78
79
  tmDataGridFilterFn,
79
80
  } from "./core/filterOperators";
80
- import { getColumnDefaultOperator, isControlColumn } from "./core/columnUtils";
81
+ import {
82
+ getColumnDefaultOperator,
83
+ isControlColumn,
84
+ isGeneratedColumn,
85
+ } from "./core/columnUtils";
81
86
  import type { TMDataGridColumnFilterOptions } from "./core/filterControls";
82
87
  import {
83
88
  resolveFilterOptions,
@@ -1050,6 +1055,16 @@ export type UseTMDataGridOptions<TData extends RowData> = Omit<
1050
1055
  * state. An approximate value is enough.
1051
1056
  */
1052
1057
  renderDetailsEstHeight?: number;
1058
+ /**
1059
+ * Which edge the details lane sits on. Defaults to `"left"`.
1060
+ *
1061
+ * `"left"` pins the chevron after the row number, checkbox and tree lanes,
1062
+ * before every column of yours. `"right"` pins it after every column of
1063
+ * yours, inside the edit lane, so the chevron closes the row the way an
1064
+ * accordion's does. On either edge it stays a structural lane: the user
1065
+ * cannot move, hide or unpin it.
1066
+ */
1067
+ detailsColumnPosition?: "left" | "right";
1053
1068
  /**
1054
1069
  * Rows the virtualizer keeps mounted above and below the viewport. Defaults
1055
1070
  * to 6.
@@ -1149,6 +1164,7 @@ export function useTMDataGrid<TData extends RowData>({
1149
1164
  editing,
1150
1165
  renderDetails,
1151
1166
  renderDetailsEstHeight = DEFAULT_DETAILS_EST_HEIGHT,
1167
+ detailsColumnPosition = "left",
1152
1168
  overscan = DEFAULT_OVERSCAN,
1153
1169
  ...options
1154
1170
  }: UseTMDataGridOptions<TData>): TMDataGridApi<TData> {
@@ -1250,6 +1266,35 @@ export function useTMDataGrid<TData extends RowData>({
1250
1266
  // rest hold two - it gets the wider track.
1251
1267
  const editWideLane = editDraft;
1252
1268
 
1269
+ // The generated lanes are structurally pinned, outermost first on each edge,
1270
+ // and re-applied on top of anything restored: a snapshot cannot unpin one,
1271
+ // and a snapshot taken before `detailsColumnPosition` changed cannot pin the
1272
+ // details lane to the edge it has since left.
1273
+ const structuralPinning = (
1274
+ restored: Partial<ColumnPinningState> | undefined,
1275
+ ): ColumnPinningState => {
1276
+ const own = (ids: string[] | undefined) =>
1277
+ (ids ?? []).filter((id) => !isGeneratedColumn(id));
1278
+ const lane = (enabled: boolean, id: string) =>
1279
+ enabled && pinningEnabled ? [id] : [];
1280
+ const detailsOn = (edge: "left" | "right") =>
1281
+ detailsColumnEnabled && detailsColumnPosition === edge;
1282
+ return {
1283
+ start: [
1284
+ ...lane(rowNumbersEnabled, ROW_NUMBER_COLUMN_ID),
1285
+ ...lane(selectColumnEnabled, SELECT_COLUMN_ID),
1286
+ ...lane(groupColumnEnabled, GROUP_COLUMN_ID),
1287
+ ...lane(detailsOn("left"), DETAILS_COLUMN_ID),
1288
+ ...own(restored?.start),
1289
+ ],
1290
+ end: [
1291
+ ...own(restored?.end),
1292
+ ...lane(detailsOn("right"), DETAILS_COLUMN_ID),
1293
+ ...lane(editColumnEnabled, EDIT_COLUMN_ID),
1294
+ ],
1295
+ };
1296
+ };
1297
+
1253
1298
  const columns = useMemo(() => {
1254
1299
  const base = withTMDataGridDefaults<TData>(
1255
1300
  options.columns as ReadonlyArray<TMDataGridColumnDef<TData>>,
@@ -1262,8 +1307,12 @@ export function useTMDataGrid<TData extends RowData>({
1262
1307
  //
1263
1308
  // The order is the order they are pinned in, and it follows what each one
1264
1309
  // is about: tick a row, find it in the tree the user grouped it into, then
1265
- // open it. The details chevron sits last because it acts on the record the
1266
- // lanes to its left have narrowed down to.
1310
+ // open it. The details chevron sits innermost on whichever edge it was
1311
+ // given - last of the left lanes, or first of the right ones - because it
1312
+ // acts on the record the lanes outside it have narrowed down to.
1313
+ const detailsColumn = detailsColumnEnabled
1314
+ ? [createDetailsColumn<TData>(detailsColumnLabel)]
1315
+ : [];
1267
1316
  return [
1268
1317
  // The gutter sits outside everything, the way a spreadsheet's does.
1269
1318
  ...(rowNumbersEnabled
@@ -1273,10 +1322,9 @@ export function useTMDataGrid<TData extends RowData>({
1273
1322
  ? [createSelectColumn<TData>(selectColumnLabel)]
1274
1323
  : []),
1275
1324
  ...(groupColumnEnabled ? [createGroupColumn<TData>(groupColumnLabel)] : []),
1276
- ...(detailsColumnEnabled
1277
- ? [createDetailsColumn<TData>(detailsColumnLabel)]
1278
- : []),
1325
+ ...(detailsColumnPosition === "left" ? detailsColumn : []),
1279
1326
  ...base,
1327
+ ...(detailsColumnPosition === "right" ? detailsColumn : []),
1280
1328
  // Last and pinned right - the row's Save belongs at the end of the row.
1281
1329
  ...(editColumnEnabled
1282
1330
  ? [createEditColumn<TData>(editColumnLabel, editWideLane)]
@@ -1287,6 +1335,7 @@ export function useTMDataGrid<TData extends RowData>({
1287
1335
  rowNumbersEnabled,
1288
1336
  selectColumnEnabled,
1289
1337
  detailsColumnEnabled,
1338
+ detailsColumnPosition,
1290
1339
  groupColumnEnabled,
1291
1340
  editColumnEnabled,
1292
1341
  editWideLane,
@@ -1619,37 +1668,14 @@ export function useTMDataGrid<TData extends RowData>({
1619
1668
  ? { [GROUP_COLUMN_ID]: initialGrouping.length > 0 }
1620
1669
  : {}),
1621
1670
  },
1622
- columnPinning: {
1623
- // The generated columns are structurally pinned, so they are re-applied
1624
- // on top of anything restored from storage.
1625
- start: [
1626
- ...(rowNumbersEnabled && pinningEnabled ? [ROW_NUMBER_COLUMN_ID] : []),
1627
- ...(selectColumnEnabled && pinningEnabled ? [SELECT_COLUMN_ID] : []),
1628
- ...(groupColumnEnabled && pinningEnabled ? [GROUP_COLUMN_ID] : []),
1629
- ...(detailsColumnEnabled && pinningEnabled ? [DETAILS_COLUMN_ID] : []),
1630
- ...(
1631
- persistedState.columnPinning?.start ??
1632
- options.initialState?.columnPinning?.start ??
1633
- []
1634
- ).filter(
1635
- (id) =>
1636
- id !== ROW_NUMBER_COLUMN_ID &&
1637
- id !== SELECT_COLUMN_ID &&
1638
- id !== DETAILS_COLUMN_ID &&
1639
- id !== GROUP_COLUMN_ID,
1640
- ),
1641
- ],
1642
- // The edit lane mirrors the generated columns on the left: structurally
1643
- // pinned, outermost, re-applied over anything restored.
1644
- end: [
1645
- ...(
1646
- persistedState.columnPinning?.end ??
1647
- options.initialState?.columnPinning?.end ??
1648
- []
1649
- ).filter((id) => id !== EDIT_COLUMN_ID),
1650
- ...(editColumnEnabled && pinningEnabled ? [EDIT_COLUMN_ID] : []),
1651
- ],
1652
- },
1671
+ columnPinning: structuralPinning({
1672
+ start:
1673
+ persistedState.columnPinning?.start ??
1674
+ options.initialState?.columnPinning?.start,
1675
+ end:
1676
+ persistedState.columnPinning?.end ??
1677
+ options.initialState?.columnPinning?.end,
1678
+ }),
1653
1679
  pagination: {
1654
1680
  pageIndex: 0,
1655
1681
  pageSize: 25,
@@ -1964,27 +1990,7 @@ export function useTMDataGrid<TData extends RowData>({
1964
1990
  });
1965
1991
  table.setColumnSizing({ ...initial?.columnSizing });
1966
1992
  table.setColumnOrder([...(initial?.columnOrder ?? [])]);
1967
- table.setColumnPinning({
1968
- start: [
1969
- ...(rowNumbersEnabled && pinningEnabled ? [ROW_NUMBER_COLUMN_ID] : []),
1970
- ...(selectColumnEnabled && pinningEnabled ? [SELECT_COLUMN_ID] : []),
1971
- ...(groupColumnEnabled && pinningEnabled ? [GROUP_COLUMN_ID] : []),
1972
- ...(detailsColumnEnabled && pinningEnabled ? [DETAILS_COLUMN_ID] : []),
1973
- ...(initial?.columnPinning?.start ?? []).filter(
1974
- (id) =>
1975
- id !== ROW_NUMBER_COLUMN_ID &&
1976
- id !== SELECT_COLUMN_ID &&
1977
- id !== DETAILS_COLUMN_ID &&
1978
- id !== GROUP_COLUMN_ID,
1979
- ),
1980
- ],
1981
- end: [
1982
- ...(initial?.columnPinning?.end ?? []).filter(
1983
- (id) => id !== EDIT_COLUMN_ID,
1984
- ),
1985
- ...(editColumnEnabled && pinningEnabled ? [EDIT_COLUMN_ID] : []),
1986
- ],
1987
- });
1993
+ table.setColumnPinning(structuralPinning(initial?.columnPinning));
1988
1994
  };
1989
1995
  const resetSettings = useCallback(() => resetSettingsRef.current(), []);
1990
1996