docs: add documentation for DataTable (#11095)
* docs: add documentation for DataTable * update package versions
This commit is contained in:
76
www/apps/ui/src/examples/data-table-commands.tsx
Normal file
76
www/apps/ui/src/examples/data-table-commands.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { DataTable, DataTableRowSelectionState, Heading, createDataTableColumnHelper, createDataTableCommandHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useState } from "react"
|
||||
|
||||
let products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20,
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
// Commands requires a select column.
|
||||
columnHelper.select(),
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
const commandHelper = createDataTableCommandHelper()
|
||||
|
||||
const useCommands = () => {
|
||||
return [
|
||||
commandHelper.command({
|
||||
label: "Delete",
|
||||
shortcut: "D",
|
||||
action: async (selection) => {
|
||||
const productsToDeleteIds = Object.keys(selection)
|
||||
|
||||
alert(`You deleted product(s) with IDs: ${productsToDeleteIds.join()}`)
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
export default function ProductTable () {
|
||||
const [rowSelection, setRowSelection] = useState<DataTableRowSelectionState>({})
|
||||
|
||||
const commands = useCommands()
|
||||
|
||||
const instance = useDataTable({
|
||||
data: products,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
commands,
|
||||
rowSelection: {
|
||||
state: rowSelection,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable instance={instance}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
{/** This component will the command bar when the user has selected at least one row. **/}
|
||||
<DataTable.CommandBar selectedLabel={(count) => `${count} selected`} />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
59
www/apps/ui/src/examples/data-table-custom-cell.tsx
Normal file
59
www/apps/ui/src/examples/data-table-custom-cell.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { createDataTableColumnHelper, useDataTable, DataTable, Heading, Badge } from "@medusajs/ui"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10,
|
||||
is_active: true
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20,
|
||||
is_active: false
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("is_active", {
|
||||
header: "Status",
|
||||
cell: ({ getValue }) => {
|
||||
const isActive = getValue()
|
||||
return (
|
||||
<Badge color={isActive ? "green" : "grey"} size="xsmall">
|
||||
{isActive ? "Active" : "Inactive"}
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
})
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const table = useDataTable({
|
||||
columns,
|
||||
data: products,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex flex-col items-start justify-between gap-2 md:flex-row md:items-center">
|
||||
<Heading>Products</Heading>
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
)
|
||||
}
|
||||
46
www/apps/ui/src/examples/data-table-demo.tsx
Normal file
46
www/apps/ui/src/examples/data-table-demo.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { createDataTableColumnHelper, useDataTable, DataTable, Heading } from "@medusajs/ui"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const table = useDataTable({
|
||||
columns,
|
||||
data: products,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex flex-col items-start justify-between gap-2 md:flex-row md:items-center">
|
||||
<Heading>Products</Heading>
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
)
|
||||
}
|
||||
137
www/apps/ui/src/examples/data-table-filters-date.tsx
Normal file
137
www/apps/ui/src/examples/data-table-filters-date.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
import { DataTable, DataTableFilteringState, Heading, createDataTableColumnHelper, createDataTableFilterHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10,
|
||||
created_at: new Date()
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20,
|
||||
created_at: new Date("2026-01-01")
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("created_at", {
|
||||
header: "Created At",
|
||||
cell: ({ getValue }) => {
|
||||
return getValue().toLocaleString()
|
||||
}
|
||||
}),
|
||||
]
|
||||
|
||||
const filterHelper = createDataTableFilterHelper<typeof products[0]>()
|
||||
|
||||
const filters = [
|
||||
filterHelper.accessor("created_at", {
|
||||
type: "date",
|
||||
label: "Created At",
|
||||
format: "date",
|
||||
formatDateValue: (date) => date.toLocaleString(),
|
||||
rangeOptionStartLabel: "From",
|
||||
rangeOptionEndLabel: "To",
|
||||
rangeOptionLabel: "Between",
|
||||
options: [
|
||||
{
|
||||
label: "Today",
|
||||
value: {
|
||||
$gte: new Date(new Date().setHours(0, 0, 0, 0)).toString(),
|
||||
$lte: new Date(new Date().setHours(23, 59, 59, 999)).toString()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Yesterday",
|
||||
value: {
|
||||
$gte: new Date(new Date().setHours(0, 0, 0, 0) - 24 * 60 * 60 * 1000).toString(),
|
||||
$lte: new Date(new Date().setHours(0, 0, 0, 0)).toString()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Last Week",
|
||||
value: {
|
||||
$gte: new Date(new Date().setHours(0, 0, 0, 0) - 7 * 24 * 60 * 60 * 1000).toString(),
|
||||
$lte: new Date(new Date().setHours(0, 0, 0, 0)).toString()
|
||||
},
|
||||
},
|
||||
]
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [filtering, setFiltering] = useState<DataTableFilteringState>({})
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
return products.filter((product) => {
|
||||
return Object.entries(filtering).every(([key, value]) => {
|
||||
if (!value) {
|
||||
return true
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
// @ts-ignore
|
||||
return product[key].toString().toLowerCase().includes(value.toString().toLowerCase())
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
// @ts-ignore
|
||||
return value.includes(product[key].toLowerCase())
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
// @ts-ignore
|
||||
const date = new Date(product[key])
|
||||
let matching = false
|
||||
if ("$gte" in value && value.$gte) {
|
||||
matching = date >= new Date(value.$gte as number)
|
||||
}
|
||||
if ("$lte" in value && value.$lte) {
|
||||
matching = date <= new Date(value.$lte as number)
|
||||
}
|
||||
if ("$lt" in value && value.$lt) {
|
||||
matching = date < new Date(value.$lt as number)
|
||||
}
|
||||
if ("$gt" in value && value.$gt) {
|
||||
matching = date > new Date(value.$gt as number)
|
||||
}
|
||||
return matching
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [filtering])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
filtering: {
|
||||
state: filtering,
|
||||
onFilteringChange: setFiltering,
|
||||
},
|
||||
filters
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/** This component will render a menu that allows the user to choose which filters to apply to the table data. **/}
|
||||
<DataTable.FilterMenu tooltip="Filter" />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
107
www/apps/ui/src/examples/data-table-filters-initial.tsx
Normal file
107
www/apps/ui/src/examples/data-table-filters-initial.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import { DataTable, DataTableFilteringState, Heading, createDataTableColumnHelper, createDataTableFilterHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
const filterHelper = createDataTableFilterHelper<typeof products[0]>()
|
||||
|
||||
const filters = [
|
||||
filterHelper.accessor("title", {
|
||||
type: "select",
|
||||
label: "Title",
|
||||
options: products.map((product) => ({
|
||||
label: product.title,
|
||||
value: product.title.toLowerCase()
|
||||
}))
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [filtering, setFiltering] = useState<DataTableFilteringState>({
|
||||
title: ["shirt"]
|
||||
})
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
return products.filter((product) => {
|
||||
return Object.entries(filtering).every(([key, value]) => {
|
||||
if (!value) {
|
||||
return true
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
// @ts-ignore
|
||||
return product[key].toString().toLowerCase().includes(value.toString().toLowerCase())
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
// @ts-ignore
|
||||
return value.includes(product[key].toLowerCase())
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
// @ts-ignore
|
||||
const date = new Date(product[key])
|
||||
let matching = false
|
||||
if ("$gte" in value && value.$gte) {
|
||||
matching = date >= new Date(value.$gte as number)
|
||||
}
|
||||
if ("$lte" in value && value.$lte) {
|
||||
matching = date <= new Date(value.$lte as number)
|
||||
}
|
||||
if ("$lt" in value && value.$lt) {
|
||||
matching = date < new Date(value.$lt as number)
|
||||
}
|
||||
if ("$gt" in value && value.$gt) {
|
||||
matching = date > new Date(value.$gt as number)
|
||||
}
|
||||
return matching
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [filtering])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
filtering: {
|
||||
state: filtering,
|
||||
onFilteringChange: setFiltering,
|
||||
},
|
||||
filters
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/** This component will render a menu that allows the user to choose which filters to apply to the table data. **/}
|
||||
<DataTable.FilterMenu tooltip="Filter" />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
105
www/apps/ui/src/examples/data-table-filters.tsx
Normal file
105
www/apps/ui/src/examples/data-table-filters.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { DataTable, DataTableFilteringState, Heading, createDataTableColumnHelper, createDataTableFilterHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
const filterHelper = createDataTableFilterHelper<typeof products[0]>()
|
||||
|
||||
const filters = [
|
||||
filterHelper.accessor("title", {
|
||||
type: "select",
|
||||
label: "Title",
|
||||
options: products.map((product) => ({
|
||||
label: product.title,
|
||||
value: product.title.toLowerCase()
|
||||
}))
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [filtering, setFiltering] = useState<DataTableFilteringState>({})
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
return products.filter((product) => {
|
||||
return Object.entries(filtering).every(([key, value]) => {
|
||||
if (!value) {
|
||||
return true
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
// @ts-ignore
|
||||
return product[key].toString().toLowerCase().includes(value.toString().toLowerCase())
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
// @ts-ignore
|
||||
return value.includes(product[key].toLowerCase())
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
// @ts-ignore
|
||||
const date = new Date(product[key])
|
||||
let matching = false
|
||||
if ("$gte" in value && value.$gte) {
|
||||
matching = date >= new Date(value.$gte as number)
|
||||
}
|
||||
if ("$lte" in value && value.$lte) {
|
||||
matching = date <= new Date(value.$lte as number)
|
||||
}
|
||||
if ("$lt" in value && value.$lt) {
|
||||
matching = date < new Date(value.$lt as number)
|
||||
}
|
||||
if ("$gt" in value && value.$gt) {
|
||||
matching = date > new Date(value.$gt as number)
|
||||
}
|
||||
return matching
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [filtering])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
filtering: {
|
||||
state: filtering,
|
||||
onFilteringChange: setFiltering,
|
||||
},
|
||||
filters
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/** This component will render a menu that allows the user to choose which filters to apply to the table data. **/}
|
||||
<DataTable.FilterMenu tooltip="Filter" />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
143
www/apps/ui/src/examples/data-table-pagination.tsx
Normal file
143
www/apps/ui/src/examples/data-table-pagination.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
import { DataTable, Heading, createDataTableColumnHelper, useDataTable, type DataTablePaginationState } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Hat",
|
||||
price: 15
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Socks",
|
||||
price: 5
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "Shoes",
|
||||
price: 50
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "Jacket",
|
||||
price: 100
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "Scarf",
|
||||
price: 25
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "Gloves",
|
||||
price: 12
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "Belt",
|
||||
price: 18
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
title: "Sunglasses",
|
||||
price: 30
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
title: "Watch",
|
||||
price: 200
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
title: "Tie",
|
||||
price: 20
|
||||
},
|
||||
{
|
||||
id: "13",
|
||||
title: "Sweater",
|
||||
price: 40
|
||||
},
|
||||
{
|
||||
id: "14",
|
||||
title: "Jeans",
|
||||
price: 60
|
||||
},
|
||||
{
|
||||
id: "15",
|
||||
title: "Shorts",
|
||||
price: 25
|
||||
},
|
||||
{
|
||||
id: "16",
|
||||
title: "Blouse",
|
||||
price: 35
|
||||
},
|
||||
{
|
||||
id: "17",
|
||||
title: "Dress",
|
||||
price: 80
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
export default function ProductTable () {
|
||||
const [pagination, setPagination] = useState<DataTablePaginationState>({
|
||||
pageSize: PAGE_SIZE,
|
||||
pageIndex: 0,
|
||||
})
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
return products.slice(
|
||||
pagination.pageIndex * pagination.pageSize,
|
||||
(pagination.pageIndex + 1) * pagination.pageSize
|
||||
)
|
||||
}, [pagination])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
rowCount: products.length,
|
||||
getRowId: (product) => product.id,
|
||||
pagination: {
|
||||
// Pass the pagination state and updater to the table instance
|
||||
state: pagination,
|
||||
onPaginationChange: setPagination,
|
||||
},
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar>
|
||||
<Heading>Products</Heading>
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
{/** This component will render the pagination controls **/}
|
||||
<DataTable.Pagination />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
60
www/apps/ui/src/examples/data-table-search.tsx
Normal file
60
www/apps/ui/src/examples/data-table-search.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createDataTableColumnHelper, useDataTable, DataTable, Heading } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
enableSorting: true,
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
enableSorting: true,
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [search, setSearch] = useState<string>("")
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
return products.filter((product) => product.title.toLowerCase().includes(search.toLowerCase()))
|
||||
}, [search])
|
||||
|
||||
const table = useDataTable({
|
||||
columns,
|
||||
data: shownProducts,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
isLoading: false,
|
||||
// Pass the state and onSearchChange to the table instance.
|
||||
search: {
|
||||
state: search,
|
||||
onSearchChange: setSearch
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex flex-col items-start justify-between gap-2 md:flex-row md:items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/* This component renders the search bar */}
|
||||
<DataTable.Search placeholder="Search..." />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
)
|
||||
}
|
||||
85
www/apps/ui/src/examples/data-table-sorting-initial.tsx
Normal file
85
www/apps/ui/src/examples/data-table-sorting-initial.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { DataTable, DataTableSortingState, Heading, createDataTableColumnHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
// Enables sorting for the column.
|
||||
enableSorting: true,
|
||||
// If omitted, the header will be used instead if it's a string,
|
||||
// otherwise the accessor key (id) will be used.
|
||||
sortLabel: "Title",
|
||||
// If omitted the default value will be "A-Z"
|
||||
sortAscLabel: "A-Z",
|
||||
// If omitted the default value will be "Z-A"
|
||||
sortDescLabel: "Z-A",
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [sorting, setSorting] = useState<DataTableSortingState | null>({
|
||||
id: "title",
|
||||
desc: false,
|
||||
})
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
if (!sorting) {
|
||||
return products
|
||||
}
|
||||
return products.slice().sort((a, b) => {
|
||||
// @ts-ignore
|
||||
const aVal = a[sorting.id]
|
||||
// @ts-ignore
|
||||
const bVal = b[sorting.id]
|
||||
if (aVal < bVal) {
|
||||
return sorting.desc ? 1 : -1
|
||||
}
|
||||
if (aVal > bVal) {
|
||||
return sorting.desc ? -1 : 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
}, [sorting])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
sorting: {
|
||||
// Pass the pagination state and updater to the table instance
|
||||
state: sorting,
|
||||
onSortingChange: setSorting,
|
||||
},
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/** This component will render a menu that allows the user to choose which column to sort by and in what direction. **/}
|
||||
<DataTable.SortingMenu tooltip="Sort" />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
82
www/apps/ui/src/examples/data-table-sorting.tsx
Normal file
82
www/apps/ui/src/examples/data-table-sorting.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import { DataTable, DataTableSortingState, Heading, createDataTableColumnHelper, useDataTable } from "@medusajs/ui"
|
||||
import { useMemo, useState } from "react"
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Shirt",
|
||||
price: 10
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Pants",
|
||||
price: 20
|
||||
}
|
||||
]
|
||||
|
||||
const columnHelper = createDataTableColumnHelper<typeof products[0]>()
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("title", {
|
||||
header: "Title",
|
||||
// Enables sorting for the column.
|
||||
enableSorting: true,
|
||||
// If omitted, the header will be used instead if it's a string,
|
||||
// otherwise the accessor key (id) will be used.
|
||||
sortLabel: "Title",
|
||||
// If omitted the default value will be "A-Z"
|
||||
sortAscLabel: "A-Z",
|
||||
// If omitted the default value will be "Z-A"
|
||||
sortDescLabel: "Z-A",
|
||||
}),
|
||||
columnHelper.accessor("price", {
|
||||
header: "Price",
|
||||
}),
|
||||
]
|
||||
|
||||
export default function ProductTable () {
|
||||
const [sorting, setSorting] = useState<DataTableSortingState | null>(null);
|
||||
|
||||
const shownProducts = useMemo(() => {
|
||||
if (!sorting) {
|
||||
return products
|
||||
}
|
||||
return products.slice().sort((a, b) => {
|
||||
// @ts-ignore
|
||||
const aVal = a[sorting.id]
|
||||
// @ts-ignore
|
||||
const bVal = b[sorting.id]
|
||||
if (aVal < bVal) {
|
||||
return sorting.desc ? 1 : -1
|
||||
}
|
||||
if (aVal > bVal) {
|
||||
return sorting.desc ? -1 : 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
}, [sorting])
|
||||
|
||||
const table = useDataTable({
|
||||
data: shownProducts,
|
||||
columns,
|
||||
getRowId: (product) => product.id,
|
||||
rowCount: products.length,
|
||||
sorting: {
|
||||
// Pass the pagination state and updater to the table instance
|
||||
state: sorting,
|
||||
onSortingChange: setSorting,
|
||||
},
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable instance={table}>
|
||||
<DataTable.Toolbar className="flex justify-between items-center">
|
||||
<Heading>Products</Heading>
|
||||
{/** This component will render a menu that allows the user to choose which column to sort by and in what direction. **/}
|
||||
<DataTable.SortingMenu tooltip="Sort" />
|
||||
</DataTable.Toolbar>
|
||||
<DataTable.Table />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user