import type { LanguageName } from '@uiw/codemirror-extensions-langs'; import type { PropertiesSchema } from 'ajv/dist/types/json-schema'; import type { ComponentType, FC, FunctionComponent, JSXElementConstructor, ReactElement, ReactNode, } from 'react'; import type { TranslateProps as ReactPolyglotTranslateProps, t } from 'react-polyglot'; import type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions, } from 'yaml'; import type { MediaFile as BackendMediaFile } from './backend'; import type { EditorControlProps } from './components/entry-editor/editor-control-pane/EditorControl'; import type { SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SORT_DIRECTION_NONE, } from './constants'; import type { Workflow, WorkflowStatus } from './constants/publishModes'; import type { BLOCKQUOTE_TOOLBAR_BUTTON, BOLD_TOOLBAR_BUTTON, CODE_BLOCK_TOOLBAR_BUTTON, CODE_TOOLBAR_BUTTON, DECREASE_IDENT_TOOLBAR_BUTTON, DELETE_COLUMN_TOOLBAR_BUTTON, DELETE_ROW_TOOLBAR_BUTTON, DELETE_TABLE_TOOLBAR_BUTTON, FILE_LINK_TOOLBAR_BUTTON, FONT_TOOLBAR_BUTTON, IMAGE_TOOLBAR_BUTTON, INCRASE_IDENT_TOOLBAR_BUTTON, INSERT_COLUMN_TOOLBAR_BUTTON, INSERT_ROW_TOOLBAR_BUTTON, INSERT_TABLE_TOOLBAR_BUTTON, ITALIC_TOOLBAR_BUTTON, ORDERED_LIST_TOOLBAR_BUTTON, SHORTCODE_TOOLBAR_BUTTON, STRIKETHROUGH_TOOLBAR_BUTTON, UNORDERED_LIST_TOOLBAR_BUTTON, } from './constants/toolbar_buttons'; import type { EditorSize, ViewStyle } from './constants/views'; import type { formatExtensions } from './formats/formats'; import type { I18N_FIELD_DUPLICATE, I18N_FIELD_NONE, I18N_FIELD_TRANSLATE, I18N_STRUCTURE_MULTIPLE_FILES, I18N_STRUCTURE_MULTIPLE_FOLDERS, I18N_STRUCTURE_SINGLE_FILE, } from './lib/i18n'; import type Cursor from './lib/util/Cursor'; import type AssetProxy from './valueObjects/AssetProxy'; export interface Page { isFetching?: boolean; page?: number; ids: string[]; } export interface Pages { [collection: string]: Page; } export type SortableField = | { key: string; name: string; label: string; } | ({ key: string; } & Field); export interface SortObject { key: string; direction: SortDirection; } export type SortMap = Record; export type Sort = Record; export type FilterMap = ViewFilterWithDefaults & { active?: boolean }; export type GroupMap = ViewGroupWithDefaults & { active?: boolean }; export type Filter = Record>; // collection.field.active export type Group = Record>; // collection.field.active export interface GroupOfEntries { id: string; label: string; value: string | boolean | undefined; paths: Set; } export type ObjectValue = { [key: string]: ValueOrNestedValue; }; export type ValueOrNestedValue = | string | number | (string | number)[] | boolean | ObjectValue | Date | ValueOrNestedValue[] | null | undefined; export type EntryData = ObjectValue | undefined | null; export interface Entry { collection: string; slug: string; path: string; partial: boolean; raw: string; data: T | undefined | null; label: string | null; isModification: boolean | null; mediaFiles: MediaFile[]; author: string; updatedOn: string; status?: WorkflowStatus; newRecord?: boolean; openAuthoring?: boolean; isFetching?: boolean; isPersisting?: boolean; isDeleting?: boolean; isPublishing?: boolean; isUpdatingStatus?: boolean; error?: string; i18n?: { [locale: string]: { data: Partial; }; }; meta?: { path: string; }; } export type Entries = Record; export interface FieldError { type: string; message?: string; } export interface FieldsErrors { [field: string]: FieldError[]; } export type FieldGetValidValueMethod = ( value: T | undefined | null, field: F, ) => T | undefined | null; export type FieldGetDefaultMethod = ( defaultValue: T | undefined | null, field: F, ) => T; export interface FieldValidationMethodProps { field: F; value: T | undefined | null; t: t; } export type FieldValidationMethod = ( props: FieldValidationMethodProps, ) => false | FieldError | Promise; export interface FieldStorageConverters< T = unknown, F extends BaseField = UnknownField, S = ValueOrNestedValue, > { deserialize(storageValue: S | null | undefined, field: F): T | null | undefined; serialize(cmsValue: T | null | undefined, field: F): S | null | undefined; } export interface EntryDraft { entry: Entry; fieldsErrors: FieldsErrors; } export interface BaseFieldFilterRule { field: string; } export interface FieldPatternFilterRule extends BaseFieldFilterRule { pattern: string | RegExp; } export interface FieldValueFilterRule extends BaseFieldFilterRule { value: string | number | boolean | (string | number | boolean)[]; matchAll?: boolean; } export type FieldFilterRule = FieldPatternFilterRule | FieldValueFilterRule; export interface FileNameFilterRule { pattern: string | RegExp; } export type FilterRule = FieldFilterRule | FileNameFilterRule; export interface BaseEditorConfig { size?: EditorSize; } export interface DefaultEditorConfig extends BaseEditorConfig { preview?: boolean; frame?: boolean; live_preview?: false; } export interface LiveEditorConfig extends BaseEditorConfig { live_preview: string; } export type EditorConfig = DefaultEditorConfig | LiveEditorConfig; export interface CollectionFile { name: string; label: string; file: string; fields: Field[]; label_singular?: string; description?: string; media_folder?: string; public_folder?: string; media_library?: MediaLibraryConfig; i18n?: boolean | Partial; editor?: EditorConfig; publish?: boolean; } export interface CollectionFileWithDefaults extends Omit, 'i18n'> { i18n?: I18nInfo; } interface Nested { summary?: string; depth: number; path?: { label?: string; index_file: string; }; } export interface I18nSettings { currentLocale: string; defaultLocale: string; locales: string[]; } export type Format = keyof typeof formatExtensions; export interface i18nCollection extends Omit, 'i18n'> { i18n: Required>['i18n']; } export interface BaseCollection { name: string; description?: string; icon?: string; isFetching?: boolean; summary?: string; summary_fields?: string[]; filter?: FilterRule | FilterRule[]; label_singular?: string; label: string; sortable_fields?: SortableFields; view_filters?: ViewFilters; view_groups?: ViewGroups; i18n?: boolean | Partial; hide?: boolean; editor?: EditorConfig; identifier_field?: string; path?: string; extension?: string; format?: Format; frontmatter_delimiter?: string | [string, string]; slug?: string; media_folder?: string; public_folder?: string; media_library?: MediaLibraryConfig; } export interface BaseCollectionWithDefaults extends Omit { i18n?: I18nInfo; view_filters?: ViewFiltersWithDefaults; view_groups?: ViewGroupsWithDefaults; } export interface FilesCollection extends BaseCollection { files: CollectionFile[]; } export interface FilesCollectionWithDefaults extends BaseCollectionWithDefaults { files: CollectionFileWithDefaults[]; } export interface BaseFolderCollection { folder: string; fields: Field[]; create?: boolean; publish?: boolean; delete?: boolean; nested?: Nested; meta?: { path: string; }; } export type FolderCollection = BaseCollection & BaseFolderCollection; export type FolderCollectionWithDefaults = BaseCollectionWithDefaults & BaseFolderCollection; export type Collection = | FilesCollection | FolderCollection; export type CollectionWithDefaults = | FilesCollectionWithDefaults | FolderCollectionWithDefaults; export type Collections = Record>; export type CollectionsWithDefaults = Record< string, CollectionWithDefaults >; export type MediaFile = BackendMediaFile & { key?: string }; export interface DisplayURLState { isFetching: boolean; url?: string; err?: Error; } export type TranslatedProps = T & ReactPolyglotTranslateProps; export interface MediaPath { path: T; alt?: string; } export interface WidgetControlProps { collection: CollectionWithDefaults; collectionFile: CollectionFileWithDefaults | undefined; config: ConfigWithDefaults; entry: Entry; field: F; fieldsErrors: FieldsErrors; submitted: boolean; forList: boolean; listItemPath: string | undefined; forSingleList: boolean; disabled: boolean; duplicate: boolean; label: string; locale: string | undefined; onChange: (value: T | null | undefined) => void; clearChildValidation: () => void; i18n: I18nSettings | undefined; hasErrors: boolean; errors: FieldError[]; path: string; query: EditorControlProps['query']; t: t; value: T | undefined | null; controlled: boolean; } export interface WidgetPreviewProps { config: ConfigWithDefaults; collection: CollectionWithDefaults; entry: Entry; field: RenderedField; value: T | undefined | null; } export type WidgetPreviewComponent = // eslint-disable-next-line @typescript-eslint/no-explicit-any | ReactElement> | ComponentType>; export type WidgetFor

= (name: K) => ReactNode; export type WidgetsFor

= ( name: K, ) => P[K] extends Array ? { data: U | null; widgets: Record; }[] : { data: P[K] | null; widgets: Record; }; export interface TemplatePreviewProps { collection: CollectionWithDefaults; fields: Field[]; entry: Entry; document: Document | undefined | null; window: Window | undefined | null; widgetFor: WidgetFor; widgetsFor: WidgetsFor; } export type TemplatePreviewComponent< T = ObjectValue, EF extends BaseField = UnknownField, > = ComponentType>; export interface TemplatePreviewCardProps { collection: CollectionWithDefaults; fields: Field[]; entry: Entry; status?: WorkflowStatus | 'published'; widgetFor: WidgetFor; widgetsFor: WidgetsFor; hasLocalBackup: boolean; } export type TemplatePreviewCardComponent< T = EntryData, EF extends BaseField = UnknownField, > = ComponentType>; export interface FieldPreviewProps { collection: CollectionWithDefaults; field: Field; value: T; } export type FieldPreviewComponent = ComponentType< FieldPreviewProps >; export interface WidgetOptions< T = unknown, F extends BaseField = UnknownField, S = ValueOrNestedValue, > { validator?: Widget['validator']; getValidValue?: Widget['getValidValue']; converters?: Widget['converters']; getDefaultValue?: Widget['getDefaultValue']; schema?: Widget['schema']; } export interface Widget { control: ComponentType>; preview?: WidgetPreviewComponent; validator: FieldValidationMethod; converters: FieldStorageConverters; getValidValue: FieldGetValidValueMethod; getDefaultValue?: FieldGetDefaultMethod; schema?: PropertiesSchema; } export interface WidgetParam { name: string; controlComponent: Widget['control']; previewComponent?: Widget['preview']; options?: WidgetOptions; } export interface PersistOptions { newEntry?: boolean; commitMessage: string; collectionName?: string; status?: WorkflowStatus; /** * Editorial Workflow */ useWorkflow?: boolean; unpublished?: boolean; } export interface PersistArgs { config: ConfigWithDefaults; rootSlug: string | undefined; collection: CollectionWithDefaults; entryDraft: EntryDraft; assetProxies: AssetProxy[]; usedSlugs: string[]; status?: WorkflowStatus; unpublished?: boolean; } export interface ImplementationEntry { data: string; file: { path: string; label?: string; id?: string | null; author?: string; updatedOn?: string }; } export interface DisplayURLObject { id: string; path: string; } export type DisplayURL = DisplayURLObject | string; export interface ImplementationMediaFile { name: string; id: string; size?: number; displayURL?: DisplayURL; path: string; draft?: boolean; url?: string; file?: File; field?: MediaField; } export interface DataFile { path: string; slug: string; raw: string; newPath?: string; } export interface BackendEntry { dataFiles: DataFile[]; assets: AssetProxy[]; } export interface Credentials { token: string | {}; refresh_token?: string; } export type User = Credentials & { backendName?: string; login?: string; name?: string; avatar_url?: string; useOpenAuthoring?: boolean; }; export interface ImplementationFile { id?: string | null | undefined; label?: string; path: string; } export interface AuthenticatorConfig { site_id?: string; base_url?: string; auth_endpoint?: string; auth_token_endpoint?: string; auth_url?: string; app_id?: string; clearHash?: () => void; } export abstract class BackendClass { // eslint-disable-next-line @typescript-eslint/no-empty-function constructor(_config: ConfigWithDefaults, _options: BackendInitializerOptions) {} abstract authComponent(): FC; abstract restoreUser(user: User): Promise; abstract authenticate(credentials: Credentials): Promise; abstract logout(): Promise | void | null; abstract getToken(): Promise; abstract getEntry(path: string): Promise; abstract entriesByFolder( folder: string, extension: string, depth: number, ): Promise; abstract entriesByFiles(files: ImplementationFile[]): Promise; abstract getMediaDisplayURL(displayURL: DisplayURL): Promise; abstract getMedia( mediaFolder?: string, folderSupport?: boolean, publicFolder?: string, ): Promise; abstract getMediaFile(path: string): Promise; abstract persistEntry(entry: BackendEntry, opts: PersistOptions): Promise; abstract persistMedia(file: AssetProxy, opts: PersistOptions): Promise; abstract deleteFiles(paths: string[], commitMessage: string): Promise; abstract allEntriesByFolder( folder: string, extension: string, depth: number, pathRegex?: RegExp, ): Promise; abstract traverseCursor( cursor: Cursor, action: string, ): Promise<{ entries: ImplementationEntry[]; cursor: Cursor }>; abstract status(): Promise<{ auth: { status: boolean }; api: { status: boolean; statusPage: string }; }>; /** * Editorial Workflow */ abstract unpublishedEntries: () => Promise; abstract unpublishedEntry: (args: { id?: string; collection?: string; slug?: string; }) => Promise; abstract unpublishedEntryDataFile: ( collection: string, slug: string, path: string, id: string, ) => Promise; abstract unpublishedEntryMediaFile: ( collection: string, slug: string, path: string, id: string, ) => Promise; abstract updateUnpublishedEntryStatus: ( collection: string, slug: string, newStatus: WorkflowStatus, ) => Promise; abstract publishUnpublishedEntry: (collection: string, slug: string) => Promise; abstract deleteUnpublishedEntry: (collection: string, slug: string) => Promise; abstract getDeployPreview: ( collectionName: string, slug: string, ) => Promise<{ url: string; status: string } | null>; } export type CustomIcon = FunctionComponent; export type WidgetValueSerializer = { serialize: (value: ValueOrNestedValue) => ValueOrNestedValue; deserialize: (value: ValueOrNestedValue) => ValueOrNestedValue; }; export interface MediaLibraryInitOptions { options: Record | undefined; handleInsert: (url: string | string[]) => void; } export interface MediaLibraryConfig { max_file_size?: number; folder_support?: boolean; } export interface RootMediaLibraryConfig extends MediaLibraryConfig { display_in_navigation?: boolean; } export type BackendType = | 'git-gateway' | 'github' | 'gitlab' | 'gitea' | 'bitbucket' | 'test-repo' | 'proxy'; export type MapWidgetType = 'Point' | 'LineString' | 'Polygon'; export interface SelectWidgetOptionObject { label: string; value: string | number; } export type AuthScope = 'repo' | 'public_repo'; export type SlugEncoding = 'unicode' | 'ascii'; export type RenderedField = F & { renderedFields?: ReactNode[]; }; export interface BaseField { name: string; label?: string; required?: boolean; hint?: string; pattern?: [string, string]; i18n?: boolean | 'translate' | 'duplicate' | 'none'; comment?: string; widget: string; condition?: FieldFilterRule | FieldFilterRule[]; } export interface MediaField extends BaseField { media_folder?: string; public_folder?: string; choose_url?: boolean; multiple?: boolean; media_library?: MediaLibraryConfig; select_folder?: boolean; } export interface BooleanField extends BaseField { widget: 'boolean'; default?: boolean; prefix?: string; suffix?: string; } export interface CodeField extends BaseField { widget: 'code'; default?: string | { [key: string]: string }; default_language?: string; allow_language_selection?: boolean; keys?: { code: string; lang: string }; output_code_only?: boolean; code_mirror_config?: { extra_keys?: Record; } & Record; } export interface ColorField extends BaseField { widget: 'color'; default?: string; allow_input?: boolean; enable_alpha?: boolean; } export interface DateTimeField extends BaseField { widget: 'datetime'; default?: string; format?: string; date_format?: boolean | string; time_format?: boolean | string; picker_utc?: boolean; } export interface FileOrImageField extends MediaField { widget: 'file' | 'image'; default?: string; } export interface ObjectField extends BaseField { widget: 'object'; collapsed?: boolean; summary?: string; fields: Field[]; } export interface KeyValueField extends BaseField { widget: 'keyvalue'; default?: Record; label_singular?: string; key_label?: string; value_label?: string; min?: number; max?: number; } export interface ListField extends BaseField { widget: 'list'; default?: ValueOrNestedValue[]; allow_add?: boolean; collapsed?: boolean; summary?: string; label_singular?: string; fields?: Field[]; max?: number; min?: number; add_to_top?: boolean; types?: ObjectField[]; type_key?: string; delimiter?: string; } export interface MapField extends BaseField { widget: 'map'; default?: string; decimals?: number; type?: MapWidgetType; height?: string; } export type MarkdownToolbarButtonType = | LowLevelMarkdownToolbarButtonType | typeof FONT_TOOLBAR_BUTTON | typeof SHORTCODE_TOOLBAR_BUTTON; export type LowLevelMarkdownToolbarButtonType = | typeof BLOCKQUOTE_TOOLBAR_BUTTON | typeof BOLD_TOOLBAR_BUTTON | typeof CODE_BLOCK_TOOLBAR_BUTTON | typeof CODE_TOOLBAR_BUTTON | typeof DECREASE_IDENT_TOOLBAR_BUTTON | typeof DELETE_COLUMN_TOOLBAR_BUTTON | typeof DELETE_ROW_TOOLBAR_BUTTON | typeof DELETE_TABLE_TOOLBAR_BUTTON | typeof INCRASE_IDENT_TOOLBAR_BUTTON | typeof INSERT_COLUMN_TOOLBAR_BUTTON | typeof IMAGE_TOOLBAR_BUTTON | typeof FILE_LINK_TOOLBAR_BUTTON | typeof INSERT_ROW_TOOLBAR_BUTTON | typeof INSERT_TABLE_TOOLBAR_BUTTON | typeof ITALIC_TOOLBAR_BUTTON | typeof ORDERED_LIST_TOOLBAR_BUTTON | typeof STRIKETHROUGH_TOOLBAR_BUTTON | typeof UNORDERED_LIST_TOOLBAR_BUTTON; export type MarkdownToolbarItem = | MarkdownToolbarButtonType | { label: string; icon?: string; groups: { items: LowLevelMarkdownToolbarButtonType[]; }[]; }; export interface MarkdownFieldToolbarButtons { main?: MarkdownToolbarItem[]; empty?: MarkdownToolbarItem[]; selection?: MarkdownToolbarItem[]; table_empty?: MarkdownToolbarItem[]; table_selection?: MarkdownToolbarItem[]; } export interface MarkdownField extends MediaField { widget: 'markdown'; toolbar_buttons?: MarkdownFieldToolbarButtons; default?: string; show_raw?: boolean; } export interface NumberField extends BaseField { widget: 'number'; default?: string | number; value_type?: 'int' | 'float' | 'string'; min?: number; max?: number; step?: number; prefix?: string; suffix?: string; } export interface SelectField extends BaseField { widget: 'select'; default?: string | number | (string | number)[]; options: (string | number)[] | SelectWidgetOptionObject[]; multiple?: boolean; min?: number; max?: number; } export interface RelationField extends BaseField { widget: 'relation'; default?: string | string[]; collection: string; value_field: string; search_fields: string[]; file?: string; display_fields?: string[]; multiple?: boolean; min?: number; max?: number; options_length?: number; } export interface HiddenField extends BaseField { widget: 'hidden'; default?: ValueOrNestedValue; } export interface StringField extends BaseField { widget: 'string'; default?: string; prefix?: string; suffix?: string; } export interface TextField extends BaseField { widget: 'text'; default?: string; } export interface UUIDField extends BaseField { widget: 'uuid'; allow_regenerate?: boolean; prefix?: string; } export interface UnknownField extends BaseField { widget: 'unknown'; } export type Field = | BooleanField | CodeField | ColorField | DateTimeField | FileOrImageField | KeyValueField | ListField | MapField | MarkdownField | NumberField | ObjectField | RelationField | SelectField | HiddenField | StringField | TextField | UUIDField | EF; export interface ViewFilter { id?: string; name: string; label: string; field: string; pattern: string | boolean | number; } export interface ViewFilterWithDefaults extends ViewFilter { id: string; } export interface ViewFilters { default?: string; filters: ViewFilter[]; } export interface ViewFiltersWithDefaults extends ViewFilters { filters: ViewFilterWithDefaults[]; } export interface ViewGroup { id?: string; name: string; label: string; field: string; pattern?: string; } export interface ViewGroupWithDefaults extends ViewGroup { id: string; } export interface ViewGroups { default?: string; groups: ViewGroup[]; } export interface ViewGroupsWithDefaults extends ViewGroups { groups: ViewGroupWithDefaults[]; } export type SortDirection = | typeof SORT_DIRECTION_ASCENDING | typeof SORT_DIRECTION_DESCENDING | typeof SORT_DIRECTION_NONE; export interface SortableFieldsDefault { field: string; direction?: SortDirection; } export interface SortableFields { default?: SortableFieldsDefault; fields: string[]; } export interface Backend { name: BackendType; repo?: string; branch?: string; api_root?: string; site_domain?: string; base_url?: string; auth_endpoint?: string; app_id?: string; auth_type?: 'implicit' | 'pkce'; proxy_url?: string; large_media_url?: string; login?: boolean; identity_url?: string; gateway_url?: string; auth_scope?: AuthScope; commit_messages?: { create?: string; update?: string; delete?: string; uploadMedia?: string; deleteMedia?: string; openAuthoring?: string; }; use_large_media_transforms_in_media_library?: boolean; /** * Editorial Workflow */ always_fork?: boolean; open_authoring?: boolean; squash_merges?: boolean; cms_label_prefix?: string; preview_context?: string; } export interface Slug { encoding?: SlugEncoding; clean_accents?: boolean; sanitize_replacement?: string; } export interface LocalBackend { url?: string; allowed_hosts?: string[]; } export interface Config { backend: Backend; collections: Collection[]; locale?: string; site_id?: string; site_url?: string; display_url?: string; base_url?: string; logo_url?: string; logo_link?: string; media_folder?: string; public_folder?: string; media_folder_relative?: boolean; media_library?: RootMediaLibraryConfig; publish_mode?: Workflow; slug?: Slug; i18n?: I18nInfo; local_backend?: boolean | LocalBackend; disable_local_backup?: boolean; editor?: EditorConfig; search?: boolean; theme?: Themes; yaml?: { documentOptions?: DocumentOptions; schemaOptions?: SchemaOptions; createNodeOptions?: CreateNodeOptions; parseOptions?: ParseOptions; toJsOptions?: ToJSOptions; toStringOptions?: ToStringOptions; }; } export interface ConfigWithDefaults extends Omit, 'collections'> { collections: CollectionWithDefaults[]; } export interface ThemeColor { main: string; light: string; dark: string; contrastColor: string; } export interface Theme { name: string; common: { gray: string; }; text: { primary: string; secondary: string; disabled: string; }; background: { main: string; light: string; dark: string; divider: string; }; scrollbar: { main: string; light: string; }; primary: ThemeColor; error: ThemeColor; warning: ThemeColor; info: ThemeColor; success: ThemeColor; codemirror: { theme: 'light' | 'dark'; }; } export interface PartialTheme extends DeepPartial> { name: string; extends: 'light' | 'dark'; } export interface Themes { default_theme?: string; include_built_in_themes?: boolean; themes?: (Theme | PartialTheme)[]; } export interface BackendInitializerOptions { updateUserCredentials: (credentials: Credentials) => void; /** * Editorial Workflow */ useWorkflow: boolean; initialWorkflowStatus: WorkflowStatus; } export interface BackendInitializer { init: (config: ConfigWithDefaults, options: BackendInitializerOptions) => BackendClass; } export interface AuthorData { login: string | undefined; name: string; } export interface EventData { entry: Entry; author: AuthorData; } export interface PrePublishEventListener { name: 'prePublish'; collection?: string; file?: string; handler: (event: { data: EventData; collection: string; file: string | undefined; }) => void | Promise; } export interface PostPublishEventListener { name: 'postPublish'; collection?: string; file?: string; handler: (event: { data: EventData; collection: string; file: string | undefined; }) => void | Promise; } export interface PreSaveEventListener { name: 'preSave'; collection?: string; file?: string; handler: (event: { data: EventData; collection: string; file: string | undefined; }) => EntryData | undefined | null | void | Promise; } export interface PostSaveEventListener { name: 'postSave'; collection?: string; file?: string; handler: (event: { data: EventData; collection: string; file: string | undefined; }) => void | Promise; } export interface MountedEventListener { name: 'mounted'; handler: () => void | Promise; } export interface LoginEventListener { name: 'login'; handler: (event: { author: AuthorData }) => void | Promise; } export interface LogoutEventListener { name: 'logout'; handler: () => void | Promise; } export interface ChangeEventListener { name: 'change'; collection?: string; file?: string; field?: string; handler: (event: { data: EntryData; collection: string; file: string | undefined; field: string; }) => EntryData | undefined | null | void | Promise; } export type EventListener = | PrePublishEventListener | PostPublishEventListener | PreSaveEventListener | PostSaveEventListener | ChangeEventListener | LoginEventListener | LogoutEventListener | MountedEventListener; export interface AdditionalLinkOptions { icon?: string; } export interface AdditionalLink { id: string; title: string; data: string | FunctionComponent; options?: AdditionalLinkOptions; } export interface AuthenticationPageProps { onLogin: (user: User) => void; inProgress?: boolean; base_url?: string; siteId?: string; authEndpoint?: string; config: ConfigWithDefaults; error?: string | undefined; clearHash?: () => void; } export interface SearchResponse { entries: Entry[]; pagination: number; } export type SearchQueryRequest = { id: string; expires: Date; queryResponse: Promise; }; export interface SearchQueryResponse { hits: Entry[]; query: string; } export interface EditorPersistOptions { createNew?: boolean; duplicate?: boolean; } export type I18nStructure = | typeof I18N_STRUCTURE_MULTIPLE_FILES | typeof I18N_STRUCTURE_MULTIPLE_FOLDERS | typeof I18N_STRUCTURE_SINGLE_FILE; export type I18nField = | typeof I18N_FIELD_DUPLICATE | typeof I18N_FIELD_TRANSLATE | typeof I18N_FIELD_NONE; export interface I18nInfo { locales: string[]; default_locale?: string; structure: I18nStructure; } export interface ProcessedCodeLanguage { label: string; identifiers: string[]; codemirror_mode: LanguageName; codemirror_mime_type: string; } export interface FileMetadata { author: string; updatedOn: string; } export interface PreviewStyleOptions { raw?: boolean; } export interface PreviewStyle { value: string; raw: boolean; } export interface MarkdownPluginFactoryProps { config: ConfigWithDefaults; field: MarkdownField; mode: 'editor' | 'preview'; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export type MarkdownPluginFactory = (props: MarkdownPluginFactoryProps) => any; export interface MarkdownToolbarItemsFactoryProps { // eslint-disable-next-line @typescript-eslint/no-explicit-any imageToolbarButton: any; } export type MarkdownToolbarItemsFactory = ( props: MarkdownToolbarItemsFactoryProps, // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => (string | any)[][]; export interface MarkdownEditorOptions { // eslint-disable-next-line @typescript-eslint/no-explicit-any initialEditType?: any; height?: string; toolbarItems?: MarkdownToolbarItemsFactory; plugins?: MarkdownPluginFactory[]; } export type ShortcodeControlProps

= P & { onChange: (props: P) => void; controlProps: WidgetControlProps; }; export type ShortcodePreviewProps

= P & { previewProps: WidgetPreviewProps; }; export interface ShortcodeConfig

{ label?: string; openTag: string; closeTag: string; separator: string; toProps?: (args: string[]) => P; toArgs?: (props: P) => string[]; control: ComponentType; preview: ComponentType; } export type DeepPartial = T extends object ? { [P in keyof T]?: DeepPartial; } : T; export interface InferredField { type: string; secondaryTypes: string[]; synonyms: string[]; defaultPreview: (value: string | boolean | number) => JSX.Element | ReactNode; fallbackToFirstField: boolean; showError: boolean; } export interface SvgProps { className: string; } export interface Breadcrumb { name?: string; to?: string; editor?: boolean; } export interface MediaLibraryDisplayURL { url?: string; isFetching: boolean; err?: unknown; } export interface MediaLibrarInsertOptions { showAlt?: boolean; chooseUrl?: boolean; } export interface BackupEntry { raw: string; path: string; mediaFiles: MediaFile[]; i18n?: Record; } export interface CollectionEntryData { collection: CollectionWithDefaults; imageFieldName: string | null | undefined; descriptionFieldName: string | null | undefined; dateFieldName: string | null | undefined; dateFormats: DateTimeFormats | undefined; viewStyle: ViewStyle; entry: Entry; key: string; collectionLabel?: string; } export interface DateTimeFormats { storageFormat: string; dateFormat: string | boolean; timeFormat: string | boolean; displayFormat: string; timezoneExtra: string; } /** * Editorial Workflow */ export interface UnpublishedEntry { pullRequestAuthor?: string; slug: string; collection: string; status: WorkflowStatus; diffs: UnpublishedEntryDiff[]; updatedAt: string; openAuthoring: boolean; } export interface UnpublishedEntryDiff { id: string; path: string; newFile: boolean; } export interface UnpublishedEntryMediaFile { id: string; path: string; }