From b80010b1a1b77fa041fc46d7277830420c72d97c Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Mon, 17 Feb 2025 14:08:23 -0500 Subject: [PATCH] feat: view component types (#11126) It is currently very difficult to build custom edit and list views or inject custom components into these views because these views and components are not explicitly typed. Instances of these components were not fully type safe as well, i.e. when rendering them via `RenderServerComponent`, there was little to no type-checking in most cases. There is now a 1:1 type match for all views and view components and they now receive type-checking at render time. The following types have been newly added and/or improved: List View: - `ListViewClientProps` - `ListViewServerProps` - `BeforeListClientProps` - `BeforeListServerProps` - `BeforeListTableClientProps` - `BeforeListTableServerProps` - `AfterListClientProps` - `AfterListServerProps` - `AfterListTableClientProps` - `AfterListTableServerProps` - `ListViewSlotSharedClientProps` Document View: - `DocumentViewClientProps` - `DocumentViewServerProps` - `SaveButtonClientProps` - `SaveButtonServerProps` - `SaveDraftButtonClientProps` - `SaveDraftButtonServerProps` - `PublishButtonClientProps` - `PublishButtonServerProps` - `PreviewButtonClientProps` - `PreviewButtonServerProps` Root View: - `AdminViewClientProps` - `AdminViewServerProps` General: - `ViewDescriptionClientProps` - `ViewDescriptionServerProps` A few other changes were made in a non-breaking way: - `Column` is now exported from `payload` - `ListPreferences` is now exported from `payload` - `ListViewSlots` is now exported from `payload` - `ListViewClientProps` is now exported from `payload` - `AdminViewProps` is now an alias of `AdminViewServerProps` (listed above) - `ClientSideEditViewProps` is now an alias of `DocumentViewClientProps` (listed above) - `ServerSideEditViewProps` is now an alias of `DocumentViewServerProps` (listed above) - `ListComponentClientProps` is now an alias of `ListViewClientProps` (listed above) - `ListComponentServerProps` is now an alias of `ListViewServerProps` (listed above) - `CustomSaveButton` is now marked as deprecated because this is only relevant to the config (see correct type above) - `CustomSaveDraftButton` is now marked as deprecated because this is only relevant to the config (see correct type above) - `CustomPublishButton` is now marked as deprecated because this is only relevant to the config (see correct type above) - `CustomPreviewButton` is now marked as deprecated because this is only relevant to the config (see correct type above) This PR _does not_ apply these changes to _root_ components, i.e. `afterNavLinks`. Those will come in a future PR. Related: #10987. --- .../DocumentHeader/Tabs/Tab/index.tsx | 9 +- .../elements/DocumentHeader/Tabs/index.tsx | 8 +- packages/next/src/views/API/index.tsx | 4 +- packages/next/src/views/Account/index.tsx | 11 +- .../next/src/views/CreateFirstUser/index.tsx | 4 +- .../src/views/Dashboard/Default/index.tsx | 18 +- packages/next/src/views/Dashboard/index.tsx | 14 +- .../src/views/Document/getViewsFromConfig.tsx | 16 +- .../views/Document/handleServerFunction.tsx | 2 + packages/next/src/views/Document/index.tsx | 39 ++-- .../views/Document/renderDocumentSlots.tsx | 22 ++- packages/next/src/views/Edit/index.tsx | 4 +- .../next/src/views/ForgotPassword/index.tsx | 4 +- .../src/views/List/handleServerFunction.tsx | 2 + packages/next/src/views/List/index.tsx | 80 ++++---- .../src/views/List/renderListViewSlots.tsx | 45 +++-- packages/next/src/views/LivePreview/index.tsx | 4 +- packages/next/src/views/Login/index.tsx | 10 +- packages/next/src/views/Logout/index.tsx | 8 +- packages/next/src/views/NotFound/index.tsx | 9 +- .../next/src/views/ResetPassword/index.tsx | 4 +- .../next/src/views/Root/getViewFromConfig.ts | 10 +- packages/next/src/views/Root/index.tsx | 11 +- .../next/src/views/Unauthorized/index.tsx | 6 +- packages/next/src/views/Verify/index.tsx | 10 +- packages/next/src/views/Version/index.tsx | 5 +- .../next/src/views/Versions/buildColumns.tsx | 3 +- .../next/src/views/Versions/index.client.tsx | 3 +- packages/next/src/views/Versions/index.tsx | 9 +- .../src/admin/elements/PreviewButton.ts | 8 +- .../src/admin/elements/PublishButton.ts | 10 +- .../payload/src/admin/elements/SaveButton.ts | 10 +- .../src/admin/elements/SaveDraftButton.ts | 8 +- packages/payload/src/admin/elements/Table.ts | 10 + packages/payload/src/admin/types.ts | 178 ++++++++++++++---- .../{elements/Tab.ts => views/document.ts} | 44 ++++- .../src/admin/views/{types.ts => index.ts} | 62 +++--- packages/payload/src/admin/views/list.ts | 75 ++++++++ .../bin/generateImportMap/iterateConfig.ts | 2 +- .../payload/src/collections/config/types.ts | 16 +- packages/payload/src/config/types.ts | 28 ++- .../src/elements/DocumentControls/index.tsx | 2 - .../ui/src/elements/PreviewButton/index.tsx | 4 +- .../ScheduleDrawer/buildUpcomingColumns.tsx | 3 +- .../PublishButton/ScheduleDrawer/index.tsx | 3 +- .../ui/src/elements/PublishButton/index.tsx | 4 +- .../src/elements/RelationshipTable/index.tsx | 3 +- packages/ui/src/elements/SaveButton/index.tsx | 4 +- .../ui/src/elements/SaveDraftButton/index.tsx | 4 +- packages/ui/src/elements/Table/index.tsx | 11 +- .../TableColumns/buildColumnState.tsx | 2 +- .../ui/src/elements/TableColumns/index.tsx | 3 +- .../ui/src/elements/ViewDescription/index.tsx | 8 +- packages/ui/src/exports/client/index.ts | 66 +++++-- packages/ui/src/utilities/buildTableState.ts | 3 +- packages/ui/src/views/Edit/index.tsx | 6 +- packages/ui/src/views/List/index.tsx | 35 +--- packages/ui/src/views/List/types.ts | 28 +-- test/admin/collections/Geo.ts | 6 +- .../components/CustomTabComponent/client.tsx | 8 +- .../components/CustomTabComponent/index.tsx | 4 +- .../components/ViewDescription/index.tsx | 6 +- .../{ => actions}/AdminButton/index.tsx | 0 .../CollectionAPIButton/index.tsx | 0 .../CollectionEditButton/index.tsx | 0 .../CollectionListButton/index.tsx | 0 .../{ => actions}/GlobalAPIButton/index.tsx | 0 .../{ => actions}/GlobalEditButton/index.tsx | 0 .../components/views/CustomAccount/index.tsx | 4 +- .../views/CustomDashboard/index.tsx | 4 +- .../components/views/CustomDefault/index.tsx | 9 +- .../components/views/CustomEdit/index.tsx | 6 +- .../views/CustomEditDefault/index.tsx | 6 +- .../components/views/CustomMinimal/index.tsx | 4 +- .../views/CustomProtectedView/index.tsx | 4 +- .../views/CustomTabComponent/index.tsx | 4 +- .../components/views/CustomTabLabel/index.tsx | 6 +- .../views/CustomTabNested/index.tsx | 6 +- .../views/CustomTabWithParam/index.tsx | 4 +- .../components/views/CustomVersions/index.tsx | 6 +- .../components/views/CustomView/index.tsx | 4 +- .../views/CustomViewNested/index.tsx | 4 +- .../views/CustomViewWithParam/index.tsx | 4 +- test/admin/config.ts | 3 +- test/admin/globals/Global.ts | 4 +- test/admin/payload-types.ts | 58 +----- 86 files changed, 683 insertions(+), 495 deletions(-) create mode 100644 packages/payload/src/admin/elements/Table.ts rename packages/payload/src/admin/{elements/Tab.ts => views/document.ts} (54%) rename packages/payload/src/admin/views/{types.ts => index.ts} (60%) create mode 100644 packages/payload/src/admin/views/list.ts rename test/admin/components/{ => actions}/AdminButton/index.tsx (100%) rename test/admin/components/{ => actions}/CollectionAPIButton/index.tsx (100%) rename test/admin/components/{ => actions}/CollectionEditButton/index.tsx (100%) rename test/admin/components/{ => actions}/CollectionListButton/index.tsx (100%) rename test/admin/components/{ => actions}/GlobalAPIButton/index.tsx (100%) rename test/admin/components/{ => actions}/GlobalEditButton/index.tsx (100%) diff --git a/packages/next/src/elements/DocumentHeader/Tabs/Tab/index.tsx b/packages/next/src/elements/DocumentHeader/Tabs/Tab/index.tsx index 5726434d2e..df46dea645 100644 --- a/packages/next/src/elements/DocumentHeader/Tabs/Tab/index.tsx +++ b/packages/next/src/elements/DocumentHeader/Tabs/Tab/index.tsx @@ -1,16 +1,16 @@ -import type { DocumentTabConfig, DocumentTabProps } from 'payload' +import type { DocumentTabConfig, DocumentTabServerProps, ServerProps } from 'payload' import type React from 'react' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' import { Fragment } from 'react' -import './index.scss' import { DocumentTabLink } from './TabLink.js' +import './index.scss' export const baseClass = 'doc-tab' export const DocumentTab: React.FC< - { readonly Pill_Component?: React.FC } & DocumentTabConfig & DocumentTabProps + { readonly Pill_Component?: React.FC } & DocumentTabConfig & DocumentTabServerProps > = (props) => { const { apiURL, @@ -27,6 +27,7 @@ export const DocumentTab: React.FC< Pill, Pill_Component, } = props + const { config } = payload const { routes } = config @@ -83,7 +84,7 @@ export const DocumentTab: React.FC< i18n, payload, permissions, - }, + } satisfies ServerProps, })} ) : null} diff --git a/packages/next/src/elements/DocumentHeader/Tabs/index.tsx b/packages/next/src/elements/DocumentHeader/Tabs/index.tsx index 2bfa190dc3..4fead80bec 100644 --- a/packages/next/src/elements/DocumentHeader/Tabs/index.tsx +++ b/packages/next/src/elements/DocumentHeader/Tabs/index.tsx @@ -1,5 +1,7 @@ import type { I18n } from '@payloadcms/translations' import type { + DocumentTabClientProps, + DocumentTabServerPropsOnly, Payload, SanitizedCollectionConfig, SanitizedGlobalConfig, @@ -64,6 +66,7 @@ export const DocumentTabs: React.FC<{ return ( = () => { +export function APIView(props: DocumentViewServerProps) { return } diff --git a/packages/next/src/views/Account/index.tsx b/packages/next/src/views/Account/index.tsx index eccabbb36e..e5058cc534 100644 --- a/packages/next/src/views/Account/index.tsx +++ b/packages/next/src/views/Account/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps, DocumentViewServerPropsOnly } from 'payload' import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider } from '@payloadcms/ui' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' @@ -18,11 +18,7 @@ import { Settings } from './Settings/index.js' export { generateAccountMetadata } from './meta.js' -export const Account: React.FC = async ({ - initPageResult, - params, - searchParams, -}) => { +export async function Account({ initPageResult, params, searchParams }: AdminViewServerProps) { const { languageOptions, locale, @@ -153,6 +149,7 @@ export const Account: React.FC = async ({ Fallback: EditView, importMap: payload.importMap, serverProps: { + doc: data, i18n, initPageResult, locale, @@ -162,7 +159,7 @@ export const Account: React.FC = async ({ routeSegments: [], searchParams, user, - }, + } satisfies DocumentViewServerPropsOnly, })} diff --git a/packages/next/src/views/CreateFirstUser/index.tsx b/packages/next/src/views/CreateFirstUser/index.tsx index 3840a8ea48..c9f701bfd5 100644 --- a/packages/next/src/views/CreateFirstUser/index.tsx +++ b/packages/next/src/views/CreateFirstUser/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { buildFormState } from '@payloadcms/ui/utilities/buildFormState' import React from 'react' @@ -11,7 +11,7 @@ import './index.scss' export { generateCreateFirstUserMetadata } from './meta.js' -export const CreateFirstUserView: React.FC = async ({ initPageResult }) => { +export async function CreateFirstUserView({ initPageResult }: AdminViewServerProps) { const { locale, req, diff --git a/packages/next/src/views/Dashboard/Default/index.tsx b/packages/next/src/views/Dashboard/Default/index.tsx index 112d91594a..524761f8c3 100644 --- a/packages/next/src/views/Dashboard/Default/index.tsx +++ b/packages/next/src/views/Dashboard/Default/index.tsx @@ -1,5 +1,5 @@ import type { groupNavItems } from '@payloadcms/ui/shared' -import type { ClientUser, SanitizedPermissions, ServerProps, VisibleEntities } from 'payload' +import type { ClientUser, Locale, ServerProps } from 'payload' import { getTranslation } from '@payloadcms/translations' import { Button, Card, Gutter, Locked } from '@payloadcms/ui' @@ -11,7 +11,11 @@ import './index.scss' const baseClass = 'dashboard' -export type DashboardProps = { +export type DashboardViewClientProps = { + locale: Locale +} + +export type DashboardViewServerPropsOnly = { globalData: Array<{ data: { _isLocked: boolean; _lastEditedAt: string; _userEditing: ClientUser | number | string } lockDuration?: number @@ -24,11 +28,11 @@ export type DashboardProps = { */ Link?: React.ComponentType navGroups?: ReturnType - permissions: SanitizedPermissions - visibleEntities: VisibleEntities } & ServerProps -export const DefaultDashboard: React.FC = (props) => { +export type DashboardViewServerProps = DashboardViewClientProps & DashboardViewServerPropsOnly + +export function DefaultDashboard(props: DashboardViewServerProps) { const { globalData, i18n, @@ -65,7 +69,7 @@ export const DefaultDashboard: React.FC = (props) => { permissions, searchParams, user, - }, + } satisfies ServerProps, })} @@ -182,7 +186,7 @@ export const DefaultDashboard: React.FC = (props) => { permissions, searchParams, user, - }, + } satisfies ServerProps, })} diff --git a/packages/next/src/views/Dashboard/index.tsx b/packages/next/src/views/Dashboard/index.tsx index b59eaaab14..5861a4a462 100644 --- a/packages/next/src/views/Dashboard/index.tsx +++ b/packages/next/src/views/Dashboard/index.tsx @@ -1,20 +1,18 @@ import type { EntityToGroup } from '@payloadcms/ui/shared' -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { HydrateAuthProvider, SetStepNav } from '@payloadcms/ui' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' import { EntityType, groupNavItems } from '@payloadcms/ui/shared' import React, { Fragment } from 'react' +import type { DashboardViewClientProps, DashboardViewServerPropsOnly } from './Default/index.js' + import { DefaultDashboard } from './Default/index.js' export { generateDashboardMetadata } from './meta.js' -export const Dashboard: React.FC = async ({ - initPageResult, - params, - searchParams, -}) => { +export async function Dashboard({ initPageResult, params, searchParams }: AdminViewServerProps) { const { locale, permissions, @@ -108,7 +106,7 @@ export const Dashboard: React.FC = async ({ {RenderServerComponent({ clientProps: { locale, - }, + } satisfies DashboardViewClientProps, Component: config.admin?.components?.views?.dashboard?.Component, Fallback: DefaultDashboard, importMap: payload.importMap, @@ -123,7 +121,7 @@ export const Dashboard: React.FC = async ({ searchParams, user, visibleEntities, - }, + } satisfies DashboardViewServerPropsOnly, })} ) diff --git a/packages/next/src/views/Document/getViewsFromConfig.tsx b/packages/next/src/views/Document/getViewsFromConfig.tsx index 3cf0494e12..e0128c38ac 100644 --- a/packages/next/src/views/Document/getViewsFromConfig.tsx +++ b/packages/next/src/views/Document/getViewsFromConfig.tsx @@ -1,12 +1,12 @@ import type { - AdminViewProps, + AdminViewServerProps, + DocumentViewServerProps, PayloadComponent, SanitizedCollectionConfig, SanitizedCollectionPermission, SanitizedConfig, SanitizedGlobalConfig, SanitizedGlobalPermission, - ServerSideEditViewProps, } from 'payload' import type React from 'react' @@ -46,18 +46,18 @@ export const getViewsFromConfig = ({ overrideDocPermissions: true } )): { - CustomView: ViewFromConfig - DefaultView: ViewFromConfig + CustomView: ViewFromConfig + DefaultView: ViewFromConfig /** * The error view to display if CustomView or DefaultView do not exist (could be either due to not found, or unauthorized). Can be null */ - ErrorView: ViewFromConfig + ErrorView: ViewFromConfig viewKey: string } | null => { // Conditionally import and lazy load the default view - let DefaultView: ViewFromConfig = null - let CustomView: ViewFromConfig = null - let ErrorView: ViewFromConfig = null + let DefaultView: ViewFromConfig = null + let CustomView: ViewFromConfig = null + let ErrorView: ViewFromConfig = null let viewKey: string const { diff --git a/packages/next/src/views/Document/handleServerFunction.tsx b/packages/next/src/views/Document/handleServerFunction.tsx index 57cb4a747d..90632aac28 100644 --- a/packages/next/src/views/Document/handleServerFunction.tsx +++ b/packages/next/src/views/Document/handleServerFunction.tsx @@ -145,6 +145,7 @@ export const renderDocumentHandler = async (args: { disableActions, documentSubViewType: 'default', drawerSlug, + i18n, importMap: payload.importMap, initialData, initPageResult: { @@ -163,6 +164,7 @@ export const renderDocumentHandler = async (args: { params: { segments: ['collections', collectionSlug, docID], }, + payload, redirectAfterDelete, redirectAfterDuplicate, searchParams: {}, diff --git a/packages/next/src/views/Document/index.tsx b/packages/next/src/views/Document/index.tsx index e4dc94b6a0..5b37230980 100644 --- a/packages/next/src/views/Document/index.tsx +++ b/packages/next/src/views/Document/index.tsx @@ -1,4 +1,11 @@ -import type { AdminViewProps, Data, PayloadComponent, ServerSideEditViewProps } from 'payload' +import type { + AdminViewServerProps, + Data, + DocumentViewClientProps, + DocumentViewServerProps, + DocumentViewServerPropsOnly, + PayloadComponent, +} from 'payload' import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider } from '@payloadcms/ui' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' @@ -41,8 +48,9 @@ export const renderDocument = async ({ searchParams, viewType, }: { + drawerSlug?: string overrideEntityVisibility?: boolean -} & AdminViewProps): Promise<{ +} & AdminViewServerProps): Promise<{ data: Data Document: React.ReactNode }> => { @@ -74,9 +82,9 @@ export const renderDocument = async ({ let isEditing = getIsEditing({ id: idFromArgs, collectionSlug, globalSlug }) let RootViewOverride: PayloadComponent - let CustomView: ViewFromConfig - let DefaultView: ViewFromConfig - let ErrorView: ViewFromConfig + let CustomView: ViewFromConfig + let DefaultView: ViewFromConfig + let ErrorView: ViewFromConfig let apiURL: string @@ -161,7 +169,7 @@ export const renderDocument = async ({ }), ]) - const serverProps: ServerSideEditViewProps = { + const documentViewServerProps: DocumentViewServerPropsOnly = { doc, i18n, initPageResult, @@ -183,9 +191,11 @@ export const renderDocument = async ({ } const params = new URLSearchParams() + if (collectionConfig.versions?.drafts) { params.append('draft', 'true') } + if (locale?.code) { params.append('locale', locale.code) } @@ -319,7 +329,12 @@ export const renderDocument = async ({ req, }) - const clientProps = { formState, ...documentSlots, documentSubViewType, viewType } + const clientProps: DocumentViewClientProps = { + formState, + ...documentSlots, + documentSubViewType, + viewType, + } return { data: doc, @@ -363,7 +378,7 @@ export const renderDocument = async ({ clientProps, Component: ErrorView.ComponentConfig || ErrorView.Component, importMap, - serverProps, + serverProps: documentViewServerProps, }) : RenderServerComponent({ clientProps, @@ -373,7 +388,7 @@ export const renderDocument = async ({ ? CustomView?.ComponentConfig || CustomView?.Component : DefaultView?.ComponentConfig || DefaultView?.Component, importMap, - serverProps, + serverProps: documentViewServerProps, })} @@ -381,16 +396,16 @@ export const renderDocument = async ({ } } -export const Document: React.FC = async (args) => { +export async function Document(props: AdminViewServerProps) { try { - const { Document: RenderedDocument } = await renderDocument(args) + const { Document: RenderedDocument } = await renderDocument(props) return RenderedDocument } catch (error) { if (error?.message === 'NEXT_REDIRECT') { throw error } - logError({ err: error, payload: args.initPageResult.req.payload }) + logError({ err: error, payload: props.initPageResult.req.payload }) if (error.message === 'not-found') { notFound() diff --git a/packages/next/src/views/Document/renderDocumentSlots.tsx b/packages/next/src/views/Document/renderDocumentSlots.tsx index b74eb50bce..dde74e5e26 100644 --- a/packages/next/src/views/Document/renderDocumentSlots.tsx +++ b/packages/next/src/views/Document/renderDocumentSlots.tsx @@ -2,11 +2,17 @@ import type { DefaultServerFunctionArgs, DocumentSlots, PayloadRequest, + PreviewButtonServerPropsOnly, + PublishButtonServerPropsOnly, SanitizedCollectionConfig, SanitizedDocumentPermissions, SanitizedGlobalConfig, + SaveButtonServerPropsOnly, + SaveDraftButtonServerPropsOnly, ServerProps, StaticDescription, + ViewDescriptionClientProps, + ViewDescriptionServerPropsOnly, } from 'payload' import { ViewDescription } from '@payloadcms/ui' @@ -44,7 +50,7 @@ export const renderDocumentSlots: (args: { components.PreviewButton = RenderServerComponent({ Component: CustomPreviewButton, importMap: req.payload.importMap, - serverProps, + serverProps: serverProps satisfies PreviewButtonServerPropsOnly, }) } @@ -64,11 +70,14 @@ export const renderDocumentSlots: (args: { if (hasDescription) { components.Description = RenderServerComponent({ - clientProps: { description: staticDescription }, + clientProps: { + collectionSlug: collectionConfig?.slug, + description: staticDescription, + } satisfies ViewDescriptionClientProps, Component: CustomDescription, Fallback: ViewDescription, importMap: req.payload.importMap, - serverProps, + serverProps: serverProps satisfies ViewDescriptionServerPropsOnly, }) } @@ -82,9 +91,10 @@ export const renderDocumentSlots: (args: { components.PublishButton = RenderServerComponent({ Component: CustomPublishButton, importMap: req.payload.importMap, - serverProps, + serverProps: serverProps satisfies PublishButtonServerPropsOnly, }) } + const CustomSaveDraftButton = collectionConfig?.admin?.components?.edit?.SaveDraftButton || globalConfig?.admin?.components?.elements?.SaveDraftButton @@ -97,7 +107,7 @@ export const renderDocumentSlots: (args: { components.SaveDraftButton = RenderServerComponent({ Component: CustomSaveDraftButton, importMap: req.payload.importMap, - serverProps, + serverProps: serverProps satisfies SaveDraftButtonServerPropsOnly, }) } } else { @@ -109,7 +119,7 @@ export const renderDocumentSlots: (args: { components.SaveButton = RenderServerComponent({ Component: CustomSaveButton, importMap: req.payload.importMap, - serverProps, + serverProps: serverProps satisfies SaveButtonServerPropsOnly, }) } } diff --git a/packages/next/src/views/Edit/index.tsx b/packages/next/src/views/Edit/index.tsx index 9922274a69..116c1affd4 100644 --- a/packages/next/src/views/Edit/index.tsx +++ b/packages/next/src/views/Edit/index.tsx @@ -1,10 +1,10 @@ 'use client' -import type { ClientSideEditViewProps } from 'payload' +import type { DocumentViewClientProps } from 'payload' import { DefaultEditView } from '@payloadcms/ui' import React from 'react' -export const EditView: React.FC = (props) => { +export const EditView: React.FC = (props) => { return } diff --git a/packages/next/src/views/ForgotPassword/index.tsx b/packages/next/src/views/ForgotPassword/index.tsx index 3cdbebaf9a..38d8e42a5d 100644 --- a/packages/next/src/views/ForgotPassword/index.tsx +++ b/packages/next/src/views/ForgotPassword/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { Button, Link } from '@payloadcms/ui' import { formatAdminURL, Translation } from '@payloadcms/ui/shared' @@ -11,7 +11,7 @@ export { generateForgotPasswordMetadata } from './meta.js' export const forgotPasswordBaseClass = 'forgot-password' -export const ForgotPasswordView: React.FC = ({ initPageResult }) => { +export function ForgotPasswordView({ initPageResult }: AdminViewServerProps) { const { req: { i18n, diff --git a/packages/next/src/views/List/handleServerFunction.tsx b/packages/next/src/views/List/handleServerFunction.tsx index 223b96291a..ea792b25ee 100644 --- a/packages/next/src/views/List/handleServerFunction.tsx +++ b/packages/next/src/views/List/handleServerFunction.tsx @@ -137,6 +137,7 @@ export const renderListHandler = async (args: { disableBulkEdit, drawerSlug, enableRowSelections, + i18n, importMap: payload.importMap, initPageResult: { collectionConfig: payload?.collections?.[collectionSlug]?.config, @@ -152,6 +153,7 @@ export const renderListHandler = async (args: { params: { segments: ['collections', collectionSlug], }, + payload, query, redirectAfterDelete, redirectAfterDuplicate, diff --git a/packages/next/src/views/List/index.tsx b/packages/next/src/views/List/index.tsx index 42e5d882fe..585035bd9c 100644 --- a/packages/next/src/views/List/index.tsx +++ b/packages/next/src/views/List/index.tsx @@ -1,10 +1,11 @@ import type { - ListComponentClientProps, - ListComponentServerProps, + AdminViewServerProps, ListPreferences, + ListQuery, ListViewClientProps, -} from '@payloadcms/ui' -import type { AdminViewProps, ListQuery, Where } from 'payload' + ListViewServerPropsOnly, + Where, +} from 'payload' import { DefaultListView, HydrateAuthProvider, ListQueryProvider } from '@payloadcms/ui' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' @@ -19,17 +20,18 @@ import { resolveAllFilterOptions } from './resolveAllFilterOptions.js' export { generateListMetadata } from './meta.js' -type ListViewArgs = { +type RenderListViewArgs = { customCellProps?: Record disableBulkDelete?: boolean disableBulkEdit?: boolean + drawerSlug?: string enableRowSelections: boolean overrideEntityVisibility?: boolean query: ListQuery -} & AdminViewProps +} & AdminViewServerProps export const renderListView = async ( - args: ListViewArgs, + args: RenderListViewArgs, ): Promise<{ List: React.ReactNode }> => { @@ -160,19 +162,20 @@ export const renderListView = async ( ? collectionConfig.admin.description({ t: i18n.t }) : collectionConfig.admin.description - const sharedClientProps: ListComponentClientProps = { - collectionSlug, - hasCreatePermission: permissions?.collections?.[collectionSlug]?.create, - newDocumentURL: formatAdminURL({ - adminRoute, - path: `/collections/${collectionSlug}/create`, - }), - } + const newDocumentURL = formatAdminURL({ + adminRoute, + path: `/collections/${collectionSlug}/create`, + }) - const sharedServerProps: ListComponentServerProps = { + const hasCreatePermission = permissions?.collections?.[collectionSlug]?.create + + const serverProps: ListViewServerPropsOnly = { collectionConfig, + data, i18n, limit, + listPreferences, + listSearchableFields: collectionConfig.admin.listSearchableFields, locale: fullLocale, params, payload, @@ -182,26 +185,17 @@ export const renderListView = async ( } const listViewSlots = renderListViewSlots({ - clientProps: sharedClientProps, + clientProps: { + collectionSlug, + hasCreatePermission, + newDocumentURL, + }, collectionConfig, description: staticDescription, payload, - serverProps: sharedServerProps, + serverProps, }) - const clientProps: ListViewClientProps = { - ...listViewSlots, - ...sharedClientProps, - columnState, - disableBulkDelete, - disableBulkEdit, - enableRowSelections, - listPreferences, - renderedFilters, - resolvedFilterOptions, - Table, - } - const isInDrawer = Boolean(drawerSlug) return { @@ -215,16 +209,24 @@ export const renderListView = async ( modifySearchParams={!isInDrawer} > {RenderServerComponent({ - clientProps, + clientProps: { + ...listViewSlots, + collectionSlug, + columnState, + disableBulkDelete, + disableBulkEdit, + enableRowSelections, + hasCreatePermission, + listPreferences, + newDocumentURL, + renderedFilters, + resolvedFilterOptions, + Table, + } satisfies ListViewClientProps, Component: collectionConfig?.admin?.components?.views?.list?.Component, Fallback: DefaultListView, importMap: payload.importMap, - serverProps: { - ...sharedServerProps, - data, - listPreferences, - listSearchableFields: collectionConfig.admin.listSearchableFields, - }, + serverProps, })} @@ -235,7 +237,7 @@ export const renderListView = async ( throw new Error('not-found') } -export const ListView: React.FC = async (args) => { +export const ListView: React.FC = async (args) => { try { const { List: RenderedList } = await renderListView({ ...args, enableRowSelections: true }) return RenderedList diff --git a/packages/next/src/views/List/renderListViewSlots.tsx b/packages/next/src/views/List/renderListViewSlots.tsx index 48419a1333..5eb3840742 100644 --- a/packages/next/src/views/List/renderListViewSlots.tsx +++ b/packages/next/src/views/List/renderListViewSlots.tsx @@ -1,18 +1,29 @@ import type { - ListComponentClientProps, - ListComponentServerProps, + AfterListClientProps, + AfterListTableClientProps, + AfterListTableServerPropsOnly, + BeforeListClientProps, + BeforeListServerPropsOnly, + BeforeListTableClientProps, + BeforeListTableServerPropsOnly, + ListViewServerPropsOnly, ListViewSlots, -} from '@payloadcms/ui' -import type { Payload, SanitizedCollectionConfig, StaticDescription } from 'payload' + ListViewSlotSharedClientProps, + Payload, + SanitizedCollectionConfig, + StaticDescription, + ViewDescriptionClientProps, + ViewDescriptionServerPropsOnly, +} from 'payload' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' type Args = { - clientProps: ListComponentClientProps + clientProps: ListViewSlotSharedClientProps collectionConfig: SanitizedCollectionConfig description?: StaticDescription payload: Payload - serverProps: ListComponentServerProps + serverProps: ListViewServerPropsOnly } export const renderListViewSlots = ({ @@ -26,49 +37,49 @@ export const renderListViewSlots = ({ if (collectionConfig.admin.components?.afterList) { result.AfterList = RenderServerComponent({ - clientProps, + clientProps: clientProps satisfies AfterListClientProps, Component: collectionConfig.admin.components.afterList, importMap: payload.importMap, - serverProps, + serverProps: serverProps satisfies AfterListTableServerPropsOnly, }) } if (collectionConfig.admin.components?.afterListTable) { result.AfterListTable = RenderServerComponent({ - clientProps, + clientProps: clientProps satisfies AfterListTableClientProps, Component: collectionConfig.admin.components.afterListTable, importMap: payload.importMap, - serverProps, + serverProps: serverProps satisfies AfterListTableServerPropsOnly, }) } if (collectionConfig.admin.components?.beforeList) { result.BeforeList = RenderServerComponent({ - clientProps, + clientProps: clientProps satisfies BeforeListClientProps, Component: collectionConfig.admin.components.beforeList, importMap: payload.importMap, - serverProps, + serverProps: serverProps satisfies BeforeListServerPropsOnly, }) } if (collectionConfig.admin.components?.beforeListTable) { result.BeforeListTable = RenderServerComponent({ - clientProps, + clientProps: clientProps satisfies BeforeListTableClientProps, Component: collectionConfig.admin.components.beforeListTable, importMap: payload.importMap, - serverProps, + serverProps: serverProps satisfies BeforeListTableServerPropsOnly, }) } if (collectionConfig.admin.components?.Description) { result.Description = RenderServerComponent({ clientProps: { + collectionSlug: collectionConfig.slug, description, - ...clientProps, - }, + } satisfies ViewDescriptionClientProps, Component: collectionConfig.admin.components.Description, importMap: payload.importMap, - serverProps, + serverProps: serverProps satisfies ViewDescriptionServerPropsOnly, }) } diff --git a/packages/next/src/views/LivePreview/index.tsx b/packages/next/src/views/LivePreview/index.tsx index 4c952a7b55..4e7f303b42 100644 --- a/packages/next/src/views/LivePreview/index.tsx +++ b/packages/next/src/views/LivePreview/index.tsx @@ -1,11 +1,11 @@ -import type { EditViewComponent, LivePreviewConfig, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps, LivePreviewConfig } from 'payload' import React from 'react' import './index.scss' import { LivePreviewClient } from './index.client.js' -export const LivePreviewView: PayloadServerReactComponent = async (props) => { +export async function LivePreviewView(props: DocumentViewServerProps) { const { doc, initPageResult } = props const { collectionConfig, globalConfig, locale, req } = initPageResult diff --git a/packages/next/src/views/Login/index.tsx b/packages/next/src/views/Login/index.tsx index 905ff2777d..3cc344530f 100644 --- a/packages/next/src/views/Login/index.tsx +++ b/packages/next/src/views/Login/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps, ServerProps } from 'payload' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' import { redirect } from 'next/navigation.js' @@ -12,7 +12,7 @@ export { generateLoginMetadata } from './meta.js' export const loginBaseClass = 'login' -export const LoginView: React.FC = ({ initPageResult, params, searchParams }) => { +export function LoginView({ initPageResult, params, searchParams }: AdminViewServerProps) { const { locale, permissions, req } = initPageResult const { @@ -24,7 +24,6 @@ export const LoginView: React.FC = ({ initPageResult, params, se const { admin: { components: { afterLogin, beforeLogin } = {}, user: userSlug }, - collections, routes: { admin }, } = config @@ -76,9 +75,8 @@ export const LoginView: React.FC = ({ initPageResult, params, se permissions, searchParams, user, - }, + } satisfies ServerProps, })} - {!collectionConfig?.auth?.disableLocalStrategy && ( = ({ initPageResult, params, se permissions, searchParams, user, - }, + } satisfies ServerProps, })} ) diff --git a/packages/next/src/views/Logout/index.tsx b/packages/next/src/views/Logout/index.tsx index a9b256ec4a..6f38365d81 100644 --- a/packages/next/src/views/Logout/index.tsx +++ b/packages/next/src/views/Logout/index.tsx @@ -1,9 +1,9 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import React from 'react' -import './index.scss' import { LogoutClient } from './LogoutClient.js' +import './index.scss' const baseClass = 'logout' @@ -12,7 +12,7 @@ export { generateLogoutMetadata } from './meta.js' export const LogoutView: React.FC< { inactivity?: boolean - } & AdminViewProps + } & AdminViewServerProps > = ({ inactivity, initPageResult, searchParams }) => { const { req: { @@ -35,6 +35,6 @@ export const LogoutView: React.FC< ) } -export const LogoutInactivity: React.FC = (props) => { +export function LogoutInactivity(props: AdminViewServerProps) { return } diff --git a/packages/next/src/views/NotFound/index.tsx b/packages/next/src/views/NotFound/index.tsx index c18e217937..235585025b 100644 --- a/packages/next/src/views/NotFound/index.tsx +++ b/packages/next/src/views/NotFound/index.tsx @@ -1,11 +1,6 @@ import type { I18n } from '@payloadcms/translations' import type { Metadata } from 'next' -import type { - AdminViewComponent, - ImportMap, - PayloadServerReactComponent, - SanitizedConfig, -} from 'payload' +import type { AdminViewServerProps, ImportMap, SanitizedConfig } from 'payload' import { formatAdminURL } from '@payloadcms/ui/shared' import React from 'react' @@ -87,6 +82,6 @@ export const NotFoundPage = async ({ ) } -export const NotFoundView: PayloadServerReactComponent = () => { +export function NotFoundView(props: AdminViewServerProps) { return } diff --git a/packages/next/src/views/ResetPassword/index.tsx b/packages/next/src/views/ResetPassword/index.tsx index 7c090bc881..46a60f3f92 100644 --- a/packages/next/src/views/ResetPassword/index.tsx +++ b/packages/next/src/views/ResetPassword/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { Button, Link } from '@payloadcms/ui' import { formatAdminURL, Translation } from '@payloadcms/ui/shared' @@ -12,7 +12,7 @@ export const resetPasswordBaseClass = 'reset-password' export { generateResetPasswordMetadata } from './meta.js' -export const ResetPassword: React.FC = ({ initPageResult, params }) => { +export function ResetPassword({ initPageResult, params }: AdminViewServerProps) { const { req } = initPageResult const { diff --git a/packages/next/src/views/Root/getViewFromConfig.ts b/packages/next/src/views/Root/getViewFromConfig.ts index 05ec03570f..3ae02d6c8e 100644 --- a/packages/next/src/views/Root/getViewFromConfig.ts +++ b/packages/next/src/views/Root/getViewFromConfig.ts @@ -1,8 +1,8 @@ import type { - AdminViewComponent, - AdminViewProps, + AdminViewServerProps, DocumentSubViewTypes, ImportMap, + PayloadComponent, SanitizedConfig, ServerPropsFromView, ViewTypes, @@ -38,12 +38,12 @@ const baseClasses = { } type OneSegmentViews = { - [K in Exclude]: React.FC + [K in Exclude]: React.FC } export type ViewFromConfig = { - Component?: React.FC - payloadComponent?: AdminViewComponent + Component?: React.FC + payloadComponent?: PayloadComponent } const oneSegmentViews: OneSegmentViews = { diff --git a/packages/next/src/views/Root/index.tsx b/packages/next/src/views/Root/index.tsx index cb53bd54a5..9877ed539d 100644 --- a/packages/next/src/views/Root/index.tsx +++ b/packages/next/src/views/Root/index.tsx @@ -1,6 +1,11 @@ import type { I18nClient } from '@payloadcms/translations' import type { Metadata } from 'next' -import type { ImportMap, SanitizedConfig } from 'payload' +import type { + AdminViewClientProps, + AdminViewServerPropsOnly, + ImportMap, + SanitizedConfig, +} from 'payload' import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' import { formatAdminURL } from '@payloadcms/ui/shared' @@ -130,7 +135,7 @@ export const RootPage = async ({ }) const RenderedView = RenderServerComponent({ - clientProps: { clientConfig, documentSubViewType, viewType }, + clientProps: { clientConfig, documentSubViewType, viewType } satisfies AdminViewClientProps, Component: DefaultView.payloadComponent, Fallback: DefaultView.Component, importMap, @@ -144,7 +149,7 @@ export const RootPage = async ({ params, payload: initPageResult?.req.payload, searchParams, - }, + } satisfies AdminViewServerPropsOnly, }) return ( diff --git a/packages/next/src/views/Unauthorized/index.tsx b/packages/next/src/views/Unauthorized/index.tsx index 86fd9d3704..cb297fc8b4 100644 --- a/packages/next/src/views/Unauthorized/index.tsx +++ b/packages/next/src/views/Unauthorized/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewComponent, PayloadServerReactComponent } from 'payload' +import type { AdminViewServerProps } from 'payload' import { Button } from '@payloadcms/ui' import { formatAdminURL } from '@payloadcms/ui/shared' @@ -11,9 +11,7 @@ export { generateUnauthorizedMetadata } from './meta.js' const baseClass = 'unauthorized' -export const UnauthorizedView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function UnauthorizedView({ initPageResult }: AdminViewServerProps) { const { permissions, req: { diff --git a/packages/next/src/views/Verify/index.tsx b/packages/next/src/views/Verify/index.tsx index cee82f0e8d..390e6510dd 100644 --- a/packages/next/src/views/Verify/index.tsx +++ b/packages/next/src/views/Verify/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { formatAdminURL } from '@payloadcms/ui/shared' import React from 'react' @@ -11,14 +11,10 @@ export const verifyBaseClass = 'verify' export { generateVerifyMetadata } from './meta.js' -export const Verify: React.FC = async ({ - initPageResult, - params, - searchParams, -}) => { +export async function Verify({ initPageResult, params, searchParams }: AdminViewServerProps) { // /:collectionSlug/verify/:token - const [collectionSlug, verify, token] = params.segments + const [collectionSlug, token] = params.segments const { locale, permissions, req } = initPageResult const { diff --git a/packages/next/src/views/Version/index.tsx b/packages/next/src/views/Version/index.tsx index 42cd32be41..deda5cf7e7 100644 --- a/packages/next/src/views/Version/index.tsx +++ b/packages/next/src/views/Version/index.tsx @@ -1,8 +1,7 @@ import type { Document, - EditViewComponent, + DocumentViewServerProps, OptionObject, - PayloadServerReactComponent, SanitizedCollectionPermission, SanitizedGlobalPermission, } from 'payload' @@ -17,7 +16,7 @@ import { getLatestVersion } from '../Versions/getLatestVersion.js' import { DefaultVersionView } from './Default/index.js' import { RenderDiff } from './RenderFieldsToDiff/index.js' -export const VersionView: PayloadServerReactComponent = async (props) => { +export async function VersionView(props: DocumentViewServerProps) { const { i18n, initPageResult, routeSegments, searchParams } = props const { diff --git a/packages/next/src/views/Versions/buildColumns.tsx b/packages/next/src/views/Versions/buildColumns.tsx index c62358d907..1e1a703809 100644 --- a/packages/next/src/views/Versions/buildColumns.tsx +++ b/packages/next/src/views/Versions/buildColumns.tsx @@ -1,5 +1,6 @@ import type { I18n } from '@payloadcms/translations' import type { + Column, PaginatedDocs, SanitizedCollectionConfig, SanitizedConfig, @@ -7,7 +8,7 @@ import type { TypeWithVersion, } from 'payload' -import { type Column, SortColumn } from '@payloadcms/ui' +import { SortColumn } from '@payloadcms/ui' import React from 'react' import { AutosaveCell } from './cells/AutosaveCell/index.js' diff --git a/packages/next/src/views/Versions/index.client.tsx b/packages/next/src/views/Versions/index.client.tsx index a84fb43b6a..a3fa76d11d 100644 --- a/packages/next/src/views/Versions/index.client.tsx +++ b/packages/next/src/views/Versions/index.client.tsx @@ -1,8 +1,7 @@ 'use client' -import type { SanitizedCollectionConfig } from 'payload' +import type { Column, SanitizedCollectionConfig } from 'payload' import { - type Column, LoadingOverlayToggle, Pagination, PerPage, diff --git a/packages/next/src/views/Versions/index.tsx b/packages/next/src/views/Versions/index.tsx index b54281b897..820ed2ce56 100644 --- a/packages/next/src/views/Versions/index.tsx +++ b/packages/next/src/views/Versions/index.tsx @@ -1,11 +1,6 @@ import { Gutter, ListQueryProvider, SetDocumentStepNav } from '@payloadcms/ui' import { notFound } from 'next/navigation.js' -import { - type EditViewComponent, - logError, - type PaginatedDocs, - type PayloadServerReactComponent, -} from 'payload' +import { type DocumentViewServerProps, logError, type PaginatedDocs } from 'payload' import { isNumber } from 'payload/shared' import React from 'react' @@ -16,7 +11,7 @@ import './index.scss' export const baseClass = 'versions' -export const VersionsView: PayloadServerReactComponent = async (props) => { +export async function VersionsView(props: DocumentViewServerProps) { const { initPageResult, searchParams } = props const { diff --git a/packages/payload/src/admin/elements/PreviewButton.ts b/packages/payload/src/admin/elements/PreviewButton.ts index dad525625b..f4e5f8bc70 100644 --- a/packages/payload/src/admin/elements/PreviewButton.ts +++ b/packages/payload/src/admin/elements/PreviewButton.ts @@ -1,3 +1,7 @@ -import type { CustomComponent } from '../../config/types.js' +import type { ServerProps } from '../../config/types.js' -export type CustomPreviewButton = CustomComponent +export type PreviewButtonClientProps = {} + +export type PreviewButtonServerPropsOnly = {} & ServerProps + +export type PreviewButtonServerProps = PreviewButtonClientProps & PreviewButtonServerPropsOnly diff --git a/packages/payload/src/admin/elements/PublishButton.ts b/packages/payload/src/admin/elements/PublishButton.ts index 8fabd59c2f..1e8256a763 100644 --- a/packages/payload/src/admin/elements/PublishButton.ts +++ b/packages/payload/src/admin/elements/PublishButton.ts @@ -1,3 +1,9 @@ -import type { CustomComponent } from '../../config/types.js' +import type { ServerProps } from '../../config/types.js' -export type CustomPublishButton = CustomComponent +export type PublishButtonClientProps = { + label?: string +} + +export type PublishButtonServerPropsOnly = {} & ServerProps + +export type PublishButtonServerProps = PublishButtonClientProps & PublishButtonServerPropsOnly diff --git a/packages/payload/src/admin/elements/SaveButton.ts b/packages/payload/src/admin/elements/SaveButton.ts index 917775cc66..4dabfc3fa9 100644 --- a/packages/payload/src/admin/elements/SaveButton.ts +++ b/packages/payload/src/admin/elements/SaveButton.ts @@ -1,3 +1,9 @@ -import type { CustomComponent } from '../../config/types.js' +import type { ServerProps } from '../../config/types.js' -export type CustomSaveButton = CustomComponent +export type SaveButtonClientProps = { + label?: string +} + +export type SaveButtonServerPropsOnly = {} & ServerProps + +export type SaveButtonServerProps = SaveButtonClientProps & SaveButtonServerPropsOnly diff --git a/packages/payload/src/admin/elements/SaveDraftButton.ts b/packages/payload/src/admin/elements/SaveDraftButton.ts index ff2f410ae8..90857845f0 100644 --- a/packages/payload/src/admin/elements/SaveDraftButton.ts +++ b/packages/payload/src/admin/elements/SaveDraftButton.ts @@ -1,3 +1,7 @@ -import type { CustomComponent } from '../../config/types.js' +import type { ServerProps } from '../../config/types.js' -export type CustomSaveDraftButton = CustomComponent +export type SaveDraftButtonClientProps = {} + +export type SaveDraftButtonServerPropsOnly = {} & ServerProps + +export type SaveDraftButtonServerProps = SaveDraftButtonClientProps & SaveDraftButtonServerPropsOnly diff --git a/packages/payload/src/admin/elements/Table.ts b/packages/payload/src/admin/elements/Table.ts new file mode 100644 index 0000000000..6da1dae223 --- /dev/null +++ b/packages/payload/src/admin/elements/Table.ts @@ -0,0 +1,10 @@ +import type { ClientField } from '../../fields/config/types.js' + +export type Column = { + readonly accessor: string + readonly active: boolean + readonly CustomLabel?: React.ReactNode + readonly field: ClientField + readonly Heading: React.ReactNode + readonly renderedCells: React.ReactNode[] +} diff --git a/packages/payload/src/admin/types.ts b/packages/payload/src/admin/types.ts index 3b20a3ac64..f98d8075b4 100644 --- a/packages/payload/src/admin/types.ts +++ b/packages/payload/src/admin/types.ts @@ -24,20 +24,58 @@ import type { Row, } from './forms/Form.js' +export type { + /** + * @deprecated + * The `CustomPreviewButton` type is deprecated and will be removed in the next major version. + * This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead. + */ + CustomComponent as CustomPreviewButton, + /** + * @deprecated + * The `CustomPublishButton` type is deprecated and will be removed in the next major version. + * This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead. + */ + CustomComponent as CustomPublishButton, + /** + * @deprecated + * The `CustomSaveButton` type is deprecated and will be removed in the next major version. + * This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead. + */ + CustomComponent as CustomSaveButton, + /** + * @deprecated + * The `CustomSaveDraftButton` type is deprecated and will be removed in the next major version. + * This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead. + */ + CustomComponent as CustomSaveDraftButton, +} from '../config/types.js' export type { DefaultCellComponentProps, DefaultServerCellComponentProps } from './elements/Cell.js' export type { ConditionalDateProps } from './elements/DatePicker.js' export type { DayPickerProps, SharedProps, TimePickerProps } from './elements/DatePicker.js' export type { NavGroupPreferences, NavPreferences } from './elements/Nav.js' -export type { CustomPreviewButton } from './elements/PreviewButton.js' -export type { CustomPublishButton } from './elements/PublishButton.js' -export type { CustomSaveButton } from './elements/SaveButton.js' -export type { CustomSaveDraftButton } from './elements/SaveDraftButton.js' export type { - DocumentTabComponent, - DocumentTabCondition, - DocumentTabConfig, - DocumentTabProps, -} from './elements/Tab.js' + PreviewButtonClientProps, + PreviewButtonServerProps, + PreviewButtonServerPropsOnly, +} from './elements/PreviewButton.js' +export type { + PublishButtonClientProps, + PublishButtonServerProps, + PublishButtonServerPropsOnly, +} from './elements/PublishButton.js' +export type { + SaveButtonClientProps, + SaveButtonServerProps, + SaveButtonServerPropsOnly, +} from './elements/SaveButton.js' +export type { + SaveDraftButtonClientProps, + SaveDraftButtonServerProps, + SaveDraftButtonServerPropsOnly, +} from './elements/SaveDraftButton.js' + +export type { Column } from './elements/Table.js' export type { CustomUpload } from './elements/Upload.js' @@ -397,14 +435,6 @@ export type { VersionTab, } from './forms/Diff.js' -export type { - FieldErrorClientComponent, - FieldErrorClientProps, - FieldErrorServerComponent, - FieldErrorServerProps, - GenericErrorProps, -} from './forms/Error.js' - export type { BuildFormStateArgs, Data, @@ -416,6 +446,14 @@ export type { Row, } +export type { + FieldErrorClientComponent, + FieldErrorClientProps, + FieldErrorServerComponent, + FieldErrorServerProps, + GenericErrorProps, +} from './forms/Error.js' + export type { ClientComponentProps, ClientFieldBase, @@ -438,18 +476,6 @@ export type { export type { RowLabel, RowLabelComponent } from './forms/RowLabel.js' -export type { - BuildTableStateArgs, - DefaultServerFunctionArgs, - ListQuery, - ServerFunction, - ServerFunctionArgs, - ServerFunctionClient, - ServerFunctionClientArgs, - ServerFunctionConfig, - ServerFunctionHandler, -} from './functions/index.js' - export type MappedServerComponent = { Component?: React.ComponentType props?: Partial @@ -535,20 +561,104 @@ export type DocumentSlots = { Upload?: React.ReactNode } +export type { + BuildTableStateArgs, + DefaultServerFunctionArgs, + ListQuery, + ServerFunction, + ServerFunctionArgs, + ServerFunctionClient, + ServerFunctionClientArgs, + ServerFunctionConfig, + ServerFunctionHandler, +} from './functions/index.js' + export type { LanguageOptions } from './LanguageOptions.js' export type { RichTextAdapter, RichTextAdapterProvider, RichTextHooks } from './RichText.js' export type { + DocumentSubViewTypes, + DocumentTabClientProps, + /** + * @deprecated + * The `DocumentTabComponent` type is deprecated and will be removed in the next major version. + * Use `DocumentTabServerProps`or `DocumentTabClientProps` instead. + */ + DocumentTabComponent, + DocumentTabCondition, + DocumentTabConfig, + /** + * @deprecated + * The `DocumentTabProps` type is deprecated and will be removed in the next major version. + * Use `DocumentTabServerProps` instead. + */ + DocumentTabServerProps as DocumentTabProps, + DocumentTabServerProps, + DocumentTabServerPropsOnly, + /** + * @deprecated + * The `ClientSideEditViewProps` type is deprecated and will be removed in the next major version. + * Use `DocumentViewClientProps` instead. + */ + DocumentViewClientProps as ClientSideEditViewProps, + DocumentViewClientProps, + /** + * @deprecated + * The `ServerSideEditViewProps` is deprecated and will be removed in the next major version. + * Use `DocumentViewServerProps` instead. + */ + DocumentViewServerProps as ServerSideEditViewProps, + DocumentViewServerProps, + DocumentViewServerPropsOnly, + EditViewProps, +} from './views/document.js' + +export type { + AdminViewClientProps, + /** + * @deprecated + * The `AdminViewComponent` type is deprecated and will be removed in the next major version. + * Type your component props directly instead. + */ AdminViewComponent, AdminViewConfig, - AdminViewProps, - ClientSideEditViewProps, - EditViewProps, + /** + * @deprecated + * The `AdminViewProps` type is deprecated and will be removed in the next major version. + * Use `AdminViewServerProps` instead. + */ + AdminViewServerProps as AdminViewProps, + AdminViewServerProps, + AdminViewServerPropsOnly, InitPageResult, - ServerSideEditViewProps, + ServerPropsFromView, + ViewDescriptionClientProps, + ViewDescriptionServerProps, + ViewDescriptionServerPropsOnly, + ViewTypes, VisibleEntities, -} from './views/types.js' +} from './views/index.js' + +export type { + AfterListClientProps, + AfterListServerProps, + AfterListServerPropsOnly, + AfterListTableClientProps, + AfterListTableServerProps, + AfterListTableServerPropsOnly, + BeforeListClientProps, + BeforeListServerProps, + BeforeListServerPropsOnly, + BeforeListTableClientProps, + BeforeListTableServerProps, + BeforeListTableServerPropsOnly, + ListViewClientProps, + ListViewServerProps, + ListViewServerPropsOnly, + ListViewSlots, + ListViewSlotSharedClientProps, +} from './views/list.js' type SchemaPath = {} & string export type FieldSchemaMap = Map< diff --git a/packages/payload/src/admin/elements/Tab.ts b/packages/payload/src/admin/views/document.ts similarity index 54% rename from packages/payload/src/admin/elements/Tab.ts rename to packages/payload/src/admin/views/document.ts index 06b6e7dcab..db0b2ee2db 100644 --- a/packages/payload/src/admin/elements/Tab.ts +++ b/packages/payload/src/admin/views/document.ts @@ -1,18 +1,45 @@ -import type { I18n } from '@payloadcms/translations' - import type { SanitizedPermissions } from '../../auth/types.js' import type { SanitizedCollectionConfig } from '../../collections/config/types.js' -import type { PayloadComponent, SanitizedConfig } from '../../config/types.js' +import type { PayloadComponent, SanitizedConfig, ServerProps } from '../../config/types.js' import type { SanitizedGlobalConfig } from '../../globals/config/types.js' -import type { Payload } from '../../index.js' +import type { Data, DocumentSlots, FormState } from '../types.js' +import type { InitPageResult, ViewTypes } from './index.js' -export type DocumentTabProps = { +export type EditViewProps = { + readonly collectionSlug?: string + readonly globalSlug?: string +} + +export type DocumentViewServerPropsOnly = { + readonly doc: Data + readonly initPageResult: InitPageResult + readonly routeSegments: string[] +} & ServerProps + +export type DocumentViewServerProps = DocumentViewClientProps & DocumentViewServerPropsOnly + +export type DocumentViewClientProps = { + documentSubViewType: DocumentSubViewTypes + formState: FormState + viewType: ViewTypes +} & DocumentSlots + +/** + * @todo: This should be renamed to `DocumentSubViewType` (singular) + */ +export type DocumentSubViewTypes = 'api' | 'default' | 'livePreview' | 'version' | 'versions' + +export type DocumentTabServerPropsOnly = { readonly apiURL?: string readonly collectionConfig?: SanitizedCollectionConfig readonly globalConfig?: SanitizedGlobalConfig - readonly i18n: I18n - readonly payload: Payload readonly permissions: SanitizedPermissions +} & ServerProps + +export type DocumentTabServerProps = DocumentTabClientProps & DocumentTabServerPropsOnly + +export type DocumentTabClientProps = { + path: string } export type DocumentTabCondition = (args: { @@ -42,6 +69,9 @@ export type DocumentTabConfig = { readonly Pill?: PayloadComponent } +/** + * @todo: Remove this type as it's only used internally for the config (above) + */ export type DocumentTabComponent = PayloadComponent<{ path: string }> diff --git a/packages/payload/src/admin/views/types.ts b/packages/payload/src/admin/views/index.ts similarity index 60% rename from packages/payload/src/admin/views/types.ts rename to packages/payload/src/admin/views/index.ts index 7dbad82c82..7e5244807d 100644 --- a/packages/payload/src/admin/views/types.ts +++ b/packages/payload/src/admin/views/index.ts @@ -1,4 +1,4 @@ -import type { ClientTranslationsObject } from '@payloadcms/translations' +import type { ClientTranslationsObject, I18n } from '@payloadcms/translations' import type { SanitizedPermissions } from '../../auth/index.js' import type { ImportMap } from '../../bin/generateImportMap/index.js' @@ -8,17 +8,19 @@ import type { CustomComponent, Locale, MetaConfig, + Params, PayloadComponent, SanitizedConfig, ServerProps, } from '../../config/types.js' import type { SanitizedGlobalConfig } from '../../globals/config/types.js' -import type { PayloadRequest } from '../../types/index.js' +import type { Payload, PayloadRequest } from '../../types/index.js' import type { LanguageOptions } from '../LanguageOptions.js' -import type { Data, DocumentSlots } from '../types.js' +import type { Data, StaticDescription } from '../types.js' +import type { DocumentSubViewTypes } from './document.js' export type AdminViewConfig = { - Component: AdminViewComponent + Component: PayloadComponent /** Whether the path should be matched exactly or as a prefix */ exact?: boolean meta?: MetaConfig @@ -27,27 +29,32 @@ export type AdminViewConfig = { strict?: boolean } -export type AdminViewProps = { +export type AdminViewClientProps = { + clientConfig: ClientConfig + documentSubViewType?: DocumentSubViewTypes + viewType: ViewTypes +} + +export type AdminViewServerPropsOnly = { readonly clientConfig: ClientConfig readonly disableActions?: boolean - readonly documentSubViewType?: DocumentSubViewTypes - readonly drawerSlug?: string + /** + * @todo remove `docID` here as it is already contained in `initPageResult` + */ + readonly docID?: number | string readonly importMap: ImportMap readonly initialData?: Data readonly initPageResult: InitPageResult - readonly params?: { [key: string]: string | string[] | undefined } readonly redirectAfterDelete?: boolean readonly redirectAfterDuplicate?: boolean - readonly searchParams: { [key: string]: string | string[] | undefined } - readonly viewType: ViewTypes -} +} & ServerProps -export type AdminViewComponent = PayloadComponent +export type AdminViewServerProps = AdminViewClientProps & AdminViewServerPropsOnly -export type EditViewProps = { - readonly collectionSlug?: string - readonly globalSlug?: string -} +/** + * @deprecated This should be removed in favor of direct props + */ +export type AdminViewComponent = PayloadComponent export type VisibleEntities = { collections: SanitizedCollectionConfig['slug'][] @@ -68,15 +75,9 @@ export type InitPageResult = { visibleEntities: VisibleEntities } -export type ServerSideEditViewProps = { - readonly doc: Data - readonly initPageResult: InitPageResult - readonly routeSegments: string[] -} & ClientSideEditViewProps & - ServerProps - -export type ClientSideEditViewProps = {} & DocumentSlots - +/** + * @todo This should be renamed to `ViewType` (singular) + */ export type ViewTypes = | 'account' | 'dashboard' @@ -85,10 +86,19 @@ export type ViewTypes = | 'reset' | 'verify' | 'version' -export type DocumentSubViewTypes = 'api' | 'default' | 'livePreview' | 'version' | 'versions' export type ServerPropsFromView = { collectionConfig?: SanitizedConfig['collections'][number] globalConfig?: SanitizedConfig['globals'][number] viewActions: CustomComponent[] } + +// Description +export type ViewDescriptionClientProps = { + collectionSlug?: SanitizedCollectionConfig['slug'] + description: StaticDescription +} + +export type ViewDescriptionServerPropsOnly = {} & ServerProps + +export type ViewDescriptionServerProps = ViewDescriptionClientProps & ViewDescriptionServerPropsOnly diff --git a/packages/payload/src/admin/views/list.ts b/packages/payload/src/admin/views/list.ts new file mode 100644 index 0000000000..c066a34331 --- /dev/null +++ b/packages/payload/src/admin/views/list.ts @@ -0,0 +1,75 @@ +import type { + CollectionAdminOptions, + SanitizedCollectionConfig, +} from '../../collections/config/types.js' +import type { ServerProps } from '../../config/types.js' +import type { ListPreferences } from '../../preferences/types.js' +import type { ResolvedFilterOptions } from '../../types/index.js' +import type { Column } from '../elements/Table.js' +import type { Data } from '../types.js' + +export type ListViewSlots = { + AfterList?: React.ReactNode + AfterListTable?: React.ReactNode + BeforeList?: React.ReactNode + BeforeListTable?: React.ReactNode + Description?: React.ReactNode + Table: React.ReactNode +} + +/** + * The `ListViewServerPropsOnly` approach is needed to ensure type strictness when injecting component props + * There is no way to do something like `Omit` + * This is because `ListViewClientProps` is a union which is impossible to exclude from + * Exporting explicitly defined `ListViewServerPropsOnly`, etc. allows for the strictest typing + */ +export type ListViewServerPropsOnly = { + collectionConfig: SanitizedCollectionConfig + data: Data + limit: number + listPreferences: ListPreferences + listSearchableFields: CollectionAdminOptions['listSearchableFields'] +} & ServerProps + +export type ListViewServerProps = ListViewClientProps & ListViewServerPropsOnly + +export type ListViewClientProps = { + beforeActions?: React.ReactNode[] + collectionSlug: SanitizedCollectionConfig['slug'] + columnState: Column[] + disableBulkDelete?: boolean + disableBulkEdit?: boolean + enableRowSelections?: boolean + hasCreatePermission: boolean + listPreferences?: ListPreferences + newDocumentURL: string + preferenceKey?: string + renderedFilters?: Map + resolvedFilterOptions?: Map +} & ListViewSlots + +export type ListViewSlotSharedClientProps = { + collectionSlug: SanitizedCollectionConfig['slug'] + hasCreatePermission: boolean + newDocumentURL: string +} + +// BeforeList +export type BeforeListClientProps = ListViewSlotSharedClientProps +export type BeforeListServerPropsOnly = {} & ListViewServerPropsOnly +export type BeforeListServerProps = BeforeListClientProps & BeforeListServerPropsOnly + +// BeforeListTable +export type BeforeListTableClientProps = ListViewSlotSharedClientProps +export type BeforeListTableServerPropsOnly = {} & ListViewServerPropsOnly +export type BeforeListTableServerProps = BeforeListTableClientProps & BeforeListTableServerPropsOnly + +// AfterList +export type AfterListClientProps = ListViewSlotSharedClientProps +export type AfterListServerPropsOnly = {} & ListViewServerPropsOnly +export type AfterListServerProps = AfterListClientProps & AfterListServerPropsOnly + +// AfterListTable +export type AfterListTableClientProps = ListViewSlotSharedClientProps +export type AfterListTableServerPropsOnly = {} & ListViewServerPropsOnly +export type AfterListTableServerProps = AfterListTableClientProps & AfterListTableServerPropsOnly diff --git a/packages/payload/src/bin/generateImportMap/iterateConfig.ts b/packages/payload/src/bin/generateImportMap/iterateConfig.ts index 9e93eeb718..c48f2ee432 100644 --- a/packages/payload/src/bin/generateImportMap/iterateConfig.ts +++ b/packages/payload/src/bin/generateImportMap/iterateConfig.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore -import type { AdminViewConfig } from '../../admin/views/types.js' +import type { AdminViewConfig } from '../../admin/views/index.js' import type { SanitizedConfig } from '../../config/types.js' import type { AddToImportMap, Imports, InternalImportMap } from './index.js' diff --git a/packages/payload/src/collections/config/types.ts b/packages/payload/src/collections/config/types.ts index eafa2be926..0f60f0e5fa 100644 --- a/packages/payload/src/collections/config/types.ts +++ b/packages/payload/src/collections/config/types.ts @@ -1,13 +1,7 @@ import type { GraphQLInputObjectType, GraphQLNonNull, GraphQLObjectType } from 'graphql' import type { DeepRequired, IsAny, MarkOptional } from 'ts-essentials' -import type { - CustomPreviewButton, - CustomPublishButton, - CustomSaveButton, - CustomSaveDraftButton, - CustomUpload, -} from '../../admin/types.js' +import type { CustomUpload } from '../../admin/types.js' import type { Arguments as MeArguments } from '../../auth/operations/me.js' import type { Arguments as RefreshArguments, @@ -287,23 +281,23 @@ export type CollectionAdminOptions = { /** * Replaces the "Preview" button */ - PreviewButton?: CustomPreviewButton + PreviewButton?: CustomComponent /** * Replaces the "Publish" button * + drafts must be enabled */ - PublishButton?: CustomPublishButton + PublishButton?: CustomComponent /** * Replaces the "Save" button * + drafts must be disabled */ - SaveButton?: CustomSaveButton + SaveButton?: CustomComponent /** * Replaces the "Save Draft" button * + drafts must be enabled * + autosave must be disabled */ - SaveDraftButton?: CustomSaveDraftButton + SaveDraftButton?: CustomComponent /** * Replaces the "Upload" section * + upload must be enabled diff --git a/packages/payload/src/config/types.ts b/packages/payload/src/config/types.ts index ac636aa58a..747b75fed3 100644 --- a/packages/payload/src/config/types.ts +++ b/packages/payload/src/config/types.ts @@ -14,18 +14,16 @@ import type { JSONSchema4 } from 'json-schema' import type { DestinationStream, Level, pino } from 'pino' import type React from 'react' import type { default as sharp } from 'sharp' -import type { DeepRequired, MarkOptional } from 'ts-essentials' +import type { DeepRequired } from 'ts-essentials' import type { RichTextAdapterProvider } from '../admin/RichText.js' -import type { DocumentTabConfig, RichTextAdapter } from '../admin/types.js' import type { - AdminViewConfig, DocumentSubViewTypes, - ServerPropsFromView, - ServerSideEditViewProps, - ViewTypes, - VisibleEntities, -} from '../admin/views/types.js' + DocumentTabConfig, + DocumentViewServerProps, + RichTextAdapter, +} from '../admin/types.js' +import type { AdminViewConfig, ViewTypes, VisibleEntities } from '../admin/views/index.js' import type { SanitizedPermissions } from '../auth/index.js' import type { AddToImportMap, @@ -383,7 +381,7 @@ export type Endpoint = { root?: never } -export type EditViewComponent = PayloadComponent +export type EditViewComponent = PayloadComponent export type EditViewConfig = { meta?: MetaConfig @@ -407,22 +405,20 @@ export type EditViewConfig = { } ) -type ClientProps = { - readonly [key: string]: unknown -} +export type Params = { [key: string]: string | string[] | undefined } export type ServerProps = { readonly documentSubViewType?: DocumentSubViewTypes readonly i18n: I18nClient readonly locale?: Locale - readonly params?: { [key: string]: string | string[] | undefined } + readonly params?: Params readonly payload: Payload readonly permissions?: SanitizedPermissions - readonly searchParams?: { [key: string]: string | string[] | undefined } + readonly searchParams?: Params readonly user?: TypedUser readonly viewType?: ViewTypes readonly visibleEntities?: VisibleEntities -} & ClientProps +} export const serverProps: (keyof ServerProps)[] = [ 'payload', @@ -1272,5 +1268,3 @@ export type EntityDescriptionFunction = ({ t }: { t: TFunction }) => string export type EntityDescription = EntityDescriptionFunction | Record | string export type { EmailAdapter, SendEmailOptions } - -export type { DocumentSubViewTypes, ServerPropsFromView, ViewTypes } diff --git a/packages/ui/src/elements/DocumentControls/index.tsx b/packages/ui/src/elements/DocumentControls/index.tsx index c63ef1aee4..be8d3495da 100644 --- a/packages/ui/src/elements/DocumentControls/index.tsx +++ b/packages/ui/src/elements/DocumentControls/index.tsx @@ -1,7 +1,5 @@ 'use client' import type { - ClientCollectionConfig, - ClientGlobalConfig, ClientUser, SanitizedCollectionConfig, SanitizedCollectionPermission, diff --git a/packages/ui/src/elements/PreviewButton/index.tsx b/packages/ui/src/elements/PreviewButton/index.tsx index da8dc5aaf6..052eb74fb0 100644 --- a/packages/ui/src/elements/PreviewButton/index.tsx +++ b/packages/ui/src/elements/PreviewButton/index.tsx @@ -1,4 +1,6 @@ 'use client' +import type { PreviewButtonClientProps } from 'payload' + import React from 'react' import { Button } from '../Button/index.js' @@ -6,7 +8,7 @@ import { usePreviewURL } from './usePreviewURL.js' const baseClass = 'preview-btn' -export const PreviewButton: React.FC = () => { +export function PreviewButton(props: PreviewButtonClientProps) { const { generatePreviewURL, label } = usePreviewURL() return ( diff --git a/packages/ui/src/elements/PublishButton/ScheduleDrawer/buildUpcomingColumns.tsx b/packages/ui/src/elements/PublishButton/ScheduleDrawer/buildUpcomingColumns.tsx index d709f5bd1f..9216710b0b 100644 --- a/packages/ui/src/elements/PublishButton/ScheduleDrawer/buildUpcomingColumns.tsx +++ b/packages/ui/src/elements/PublishButton/ScheduleDrawer/buildUpcomingColumns.tsx @@ -1,9 +1,8 @@ -import type { ClientConfig } from 'payload' +import type { ClientConfig, Column } from 'payload' import { getTranslation, type I18nClient, type TFunction } from '@payloadcms/translations' import React from 'react' -import type { Column } from '../../Table/index.js' import type { UpcomingEvent } from './types.js' import { formatDate } from '../../../utilities/formatDate.js' diff --git a/packages/ui/src/elements/PublishButton/ScheduleDrawer/index.tsx b/packages/ui/src/elements/PublishButton/ScheduleDrawer/index.tsx index 20de068e5d..295fb75bd9 100644 --- a/packages/ui/src/elements/PublishButton/ScheduleDrawer/index.tsx +++ b/packages/ui/src/elements/PublishButton/ScheduleDrawer/index.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-console */ 'use client' -import type { Where } from 'payload' +import type { Column, Where } from 'payload' import { TZDateMini as TZDate } from '@date-fns/tz/date/mini' import { useModal } from '@faceless-ui/modal' @@ -11,7 +11,6 @@ import * as qs from 'qs-esm' import React, { useCallback, useMemo } from 'react' import { toast } from 'sonner' -import type { Column } from '../../Table/index.js' import type { PublishType, UpcomingEvent } from './types.js' import { FieldLabel } from '../../../fields/FieldLabel/index.js' diff --git a/packages/ui/src/elements/PublishButton/index.tsx b/packages/ui/src/elements/PublishButton/index.tsx index f74b83be5b..66031e0051 100644 --- a/packages/ui/src/elements/PublishButton/index.tsx +++ b/packages/ui/src/elements/PublishButton/index.tsx @@ -1,5 +1,7 @@ 'use client' +import type { PublishButtonClientProps } from 'payload' + import { useModal } from '@faceless-ui/modal' import * as qs from 'qs-esm' import React, { useCallback } from 'react' @@ -16,7 +18,7 @@ import { useTranslation } from '../../providers/Translation/index.js' import { PopupList } from '../Popup/index.js' import { ScheduleDrawer } from './ScheduleDrawer/index.js' -export const PublishButton: React.FC<{ label?: string }> = ({ label: labelProp }) => { +export function PublishButton({ label: labelProp }: PublishButtonClientProps) { const { id, collectionSlug, diff --git a/packages/ui/src/elements/RelationshipTable/index.tsx b/packages/ui/src/elements/RelationshipTable/index.tsx index bd02f9dfcd..d3250fb1a7 100644 --- a/packages/ui/src/elements/RelationshipTable/index.tsx +++ b/packages/ui/src/elements/RelationshipTable/index.tsx @@ -1,11 +1,10 @@ 'use client' -import type { JoinFieldClient, ListQuery, PaginatedDocs, Where } from 'payload' +import type { Column, JoinFieldClient, ListQuery, PaginatedDocs, Where } from 'payload' import { getTranslation } from '@payloadcms/translations' import React, { Fragment, useCallback, useEffect, useState } from 'react' import type { DocumentDrawerProps } from '../DocumentDrawer/types.js' -import type { Column } from '../Table/index.js' import { Button } from '../../elements/Button/index.js' import { Pill } from '../../elements/Pill/index.js' diff --git a/packages/ui/src/elements/SaveButton/index.tsx b/packages/ui/src/elements/SaveButton/index.tsx index 633d553f83..689038d4f0 100644 --- a/packages/ui/src/elements/SaveButton/index.tsx +++ b/packages/ui/src/elements/SaveButton/index.tsx @@ -1,5 +1,7 @@ 'use client' +import type { SaveButtonClientProps } from 'payload' + import React, { useRef } from 'react' import { useForm, useFormModified } from '../../forms/Form/context.js' @@ -10,7 +12,7 @@ import { useEditDepth } from '../../providers/EditDepth/index.js' import { useOperation } from '../../providers/Operation/index.js' import { useTranslation } from '../../providers/Translation/index.js' -export const SaveButton: React.FC<{ label?: string }> = ({ label: labelProp }) => { +export function SaveButton({ label: labelProp }: SaveButtonClientProps) { const { uploadStatus } = useDocumentInfo() const { t } = useTranslation() const { submit } = useForm() diff --git a/packages/ui/src/elements/SaveDraftButton/index.tsx b/packages/ui/src/elements/SaveDraftButton/index.tsx index cc6d6216b3..509c51c8e0 100644 --- a/packages/ui/src/elements/SaveDraftButton/index.tsx +++ b/packages/ui/src/elements/SaveDraftButton/index.tsx @@ -1,5 +1,7 @@ 'use client' +import type { SaveDraftButtonClientProps } from 'payload' + import React, { useCallback, useRef } from 'react' import { useForm, useFormModified } from '../../forms/Form/context.js' @@ -14,7 +16,7 @@ import { useTranslation } from '../../providers/Translation/index.js' const baseClass = 'save-draft' -export const SaveDraftButton: React.FC = () => { +export function SaveDraftButton(props: SaveDraftButtonClientProps) { const { config: { routes: { api }, diff --git a/packages/ui/src/elements/Table/index.tsx b/packages/ui/src/elements/Table/index.tsx index 9c915aff1a..15aa757e26 100644 --- a/packages/ui/src/elements/Table/index.tsx +++ b/packages/ui/src/elements/Table/index.tsx @@ -1,6 +1,6 @@ 'use client' -import type { ClientField } from 'payload' +import type { Column } from 'payload' import React from 'react' @@ -8,15 +8,6 @@ import './index.scss' const baseClass = 'table' -export type Column = { - readonly accessor: string - readonly active: boolean - readonly CustomLabel?: React.ReactNode - readonly field: ClientField - readonly Heading: React.ReactNode - readonly renderedCells: React.ReactNode[] -} - export type Props = { readonly appearance?: 'condensed' | 'default' readonly columns?: Column[] diff --git a/packages/ui/src/elements/TableColumns/buildColumnState.tsx b/packages/ui/src/elements/TableColumns/buildColumnState.tsx index c0d2532192..8eaacb507d 100644 --- a/packages/ui/src/elements/TableColumns/buildColumnState.tsx +++ b/packages/ui/src/elements/TableColumns/buildColumnState.tsx @@ -3,6 +3,7 @@ import type { ClientCollectionConfig, ClientComponentProps, ClientField, + Column, DefaultCellComponentProps, DefaultServerCellComponentProps, Field, @@ -24,7 +25,6 @@ import { import React from 'react' import type { SortColumnProps } from '../SortColumn/index.js' -import type { Column } from '../Table/index.js' import { RenderCustomComponent, diff --git a/packages/ui/src/elements/TableColumns/index.tsx b/packages/ui/src/elements/TableColumns/index.tsx index 7458f9adef..4c79730a7b 100644 --- a/packages/ui/src/elements/TableColumns/index.tsx +++ b/packages/ui/src/elements/TableColumns/index.tsx @@ -1,10 +1,9 @@ 'use client' -import type { ClientCollectionConfig, ListPreferences, SanitizedCollectionConfig } from 'payload' +import type { Column, ListPreferences, SanitizedCollectionConfig } from 'payload' import React, { createContext, useCallback, useContext, useEffect } from 'react' import type { SortColumnProps } from '../SortColumn/index.js' -import type { Column } from '../Table/index.js' import { useConfig } from '../../providers/Config/index.js' import { usePreferences } from '../../providers/Preferences/index.js' diff --git a/packages/ui/src/elements/ViewDescription/index.tsx b/packages/ui/src/elements/ViewDescription/index.tsx index e227549e18..57207c376f 100644 --- a/packages/ui/src/elements/ViewDescription/index.tsx +++ b/packages/ui/src/elements/ViewDescription/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { DescriptionFunction, StaticDescription } from 'payload' +import type { DescriptionFunction, StaticDescription, ViewDescriptionClientProps } from 'payload' import { getTranslation } from '@payloadcms/translations' import React from 'react' @@ -10,15 +10,11 @@ export type ViewDescriptionComponent = React.ComponentType type Description = DescriptionFunction | StaticDescription | string | ViewDescriptionComponent -export type ViewDescriptionProps = { - readonly description?: StaticDescription -} - export function isComponent(description: Description): description is ViewDescriptionComponent { return React.isValidElement(description) } -export const ViewDescription: React.FC = (props) => { +export function ViewDescription(props: ViewDescriptionClientProps) { const { i18n } = useTranslation() const { description } = props diff --git a/packages/ui/src/exports/client/index.ts b/packages/ui/src/exports/client/index.ts index 2695b849b3..70c9cc0fb7 100644 --- a/packages/ui/src/exports/client/index.ts +++ b/packages/ui/src/exports/client/index.ts @@ -114,7 +114,15 @@ export { RelationshipProvider, useListRelationships, } from '../../elements/Table/RelationshipProvider/index.js' -export { type Column, Table } from '../../elements/Table/index.js' +export { Table } from '../../elements/Table/index.js' +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import { Column } from 'payload'` instead. + */ + Column, +} from 'payload' export { DefaultCell } from '../../elements/Table/DefaultCell/index.js' export { Thumbnail } from '../../elements/Thumbnail/index.js' export { Tooltip } from '../../elements/Tooltip/index.js' @@ -293,20 +301,52 @@ export { SelectAll } from '../../elements/SelectAll/index.js' export { SelectRow } from '../../elements/SelectRow/index.js' export { SelectMany } from '../../elements/SelectMany/index.js' -export { - DefaultListView, - type ListViewClientProps, - type ListViewSlots, -} from '../../views/List/index.js' +export { DefaultListView } from '../../views/List/index.js' -export type { ListComponentClientProps, ListComponentServerProps } from '../../views/List/types.js' +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import type { ListViewSlots } from 'payload'` instead. + */ + ListViewSlots, +} from 'payload' -/* - @deprecated - This export will be removed in the next major version. - Use `import { ListPreferences } from 'payload'` instead. -*/ -export type { ListPreferences } from 'payload' +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import type { ListViewClientProps } from 'payload'` instead. + */ + ListViewClientProps, +} from 'payload' + +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import type { ListViewClientProps } from 'payload'` instead. + */ + ListViewClientProps as ListComponentClientProps, +} from 'payload' + +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import type { ListViewServerProps } from 'payload'` instead. + */ + ListViewServerProps as ListComponentServerProps, +} from 'payload' + +export type { + /** + * @deprecated + * This export will be removed in the next major version. + * Use `import type { ListPreferences } from 'payload'` instead. + */ + ListPreferences, +} from 'payload' export type { ListHeaderProps } from '../../views/List/ListHeader/index.js' diff --git a/packages/ui/src/utilities/buildTableState.ts b/packages/ui/src/utilities/buildTableState.ts index 49572dcbe8..0f170f6a24 100644 --- a/packages/ui/src/utilities/buildTableState.ts +++ b/packages/ui/src/utilities/buildTableState.ts @@ -2,6 +2,7 @@ import type { BuildTableStateArgs, ClientCollectionConfig, ClientConfig, + Column, ErrorResult, ListPreferences, PaginatedDocs, @@ -11,8 +12,6 @@ import type { import { formatErrors } from 'payload' import { isNumber } from 'payload/shared' -import type { Column } from '../elements/Table/index.js' - import { getClientConfig } from './getClientConfig.js' import { renderFilters, renderTable } from './renderTable.js' import { upsertPreferences } from './upsertPreferences.js' diff --git a/packages/ui/src/views/Edit/index.tsx b/packages/ui/src/views/Edit/index.tsx index 1ae69566b2..0925d6ba7d 100644 --- a/packages/ui/src/views/Edit/index.tsx +++ b/packages/ui/src/views/Edit/index.tsx @@ -1,6 +1,6 @@ 'use client' -import type { ClientSideEditViewProps, ClientUser, FormState } from 'payload' +import type { ClientUser, DocumentViewClientProps, FormState } from 'payload' import { useRouter, useSearchParams } from 'next/navigation.js' import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -41,14 +41,14 @@ const baseClass = 'collection-edit' // This component receives props only on _pages_ // When rendered within a drawer, props are empty // This is solely to support custom edit views which get server-rendered -export const DefaultEditView: React.FC = ({ +export function DefaultEditView({ Description, PreviewButton, PublishButton, SaveButton, SaveDraftButton, Upload: CustomUpload, -}) => { +}: DocumentViewClientProps) { const { id, action, diff --git a/packages/ui/src/views/List/index.tsx b/packages/ui/src/views/List/index.tsx index f92129d60e..fc9d48df34 100644 --- a/packages/ui/src/views/List/index.tsx +++ b/packages/ui/src/views/List/index.tsx @@ -1,14 +1,12 @@ 'use client' -import type { ListPreferences, ResolvedFilterOptions } from 'payload' +import type { ListViewClientProps } from 'payload' import { getTranslation } from '@payloadcms/translations' import { useRouter } from 'next/navigation.js' import { formatFilesize, isNumber } from 'payload/shared' import React, { Fragment, useEffect, useState } from 'react' -import type { Column } from '../../elements/Table/index.js' - import { useBulkUpload } from '../../elements/BulkUpload/index.js' import { Button } from '../../elements/Button/index.js' import { DeleteMany } from '../../elements/DeleteMany/index.js' @@ -40,31 +38,7 @@ import './index.scss' const baseClass = 'collection-list' -export type ListViewSlots = { - AfterList?: React.ReactNode - AfterListTable?: React.ReactNode - BeforeList?: React.ReactNode - BeforeListTable?: React.ReactNode - Description?: React.ReactNode - Table: React.ReactNode -} - -export type ListViewClientProps = { - beforeActions?: React.ReactNode[] - collectionSlug: string - columnState: Column[] - disableBulkDelete?: boolean - disableBulkEdit?: boolean - enableRowSelections?: boolean - hasCreatePermission: boolean - listPreferences?: ListPreferences - newDocumentURL: string - preferenceKey?: string - renderedFilters?: Map - resolvedFilterOptions?: Map -} & ListViewSlots - -export const DefaultListView: React.FC = (props) => { +export function DefaultListView(props: ListViewClientProps) { const { AfterList, AfterListTable, @@ -193,7 +167,10 @@ export const DefaultListView: React.FC = (props) => { + } /> diff --git a/packages/ui/src/views/List/types.ts b/packages/ui/src/views/List/types.ts index 24bb1eef02..8c49dd0718 100644 --- a/packages/ui/src/views/List/types.ts +++ b/packages/ui/src/views/List/types.ts @@ -1,12 +1,4 @@ -import type { I18n } from '@payloadcms/translations' -import type { - AdminViewProps, - Locale, - Payload, - SanitizedCollectionConfig, - SanitizedPermissions, - User, -} from 'payload' +import type { SanitizedCollectionConfig } from 'payload' export type DefaultListViewProps = { collectionSlug: SanitizedCollectionConfig['slug'] @@ -16,21 +8,3 @@ export type DefaultListViewProps = { export type ListIndexProps = { collection: SanitizedCollectionConfig } - -export type ListComponentClientProps = { - collectionSlug: SanitizedCollectionConfig['slug'] - hasCreatePermission: boolean - newDocumentURL: string -} - -export type ListComponentServerProps = { - collectionConfig: SanitizedCollectionConfig - i18n: I18n - limit: number - locale: Locale - params: AdminViewProps['params'] - payload: Payload - permissions: SanitizedPermissions - searchParams: AdminViewProps['searchParams'] - user: User -} diff --git a/test/admin/collections/Geo.ts b/test/admin/collections/Geo.ts index dd87ba976b..88c6dca8de 100644 --- a/test/admin/collections/Geo.ts +++ b/test/admin/collections/Geo.ts @@ -9,14 +9,14 @@ export const Geo: CollectionConfig = { views: { edit: { api: { - actions: ['/components/CollectionAPIButton/index.js#CollectionAPIButton'], + actions: ['/components/actions/CollectionAPIButton/index.js#CollectionAPIButton'], }, default: { - actions: ['/components/CollectionEditButton/index.js#CollectionEditButton'], + actions: ['/components/actions/CollectionEditButton/index.js#CollectionEditButton'], }, }, list: { - actions: ['/components/CollectionListButton/index.js#CollectionListButton'], + actions: ['/components/actions/CollectionListButton/index.js#CollectionListButton'], }, }, }, diff --git a/test/admin/components/CustomTabComponent/client.tsx b/test/admin/components/CustomTabComponent/client.tsx index ab1305568d..070c9f2114 100644 --- a/test/admin/components/CustomTabComponent/client.tsx +++ b/test/admin/components/CustomTabComponent/client.tsx @@ -1,5 +1,7 @@ 'use client' +import type { DocumentTabClientProps } from 'payload' + import { useConfig } from '@payloadcms/ui' import LinkImport from 'next/link.js' import { useParams } from 'next/navigation.js' @@ -7,9 +9,7 @@ import React from 'react' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default -export const CustomTabComponentClient: React.FC<{ - readonly path: string -}> = ({ path }) => { +export function CustomTabComponentClient({ path }: DocumentTabClientProps) { const { config: { routes: { admin: adminRoute }, @@ -18,7 +18,7 @@ export const CustomTabComponentClient: React.FC<{ const params = useParams() - const baseRoute = (params.segments.slice(0, 3) as string[]).join('/') + const baseRoute = (params.segments?.slice(0, 3) as string[]).join('/') return Custom Tab Component } diff --git a/test/admin/components/CustomTabComponent/index.tsx b/test/admin/components/CustomTabComponent/index.tsx index f15594e591..498eed6f7b 100644 --- a/test/admin/components/CustomTabComponent/index.tsx +++ b/test/admin/components/CustomTabComponent/index.tsx @@ -1,11 +1,11 @@ -import type { DocumentTabComponent } from 'payload' +import type { DocumentTabServerProps } from 'payload' import React from 'react' import { CustomTabComponentClient } from './client.js' import './index.scss' -export const CustomTabComponent: DocumentTabComponent = (props) => { +export function CustomTabComponent(props: DocumentTabServerProps) { const { path } = props return ( diff --git a/test/admin/components/ViewDescription/index.tsx b/test/admin/components/ViewDescription/index.tsx index 0ab57475f7..bc94cdd50a 100644 --- a/test/admin/components/ViewDescription/index.tsx +++ b/test/admin/components/ViewDescription/index.tsx @@ -1,15 +1,15 @@ 'use client' -import type { StaticDescription } from 'payload' +import type { ViewDescriptionClientProps } from 'payload' import { ViewDescription as DefaultViewDescription } from '@payloadcms/ui' import React from 'react' import { Banner } from '../Banner/index.js' -export const ViewDescription: React.FC<{ description: StaticDescription }> = ({ +export function ViewDescription({ description = 'This is a custom view description component.', -}) => { +}: ViewDescriptionClientProps) { return ( diff --git a/test/admin/components/AdminButton/index.tsx b/test/admin/components/actions/AdminButton/index.tsx similarity index 100% rename from test/admin/components/AdminButton/index.tsx rename to test/admin/components/actions/AdminButton/index.tsx diff --git a/test/admin/components/CollectionAPIButton/index.tsx b/test/admin/components/actions/CollectionAPIButton/index.tsx similarity index 100% rename from test/admin/components/CollectionAPIButton/index.tsx rename to test/admin/components/actions/CollectionAPIButton/index.tsx diff --git a/test/admin/components/CollectionEditButton/index.tsx b/test/admin/components/actions/CollectionEditButton/index.tsx similarity index 100% rename from test/admin/components/CollectionEditButton/index.tsx rename to test/admin/components/actions/CollectionEditButton/index.tsx diff --git a/test/admin/components/CollectionListButton/index.tsx b/test/admin/components/actions/CollectionListButton/index.tsx similarity index 100% rename from test/admin/components/CollectionListButton/index.tsx rename to test/admin/components/actions/CollectionListButton/index.tsx diff --git a/test/admin/components/GlobalAPIButton/index.tsx b/test/admin/components/actions/GlobalAPIButton/index.tsx similarity index 100% rename from test/admin/components/GlobalAPIButton/index.tsx rename to test/admin/components/actions/GlobalAPIButton/index.tsx diff --git a/test/admin/components/GlobalEditButton/index.tsx b/test/admin/components/actions/GlobalEditButton/index.tsx similarity index 100% rename from test/admin/components/GlobalEditButton/index.tsx rename to test/admin/components/actions/GlobalEditButton/index.tsx diff --git a/test/admin/components/views/CustomAccount/index.tsx b/test/admin/components/views/CustomAccount/index.tsx index 11f747d2a4..c01fe20117 100644 --- a/test/admin/components/views/CustomAccount/index.tsx +++ b/test/admin/components/views/CustomAccount/index.tsx @@ -1,8 +1,8 @@ -import type { AdminViewComponent, PayloadServerReactComponent } from 'payload' +import type { AdminViewServerProps } from 'payload' import React, { Fragment } from 'react' -export const CustomAccountView: PayloadServerReactComponent = () => { +export function CustomAccountView(props: AdminViewServerProps) { return (
= () => { +export function CustomDashboardView(props: AdminViewServerProps) { return (
= ({ - initPageResult, - params, - searchParams, -}) => { +export function CustomDefaultView({ initPageResult, params, searchParams }: AdminViewServerProps) { const { permissions, req: { diff --git a/test/admin/components/views/CustomEdit/index.tsx b/test/admin/components/views/CustomEdit/index.tsx index 04a8e54ce3..987bdc9af0 100644 --- a/test/admin/components/views/CustomEdit/index.tsx +++ b/test/admin/components/views/CustomEdit/index.tsx @@ -1,12 +1,10 @@ -import type { EditViewComponent, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound, redirect } from 'next/navigation.js' import React, { Fragment } from 'react' -export const CustomEditView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function CustomEditView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomEditDefault/index.tsx b/test/admin/components/views/CustomEditDefault/index.tsx index 469af39dfb..9f2464e4f3 100644 --- a/test/admin/components/views/CustomEditDefault/index.tsx +++ b/test/admin/components/views/CustomEditDefault/index.tsx @@ -1,12 +1,10 @@ -import type { EditViewComponent, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound, redirect } from 'next/navigation.js' import React, { Fragment } from 'react' -export const CustomDefaultEditView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function CustomDefaultEditView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomMinimal/index.tsx b/test/admin/components/views/CustomMinimal/index.tsx index dc3f8e9b6f..057ae8922b 100644 --- a/test/admin/components/views/CustomMinimal/index.tsx +++ b/test/admin/components/views/CustomMinimal/index.tsx @@ -10,7 +10,7 @@ const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport. // import { Button } from 'payload/components/elements'; // import { useConfig } from 'payload/components/utilities'; -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { MinimalTemplate } from '@payloadcms/next/templates' import { Button } from '@payloadcms/ui' @@ -20,7 +20,7 @@ import './index.scss' const baseClass = 'custom-minimal-view' -export const CustomMinimalView: React.FC = ({ initPageResult }) => { +export function CustomMinimalView({ initPageResult }: AdminViewServerProps) { const { req: { payload: { diff --git a/test/admin/components/views/CustomProtectedView/index.tsx b/test/admin/components/views/CustomProtectedView/index.tsx index afcb5e757d..7b828d3d44 100644 --- a/test/admin/components/views/CustomProtectedView/index.tsx +++ b/test/admin/components/views/CustomProtectedView/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { Button } from '@payloadcms/ui' import LinkImport from 'next/link.js' @@ -10,7 +10,7 @@ import { settingsGlobalSlug } from '../../../slugs.js' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default -export const CustomProtectedView: React.FC = async ({ initPageResult }) => { +export async function CustomProtectedView({ initPageResult }: AdminViewServerProps) { const { req: { payload: { diff --git a/test/admin/components/views/CustomTabComponent/index.tsx b/test/admin/components/views/CustomTabComponent/index.tsx index 4126ac5d04..35cbd0cd5a 100644 --- a/test/admin/components/views/CustomTabComponent/index.tsx +++ b/test/admin/components/views/CustomTabComponent/index.tsx @@ -1,4 +1,4 @@ -import type { ServerSideEditViewProps } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound } from 'next/navigation.js' @@ -6,7 +6,7 @@ import React, { Fragment } from 'react' import { customTabViewComponentTitle } from '../../../shared.js' -export const CustomTabComponentView: React.FC = ({ initPageResult }) => { +export function CustomTabComponentView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomTabLabel/index.tsx b/test/admin/components/views/CustomTabLabel/index.tsx index 72e0c3f4ed..4003c6deed 100644 --- a/test/admin/components/views/CustomTabLabel/index.tsx +++ b/test/admin/components/views/CustomTabLabel/index.tsx @@ -1,4 +1,4 @@ -import type { EditViewComponent, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound } from 'next/navigation.js' @@ -6,9 +6,7 @@ import React, { Fragment } from 'react' import { customTabLabelViewTitle } from '../../../shared.js' -export const CustomTabLabelView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function CustomTabLabelView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomTabNested/index.tsx b/test/admin/components/views/CustomTabNested/index.tsx index a02f57d8ce..6d259975d7 100644 --- a/test/admin/components/views/CustomTabNested/index.tsx +++ b/test/admin/components/views/CustomTabNested/index.tsx @@ -1,4 +1,4 @@ -import type { EditViewComponent, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound } from 'next/navigation.js' @@ -6,9 +6,7 @@ import React, { Fragment } from 'react' import { customNestedTabViewTitle } from '../../../shared.js' -export const CustomNestedTabView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function CustomNestedTabView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomTabWithParam/index.tsx b/test/admin/components/views/CustomTabWithParam/index.tsx index a085ad27e7..28df8560e9 100644 --- a/test/admin/components/views/CustomTabWithParam/index.tsx +++ b/test/admin/components/views/CustomTabWithParam/index.tsx @@ -1,10 +1,10 @@ -import type { AdminViewProps } from 'payload' +import type { DocumentViewServerProps } from 'payload' import React from 'react' import { customParamViewTitle } from '../../../shared.js' -export const CustomTabWithParamView: React.FC = ({ params }) => { +export function CustomTabWithParamView({ params }: DocumentViewServerProps) { const paramValue = params?.segments?.[4] return ( diff --git a/test/admin/components/views/CustomVersions/index.tsx b/test/admin/components/views/CustomVersions/index.tsx index e6a7ce547b..b72129cb04 100644 --- a/test/admin/components/views/CustomVersions/index.tsx +++ b/test/admin/components/views/CustomVersions/index.tsx @@ -1,12 +1,10 @@ -import type { EditViewComponent, PayloadServerReactComponent } from 'payload' +import type { DocumentViewServerProps } from 'payload' import { SetStepNav } from '@payloadcms/ui' import { notFound, redirect } from 'next/navigation.js' import React, { Fragment } from 'react' -export const CustomVersionsView: PayloadServerReactComponent = ({ - initPageResult, -}) => { +export function CustomVersionsView({ initPageResult }: DocumentViewServerProps) { if (!initPageResult) { notFound() } diff --git a/test/admin/components/views/CustomView/index.tsx b/test/admin/components/views/CustomView/index.tsx index 4444fe4acc..1dde3d5539 100644 --- a/test/admin/components/views/CustomView/index.tsx +++ b/test/admin/components/views/CustomView/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import LinkImport from 'next/link.js' import React from 'react' @@ -10,7 +10,7 @@ import { Button } from '@payloadcms/ui' import { customNestedViewPath, customViewTitle } from '../../../shared.js' import { ClientForm } from './index.client.js' -export const CustomView: React.FC = ({ initPageResult }) => { +export function CustomView({ initPageResult }: AdminViewServerProps) { const { req: { payload: { diff --git a/test/admin/components/views/CustomViewNested/index.tsx b/test/admin/components/views/CustomViewNested/index.tsx index d14e290190..d77e92a326 100644 --- a/test/admin/components/views/CustomViewNested/index.tsx +++ b/test/admin/components/views/CustomViewNested/index.tsx @@ -1,4 +1,4 @@ -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { Button } from '@payloadcms/ui' import LinkImport from 'next/link.js' @@ -8,7 +8,7 @@ import { customNestedViewTitle, customViewPath } from '../../../shared.js' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default -export const CustomNestedView: React.FC = ({ initPageResult }) => { +export function CustomNestedView({ initPageResult }: AdminViewServerProps) { const { req: { payload: { diff --git a/test/admin/components/views/CustomViewWithParam/index.tsx b/test/admin/components/views/CustomViewWithParam/index.tsx index b97b16d3ba..bca77e334d 100644 --- a/test/admin/components/views/CustomViewWithParam/index.tsx +++ b/test/admin/components/views/CustomViewWithParam/index.tsx @@ -4,7 +4,7 @@ import React from 'react' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default -import type { AdminViewProps } from 'payload' +import type { AdminViewServerProps } from 'payload' import { customParamViewPath, @@ -12,7 +12,7 @@ import { customParamViewTitle, } from '../../../shared.js' -export const CustomViewWithParam: React.FC = ({ initPageResult, params }) => { +export function CustomViewWithParam({ initPageResult, params }: AdminViewServerProps) { const { req: { payload: { diff --git a/test/admin/config.ts b/test/admin/config.ts index 10f587d43b..4f5ede8e4b 100644 --- a/test/admin/config.ts +++ b/test/admin/config.ts @@ -16,7 +16,6 @@ import { CollectionGroup2B } from './collections/Group2B.js' import { CollectionHidden } from './collections/Hidden.js' import { CollectionNoApiView } from './collections/NoApiView.js' import { CollectionNotInView } from './collections/NotInView.js' -import { Orders } from './collections/Orders.js' import { Posts } from './collections/Posts.js' import { UploadCollection } from './collections/Upload.js' import { Users } from './collections/Users.js' @@ -47,7 +46,7 @@ export default buildConfigWithDefaults({ baseDir: path.resolve(dirname), }, components: { - actions: ['/components/AdminButton/index.js#AdminButton'], + actions: ['/components/actions/AdminButton/index.js#AdminButton'], afterDashboard: [ '/components/AfterDashboard/index.js#AfterDashboard', '/components/AfterDashboardClient/index.js#AfterDashboardClient', diff --git a/test/admin/globals/Global.ts b/test/admin/globals/Global.ts index b2bd2323d2..e654c584b6 100644 --- a/test/admin/globals/Global.ts +++ b/test/admin/globals/Global.ts @@ -9,10 +9,10 @@ export const Global: GlobalConfig = { views: { edit: { api: { - actions: ['/components/GlobalAPIButton/index.js#GlobalAPIButton'], + actions: ['/components/actions/GlobalAPIButton/index.js#GlobalAPIButton'], }, default: { - actions: ['/components/GlobalEditButton/index.js#GlobalEditButton'], + actions: ['/components/actions/GlobalEditButton/index.js#GlobalEditButton'], }, }, }, diff --git a/test/admin/payload-types.ts b/test/admin/payload-types.ts index 2574eaa861..b66ed60198 100644 --- a/test/admin/payload-types.ts +++ b/test/admin/payload-types.ts @@ -6,65 +6,10 @@ * and re-run `payload generate:types` to regenerate this file. */ -/** - * Supported timezones in IANA format. - * - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "supportedTimezones". - */ -export type SupportedTimezones = - | 'Pacific/Midway' - | 'Pacific/Niue' - | 'Pacific/Honolulu' - | 'Pacific/Rarotonga' - | 'America/Anchorage' - | 'Pacific/Gambier' - | 'America/Los_Angeles' - | 'America/Tijuana' - | 'America/Denver' - | 'America/Phoenix' - | 'America/Chicago' - | 'America/Guatemala' - | 'America/New_York' - | 'America/Bogota' - | 'America/Caracas' - | 'America/Santiago' - | 'America/Buenos_Aires' - | 'America/Sao_Paulo' - | 'Atlantic/South_Georgia' - | 'Atlantic/Azores' - | 'Atlantic/Cape_Verde' - | 'Europe/London' - | 'Europe/Berlin' - | 'Africa/Lagos' - | 'Europe/Athens' - | 'Africa/Cairo' - | 'Europe/Moscow' - | 'Asia/Riyadh' - | 'Asia/Dubai' - | 'Asia/Baku' - | 'Asia/Karachi' - | 'Asia/Tashkent' - | 'Asia/Calcutta' - | 'Asia/Dhaka' - | 'Asia/Almaty' - | 'Asia/Jakarta' - | 'Asia/Bangkok' - | 'Asia/Shanghai' - | 'Asia/Singapore' - | 'Asia/Tokyo' - | 'Asia/Seoul' - | 'Australia/Sydney' - | 'Pacific/Guam' - | 'Pacific/Noumea' - | 'Pacific/Auckland' - | 'Pacific/Fiji'; - export interface Config { auth: { users: UserAuthOperations; }; - blocks: {}; collections: { uploads: Upload; posts: Post; @@ -332,6 +277,9 @@ export interface CustomField { * Static field description. */ descriptionAsString?: string | null; + /** + * Function description + */ descriptionAsFunction?: string | null; descriptionAsComponent?: string | null; customSelectField?: string | null;