UNPKG

payload

Version:

Node, React and MongoDB Headless CMS and Application Framework

546 lines • 21.1 kB
import type { EditorProps } from '@monaco-editor/react'; import type { TFunction } from 'i18next'; import type { CSSProperties } from 'react'; import type React from 'react'; import type { ConditionalDateProps } from '../../admin/components/elements/DatePicker/types'; import type { Props as ErrorProps } from '../../admin/components/forms/Error/types'; import type { Description } from '../../admin/components/forms/FieldDescription/types'; import type { Props as LabelProps } from '../../admin/components/forms/Label/types'; import type { RowLabel } from '../../admin/components/forms/RowLabel/types'; import type { RichTextAdapter } from '../../admin/components/forms/field-types/RichText/types'; import type { User } from '../../auth'; import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types'; import type { SanitizedConfig } from '../../config/types'; import type { PayloadRequest, RequestContext } from '../../express/types'; import type { SanitizedGlobalConfig } from '../../globals/config/types'; import type { Payload } from '../../payload'; import type { Operation, Where } from '../../types'; export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = { /** The collection which the field belongs to. If the field belongs to a global, this will be null. */ collection: SanitizedCollectionConfig | null; context: RequestContext; /** The data passed to update the document within create and update operations, and the full document itself in the afterRead hook. */ data?: Partial<T>; /** The field which the hook is running against. */ field: FieldAffectingData; /** Boolean to denote if this hook is running against finding one, or finding many within the afterRead hook. */ findMany?: boolean; /** The global which the field belongs to. If the field belongs to a collection, this will be null. */ global: SanitizedGlobalConfig | null; /** A string relating to which operation the field type is currently executing within. Useful within beforeValidate, beforeChange, and afterChange hooks to differentiate between create and update operations. */ operation?: 'create' | 'delete' | 'read' | 'update'; /** The full original document in `update` operations. In the `afterChange` hook, this is the resulting document of the operation. */ originalDoc?: T; /** The document before changes were applied, only in `afterChange` hooks. */ previousDoc?: T; /** The sibling data of the document before changes being applied, only in `beforeChange` and `afterChange` hook. */ previousSiblingDoc?: T; /** The previous value of the field, before changes, only in `beforeChange` and `afterChange` hooks. */ previousValue?: P; /** The Express request object. It is mocked for Local API operations. */ req: PayloadRequest; /** The sibling data passed to a field that the hook is running against. */ siblingData: Partial<S>; /** The value of the field. */ value?: P; }; export type FieldHook<T extends TypeWithID = any, P = any, S = any> = (args: FieldHookArgs<T, P, S>) => P | Promise<P>; export type FieldAccess<T extends TypeWithID = any, P = any, U = any> = (args: { /** * The incoming data used to `create` or `update` the document with. `data` is undefined during the `read` operation. */ data?: Partial<T>; /** * The original data of the document before the `update` is applied. `doc` is undefined during the `create` operation. */ doc?: T; /** * The `id` of the current document being read or updated. `id` is undefined during the `create` operation. */ id?: number | string; /** The `Express` request object containing the currently authenticated `user` */ req: PayloadRequest<U>; /** * Immediately adjacent data to this field. For example, if this is a `group` field, then `siblingData` will be the other fields within the group. */ siblingData?: Partial<P>; }) => Promise<boolean> | boolean; export type Condition<T extends TypeWithID = any, P = any> = (data: Partial<T>, siblingData: Partial<P>, { user }: { user: User; }) => boolean; export type FilterOptionsProps<T = any> = { data: T; id: number | string; relationTo: string; siblingData: unknown; user: Partial<User>; }; export type FilterOptions<T = any> = ((options: FilterOptionsProps<T>) => Promise<Where | boolean> | Where | boolean) | Where | null; type Admin = { className?: string; components?: { Cell?: React.ComponentType<any>; Field?: React.ComponentType<any>; Filter?: React.ComponentType<any>; }; /** * You can programmatically show / hide fields based on what other fields are doing. * This is also run on the server, to determine if the field should be validated. */ condition?: Condition; description?: Description; disableBulkEdit?: boolean; disabled?: boolean; hidden?: boolean; position?: 'sidebar'; readOnly?: boolean; style?: CSSProperties; width?: string; }; export type Labels = { plural: Record<string, string> | string; singular: Record<string, string> | string; }; export type ValidateOptions<TData, TSiblingData, TFieldConfig> = { config: SanitizedConfig; data: Partial<TData>; id?: number | string; operation?: Operation; payload?: Payload; req?: PayloadRequest; siblingData: Partial<TSiblingData>; t: TFunction; user?: Partial<User>; } & TFieldConfig; export type Validate<TValue = any, TData = any, TSiblingData = any, TFieldConfig = any> = (value: TValue, options: ValidateOptions<TData, TSiblingData, TFieldConfig>) => Promise<string | true> | string | true; export type OptionObject = { label: Record<string, string> | string; value: string; }; export type Option = OptionObject | string; export interface FieldBase { access?: { create?: FieldAccess; read?: FieldAccess; update?: FieldAccess; }; admin?: Admin; /** Extension point to add your custom data. */ custom?: Record<string, any>; defaultValue?: any; hidden?: boolean; hooks?: { afterChange?: FieldHook[]; afterRead?: FieldHook[]; beforeChange?: FieldHook[]; beforeValidate?: FieldHook[]; }; index?: boolean; label?: Record<string, string> | false | string; localized?: boolean; name: string; required?: boolean; saveToJWT?: boolean | string; unique?: boolean; validate?: Validate; } export type NumberField = FieldBase & { admin?: Admin & { /** Set this property to a string that will be used for browser autocomplete. */ autoComplete?: string; components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; /** Set this property to define a placeholder string for the field. */ placeholder?: Record<string, string> | string; /** Set a value for the number field to increment / decrement using browser controls. */ step?: number; }; /** Maximum value accepted. Used in the default `validation` function. */ max?: number; /** Minimum value accepted. Used in the default `validation` function. */ min?: number; type: 'number'; } & ({ /** Makes this field an ordered array of numbers instead of just a single number. */ hasMany: true; /** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */ maxRows?: number; /** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */ minRows?: number; } | { /** Makes this field an ordered array of numbers instead of just a single number. */ hasMany?: false | undefined; /** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */ maxRows?: undefined; /** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */ minRows?: undefined; }); export type TextField = FieldBase & { admin?: Admin & { autoComplete?: string; components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; placeholder?: Record<string, string> | string; rtl?: boolean; }; maxLength?: number; minLength?: number; type: 'text'; } & ({ /** Makes this field an ordered array of strings instead of just a single string. */ hasMany: true; /** Maximum number of strings in the strings array, if `hasMany` is set to true. */ maxRows?: number; /** Minimum number of strings in the strings array, if `hasMany` is set to true. */ minRows?: number; } | { /** Makes this field an ordered array of strings instead of just a single string. */ hasMany?: false | undefined; /** Maximum number of strings in the strings array, if `hasMany` is set to true. */ maxRows?: undefined; /** Minimum number of strings in the strings array, if `hasMany` is set to true. */ minRows?: undefined; }); export type EmailField = FieldBase & { admin?: Admin & { autoComplete?: string; components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; placeholder?: Record<string, string> | string; }; type: 'email'; }; export type TextareaField = FieldBase & { admin?: Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; placeholder?: Record<string, string> | string; rows?: number; rtl?: boolean; }; maxLength?: number; minLength?: number; type: 'textarea'; }; export type CheckboxField = FieldBase & { admin?: Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; }; type: 'checkbox'; }; export type DateField = FieldBase & { admin?: Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; afterInput?: React.ComponentType<any>[]; beforeInput?: React.ComponentType<any>[]; }; date?: ConditionalDateProps; placeholder?: Record<string, string> | string; }; type: 'date'; }; export type GroupField = Omit<FieldBase, 'required' | 'validation'> & { admin?: Admin & { hideGutter?: boolean; }; fields: Field[]; /** Customize generated GraphQL and Typescript schema names. * By default it is bound to the collection. * * This is useful if you would like to generate a top level type to share amongst collections/fields. * **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs. */ interfaceName?: string; type: 'group'; }; export type RowAdmin = Omit<Admin, 'description'>; export type RowField = Omit<FieldBase, 'admin' | 'label' | 'name'> & { admin?: RowAdmin; fields: Field[]; type: 'row'; }; export type CollapsibleField = Omit<FieldBase, 'label' | 'name'> & { admin?: Admin & { initCollapsed?: boolean | false; }; fields: Field[]; label: RowLabel; type: 'collapsible'; }; export type TabsAdmin = Omit<Admin, 'description'>; type TabBase = Omit<FieldBase, 'required' | 'validation'> & { description?: Description; fields: Field[]; interfaceName?: string; saveToJWT?: boolean | string; }; export type NamedTab = TabBase & { /** Customize generated GraphQL and Typescript schema names. * The slug is used by default. * * This is useful if you would like to generate a top level type to share amongst collections/fields. * **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs. */ interfaceName?: string; }; export type UnnamedTab = Omit<TabBase, 'name'> & { interfaceName?: never; label: Record<string, string> | string; localized?: never; }; export type Tab = NamedTab | UnnamedTab; export type TabsField = Omit<FieldBase, 'admin' | 'localized' | 'name' | 'saveToJWT'> & { admin?: TabsAdmin; tabs: Tab[]; type: 'tabs'; }; export type TabAsField = Tab & { name?: string; type: 'tab'; }; export type UIField = { admin: { components?: { Cell?: React.ComponentType<any>; Field: React.ComponentType<any>; Filter?: React.ComponentType<any>; }; condition?: Condition; disableBulkEdit?: boolean; position?: string; width?: string; }; /** Extension point to add your custom data. */ custom?: Record<string, any>; label?: Record<string, string> | string; name: string; type: 'ui'; }; export type UploadField = FieldBase & { admin?: { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; }; filterOptions?: FilterOptions; maxDepth?: number; relationTo: string; type: 'upload'; }; type CodeAdmin = Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; editorOptions?: EditorProps['options']; language?: string; }; export type CodeField = Omit<FieldBase, 'admin'> & { admin?: CodeAdmin; maxLength?: number; minLength?: number; type: 'code'; }; type JSONAdmin = Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; editorOptions?: EditorProps['options']; }; export type JSONField = Omit<FieldBase, 'admin'> & { admin?: JSONAdmin; type: 'json'; }; export type SelectField = FieldBase & { admin?: Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; isClearable?: boolean; isSortable?: boolean; }; hasMany?: boolean; options: Option[]; type: 'select'; }; type SharedRelationshipProperties = FieldBase & { filterOptions?: FilterOptions; hasMany?: boolean; maxDepth?: number; type: 'relationship'; } & ({ hasMany: true; /** * @deprecated Use 'maxRows' instead */ max?: number; maxRows?: number; /** * @deprecated Use 'minRows' instead */ min?: number; minRows?: number; } | { hasMany?: false | undefined; /** * @deprecated Use 'maxRows' instead */ max?: undefined; maxRows?: undefined; /** * @deprecated Use 'minRows' instead */ min?: undefined; minRows?: undefined; }); type RelationshipAdmin = Admin & { allowCreate?: boolean; components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; isSortable?: boolean; }; export type PolymorphicRelationshipField = SharedRelationshipProperties & { admin?: RelationshipAdmin & { sortOptions?: { [collectionSlug: string]: string; }; }; relationTo: string[]; }; export type SingleRelationshipField = SharedRelationshipProperties & { admin?: RelationshipAdmin & { sortOptions?: string; }; relationTo: string; }; export type RelationshipField = PolymorphicRelationshipField | SingleRelationshipField; export type ValueWithRelation = { relationTo: string; value: number | string; }; export declare function valueIsValueWithRelation(value: unknown): value is ValueWithRelation; export type RelationshipValue = (number | string)[] | ValueWithRelation | ValueWithRelation[] | (number | string); export type RichTextField<Value extends object = any, AdapterProps = any, ExtraProperties = {}> = FieldBase & { admin?: Admin; editor?: RichTextAdapter<Value, AdapterProps, AdapterProps>; type: 'richText'; } & ExtraProperties; export type ArrayField = FieldBase & { admin?: Admin & { components?: { RowLabel?: RowLabel; } & Admin['components']; initCollapsed?: boolean | false; }; fields: Field[]; /** Customize generated GraphQL and Typescript schema names. * By default it is bound to the collection. * * This is useful if you would like to generate a top level type to share amongst collections/fields. * **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs. */ interfaceName?: string; labels?: Labels; maxRows?: number; minRows?: number; type: 'array'; }; export type RadioField = FieldBase & { admin?: Admin & { components?: { Error?: React.ComponentType<ErrorProps>; Label?: React.ComponentType<LabelProps>; }; layout?: 'horizontal' | 'vertical'; }; options: Option[]; type: 'radio'; }; export type Block = { fields: Field[]; /** @deprecated - please migrate to the interfaceName property instead. */ graphQL?: { singularName?: string; }; imageAltText?: string; imageURL?: string; /** Customize generated GraphQL and Typescript schema names. * The slug is used by default. * * This is useful if you would like to generate a top level type to share amongst collections/fields. * **Note**: Top level types can collide, ensure they are unique among collections, arrays, groups, blocks, tabs. */ interfaceName?: string; labels?: Labels; slug: string; /** Extension point to add your custom data. */ custom?: Record<string, any>; }; export type BlockField = FieldBase & { admin?: Admin & { initCollapsed?: boolean | false; }; blocks: Block[]; defaultValue?: unknown; labels?: Labels; maxRows?: number; minRows?: number; type: 'blocks'; }; export type PointField = FieldBase & { type: 'point'; }; export type Field = ArrayField | BlockField | CheckboxField | CodeField | CollapsibleField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | RowField | SelectField | TabsField | TextField | TextareaField | UIField | UploadField; export type FieldAffectingData = ArrayField | BlockField | CheckboxField | CodeField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | SelectField | TabAsField | TextField | TextareaField | UploadField; export type NonPresentationalField = ArrayField | BlockField | CheckboxField | CodeField | CollapsibleField | DateField | EmailField | GroupField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | RowField | SelectField | TabsField | TextField | TextareaField | UploadField; export type FieldWithPath = Field & { path?: string; }; export type FieldWithSubFields = ArrayField | CollapsibleField | GroupField | RowField; export type FieldPresentationalOnly = UIField; export type FieldWithMany = RelationshipField | SelectField; export type FieldWithMaxDepth = RelationshipField | UploadField; export declare function fieldHasSubFields(field: Field): field is FieldWithSubFields; export declare function fieldIsArrayType(field: Field): field is ArrayField; export declare function fieldIsBlockType(field: Field): field is BlockField; export declare function fieldIsGroupType(field: Field): field is GroupField; export declare function optionIsObject(option: Option): option is OptionObject; export declare function optionsAreObjects(options: Option[]): options is OptionObject[]; export declare function optionIsValue(option: Option): option is string; export declare function fieldSupportsMany(field: Field): field is FieldWithMany; export declare function fieldHasMaxDepth(field: Field): field is FieldWithMaxDepth; export declare function fieldIsPresentationalOnly(field: Field | TabAsField): field is UIField; export declare function fieldAffectsData(field: Field | TabAsField): field is FieldAffectingData; export declare function tabHasName(tab: Tab): tab is NamedTab; export declare function fieldIsLocalized(field: Field | Tab): boolean; export type HookName = 'afterChange' | 'afterRead' | 'beforeChange' | 'beforeRead' | 'beforeValidate'; export {}; //# sourceMappingURL=types.d.ts.map