diff --git a/types/rebass__grid/index.d.ts b/types/rebass__grid/index.d.ts index 079506e631..3f5012851f 100644 --- a/types/rebass__grid/index.d.ts +++ b/types/rebass__grid/index.d.ts @@ -34,6 +34,10 @@ export interface CommonProps { px?: ResponsiveProp; py?: ResponsiveProp; theme?: any; + // this is actually more powerful than the plugin because of some limitations of the transform + /** + * This works even without babel-plugin-styled-components. + */ css?: Interpolation; } diff --git a/types/rebass__grid/rebass__grid-tests.tsx b/types/rebass__grid/rebass__grid-tests.tsx index 2cef66a972..147f3ff084 100644 --- a/types/rebass__grid/rebass__grid-tests.tsx +++ b/types/rebass__grid/rebass__grid-tests.tsx @@ -1,8 +1,11 @@ import * as React from "react"; import { Flex, Box } from "@rebass/grid"; +import { css } from "styled-components"; const Layout = () => ( ); + +const cssTest = ; diff --git a/types/styled-components/cssprop.d.ts b/types/styled-components/cssprop.d.ts new file mode 100644 index 0000000000..e19b03dc2c --- /dev/null +++ b/types/styled-components/cssprop.d.ts @@ -0,0 +1,19 @@ +import {} from "react"; +import { CSSProp } from "."; + +declare module "react" { + interface Attributes { + // NOTE: unlike the plain javascript version, it is not possible to get access + // to the element's own attributes inside function interpolations. + // Only theme will be accessible, and only with the DefaultTheme due to the global + // nature of this declaration. + // If you are writing this inline you already have access to all the attributes anyway, + // no need for the extra indirection. + /** + * If present, this React element will be converted by + * `babel-plugin-styled-components` into a styled component + * with the given css as its styles. + */ + css?: CSSProp; + } +} diff --git a/types/styled-components/index.d.ts b/types/styled-components/index.d.ts index 1b26568498..2f6fa61317 100644 --- a/types/styled-components/index.d.ts +++ b/types/styled-components/index.d.ts @@ -440,4 +440,35 @@ export class StyleSheetManager extends React.Component< StyleSheetManagerProps > {} +/** + * 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. + * + * You can load a default declaration by using writing this special import from + * a typescript file. This module does not exist in reality, which is why the {} is important: + * + * ```ts + * import {} from 'styled-components/cssprop' + * ``` + * + * Or you can declare your own module augmentation, which allows you to specify the type of Theme: + * + * ```ts + * import { CSSProp } from 'styled-components' + * + * interface MyTheme {} + * + * declare module 'react' { + * interface Attributes { + * css?: CSSProp + * } + * } + * ``` + */ +// ONLY string literals and inline invocations of css`` are supported, anything else crashes the plugin +export type CSSProp> = + string | + FlattenInterpolation>; + export default styled; diff --git a/types/styled-components/macro.d.ts b/types/styled-components/macro.d.ts index 08cee96a96..51f6cced26 100644 --- a/types/styled-components/macro.d.ts +++ b/types/styled-components/macro.d.ts @@ -1,2 +1,7 @@ export { default } from '.'; export * from '.'; + +/** + * Recommended: also `import {} from 'styled-components/cssprop'`, + * or augment react's `Attribute` interface with your own version. + */ diff --git a/types/styled-components/test/index.tsx b/types/styled-components/test/index.tsx index 50a17b7069..2d70f74106 100644 --- a/types/styled-components/test/index.tsx +++ b/types/styled-components/test/index.tsx @@ -16,6 +16,7 @@ import styled, { StyledComponent, ThemedStyledComponentsModule } from "styled-components"; +import {} from "styled-components/cssprop"; /** * general usage @@ -187,7 +188,6 @@ const styledButton = styled.button` const name = "hey"; const ThemedMyButton = withTheme(MyButton); - ; /** @@ -305,7 +305,6 @@ const ObjectStylesBox = styled.div` fontSize: 2 }}; `; - ; /** @@ -337,7 +336,6 @@ const AttrsWithOnlyNewProps = styled.h2.attrs({ as: "h1" })` `; const AttrsInputExtra = styled(AttrsInput).attrs({ autoComplete: "off" })``; - ; /** @@ -434,10 +432,8 @@ const Component = (props: WithThemeProps) => ( ); const ComponentWithTheme = withTheme(Component); - ; // ok ; // ok - {theme => }; /** @@ -625,7 +621,6 @@ const divFnRef = (ref: HTMLDivElement | null) => { const divRef = React.createRef(); const StyledDiv = styled.div``; - ; ; ; // $ExpectError @@ -786,3 +781,89 @@ async function themeAugmentation() { ); } + +// NOTE: this is needed for some tests inside cssProp, +// but actually running this module augmentation will cause +// tests elsewhere to break, and there is no way to contain it. +// Uncomment out as needed to run tests. + +// declare module "styled-components" { +// interface DefaultTheme { +// background: string; +// } +// } + +function cssProp() { + function Custom(props: React.ComponentPropsWithoutRef<"div">) { + return
; + } + + const myCss = "background: blue;"; + + return ( + <> +
+ {/* + For some reason $ExpectError doesn't work on this expression. + Only strings work, objects crash the plugin. +
+ */} +
+
+
+
+
"blue"}; + `} + /> +
{ + // This requires the DefaultTheme augmentation + // // $ExpectType string + // props.theme.background; + return props.theme.background; + }}; + `} + /> + + + + "blue"}; + `} + /> + { + // This requires the DefaultTheme augmentation + // // $ExpectType string + // props.theme.background; + return props.theme.background; + }}; + `} + /> + + ); +} diff --git a/types/styled-components/tsconfig.json b/types/styled-components/tsconfig.json index 22af0d4a13..fb9b5a0f7b 100644 --- a/types/styled-components/tsconfig.json +++ b/types/styled-components/tsconfig.json @@ -3,20 +3,26 @@ "baseUrl": "../", "forceConsistentCasingInFileNames": true, "jsx": "react", - "lib": ["es6", "dom"], + "lib": [ + "es6", + "dom" + ], "module": "commonjs", "noEmit": true, "noImplicitAny": true, "noImplicitThis": true, "strictFunctionTypes": true, "strictNullChecks": true, - "typeRoots": ["../"], + "typeRoots": [ + "../" + ], "types": [] }, "files": [ "index.d.ts", "macro.d.ts", + "cssprop.d.ts", "test/index.tsx", "test/macro.tsx" ] -} +} \ No newline at end of file