Comparing version 0.30.2 to 0.31.0
{ | ||
"name": "gestalt", | ||
"version": "0.30.2", | ||
"version": "0.31.0", | ||
"license": "Apache-2.0", | ||
@@ -11,10 +11,7 @@ "homepage": "https://pinterest.github.io/gestalt", | ||
"style": "dist/gestalt.css", | ||
"files": [ | ||
"dist", | ||
"src" | ||
], | ||
"files": ["dist", "src"], | ||
"dependencies": { | ||
"classnames": "^2.2.5", | ||
"prop-types": "^15.5.10", | ||
"react": "^15.4.1 || >=16.0.0-alpha.0 < 16.0.1" | ||
"react": "^15.4.1" | ||
}, | ||
@@ -98,5 +95,5 @@ "scripts": { | ||
"style-loader": "^0.13.0", | ||
"stylelint": "^7.12.0", | ||
"stylelint-config-standard": "^16.0.0", | ||
"stylelint-order": "^0.5.0", | ||
"stylelint": "^8.0.0", | ||
"stylelint-config-standard": "^17.0.0", | ||
"stylelint-order": "^0.6.0", | ||
"svg-path-loader": "^0.0.2", | ||
@@ -114,8 +111,4 @@ "webpack": "^1.12.14", | ||
"stylelint": { | ||
"extends": [ | ||
"stylelint-config-standard" | ||
], | ||
"plugins": [ | ||
"stylelint-order" | ||
], | ||
"extends": ["stylelint-config-standard"], | ||
"plugins": ["stylelint-order"], | ||
"rules": { | ||
@@ -125,5 +118,3 @@ "color-named": [ | ||
{ | ||
"ignoreProperties": [ | ||
"composes" | ||
] | ||
"ignoreProperties": ["composes"] | ||
} | ||
@@ -134,5 +125,3 @@ ], | ||
{ | ||
"ignore": [ | ||
"consecutive-duplicates" | ||
] | ||
"ignore": ["consecutive-duplicates"] | ||
} | ||
@@ -154,5 +143,3 @@ ], | ||
"order/properties-order": [ | ||
[ | ||
"composes" | ||
], | ||
["composes"], | ||
{ | ||
@@ -165,5 +152,3 @@ "unspecified": "bottomAlphabetical" | ||
{ | ||
"ignoreProperties": [ | ||
"composes" | ||
] | ||
"ignoreProperties": ["composes"] | ||
} | ||
@@ -175,13 +160,9 @@ ], | ||
{ | ||
"except": [ | ||
"first-nested" | ||
] | ||
"except": ["first-nested"] | ||
} | ||
], | ||
"selector-no-id": true, | ||
"selector-max-id": 0, | ||
"selector-no-vendor-prefix": true, | ||
"selector-pseudo-class-no-unknown": true, | ||
"unit-blacklist": [ | ||
"em" | ||
], | ||
"unit-blacklist": ["em"], | ||
"value-no-vendor-prefix": true | ||
@@ -188,0 +169,0 @@ } |
@@ -29,3 +29,3 @@ // @flow | ||
onClick?: (event: SyntheticEvent) => void, | ||
size?: 'md' | 'lg', /* default: lg */ | ||
size?: 'md' | 'lg', /* default: md */ | ||
text: string, | ||
@@ -105,6 +105,6 @@ type?: 'submit' | 'button', /* default: button */ | ||
<Box xs={{ column: 6, display: 'flex' }} padding={{ x: 1 }}> | ||
<Button color="transparent" text="Later" size="md" /> | ||
<Button color="transparent" text="Later" /> | ||
</Box> | ||
<Box xs={{ column: 6 }} padding={{ x: 1 }}> | ||
<Button color="white" text="Learn more" size="md" /> | ||
<Button color="white" text="Learn more" /> | ||
</Box> | ||
@@ -118,7 +118,6 @@ </Box> | ||
md` | ||
There are two different sizes for buttons. The medium buttons have smaller font sizes & less padding. The default size is \`lg\`. | ||
There are two different sizes for buttons. The medium buttons have smaller font sizes & less padding. The default size is \`md\`. | ||
\`\`\`html | ||
<Button | ||
size="md" | ||
text="Medium sized button" | ||
@@ -129,2 +128,3 @@ /> | ||
<Button | ||
size="lg" | ||
text="Large sized button" | ||
@@ -136,6 +136,6 @@ /> | ||
<Box padding={2}> | ||
<Button size="md" text="Medium sized button" /> | ||
<Button text="Medium sized button" /> | ||
</Box> | ||
<Box padding={2}> | ||
<Button text="Large sized button" /> | ||
<Button size="lg" text="Large sized button" /> | ||
</Box> | ||
@@ -142,0 +142,0 @@ </Box> |
@@ -31,3 +31,3 @@ // @flow | ||
onClick, | ||
size = 'lg', | ||
size = 'md', | ||
text, | ||
@@ -34,0 +34,0 @@ type = 'button', |
@@ -33,2 +33,4 @@ // @flow | ||
const ariaHidden = accessibilityLabel === '' ? true : null; | ||
return ( | ||
@@ -40,2 +42,3 @@ <svg | ||
viewBox="0 0 16 16" | ||
aria-hidden={ariaHidden} | ||
aria-label={accessibilityLabel} | ||
@@ -42,0 +45,0 @@ role="img" |
@@ -26,2 +26,3 @@ // @flow | ||
color: string, | ||
fit?: 'cover' | 'contain' | 'none', | ||
naturalHeight: number, | ||
@@ -121,1 +122,137 @@ naturalWidth: number, | ||
); | ||
card( | ||
'Fit', | ||
md` | ||
In some cases, you may want to scale an image to fit into its container. | ||
To achieve that, you can set \`fit\` to either \`cover\` or \`contain\`, depending on the effect you wish to achieve. | ||
Contain - This makes it so that the image is "contained" within its container. This means that the image is resized appropriately | ||
such that the entire image can fit in the container, while maintaining its aspect ratio (think letterbox); | ||
\`\`\`jsx | ||
<Image | ||
alt="..." | ||
color="#000" | ||
fit="contain" | ||
src="..." | ||
/> | ||
\`\`\` | ||
Cover - This does the opposite of contain and tries to scale the image as large as possible so that the entire container is occupied, | ||
while maintaining the aspect ratio of the image. | ||
\`\`\`jsx | ||
<Image | ||
alt="..." | ||
color="#000" | ||
fit="cover" | ||
src="..." | ||
/> | ||
\`\`\` | ||
Notes: | ||
- When using cover/contain, \`naturalHeight\` and \`naturalWidth\` are ignored since the aspect ratio is handled by the browser. | ||
- In order for cover/contain to work properly, the container must have some sort of implicit height. | ||
`, | ||
<Box xs={{ display: 'flex' }} wrap> | ||
<Box> | ||
<h3>Tall content: cover vs contain</h3> | ||
<Box xs={{ display: 'flex' }} justifyContent="around"> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="contain" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/a9/dd/08/a9dd080b383ba4f336b5e4705cacdfba.jpg" | ||
/> | ||
</Box> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="cover" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/a9/dd/08/a9dd080b383ba4f336b5e4705cacdfba.jpg" | ||
/> | ||
</Box> | ||
</Box> | ||
</Box> | ||
<Box> | ||
<h3>Wide content: cover vs contain</h3> | ||
<Box xs={{ display: 'flex' }} justifyContent="around"> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="contain" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/47/b8/ec/47b8ec3948ef1f8eba0b0fe1dde28622.jpg" | ||
/> | ||
</Box> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="cover" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/47/b8/ec/47b8ec3948ef1f8eba0b0fe1dde28622.jpg" | ||
/> | ||
</Box> | ||
</Box> | ||
</Box> | ||
<Box> | ||
<h3>Square content: cover vs contain</h3> | ||
<Box xs={{ display: 'flex' }} justifyContent="around"> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="contain" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/10/7d/99/107d993c7818ed41bc0afc27ab2a2f15.jpg" | ||
/> | ||
</Box> | ||
<Box | ||
color="darkGray" | ||
dangerouslySetInlineStyle={{ __style: { height: 200, width: 200 } }} | ||
margin={{ left: 4, right: 4 }} | ||
> | ||
<Image | ||
alt="tall" | ||
color="000" | ||
fit="cover" | ||
naturalHeight={1} | ||
naturalWidth={1} | ||
src="https://s-media-cache-ak0.pinimg.com/564x/10/7d/99/107d993c7818ed41bc0afc27ab2a2f15.jpg" | ||
/> | ||
</Box> | ||
</Box> | ||
</Box> | ||
</Box>, | ||
{ stacked: true } | ||
); |
@@ -23,1 +23,33 @@ /* eslint-env jest */ | ||
}); | ||
test('Image with fit: cover matches snapshot', () => { | ||
const component = renderer.create( | ||
<Image | ||
alt="foo" | ||
fit="cover" | ||
naturalHeight={50} | ||
naturalWidth={50} | ||
src="foo.png" | ||
> | ||
Foo.png | ||
</Image> | ||
); | ||
const tree = component.toJSON(); | ||
expect(tree).toMatchSnapshot(); | ||
}); | ||
test('Image with fit: contain matches snapshot', () => { | ||
const component = renderer.create( | ||
<Image | ||
alt="foo" | ||
fit="contain" | ||
naturalHeight={50} | ||
naturalWidth={50} | ||
src="foo.png" | ||
> | ||
Foo.png | ||
</Image> | ||
); | ||
const tree = component.toJSON(); | ||
expect(tree).toMatchSnapshot(); | ||
}); |
// @flow | ||
import React, { Component } from 'react'; | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
@@ -7,3 +7,19 @@ import Box from '../Box/Box'; | ||
export default class Image extends Component { | ||
const shouldScaleImage = fit => fit === 'cover' || fit === 'contain'; | ||
type Props = {| | ||
alt: string, | ||
children?: any, | ||
color: string, | ||
fit: 'contain' | 'cover' | 'none', | ||
naturalHeight: number, | ||
naturalWidth: number, | ||
onError?: () => void, | ||
onLoad?: () => void, | ||
sizes?: string, | ||
src: string, | ||
srcSet?: { [key: string]: string }, | ||
|}; | ||
export default class Image extends PureComponent { | ||
static propTypes = { | ||
@@ -13,2 +29,3 @@ alt: PropTypes.string.isRequired, | ||
color: PropTypes.string, | ||
fit: PropTypes.oneOf(['contain', 'cover', 'none']), | ||
naturalHeight: PropTypes.number.isRequired, | ||
@@ -25,17 +42,20 @@ naturalWidth: PropTypes.number.isRequired, | ||
color: 'transparent', | ||
fit: 'none', | ||
}; | ||
props: {| | ||
alt: string, | ||
children?: any, | ||
color: string, | ||
naturalHeight: number, | ||
naturalWidth: number, | ||
onError?: () => void, | ||
onLoad?: () => void, | ||
sizes?: string, | ||
src: string, | ||
srcSet?: { [key: string]: string }, | ||
|}; | ||
componentDidMount() { | ||
if (shouldScaleImage(this.props.fit)) { | ||
this.loadImage(); | ||
} | ||
} | ||
componentDidUpdate(prevProps: Props) { | ||
const { fit, src } = this.props; | ||
if (shouldScaleImage(fit) && prevProps.src !== src) { | ||
this.loadImage(); | ||
} | ||
} | ||
props: Props; | ||
handleLoad = () => { | ||
@@ -53,2 +73,11 @@ if (this.props.onLoad) { | ||
loadImage() { | ||
if (typeof window !== 'undefined') { | ||
const image = new window.Image(); | ||
image.onload = this.handleLoad; | ||
image.onerror = this.handleError; | ||
image.src = this.props.src; | ||
} | ||
} | ||
render() { | ||
@@ -59,2 +88,3 @@ const { | ||
children, | ||
fit, | ||
naturalHeight, | ||
@@ -67,26 +97,42 @@ naturalWidth, | ||
const aspect = naturalHeight / naturalWidth * 100; | ||
const style = { | ||
backgroundColor: color, | ||
paddingBottom: `${aspect}%`, | ||
}; | ||
const isScaledImage = shouldScaleImage(fit); | ||
const childContent = children | ||
? <Box position="absolute" top left bottom right overflow="hidden"> | ||
{children} | ||
</Box> | ||
: null; | ||
return ( | ||
<Box position="relative" dangerouslySetInlineStyle={{ __style: style }}> | ||
<img | ||
alt={alt} | ||
className={styles.img} | ||
onError={this.handleError} | ||
onLoad={this.handleLoad} | ||
sizes={sizes} | ||
src={src} | ||
srcSet={srcSet} | ||
/> | ||
{children && | ||
<Box position="absolute" top left bottom right overflow="hidden"> | ||
{children} | ||
</Box>} | ||
</Box> | ||
); | ||
return isScaledImage | ||
? <div | ||
aria-label={alt} | ||
className={styles[fit]} | ||
style={{ | ||
backgroundColor: color, | ||
backgroundImage: `url('${src}')`, | ||
}} | ||
role="img" | ||
> | ||
{childContent} | ||
</div> | ||
: <Box | ||
position="relative" | ||
dangerouslySetInlineStyle={{ | ||
__style: { | ||
backgroundColor: color, | ||
paddingBottom: `${naturalHeight / naturalWidth * 100}%`, | ||
}, | ||
}} | ||
> | ||
<img | ||
alt={alt} | ||
className={styles.img} | ||
onError={this.handleError} | ||
onLoad={this.handleLoad} | ||
sizes={sizes} | ||
src={src} | ||
srcSet={srcSet} | ||
/> | ||
{childContent} | ||
</Box>; | ||
} | ||
} |
@@ -89,2 +89,3 @@ // @flow | ||
<Button | ||
size="lg" | ||
text="View padding" | ||
@@ -255,2 +256,3 @@ onClick={() => atom.reset({ isOpen: !atom.deref().isOpen })} | ||
<Button | ||
size="lg" | ||
text="Edit board" | ||
@@ -325,3 +327,3 @@ onClick={() => atom.reset({ isOpen: !atom.deref().isOpen })} | ||
<Box xs={{ display: 'flex' }} justifyContent="end"> | ||
<Button text="Cancel" onClick={onClose} /> | ||
<Button size="lg" text="Cancel" onClick={onClose} /> | ||
</Box> | ||
@@ -355,2 +357,3 @@ ); | ||
<Button | ||
size="lg" | ||
text="View images" | ||
@@ -386,6 +389,6 @@ onClick={() => atom.reset({ isOpen: !atom.deref().isOpen })} | ||
<Box padding={{ y: 1 }}> | ||
<Button text="Cancel" onClick={onClose} /> | ||
<Button size="lg" text="Cancel" onClick={onClose} /> | ||
</Box> | ||
<Box padding={{ y: 1 }}> | ||
<Button color="red" text="Block" onClick={onClose} /> | ||
<Button size="lg" color="red" text="Block" onClick={onClose} /> | ||
</Box> | ||
@@ -411,2 +414,3 @@ </Box> | ||
<Button | ||
size="lg" | ||
text="Block Chris" | ||
@@ -413,0 +417,0 @@ onClick={() => atom.reset({ isOpen: !atom.deref().isOpen })} |
// @flow | ||
import React, { Component, PropTypes } from 'react'; | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import classnames from 'classnames'; | ||
@@ -4,0 +5,0 @@ import Text from '../Text/Text'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1969274
281
34066
+ Addedcreate-react-class@15.7.0(transitive)
+ Addedreact@15.7.0(transitive)
- Removedreact@16.0.0(transitive)
Updatedreact@^15.4.1