Don't augment the css prop by default, check and document limitations

This commit is contained in:
Jessica
2018-11-30 19:29:09 +09:00
parent 12b2403208
commit 38c7639b43
6 changed files with 86 additions and 30 deletions
+4 -3
View File
@@ -10,7 +10,7 @@
export type Omit<T, K extends keyof T> = Pick<T, ({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never, [x: number]: never })[keyof T]>;
import { ComponentType } from "react";
import { StyledComponent, CSSIntrinsicAttributeType } from "styled-components";
import { StyledComponent, Interpolation } from "styled-components";
export type ResponsiveProp = number | string | Array<string | number>;
@@ -34,10 +34,11 @@ export interface CommonProps {
px?: ResponsiveProp;
py?: ResponsiveProp;
theme?: any;
// this is actually more powerful than the plugin because of some limitations of the transform
/**
* NOTE: this is not compatible with the styled-components babel plugin anymore
* This works even without babel-plugin-styled-components.
*/
css?: CSSIntrinsicAttributeType;
css?: Interpolation<any>;
}
export interface BoxProps
@@ -1,8 +1,11 @@
import * as React from "react";
import { Flex, Box } from "@rebass/grid";
import { css } from "styled-components";
const Layout = () => (
<Flex m={4}>
<Box px={3} py={2} />
</Flex>
);
const cssTest = <Flex css='background: transparent;'><Box css={css`${{color: 'inherit'}}`}/></Flex>;
+19
View File
@@ -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;
}
}
+30 -24
View File
@@ -436,29 +436,35 @@ export class StyleSheetManager extends React.Component<
StyleSheetManagerProps
> {}
export type CSSIntrinsicAttributeType =
| string
| CSSObject
| FlattenSimpleInterpolation
// Sad, but because this is global, there is no way to override it with the ThemedStyledComponentsModule
// Only augmenting DefaultTheme will work for inline css prop
| FlattenInterpolation<ThemeProps<AnyIfEmpty<DefaultTheme>>>;
/**
* 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<MyTheme>
* }
* }
* ```
*/
// ONLY string literals and inline invocations of css`` are supported, anything else crashes the plugin
export type CSSProp<T = AnyIfEmpty<DefaultTheme>> =
string |
FlattenInterpolation<ThemeProps<T>>;
export default styled;
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?: CSSIntrinsicAttributeType;
}
}
+5
View File
@@ -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.
*/
+25 -3
View File
@@ -16,6 +16,7 @@ import styled, {
StyledComponent,
ThemedStyledComponentsModule
} from "styled-components";
import {} from "styled-components/cssprop";
/**
* general usage
@@ -782,16 +783,34 @@ function cssProp() {
return <div {...props} />;
}
const myCss = 'background: blue;';
return (
<>
<div css="background: blue;" />
<div css={{ background: "blue" }} />
<div css={undefined} />
<div
// $ExpectError only strings work, objects crash the plugin
css={{ background: "blue" }}
/>
<div
// would be nice to be able to turn this into an error as it also crashes the plugin,
// but this is how optional properties work in TypeScript...
css={undefined}
/>
<div
// css used as tagged function is fine and is correctly handled by the plugin
css={css`
background: blue;
`}
/>
<div
// but this crashes the plugin, even though it's valid type-wise and we can't forbid it
css={css({ background: 'blue' })}
/>
<div
// this also crashes the plugin, only inline strings or css template tag work
css={myCss}
/>
<div
css={css`
background: ${() => "blue"};
@@ -808,7 +827,10 @@ function cssProp() {
`}
/>
<Custom css="background: blue;" />
<Custom css={{ background: "blue" }} />
<Custom
// $ExpectError only strings work, objects crash the plugin
css={{ background: "blue" }}
/>
<Custom css={undefined} />
<Custom
css={css`