import type { UIStoreActions } from '@ui-schema/react/UIStoreActions';
import type { SchemaKeywordType, SchemaTypesType, SomeSchema } from '@ui-schema/ui-schema/CommonTypings';
import type { WidgetMatch } from '@ui-schema/ui-schema/matchWidget';
import type { StoreKeys } from '@ui-schema/ui-schema/ValueStore';
import type { WidgetPayload } from '@ui-schema/ui-schema/Widget';
import type { ComponentType, FunctionComponent, ReactNode, Component } from 'react';
import type { WidgetPluginProps, WidgetPluginType } from '@ui-schema/react/WidgetEngine';
import type { WithOnChange, WithValuePlain } from '@ui-schema/react/UIStore';
import type { UIMetaContextBase } from '@ui-schema/react/UIMeta';
import type { List } from 'immutable';
import type { WidgetsBindingRoot } from '@ui-schema/ui-schema/WidgetsBinding';
import type { WidgetProps } from './Widget.js';
/**
* note: we can't use ComponentType here, as it leads to problems with FC vs. others and
* throwing errors if a component has optional props, which are defined are required in the binding,
* which is of course ok, as a widget can always rely on less, just not more (required) as defined in the shared interface
*
* @experimental mv into central react and use for any component type?
* @todo setup CI test to check against lowest possible react version, so that error doesn't occur,
* even if dev setup react is "fixed" (react19 has propTypes any)
* @todo care about `ClassComponent` at all or enforce `.FC` usage?
*/
type MinimalClassComponent
= {
new (props: P): Component;
displayName?: string;
};
export type MinimalComponentType = {
(props: P): ReturnType;
displayName?: string;
} | MinimalClassComponent;
type WidgetsBinding = WidgetProps> = {
[K in SchemaKeywordType]?: MinimalComponentType;
} & Record>;
export interface NoWidgetProps {
storeKeys: StoreKeys;
scope?: string;
widgetId?: string;
}
export interface GroupRendererProps {
storeKeys: StoreKeys;
schema: SomeSchema;
noGrid?: boolean;
style?: {};
className?: string;
spacing?: number;
children: ReactNode;
}
export interface ErrorFallbackProps {
error: any | null;
storeKeys: StoreKeys;
type?: string | List;
widget?: string;
}
export interface BindingComponents {
/**
* Wrapped around each schema layer, used to catch errors during rendering.
*/
ErrorFallback?: ComponentType;
/**
* Wraps any `object` that has no custom widget.
*/
GroupRenderer?: ComponentType;
/**
* When used with `isVirtual` in `WidgetEngine`, this component is used to render virtual widgets.
*/
VirtualRenderer?: ComponentType;
/**
* When `matchWidget` cannot find a widget and throws an `ErrorNoWidgetMatching`, this component is used.
*/
NoWidget?: ComponentType;
/**
* Widget plugins, used by `WidgetEngine` to render a schema layer.
*/
widgetPlugins?: WidgetPluginType[];
}
export interface WidgetMatchProps {
widgetName: string | undefined;
schemaType: SchemaTypesType;
widgets?: Record>;
}
/**
* widget binding
* - `C` = own `UIMetaContext` definition
* - `TW` = own type widgets definition
* - `CW` = own custom widgets definition
* @todo support OnChange generics
* @todo typing `PWidgetPlugins` strict here leads again to the problem with circular types, but why isn't that the cause with `widgetPlugins`?
* switched to `any` here, as the stricter typing comes from mui bindingType and WidgetRenderer atm.,
* and here it must be as loose as possible to infer it correctly, while there is must be infer all at once.
*/
export type BindingTypeGeneric = Omit & {
widgetPlugins?: MinimalComponentType[];
/**
* The component which is rendered inside the WidgetEngine, after any widgetPlugin is applied.
*/
WidgetRenderer?: MinimalComponentType;
widgets?: WidgetsBindingRoot;
matchWidget?: (props: WidgetMatchProps) => null | WidgetMatch>;
};
export type BindingType = WidgetProps> = Omit & BindingTypeWidgets;
export type BindingTypeWidgets = WidgetProps> = {
widgetPlugins?: MinimalComponentType, keyof WP>>[];
} & {
/**
* The component which is rendered inside the WidgetEngine, after any widgetPlugin is applied.
*/
WidgetRenderer?: MinimalComponentType, keyof WP>>;
} & {
widgets?: WidgetsBinding;
} & {
matchWidget?: (props: WidgetMatchProps) => null | WidgetMatch>;
};
export {};