import type * as CSS from 'csstype';
import React from 'react';
import ComponentStyle from './models/ComponentStyle';
import { DefaultTheme } from './models/ThemeProvider';
import createWarnTooManyClasses from './utils/createWarnTooManyClasses';
import type { SupportedHTMLElements } from './utils/domElements';
export { CSS, DefaultTheme, SupportedHTMLElements };
export interface ExoticComponentWithDisplayName<P extends BaseObject = {}> extends React.ExoticComponent<P> {
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
}
/**
 * Use this type to disambiguate between a styled-component instance
 * and a StyleFunction or any other type of function.
 */
export type StyledComponentBrand = {
    readonly _sc: symbol;
};
export type BaseObject = {};
export type OmitNever<T> = {
    [K in keyof T as T[K] extends never ? never : K]: T[K];
};
export type FastOmit<T extends BaseObject, U extends string | number | symbol> = {
    [K in keyof T as K extends U ? never : K]: T[K];
};
export type Runtime = 'web' | 'native';
export type AnyComponent<P extends BaseObject = any> = ExoticComponentWithDisplayName<P> | React.ComponentType<P>;
export type KnownTarget = SupportedHTMLElements | AnyComponent;
export type WebTarget = string | KnownTarget;
export type NativeTarget = AnyComponent;
export type StyledTarget<R extends Runtime> = R extends 'web' ? WebTarget : NativeTarget;
export interface StyledOptions<R extends Runtime, Props extends BaseObject> {
    attrs?: Attrs<Props>[] | undefined;
    componentId?: (R extends 'web' ? string : never) | undefined;
    displayName?: string | undefined;
    parentComponentId?: (R extends 'web' ? string : never) | undefined;
    shouldForwardProp?: ShouldForwardProp<R> | undefined;
}
export type Dict<T = any> = {
    [key: string]: T;
};
/**
 * This type is intended for when data attributes are composed via
 * the `.attrs` API:
 *
 * ```tsx
 * styled.div.attrs<DataAttributes>({ 'data-testid': 'foo' })``
 * ```
 *
 * Would love to figure out how to support this natively without having to
 * manually compose the type, but haven't figured out a way to do so yet that
 * doesn't cause specificity loss (see `test/types.tsx` if you attempt to embed
 * `DataAttributes` directly in the `Attrs<>` type.)
 */
export type DataAttributes = {
    [key: `data-${string}`]: any;
};
export type ExecutionProps = {
    /**
     * Dynamically adjust the rendered component or HTML tag, e.g.
     * ```
     * const StyledButton = styled.button``
     *
     * <StyledButton as="a" href="/foo">
     *   I'm an anchor now
     * </StyledButton>
     * ```
     */
    as?: KnownTarget | undefined;
    forwardedAs?: KnownTarget | undefined;
    theme?: DefaultTheme | undefined;
};
/**
 * ExecutionProps but with `theme` narrowed from optional to required.
 *
 * Note: in RSC environments where ThemeProvider is a no-op,
 * `theme` will be `undefined` at runtime.
 */
export interface ExecutionContext extends ExecutionProps {
    theme: DefaultTheme;
}
export interface StyleFunction<Props extends BaseObject> {
    (executionContext: ExecutionContext & Props): Interpolation<Props>;
}
export type Interpolation<Props extends BaseObject> = StyleFunction<Props> | StyledObject<Props> | TemplateStringsArray | string | number | false | undefined | null | Keyframes | StyledComponentBrand | RuleSet<Props> | Interpolation<Props>[];
export type Attrs<Props extends BaseObject = BaseObject> = (ExecutionProps & Partial<OverrideStyle<Props>>) | ((props: ExecutionContext & Props) => ExecutionProps & Partial<OverrideStyle<Props>>);
export type RuleSet<Props extends BaseObject = BaseObject> = Interpolation<Props>[];
export type Styles<Props extends BaseObject> = TemplateStringsArray | StyledObject<Props> | StyleFunction<Props>;
export type NameGenerator = (hash: number) => string;
export interface StyleSheet {
    create: Function;
}
export interface Keyframes {
    id: string;
    name: string;
    rules: string;
}
export interface Flattener<Props extends BaseObject> {
    (chunks: Interpolation<Props>[], executionContext: object | null | undefined, styleSheet: StyleSheet | null | undefined): Interpolation<Props>[];
}
export interface Stringifier {
    (css: string, selector?: string | undefined, prefix?: string | undefined, componentId?: string | undefined): string[];
    hash: string;
}
export interface ShouldForwardProp<R extends Runtime> {
    (prop: string, elementToBeCreated: StyledTarget<R>): boolean;
}
export interface CommonStatics<R extends Runtime, Props extends BaseObject> {
    attrs: Attrs<Props>[];
    target: StyledTarget<R>;
    shouldForwardProp?: ShouldForwardProp<R> | undefined;
}
export interface IStyledStatics<R extends Runtime, OuterProps extends BaseObject> extends CommonStatics<R, OuterProps> {
    componentStyle: R extends 'web' ? ComponentStyle : never;
    foldedComponentIds: R extends 'web' ? string : never;
    inlineStyle: R extends 'native' ? InstanceType<IInlineStyleConstructor<OuterProps>> : never;
    target: StyledTarget<R>;
    styledComponentId: R extends 'web' ? string : never;
    warnTooManyClasses?: (R extends 'web' ? ReturnType<typeof createWarnTooManyClasses> : never) | undefined;
}
/**
 * Used by PolymorphicComponent to define prop override cascading order.
 */
export type PolymorphicComponentProps<R extends Runtime, BaseProps extends BaseObject, AsTarget extends StyledTarget<R> | void, ForwardedAsTarget extends StyledTarget<R> | void, AsTargetProps extends BaseObject = AsTarget extends KnownTarget ? React.ComponentPropsWithRef<AsTarget> : {}, ForwardedAsTargetProps extends BaseObject = ForwardedAsTarget extends KnownTarget ? React.ComponentPropsWithRef<ForwardedAsTarget> : {}> = OverrideStyle<NoInfer<FastOmit<Substitute<BaseProps, Substitute<ForwardedAsTargetProps, AsTargetProps>>, keyof ExecutionProps>> & FastOmit<ExecutionProps, 'as' | 'forwardedAs'> & {
    as?: AsTarget;
    forwardedAs?: ForwardedAsTarget;
}>;
/**
 * This type forms the signature for a forwardRef-enabled component
 * that accepts the "as" prop to dynamically change the underlying
 * rendered JSX. The interface will automatically attempt to extract
 * props from the given rendering target to get proper typing for
 * any specialized props in the target component.
 */
export interface PolymorphicComponent<R extends Runtime, BaseProps extends BaseObject> extends React.ForwardRefExoticComponent<BaseProps> {
    <AsTarget extends StyledTarget<R> | void = void, ForwardedAsTarget extends StyledTarget<R> | void = void>(props: PolymorphicComponentProps<R, BaseProps, AsTarget, ForwardedAsTarget>): React.JSX.Element;
}
export interface IStyledComponentBase<R extends Runtime, Props extends BaseObject = BaseObject> extends PolymorphicComponent<R, Props>, IStyledStatics<R, Props>, StyledComponentBrand {
    defaultProps?: (ExecutionProps & Partial<Props>) | undefined;
    toString: () => string;
}
export type IStyledComponent<R extends Runtime, Props extends BaseObject = BaseObject> = IStyledComponentBase<R, Props> & 
/**
 * TypeScript doesn't allow using a styled component as a key inside object
 * styles because "A computed property name must be of type 'string', 'number',
 * 'symbol', or 'any'.". The toString() method only exists in the web runtime.
 * This hack intersects the `IStyledComponent` type with the built-in `string`
 * type to keep TSC happy.
 *
 * @example
 *  const H1 = styled.h1({
 *    fontSize: '2rem'
 *  });
 *
 *  const Header = styled.header({
 *    [H1]: {
 *      marginBottom: '1rem'
 *    }
 *  })
 */
(R extends 'web' ? string : {});
export interface IStyledComponentFactory<R extends Runtime, Target extends StyledTarget<R>, OuterProps extends BaseObject, OuterStatics extends BaseObject = BaseObject> {
    <Props extends BaseObject = BaseObject, Statics extends BaseObject = BaseObject>(target: Target, options: StyledOptions<R, OuterProps & Props>, rules: RuleSet<OuterProps & Props>): IStyledComponent<R, Substitute<OuterProps, Props>> & OuterStatics & Statics;
}
export interface IInlineStyleConstructor<Props extends BaseObject> {
    new (rules: RuleSet<Props>): IInlineStyle<Props>;
}
export interface IInlineStyle<Props extends BaseObject> {
    rules: RuleSet<Props>;
    generateStyleObject(executionContext: ExecutionContext & Props): object;
}
export type CSSProperties = CSS.Properties<number | (string & {})>;
export type CSSPropertiesWithVars = CSSProperties & {
    [key: `--${string}`]: string | number | undefined;
};
type OverrideStyle<P> = P extends {
    style?: infer S;
} ? Omit<P, 'style'> & {
    style?: CSSPropertiesWithVars | (S & {});
} : P;
export type CSSPseudos = {
    [K in CSS.Pseudos]?: CSSObject;
};
export type CSSKeyframes = object & {
    [key: string]: CSSObject;
};
export type CSSObject<Props extends BaseObject = BaseObject> = StyledObject<Props>;
export interface StyledObject<Props extends BaseObject = BaseObject> extends CSSProperties, CSSPseudos {
    [key: string]: StyledObject<Props> | string | number | StyleFunction<Props> | RuleSet<any> | undefined;
}
/**
 * The `css` prop is not declared by default in the types as it would cause `css` to be present
 * on the types of anything that uses styled-components indirectly, even if they do not use the
 * babel plugin.
 *
 * To enable support for the `css` prop in TypeScript, create a `styled-components.d.ts` file in
 * your project source with the following contents:
 *
 * ```ts
 * import type { CSSProp } from "styled-components";
 *
 * declare module "react" {
 *  interface Attributes {
 *    css?: CSSProp;
 *  }
 * }
 * ```
 *
 * In order to get accurate typings for `props.theme` in `css` interpolations, see
 * {@link DefaultTheme}.
 */
export type CSSProp = Interpolation<any>;
export type NoInfer<T> = [T][T extends any ? 0 : never];
export type Substitute<A extends BaseObject, B extends BaseObject> = FastOmit<A, keyof B> & B;
export type InsertionTarget = HTMLElement | ShadowRoot;
