import { ComponentType, ReactElement, ReactNode } from 'react';

type SlotComponent = ComponentType<any> & {
    displayName?: string;
};
type SlotMap = Record<string, SlotComponent>;
type ExtraMap = Record<string, unknown>;
type SlotRules<T extends SlotMap> = {
    [K in keyof T]: 'single' | 'multiple';
};
type SlotResult<T extends SlotMap> = {
    [K in keyof T]?: ReactElement | ReactElement[];
} & {
    others: ReactNode[];
};

interface DefineSlotComponentOptions<TSlots extends SlotMap, TExtras extends ExtraMap> {
    slots: TSlots;
    extras?: TExtras;
    rules?: Partial<SlotRules<TSlots>>;
}
type NamedComponent<TProps = any> = ((props: TProps) => ReactElement) | React.MemoExoticComponent<any> | React.ForwardRefExoticComponent<any>;
declare function defineSlotComponent<TProps extends {} = {
    children: ReactNode;
}, TSlots extends SlotMap = {}, TExtras extends ExtraMap = {}>(render: NamedComponent<TProps>, options: DefineSlotComponentOptions<TSlots, TExtras>): typeof render & {
    [K in keyof TSlots as Capitalize<string & K>]: TSlots[K];
} & {
    slots: TSlots;
    rules?: Partial<SlotRules<TSlots>>;
} & TExtras;

declare function getSlots<T extends {
    slots: SlotMap;
    rules?: Partial<SlotRules<T['slots']>>;
}>(children: ReactNode, slotHost: T): SlotResult<T['slots']>;

declare function getDisplayName(component: unknown): string;

export { type ExtraMap, type SlotComponent, type SlotMap, type SlotResult, type SlotRules, defineSlotComponent, getDisplayName, getSlots };
