diff --git a/types/react-jss/index.d.ts b/types/react-jss/index.d.ts new file mode 100644 index 0000000000..7656897a08 --- /dev/null +++ b/types/react-jss/index.d.ts @@ -0,0 +1,26 @@ +// Type definitions for react-jss 8.6 +// Project: https://github.com/cssinjs/react-jss#readme +// Definitions by: Sebastian Silbermann +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 +import { createGenerateClassName, JSS, SheetsRegistry } from "jss"; +import * as React from "react"; +import { createTheming, ThemeProvider, withTheme } from "theming"; + +import injectSheet from "./lib/injectSheet"; +import JssProvider, { Props as JssProviderProps } from "./lib/JssProvider"; + +// re-export types +export * from "./lib/injectSheet"; +export { JssProviderProps }; +// library implementations +export const jss: JSS; +export { + createGenerateClassName, + createTheming, + JssProvider, + SheetsRegistry, + ThemeProvider, + withTheme +}; +export default injectSheet; diff --git a/types/react-jss/lib/JssProvider.d.ts b/types/react-jss/lib/JssProvider.d.ts new file mode 100644 index 0000000000..bde15a8ce9 --- /dev/null +++ b/types/react-jss/lib/JssProvider.d.ts @@ -0,0 +1,14 @@ +import * as React from "react"; + +import { GenerateClassName, JSS, SheetsRegistry } from "jss"; + +export interface Props { + children: React.ReactNode; + classNamePrefix?: string; + disableStylesGeneration?: boolean; + jss?: JSS; + generateClassName?: GenerateClassName; + registry?: SheetsRegistry; +} + +export default class JssProvider extends React.Component {} diff --git a/types/react-jss/lib/injectSheet.d.ts b/types/react-jss/lib/injectSheet.d.ts new file mode 100644 index 0000000000..fd66af5c38 --- /dev/null +++ b/types/react-jss/lib/injectSheet.d.ts @@ -0,0 +1,116 @@ +import * as CSS from "csstype"; +import { CreateStyleSheetOptions, JSS } from "jss"; +import * as React from "react"; +import { + channel, + createTheming, + themeListener, + ThemeProvider, + withTheme +} from "theming"; + +/** + * omit from T every key K + * + * @internal + */ +export type Omit = Pick>; +/** + * `T extends ConsistentWith` means that where `T` has overlapping properties with + * `U`, their value types do not conflict. + * + * @internal + */ +export type ConsistentWith = { + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P] +}; + +/** + * Like `T & U`, but using the value types from `U` where their properties overlap. + * + * @internal + */ +export type Overwrite = Omit & U; + +/** + * @internal + */ +export type PropsOf = C extends new (props: infer P) => React.Component + ? P + : C extends (props: infer P) => React.ReactElement | null ? P : never; + +/** + * a function that takes {component} and returns a component that passes along + * all the props to {component} except the {InjectedProps} and will accept + * additional {AdditionalProps} + * + * source mui-org/material-ui#12673 + * @internal + */ +export type PropInjector = < + C extends React.ComponentType, InjectedProps>> +>( + component: C +) => React.ComponentType< + Omit>, keyof InjectedProps> & + AdditionalProps +>; + +export interface CSSProperties extends CSS.Properties { + // Allow pseudo selectors and media queries + [k: string]: + | CSS.Properties[keyof CSS.Properties] + | CSSProperties; +} +export type Styles = Record< + ClassKey, + CSSProperties +>; +export type StyleCreator = ( + theme: T +) => Styles; + +export interface Theming { + channel: string; + createTheming: typeof createTheming; + themeListener: typeof themeListener; + ThemeProvider: typeof ThemeProvider; + withTheme: typeof withTheme; +} +export interface InjectOptions extends CreateStyleSheetOptions { + jss?: JSS; + theming?: Theming; +} + +export type ClassNameMap = Record; +export type WithSheet< + S extends string | Styles | StyleCreator, + GivenTheme = undefined +> = { + classes: ClassNameMap< + S extends string + ? S + : S extends StyleCreator + ? C + : S extends Styles ? C : never + >; +} & WithTheme ? T : GivenTheme>; + +export interface WithTheme { + theme: T; + innerRef?: React.Ref | React.RefObject; +} + +export interface StyledComponentProps { + classes?: Partial>; + innerRef?: React.Ref | React.RefObject; +} + +export default function injectSheet( + stylesOrCreator: Styles | StyleCreator, + options?: InjectOptions +): PropInjector, StyledComponentProps>; diff --git a/types/react-jss/package.json b/types/react-jss/package.json new file mode 100644 index 0000000000..2010e4d437 --- /dev/null +++ b/types/react-jss/package.json @@ -0,0 +1,8 @@ +{ + "private": true, + "dependencies": { + "csstype": "^2.0.0", + "jss": "^9.5.0", + "theming": "^1.3.0" + } +} diff --git a/types/react-jss/react-jss-tests.tsx b/types/react-jss/react-jss-tests.tsx new file mode 100644 index 0000000000..803170bb99 --- /dev/null +++ b/types/react-jss/react-jss-tests.tsx @@ -0,0 +1,97 @@ +import * as React from "react"; +import injectSheet, { + JssProvider, + SheetsRegistry, + Styles, + WithSheet, + ThemeProvider +} from "react-jss"; + +interface MyTheme { + color: { + primary: string; + secondary: string; + }; +} + +/** + * helper function to counter typescripts type widening + */ +function createStyles(styles: Styles): Styles { + return styles; +} + +const styles = (theme: MyTheme) => + createStyles({ + myButton: { + color: theme.color.primary, + margin: 1, + "& span": { + fontWeight: "revert" + } + }, + myLabel: { + fontStyle: "italic" + } + }); + +interface ButtonProps extends WithSheet { + label: string; +} + +const Button: React.SFC = ({ classes, children }) => { + return ( + + ); +}; + +const ManuallyStyles = () => { + return ( +