feat(ui,dashboard): Add DataTable block (#10024)

**What**
- Adds opinionated DataTable block to `@medusajs/ui` 
- Adds new DataTable to `@medusajs/dashboard` that uses the above mentioned block as the primitive.

The PR also replaces the table on /customer-groups and the variants table on /products/:id with the new DataTable, to provide an example of it's usage. The previous DataTable component has been renamed to `_DataTable` and has been deprecated.

**Note**
This PR has a lot of LOC. 5,346 of these changes are the fr.json file, which wasn't formatted correctly before. When adding the new translations needed for this PR the file was formatted which caused each line to change to have the proper indentation.

Resolves CMRC-333
This commit is contained in:
Kasper Fabricius Kristensen
2025-01-20 14:26:12 +01:00
committed by GitHub
parent c3976a312b
commit 147c0e5a35
130 changed files with 9238 additions and 3884 deletions
@@ -0,0 +1,76 @@
"use client"
import { createColumnHelper as createColumnHelperTanstack } from "@tanstack/react-table"
import * as React from "react"
import { DataTableActionCell } from "../components/data-table-action-cell"
import {
DataTableSelectCell,
DataTableSelectHeader,
} from "../components/data-table-select-cell"
import {
DataTableActionColumnDef,
DataTableColumnHelper,
DataTableSelectColumnDef,
DataTableSortableColumnDef,
DataTableSortableColumnDefMeta,
} from "../types"
const createDataTableColumnHelper = <
TData,
>(): DataTableColumnHelper<TData> => {
const { accessor: accessorTanstack, display } =
createColumnHelperTanstack<TData>()
return {
accessor: (accessor, column) => {
const {
sortLabel,
sortAscLabel,
sortDescLabel,
meta,
enableSorting,
...rest
} = column as any & DataTableSortableColumnDef
const extendedMeta: DataTableSortableColumnDefMeta = {
___sortMetaData: { sortLabel, sortAscLabel, sortDescLabel },
...(meta || {}),
}
return accessorTanstack(accessor, {
...rest,
enableSorting: enableSorting ?? false,
meta: extendedMeta,
})
},
display,
action: ({ actions, ...props }: DataTableActionColumnDef<TData>) =>
display({
id: "action",
cell: (ctx) => <DataTableActionCell ctx={ctx} />,
meta: {
___actions: actions,
...(props.meta || {}),
},
...props,
}),
select: (props?: DataTableSelectColumnDef<TData>) =>
display({
id: "select",
header: props?.header
? props.header
: (ctx) => <DataTableSelectHeader ctx={ctx} />,
cell: props?.cell
? props.cell
: (ctx) => <DataTableSelectCell ctx={ctx} />,
}),
}
}
const helper = createColumnHelperTanstack()
helper.accessor("name", {
meta: {},
})
export { createDataTableColumnHelper }
@@ -0,0 +1,8 @@
import { DataTableCommand } from "../types"
const createDataTableCommandHelper = () => ({
command: (command: DataTableCommand) => command,
})
export { createDataTableCommandHelper }
@@ -0,0 +1,14 @@
import { DeepKeys } from "@tanstack/react-table"
import { DataTableFilter, DataTableFilterProps } from "../types"
const createDataTableFilterHelper = <TData>() => ({
accessor: (accessor: DeepKeys<TData>, props: DataTableFilterProps) => ({
id: accessor,
...props,
}),
custom: <T extends DataTableFilterProps>(props: DataTableFilter<T>) => props,
})
export { createDataTableFilterHelper }
@@ -0,0 +1,19 @@
import { DataTableDateComparisonOperator } from "../types";
export function isDateComparisonOperator(
value: unknown
): value is DataTableDateComparisonOperator {
if (typeof value !== "object" || value === null) {
return false
}
const validOperators = ["$gte", "$lte", "$gt", "$lt"]
const hasAtLeastOneOperator = validOperators.some((op) => op in value)
const allPropertiesValid = Object.entries(value as Record<string, unknown>)
.every(([key, val]) =>
validOperators.includes(key) && (typeof val === "string" || val === undefined)
)
return hasAtLeastOneOperator && allPropertiesValid
}