Improve typing for extra widget types

This commit is contained in:
Daniel Lautzenheiser 2022-11-05 11:37:39 -04:00
parent 13d30beba0
commit 9706d094e4
No known key found for this signature in database
GPG Key ID: D2F75F7DD915527E
2 changed files with 55 additions and 40 deletions

View File

@ -19,7 +19,7 @@ export interface Pages {
[collection: string]: { isFetching?: boolean; page?: number; ids: string[] }; [collection: string]: { isFetching?: boolean; page?: number; ids: string[] };
} }
export type SortableField = export type SortableField<EF extends BaseField = UnknownField> =
| { | {
key: string; key: string;
name: string; name: string;
@ -27,7 +27,7 @@ export type SortableField =
} }
| ({ | ({
key: string; key: string;
} & Field); } & Field<EF>);
export interface SortObject { export interface SortObject {
key: string; key: string;
@ -131,11 +131,11 @@ export interface EditorConfig {
frame?: boolean; frame?: boolean;
} }
export interface CollectionFile { export interface CollectionFile<EF extends BaseField = UnknownField> {
name: string; name: string;
label: string; label: string;
file: string; file: string;
fields: Field[]; fields: Field<EF>[];
label_singular?: string; label_singular?: string;
description?: string; description?: string;
media_folder?: string; media_folder?: string;
@ -157,17 +157,18 @@ export interface I18nSettings {
export type Format = keyof typeof formatExtensions; export type Format = keyof typeof formatExtensions;
export interface i18nCollection extends Omit<Collection, 'i18n'> { export interface i18nCollection<EF extends BaseField = UnknownField>
i18n: Required<Collection>['i18n']; extends Omit<Collection<EF>, 'i18n'> {
i18n: Required<Collection<EF>>['i18n'];
} }
export interface Collection { export interface Collection<EF extends BaseField = UnknownField> {
name: string; name: string;
description?: string; description?: string;
icon?: string; icon?: string;
folder?: string; folder?: string;
files?: CollectionFile[]; files?: CollectionFile<EF>[];
fields: Field[]; fields: Field<EF>[];
isFetching?: boolean; isFetching?: boolean;
media_folder?: string; media_folder?: string;
public_folder?: string; public_folder?: string;
@ -193,7 +194,7 @@ export interface Collection {
editor?: EditorConfig; editor?: EditorConfig;
} }
export type Collections = Record<string, Collection>; export type Collections<EF extends BaseField = UnknownField> = Record<string, Collection<EF>>;
export interface MediaLibraryInstance { export interface MediaLibraryInstance {
show: (args: { show: (args: {
@ -221,9 +222,9 @@ export type TranslatedProps<T> = T & ReactPolyglotTranslateProps;
export type GetAssetFunction = (path: string, field?: Field) => Promise<AssetProxy>; export type GetAssetFunction = (path: string, field?: Field) => Promise<AssetProxy>;
export interface WidgetControlProps<T, F extends Field = Field> { export interface WidgetControlProps<T, F extends Field = Field, EF extends BaseField = Field> {
collection: Collection; collection: Collection<EF>;
config: Config; config: Config<EF>;
entry: Entry; entry: Entry;
field: F; field: F;
fieldsErrors: FieldsErrors; fieldsErrors: FieldsErrors;
@ -249,19 +250,27 @@ export interface WidgetControlProps<T, F extends Field = Field> {
value: T | undefined | null; value: T | undefined | null;
} }
export interface WidgetPreviewProps<T = unknown, F extends Field = Field> { export interface WidgetPreviewProps<
config: Config; T = unknown,
collection: Collection; F extends Field = Field,
EF extends BaseField = Field,
> {
config: Config<EF>;
collection: Collection<EF>;
entry: Entry; entry: Entry;
field: RenderedField<F>; field: RenderedField<F>;
getAsset: GetAssetFunction; getAsset: GetAssetFunction;
value: T | undefined | null; value: T | undefined | null;
} }
export type WidgetPreviewComponent<T = unknown, F extends Field = Field> = export type WidgetPreviewComponent<
T = unknown,
F extends Field = Field,
EF extends BaseField = Field,
> =
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
| React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
| ComponentType<WidgetPreviewProps<T, F>>; | ComponentType<WidgetPreviewProps<T, F, EF>>;
export type WidgetsFor<P = EntryData> = <K extends keyof P>( export type WidgetsFor<P = EntryData> = <K extends keyof P>(
name: K, name: K,
@ -275,9 +284,9 @@ export type WidgetsFor<P = EntryData> = <K extends keyof P>(
widgets: Record<keyof P[K], React.ReactNode>; widgets: Record<keyof P[K], React.ReactNode>;
}; };
export interface TemplatePreviewProps<T = EntryData> { export interface TemplatePreviewProps<T = EntryData, EF extends BaseField = Field> {
collection: Collection; collection: Collection<EF>;
fields: Field[]; fields: Field<EF>[];
entry: Entry<T>; entry: Entry<T>;
document: Document | undefined | null; document: Document | undefined | null;
window: Window | undefined | null; window: Window | undefined | null;
@ -286,7 +295,9 @@ export interface TemplatePreviewProps<T = EntryData> {
widgetsFor: WidgetsFor<T>; widgetsFor: WidgetsFor<T>;
} }
export type TemplatePreviewComponent<T = EntryData> = ComponentType<TemplatePreviewProps<T>>; export type TemplatePreviewComponent<T = EntryData, EF extends BaseField = Field> = ComponentType<
TemplatePreviewProps<T, EF>
>;
export interface WidgetOptions<T = unknown, F extends Field = Field> { export interface WidgetOptions<T = unknown, F extends Field = Field> {
validator?: Widget<T, F>['validator']; validator?: Widget<T, F>['validator'];
@ -294,18 +305,18 @@ export interface WidgetOptions<T = unknown, F extends Field = Field> {
schema?: Widget<T, F>['schema']; schema?: Widget<T, F>['schema'];
} }
export interface Widget<T = unknown, F extends Field = Field> { export interface Widget<T = unknown, F extends Field = Field, EF extends BaseField = Field> {
control: ComponentType<WidgetControlProps<T, F>>; control: ComponentType<WidgetControlProps<T, F, EF>>;
preview?: WidgetPreviewComponent<T, F>; preview?: WidgetPreviewComponent<T, F, EF>;
validator: FieldValidationMethod<T, F>; validator: FieldValidationMethod<T, F>;
getValidValue: (value: T | undefined | null) => T | undefined | null; getValidValue: (value: T | undefined | null) => T | undefined | null;
schema?: PropertiesSchema<unknown>; schema?: PropertiesSchema<unknown>;
} }
export interface WidgetParam<T = unknown, F extends Field = Field> { export interface WidgetParam<T = unknown, F extends Field = Field, EF extends BaseField = Field> {
name: string; name: string;
controlComponent: Widget<T, F>['control']; controlComponent: Widget<T, F, EF>['control'];
previewComponent?: Widget<T, F>['preview']; previewComponent?: Widget<T, F, EF>['preview'];
options?: WidgetOptions<T, F>; options?: WidgetOptions<T, F>;
} }
@ -529,15 +540,15 @@ export interface FileOrImageField extends BaseField {
public_folder?: string; public_folder?: string;
} }
export interface ObjectField extends BaseField { export interface ObjectField<EF extends BaseField = UnknownField> extends BaseField {
widget: 'object'; widget: 'object';
collapsed?: boolean; collapsed?: boolean;
summary?: string; summary?: string;
fields: Field[]; fields: Field<EF>[];
} }
export interface ListField extends BaseField { export interface ListField<EF extends BaseField = UnknownField> extends BaseField {
widget: 'list'; widget: 'list';
default?: ObjectValue[]; default?: ObjectValue[];
@ -545,7 +556,7 @@ export interface ListField extends BaseField {
collapsed?: boolean; collapsed?: boolean;
summary?: string; summary?: string;
label_singular?: string; label_singular?: string;
fields?: Field[]; fields?: Field<EF>[];
max?: number; max?: number;
min?: number; min?: number;
add_to_top?: boolean; add_to_top?: boolean;
@ -618,7 +629,11 @@ export interface StringOrTextField extends BaseField {
default?: string; default?: string;
} }
export type Field = export interface UnknownField extends BaseField {
widget: 'unknown';
}
export type Field<EF extends BaseField = UnknownField> =
| BooleanField | BooleanField
| CodeField | CodeField
| ColorField | ColorField
@ -632,7 +647,8 @@ export type Field =
| RelationField | RelationField
| SelectField | SelectField
| HiddenField | HiddenField
| StringOrTextField; | StringOrTextField
| EF;
export interface ViewFilter { export interface ViewFilter {
id: string; id: string;
@ -701,9 +717,9 @@ export interface LocalBackend {
allowed_hosts?: string[]; allowed_hosts?: string[];
} }
export interface Config { export interface Config<EF extends BaseField = UnknownField> {
backend: Backend; backend: Backend;
collections: Collection[]; collections: Collection<EF>[];
locale?: string; locale?: string;
site_id?: string; site_id?: string;
site_url?: string; site_url?: string;
@ -723,8 +739,8 @@ export interface Config {
search?: boolean; search?: boolean;
} }
export interface InitOptions { export interface InitOptions<EF extends BaseField = UnknownField> {
config: Config; config: Config<EF>;
} }
export interface BackendInitializerOptions { export interface BackendInitializerOptions {

View File

@ -121,8 +121,7 @@ export function getPreviewTemplate(name: string): TemplatePreviewComponent<Entry
/** /**
* Editor Widgets * Editor Widgets
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any export function registerWidget(widgets: WidgetParam[]): void;
export function registerWidget(widgets: WidgetParam<any, any>[]): void;
export function registerWidget(widget: WidgetParam): void; export function registerWidget(widget: WidgetParam): void;
export function registerWidget<T = unknown>( export function registerWidget<T = unknown>(
name: string, name: string,