// Definitions by: Pat Sissons // TypeScript Version: 3.4 import { ComponentPropsWithoutRef, ComponentType, NamedExoticComponent, PropsWithChildren, } from 'react'; import * as RN from 'react-native'; import { ReactNativeStyle, ReactNativeStyleType, Theme } from './StyleSheet'; export type ReactNative = typeof RN; export type ReactNativeComponentNames = | 'ActivityIndicator' | 'Button' | 'DatePickerIOS' | 'DrawerLayoutAndroid' | 'FlatList' | 'Image' | 'ImageBackground' | 'KeyboardAvoidingView' | 'ListView' | 'Modal' | 'NavigatorIOS' | 'Picker' | 'PickerIOS' | 'ProgressBarAndroid' | 'ProgressViewIOS' | 'RecyclerViewBackedScrollView' | 'RefreshControl' | 'SafeAreaView' | 'ScrollView' | 'SectionList' | 'SegmentedControlIOS' | 'Slider' | 'SnapshotViewIOS' | 'StatusBar' | 'SwipeableListView' | 'Switch' | 'SwitchIOS' | 'TabBarIOS' | 'Text' | 'TextInput' | 'ToolbarAndroid' | 'TouchableHighlight' | 'TouchableNativeFeedback' | 'TouchableOpacity' | 'TouchableWithoutFeedback' | 'View' | 'ViewPagerAndroid'; export type ReactNativeComponents = Pick< ReactNative, ReactNativeComponentNames >; export type ReactNativeComponentProps< ComponentName extends ReactNativeComponentNames > = ComponentPropsWithoutRef; export type InterpolationPrimitive< StyleType extends ReactNativeStyle = ReactNativeStyle > = | null | undefined | boolean | number | string | ObjectInterpolation; export type ObjectInterpolation< StyleType extends ReactNativeStyle = ReactNativeStyle > = StyleType; export interface ArrayCSSInterpolation< StyleType extends ReactNativeStyle = ReactNativeStyle > extends Array> {} export type CSSInterpolation< StyleType extends ReactNativeStyle = ReactNativeStyle > = InterpolationPrimitive | ArrayCSSInterpolation; export interface ArrayInterpolation< MergedProps, StyleType extends ReactNativeStyle = ReactNativeStyle > extends Array> {} export interface FunctionInterpolation< MergedProps, StyleType extends ReactNativeStyle = ReactNativeStyle > { (mergedProps: MergedProps): Interpolation; } export type Interpolation< MergedProps = unknown, StyleType extends ReactNativeStyle = ReactNativeStyle > = | InterpolationPrimitive | ArrayInterpolation | FunctionInterpolation; /** Same as StyledOptions but getShouldForwardProp must be a type guard */ export interface FilteringStyledOptions< Props, ForwardedProps extends keyof Props = keyof Props > { shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps; } export interface StyledOptions { shouldForwardProp?(propName: keyof Props): boolean; } /** * @typeparam ComponentProps Props which will be included when withComponent is called * @typeparam SpecificComponentProps Props which will *not* be included when withComponent is called */ export interface StyledComponent< ComponentProps extends {}, SpecificComponentProps extends {} = {} > extends NamedExoticComponent< PropsWithChildren > { withComponent< Component extends ComponentType> >( component: Component ): StyledComponent>; withComponent( component: ReactNativeComponents[ComponentName] ): StyledComponent>; } /** * @typeparam ComponentProps Props which will be included when withComponent is called * @typeparam SpecificComponentProps Props which will *not* be included when withComponent is called */ export interface CreateStyledComponent< ComponentProps extends {}, SpecificComponentProps extends {} = {}, StyleType extends ReactNativeStyle = ReactNativeStyle > { /** * @typeparam AdditionalProps Additional props to add to your styled component */ ( ...styles: ArrayInterpolation< ComponentProps & SpecificComponentProps & AdditionalProps & { theme: Theme }, StyleType > ): StyledComponent; /** * @typeparam AdditionalProps Additional props to add to your styled component */ ( template: TemplateStringsArray, ...styles: ArrayInterpolation< ComponentProps & SpecificComponentProps & AdditionalProps & { theme: Theme }, StyleType > ): StyledComponent; } /** * @desc * This function accepts a React component. * * @example styled(MyComponent)({ width: 100 }) * @example styled(MyComponent)(myComponentProps => ({ width: myComponentProps.width }) * @example styled(View)({ width: 100 }) * @example styled(View)(props => ({ width: props.width }) */ export interface CreateStyled { < Component extends ComponentType>, ForwardedProps extends keyof ComponentPropsWithoutRef< Component > = keyof ComponentPropsWithoutRef >( component: Component, options: FilteringStyledOptions< ComponentPropsWithoutRef, ForwardedProps > ): CreateStyledComponent< Pick, ForwardedProps> & { theme?: Theme; }, {}, ReactNativeStyleType> >; >>( component: Component, options?: StyledOptions> ): CreateStyledComponent< ComponentPropsWithoutRef & { theme?: Theme }, {}, ReactNativeStyleType> >; < ComponentName extends ReactNativeComponentNames, ForwardedProps extends keyof ReactNativeComponentProps< ComponentName > = keyof ReactNativeComponentProps >( component: ReactNativeComponents[ComponentName], options: FilteringStyledOptions< ReactNativeComponentProps, ForwardedProps > ): CreateStyledComponent< { theme?: Theme }, Pick, ForwardedProps>, ReactNativeStyleType> >; ( component: ReactNativeComponents[ComponentName], options?: StyledOptions> ): CreateStyledComponent< { theme?: Theme }, ReactNativeComponentProps, ReactNativeStyleType> >; } export interface CreateStyledExtended { < Component extends ComponentType>, ForwardedProps extends keyof ComponentPropsWithoutRef< Component > = keyof ComponentPropsWithoutRef >( component: Component, options: FilteringStyledOptions< ComponentPropsWithoutRef, ForwardedProps > ): CreateStyledComponent< Pick, ForwardedProps> & { theme?: Theme; }, {}, ReactNativeStyleType> >; >>( component: Component, options?: StyledOptions> ): CreateStyledComponent< ComponentPropsWithoutRef & { theme?: Theme }, {}, ReactNativeStyleType> >; < ComponentName extends ReactNativeComponentNames, ForwardedProps extends keyof ReactNativeComponentProps< ComponentName > = keyof ReactNativeComponentProps >( component: ReactNativeComponents[ComponentName], options: FilteringStyledOptions< ReactNativeComponentProps, ForwardedProps > ): CreateStyledComponent< { theme?: Theme }, Pick, ForwardedProps>, ReactNativeStyleType> >; ( component: ReactNativeComponents[ComponentName], options?: StyledOptions> ): CreateStyledComponent< { theme?: Theme }, ReactNativeComponentProps, ReactNativeStyleType> >; }