🏷️(react) allow autocompletion for DataGrid's renderCell

Previously the type of the row parameter of renderCell was hardcoded as
Row. This wasn't ideal because the best case scenario we want it to enable
Typescript to use the type of rows props. Now that's the case.

Resolve #62
This commit is contained in:
Nathan Vasse
2023-05-24 17:21:14 +02:00
committed by NathanVss
parent 9127fd803c
commit 787bd3de75
6 changed files with 42 additions and 30 deletions

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": minor
---
allow autocompletion for DataGrid's renderCell

View File

@@ -1,6 +1,6 @@
import React from "react";
import { BaseProps, DataGrid } from ":/components/DataGrid/index";
import { BaseProps, DataGrid, Row } from ":/components/DataGrid/index";
export const DataList = ({ rows, ...props }: BaseProps) => {
export const DataList = <T extends Row>({ rows, ...props }: BaseProps<T>) => {
return <DataGrid {...props} displayHeader={false} rows={rows} />;
};

View File

@@ -10,18 +10,18 @@ import {
/**
* Handles sorting, pagination.
*/
export const SimpleDataGrid = ({
export const SimpleDataGrid = <T extends Row>({
rows,
defaultPaginationParams,
defaultSortModel = [],
...props
}: BaseProps & {
}: BaseProps<T> & {
/** Pagination default props, should never change. */
defaultPaginationParams?: Parameters<typeof usePagination>[0] | boolean;
/** Pagination default props, should never change. */
defaultSortModel?: SortModel;
}) => {
const [realRows, setRealRows] = useState<Row[]>([]);
const [realRows, setRealRows] = useState<T[]>([]);
const [sortModel, setSortModel] = useState<SortModel>(defaultSortModel);
const realPaginationParams = useMemo(() => {
if (typeof defaultPaginationParams === "boolean") {

View File

@@ -173,7 +173,7 @@ export const FullServerSide = () => {
sort: "desc",
},
]);
const [rows, setRows] = useState<any[]>([]);
const [rows, setRows] = useState<typeof database>([]);
useEffect(() => {
// Simulate server-side fetching.
@@ -258,19 +258,29 @@ export const DataListOnly = () => {
id: `list key for element ${index}`,
title: faker.random.word(),
date: faker.date.past(1).toISOString(),
action: (
<Button size="small" color="secondary">
Do it
</Button>
),
})),
[]
);
const columns = [{ field: "title" }, { field: "date" }, { field: "action" }];
return (
<CunninghamProvider>
<DataList rows={database} columns={columns} />
<DataList
rows={database}
columns={[
{ field: "title" },
{ field: "date" },
{
headerName: "action",
renderCell: () => {
return (
<Button size="small" color="secondary">
Do it
</Button>
);
},
},
]}
/>
</CunninghamProvider>
);
};

View File

@@ -37,7 +37,7 @@ export interface BaseProps<T extends Row = Row> {
columns: Column<T>[];
rows: T[];
isLoading?: boolean;
enableRowSelection?: boolean | ((row: T) => boolean);
enableRowSelection?: TableOptions<T>["enableRowSelection"];
onRowSelectionChange?: (newSelection: RowSelectionState) => void;
rowSelection?: RowSelectionState;
}
@@ -47,11 +47,11 @@ interface Props<T extends Row = Row> extends BaseProps<T> {
sortModel?: SortModel;
onSortModelChange?: (newSortModel: SortModel) => void;
/** Options for the underlying tanstack table. */
tableOptions?: TableOptions<Row>;
tableOptions?: TableOptions<T>;
displayHeader?: boolean;
}
export const DataGrid = ({
export const DataGrid = <T extends Row>({
columns,
rows,
pagination,
@@ -63,7 +63,7 @@ export const DataGrid = ({
rowSelection,
tableOptions,
displayHeader = true,
}: Props) => {
}: Props<T>) => {
const { t } = useCunningham();
const headlessColumns = useHeadlessColumns({ columns, enableRowSelection });

View File

@@ -1,32 +1,27 @@
import {
CellContext,
ColumnDef,
createColumnHelper,
PaginationState,
SortingState,
} from "@tanstack/react-table";
import React, { ReactNode } from "react";
import {
ColumnDefBase,
DisplayColumnDef,
} from "@tanstack/table-core/src/types";
import React from "react";
import { Checkbox } from ":/components/Forms/Checkbox";
import { PaginationProps } from ":/components/Pagination";
import { Column, Row, SortModel } from ":/components/DataGrid/index";
import { BaseProps, Column, Row, SortModel } from ":/components/DataGrid/index";
import { useCunningham } from ":/components/Provider";
/**
* Converts Cunningham's columns to the underlying tanstack table.
*/
export const useHeadlessColumns = ({
export const useHeadlessColumns = <T extends Row>({
columns,
enableRowSelection,
}: {
columns: Column[];
enableRowSelection?: boolean | ((row: Row) => boolean);
}): ColumnDef<Row, any>[] => {
columns: Column<T>[];
enableRowSelection?: BaseProps<T>["enableRowSelection"];
}): ColumnDef<T, any>[] => {
const { t } = useCunningham();
const columnHelper = createColumnHelper<Row>();
const columnHelper = createColumnHelper<T>();
let headlessColumns = columns.map((column) => {
const opts = {
id: column.field ?? "actions",
@@ -34,7 +29,9 @@ export const useHeadlessColumns = ({
header: column.headerName,
};
if (column.field) {
return columnHelper.accessor(column.field, opts);
// The any cast is needed because the type of the accessor is hard-defined on react-table.
// On our side we only use string as type for simplicity purpose.
return columnHelper.accessor(column.field as any, opts);
}
return columnHelper.display({
...opts,