diff --git a/packages/next/src/views/Versions/cells/CreatedAt/index.tsx b/packages/next/src/views/Versions/cells/CreatedAt/index.tsx index 0326d4321..48c52e2ee 100644 --- a/packages/next/src/views/Versions/cells/CreatedAt/index.tsx +++ b/packages/next/src/views/Versions/cells/CreatedAt/index.tsx @@ -36,5 +36,9 @@ export const CreatedAtCell: React.FC = ({ if (globalSlug) to = `${admin}/globals/${globalSlug}/versions/${versionID}` - return {cellData && formatDate(cellData, dateFormat, i18n.language)} + return ( + + {cellData && formatDate(cellData as Date | number | string, dateFormat, i18n.language)} + + ) } diff --git a/packages/next/src/views/Versions/cells/ID/index.tsx b/packages/next/src/views/Versions/cells/ID/index.tsx index 00e3d0592..fd9d096da 100644 --- a/packages/next/src/views/Versions/cells/ID/index.tsx +++ b/packages/next/src/views/Versions/cells/ID/index.tsx @@ -4,5 +4,5 @@ import React, { Fragment } from 'react' export const IDCell: React.FC = () => { const { cellData } = useTableCell() - return {cellData} + return {cellData as number | string} } diff --git a/packages/payload/src/admin/elements/Cell.ts b/packages/payload/src/admin/elements/Cell.ts index 2317a2d22..596f8b437 100644 --- a/packages/payload/src/admin/elements/Cell.ts +++ b/packages/payload/src/admin/elements/Cell.ts @@ -9,7 +9,9 @@ import type { SelectField, } from '../../fields/config/types.js' -export type CellProps = { +export type RowData = Record + +export type CellComponentProps = { /** * A custom component to override the default cell component. If this is not set, the React component will be * taken from cellComponents based on the field type. @@ -32,19 +34,18 @@ export type CellProps = { onClick?: (args: { cellData: unknown collectionSlug: SanitizedCollectionConfig['slug'] - rowData: Record + rowData: RowData }) => void options?: SelectField['options'] relationTo?: RelationshipField['relationTo'] richTextComponentMap?: Map // any should be MappedField } -export type CellComponentProps = { - cellData: Data +export type DefaultCellComponentProps = CellComponentProps & { + cellData: T customCellContext?: { collectionSlug?: SanitizedCollectionConfig['slug'] uploadConfig?: SanitizedCollectionConfig['upload'] } - richTextComponentMap?: Map - rowData?: Record + rowData: RowData } diff --git a/packages/payload/src/admin/types.ts b/packages/payload/src/admin/types.ts index 20bfd82a0..5e3eec2da 100644 --- a/packages/payload/src/admin/types.ts +++ b/packages/payload/src/admin/types.ts @@ -1,5 +1,5 @@ export type { RichTextAdapter, RichTextFieldProps } from './RichText.js' -export type { CellComponentProps, CellProps } from './elements/Cell.js' +export type { CellComponentProps, DefaultCellComponentProps } from './elements/Cell.js' export type { ConditionalDateProps } from './elements/DatePicker.js' export type { DayPickerProps, SharedProps, TimePickerProps } from './elements/DatePicker.js' export type { DefaultPreviewButtonProps } from './elements/PreviewButton.js' diff --git a/packages/richtext-slate/src/cell/index.tsx b/packages/richtext-slate/src/cell/index.tsx index fc7dae6b3..0073d521a 100644 --- a/packages/richtext-slate/src/cell/index.tsx +++ b/packages/richtext-slate/src/cell/index.tsx @@ -1,9 +1,9 @@ 'use client' -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import React from 'react' -export const RichTextCell: React.FC> = ({ cellData }) => { +export const RichTextCell: React.FC> = ({ cellData }) => { const flattenedText = cellData?.map((i) => i?.children?.map((c) => c.text)).join(' ') // Limiting the number of characters shown is done in a CSS rule diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Array/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Array/index.tsx index dbe0a4457..653fec030 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Array/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Array/index.tsx @@ -1,12 +1,12 @@ 'use client' -import type { CellComponentProps, CellProps } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps } from 'payload/types' import { getTranslation } from '@payloadcms/translations' import { useTranslation } from '@payloadcms/ui/providers/Translation' import React from 'react' -export interface ArrayCellProps extends CellComponentProps[]> { - labels: CellProps['labels'] +export interface ArrayCellProps extends DefaultCellComponentProps[]> { + labels: CellComponentProps['labels'] } export const ArrayCell: React.FC = ({ cellData, labels }) => { diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Blocks/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Blocks/index.tsx index d37f90ac2..b66134d4f 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Blocks/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Blocks/index.tsx @@ -1,13 +1,13 @@ 'use client' -import type { CellComponentProps, CellProps } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps } from 'payload/types' import { getTranslation } from '@payloadcms/translations' import { useTranslation } from '@payloadcms/ui/providers/Translation' import React from 'react' -export interface BlocksCellProps extends CellComponentProps { - blocks: CellProps['blocks'] - labels: CellProps['labels'] +export interface BlocksCellProps extends DefaultCellComponentProps { + blocks: CellComponentProps['blocks'] + labels: CellComponentProps['labels'] } export const BlocksCell: React.FC = ({ blocks, cellData, labels }) => { diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Checkbox/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Checkbox/index.tsx index 261890329..45b2c09da 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Checkbox/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Checkbox/index.tsx @@ -1,11 +1,11 @@ 'use client' -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import React from 'react' import './index.scss' -export const CheckboxCell: React.FC> = ({ cellData }) => ( +export const CheckboxCell: React.FC> = ({ cellData }) => ( {JSON.stringify(cellData)} diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Code/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Code/index.tsx index 3efc27cae..836b917e9 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Code/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Code/index.tsx @@ -1,10 +1,10 @@ -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import React from 'react' import './index.scss' -export interface CodeCellProps extends CellComponentProps { +export interface CodeCellProps extends DefaultCellComponentProps { nowrap?: boolean } diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Date/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Date/index.tsx index 56f4862f3..0bb2df223 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Date/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Date/index.tsx @@ -1,16 +1,15 @@ 'use client' -import type { CellComponentProps, CellProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import { useConfig } from '@payloadcms/ui/providers/Config' import { useTranslation } from '@payloadcms/ui/providers/Translation' import { formatDate } from '@payloadcms/ui/utilities/formatDate' import React from 'react' -export interface DateCellProps extends CellComponentProps { - dateDisplayFormat?: CellProps['dateDisplayFormat'] -} - -export const DateCell: React.FC = ({ cellData, dateDisplayFormat }) => { +export const DateCell: React.FC> = ({ + cellData, + dateDisplayFormat, +}) => { const { admin: { dateFormat: dateFormatFromConfig }, } = useConfig() diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/File/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/File/index.tsx index ad19cbf6b..474d9b561 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/File/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/File/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import { Thumbnail } from '@payloadcms/ui/elements/Thumbnail' import React from 'react' @@ -8,7 +8,7 @@ import './index.scss' const baseClass = 'file' -export interface FileCellProps extends CellComponentProps {} +export interface FileCellProps extends DefaultCellComponentProps {} export const FileCell: React.FC = ({ cellData, customCellContext, rowData }) => { const { collectionSlug, uploadConfig } = customCellContext diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/JSON/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/JSON/index.tsx index 9b2211979..2400d81fc 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/JSON/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/JSON/index.tsx @@ -1,11 +1,11 @@ 'use client' -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import React from 'react' import './index.scss' -export const JSONCell: React.FC> = ({ cellData }) => { +export const JSONCell: React.FC> = ({ cellData }) => { const textToShow = cellData.length > 100 ? `${cellData.substring(0, 100)}\u2026` : cellData return ( diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Relationship/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Relationship/index.tsx index 3df4f67e8..758dc0203 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Relationship/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Relationship/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { CellComponentProps, CellProps } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps } from 'payload/types' import { getTranslation } from '@payloadcms/translations' import { useIntersect } from '@payloadcms/ui/hooks/useIntersect' @@ -16,9 +16,9 @@ type Value = { relationTo: string; value: number | string } const baseClass = 'relationship-cell' const totalToShow = 3 -export interface RelationshipCellProps extends CellComponentProps { - label: CellProps['label'] - relationTo: CellProps['relationTo'] +export interface RelationshipCellProps extends DefaultCellComponentProps { + label: CellComponentProps['label'] + relationTo: CellComponentProps['relationTo'] } export const RelationshipCell: React.FC = ({ diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Select/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Select/index.tsx index b63711d8c..c721ddf4b 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Select/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Select/index.tsx @@ -1,13 +1,13 @@ 'use client' -import type { CellComponentProps, CellProps, OptionObject } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps, OptionObject } from 'payload/types' import { getTranslation } from '@payloadcms/translations' import { useTranslation } from '@payloadcms/ui/providers/Translation' import { optionsAreObjects } from 'payload/types' import React from 'react' -export interface SelectCellProps extends CellComponentProps { - options: CellProps['options'] +export interface SelectCellProps extends DefaultCellComponentProps { + options: CellComponentProps['options'] } export const SelectCell: React.FC = ({ cellData, options }) => { diff --git a/packages/ui/src/elements/Table/DefaultCell/fields/Textarea/index.tsx b/packages/ui/src/elements/Table/DefaultCell/fields/Textarea/index.tsx index 413fe41f4..46a7c8c85 100644 --- a/packages/ui/src/elements/Table/DefaultCell/fields/Textarea/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/fields/Textarea/index.tsx @@ -1,9 +1,9 @@ 'use client' -import type { CellComponentProps } from 'payload/types' +import type { DefaultCellComponentProps } from 'payload/types' import React from 'react' -export const TextareaCell: React.FC> = ({ cellData }) => { +export const TextareaCell: React.FC> = ({ cellData }) => { const textToShow = cellData?.length > 100 ? `${cellData.substr(0, 100)}\u2026` : cellData return {textToShow} } diff --git a/packages/ui/src/elements/Table/DefaultCell/index.tsx b/packages/ui/src/elements/Table/DefaultCell/index.tsx index 10df522a7..b74c1c581 100644 --- a/packages/ui/src/elements/Table/DefaultCell/index.tsx +++ b/packages/ui/src/elements/Table/DefaultCell/index.tsx @@ -2,7 +2,7 @@ import LinkImport from 'next/link.js' import React from 'react' // TODO: abstract this out to support all routers -import type { CellProps } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps } from 'payload/types' import { getTranslation } from '@payloadcms/translations' import { TableCellProvider, useTableCell } from '@payloadcms/ui/elements/Table' @@ -14,7 +14,7 @@ import { cellComponents } from './fields/index.js' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default -export const DefaultCell: React.FC = (props) => { +export const DefaultCell: React.FC = (props) => { const { name, CellComponentOverride, @@ -77,12 +77,12 @@ export const DefaultCell: React.FC = (props) => { if (name === 'id') { return ( - + ) } - const DefaultCellComponent = cellComponents[fieldType] + const DefaultCellComponent: React.FC = cellComponents[fieldType] let CellComponent: React.ReactNode = cellData && diff --git a/packages/ui/src/elements/Table/TableCellProvider/index.tsx b/packages/ui/src/elements/Table/TableCellProvider/index.tsx index 6d2a67634..a539a0184 100644 --- a/packages/ui/src/elements/Table/TableCellProvider/index.tsx +++ b/packages/ui/src/elements/Table/TableCellProvider/index.tsx @@ -1,27 +1,27 @@ 'use client' -import type { CellComponentProps, CellProps } from 'payload/types' +import type { CellComponentProps, DefaultCellComponentProps } from 'payload/types' import React from 'react' export type ITableCellContext = { - cellData: any - cellProps?: Partial + cellData: DefaultCellComponentProps['cellData'] + cellProps?: Partial columnIndex?: number - customCellContext: CellComponentProps['customCellContext'] - richTextComponentMap?: CellComponentProps['richTextComponentMap'] - rowData: any + customCellContext: DefaultCellComponentProps['customCellContext'] + richTextComponentMap?: DefaultCellComponentProps['richTextComponentMap'] + rowData: DefaultCellComponentProps['rowData'] } const TableCellContext = React.createContext({} as ITableCellContext) export const TableCellProvider: React.FC<{ - cellData?: any - cellProps?: Partial + cellData?: DefaultCellComponentProps['cellData'] + cellProps?: Partial children: React.ReactNode columnIndex?: number - customCellContext?: CellComponentProps['customCellContext'] - richTextComponentMap?: CellComponentProps['richTextComponentMap'] - rowData?: any + customCellContext?: DefaultCellComponentProps['customCellContext'] + richTextComponentMap?: DefaultCellComponentProps['richTextComponentMap'] + rowData?: DefaultCellComponentProps['rowData'] }> = (props) => { const { cellData, diff --git a/packages/ui/src/elements/Table/index.tsx b/packages/ui/src/elements/Table/index.tsx index 8cbb34e94..35062ea66 100644 --- a/packages/ui/src/elements/Table/index.tsx +++ b/packages/ui/src/elements/Table/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { CellProps, FieldBase } from 'payload/types' +import type { CellComponentProps, FieldBase } from 'payload/types' import React from 'react' @@ -11,12 +11,14 @@ import { useTableColumns } from '../TableColumns/index.js' import { TableCellProvider } from './TableCellProvider/index.js' import './index.scss' +export { TableCellProvider } + const baseClass = 'table' export type Column = { accessor: string active: boolean - cellProps?: Partial + cellProps?: Partial components: { Cell: React.ReactNode Heading: React.ReactNode @@ -28,7 +30,7 @@ export type Column = { export type Props = { columns?: Column[] customCellContext?: Record - data: unknown[] + data: Record[] fieldMap: FieldMap } diff --git a/packages/ui/src/elements/TableColumns/buildColumns.tsx b/packages/ui/src/elements/TableColumns/buildColumns.tsx index 6e726662a..5324e2e2b 100644 --- a/packages/ui/src/elements/TableColumns/buildColumns.tsx +++ b/packages/ui/src/elements/TableColumns/buildColumns.tsx @@ -1,5 +1,5 @@ import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel' -import { type CellProps, type SanitizedCollectionConfig } from 'payload/types' +import { type CellComponentProps, type SanitizedCollectionConfig } from 'payload/types' import React from 'react' import type { FieldMap, MappedField } from '../../providers/ComponentMap/buildComponentMap/types.js' @@ -15,7 +15,7 @@ import { DefaultCell } from '../Table/DefaultCell/index.js' const fieldIsPresentationalOnly = (field: MappedField): boolean => field.type === 'ui' export const buildColumns = (args: { - cellProps: Partial[] + cellProps: Partial[] columnPreferences: ColumnPreferences defaultColumns?: string[] enableRowSelections: boolean diff --git a/packages/ui/src/elements/TableColumns/index.tsx b/packages/ui/src/elements/TableColumns/index.tsx index cbc0b6000..a7b21e3db 100644 --- a/packages/ui/src/elements/TableColumns/index.tsx +++ b/packages/ui/src/elements/TableColumns/index.tsx @@ -1,6 +1,6 @@ 'use client' import type { SanitizedCollectionConfig } from 'payload/types' -import type { CellProps } from 'payload/types' +import type { CellComponentProps } from 'payload/types' import React, { createContext, useCallback, useContext, useEffect, useReducer, useRef } from 'react' @@ -31,7 +31,7 @@ export type ListPreferences = { } type Props = { - cellProps?: Partial[] + cellProps?: Partial[] children: React.ReactNode collectionSlug: string enableRowSelections?: boolean diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx index d0569ccad..9c588af5d 100644 --- a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx +++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx @@ -1,6 +1,6 @@ import type { FieldDescriptionProps } from '@payloadcms/ui/forms/FieldDescription' import type { - CellProps, + CellComponentProps, Field, FieldWithPath, LabelProps, @@ -189,7 +189,7 @@ export const mapFields = (args: { let fieldComponentProps: FieldComponentProps - const cellComponentProps: CellProps = { + const cellComponentProps: CellComponentProps = { name: 'name' in field ? field.name : undefined, fieldType: field.type, isFieldAffectingData, diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts b/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts index 38adfab7a..c3c3b97b8 100644 --- a/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts +++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts @@ -2,7 +2,7 @@ import type { HiddenInputFieldProps } from '@payloadcms/ui/fields/HiddenInput' import type { FieldTypes } from 'payload/config' import type { BlockField, - CellProps, + CellComponentProps, SanitizedCollectionConfig, SanitizedGlobalConfig, TabsField, @@ -67,7 +67,7 @@ export type FieldComponentProps = export type MappedField = { CustomCell?: React.ReactNode CustomField?: React.ReactNode - cellComponentProps: CellProps + cellComponentProps: CellComponentProps disableBulkEdit?: boolean disabled?: boolean fieldComponentProps: FieldComponentProps diff --git a/test/admin/collections/Posts.ts b/test/admin/collections/Posts.ts index 5fa558341..bc5ee3132 100644 --- a/test/admin/collections/Posts.ts +++ b/test/admin/collections/Posts.ts @@ -2,6 +2,7 @@ import type { CollectionConfig } from 'payload/types' import { slateEditor } from '@payloadcms/richtext-slate' +import { CustomCell } from '../components/CustomCell/index.js' import { DemoUIFieldCell } from '../components/DemoUIField/Cell.js' import { DemoUIField } from '../components/DemoUIField/Field.js' import { @@ -82,6 +83,15 @@ export const Posts: CollectionConfig = { }, relationTo: 'posts', }, + { + name: 'customCell', + type: 'text', + admin: { + components: { + Cell: CustomCell, + }, + }, + }, { name: 'sidebarField', type: 'text', diff --git a/test/admin/components/CustomCell/index.tsx b/test/admin/components/CustomCell/index.tsx new file mode 100644 index 000000000..9d768ccef --- /dev/null +++ b/test/admin/components/CustomCell/index.tsx @@ -0,0 +1,10 @@ +'use client' +import type { CellComponentProps } from 'payload/types' + +import { useTableCell } from '@payloadcms/ui/elements/Table' +import React from 'react' + +export const CustomCell: React.FC = (props) => { + const context = useTableCell() + return
{`Custom cell: ${context.cellData || 'No data'}`}
+}