From 9b21420bf8b03ff06047636de474016c56fac38b Mon Sep 17 00:00:00 2001 From: Barry Low Date: Tue, 16 Oct 2018 23:27:29 -0700 Subject: [PATCH] Rebuild ImageUpload imagePreview component --- README.md | 13 ++- src/image-upload/components/ImagePreview.js | 105 ++++++++++++++++++-- src/image-upload/index.js | 11 +- stories/index.stories.js | 5 +- 4 files changed, 115 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 7d2d652..67bf77b 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ const YourComponent = ({ handleAvatar, filename, containerName, avatar, AzureSto fileName={fileName} containerName={containerName} existingImage={avatar} - cropContainer={{ x: 10, y: 10, width: 200, height: 200 }} + imagePreviewConfig={{ width: 350, title: 'Change Avatar' }} + cropContainerConfig={{ x: 10, y: 10, width: 200, height: 200 }} cropPreviewBox={{ width: 350, height: 350 }} saveImageConfig={{ quality: 0.6, @@ -98,7 +99,8 @@ export default YourComponent | `fileName` | String | *Required.* File name that image is uploaded to storage as | | `containerName` | String | *Required.* StorageContainer name that image is uploaded to | | `existingImage` | String (url) | Url of pre-existing image. Usually will be same as URL returned from `handleUrl` | -| `cropContainer` | Object | Size and location of cropper on image in crop mode | +| `imagePreviewConfig` | Object | Existing image preview and change button text | +| `cropContainerConfig` | Object | Size and location of cropper on image in crop mode | | `cropPreviewBox` | Object | Dimensions of cropper preview | | `cropRatio` | Number | ratio (width/height) image is cropped at eg. 1/1, 4/1, 16/9, 800/150 | | `saveImageConfig` | Object | Configuration of image saved to storage | @@ -108,7 +110,8 @@ export default YourComponent #### Default Values | Props | Default | | ------------------ | ------------- | -| `cropContainer` | `{ x: 10, y: 10, width: 200, height: 200 }` | +| `imagePreviewConfig` | `{ width: 350, title: 'Change Avatar' }` | +| `cropContainerConfig` | `{ x: 10, y: 10, width: 200, height: 200 }` | |`cropPreviewBox` | `{ width: 350, height: 350 }` | |`cropRatio` | `1 / 1` | |`saveImageConfig` | `{quality: 0.6, maxWidth: 200, maxHeight: 200, autoRotate: true, debug: true, mimeType: 'image/jpeg}` | @@ -174,8 +177,8 @@ export class YourComponent extends Component { fileName={fileName} containerName={containerName} existingImage={avatar} - cropContainer={{ x: 10, y: 10, width: 200, height: 200 }} - cropPreviewBox={{ width: 350, height: 350 }} + imagePreviewConfig={{ width: 350, title: 'Change Avatar' }} + cropContainerConfig={{ x: 10, y: 10, width: 200, height: 200 }} cropPreviewBox={{ width: 350, height: 350 }} saveImageConfig={{ quality: 0.6, maxWidth: 200, diff --git a/src/image-upload/components/ImagePreview.js b/src/image-upload/components/ImagePreview.js index 2dab57f..1819d86 100644 --- a/src/image-upload/components/ImagePreview.js +++ b/src/image-upload/components/ImagePreview.js @@ -2,31 +2,114 @@ import React from 'react' import PropTypes from 'prop-types' import { withStyles } from '@material-ui/core/styles' -import Button from '@material-ui/core/Button' +import ButtonBase from '@material-ui/core/ButtonBase' +import Typography from '@material-ui/core/Typography' const styles = theme => ({ - imagePreview: { - maxWidth: '100%', - height: 'auto' + root: { + display: 'flex', + flexWrap: 'wrap', + minWidth: 300, + width: '100%' + }, + image: { + position: 'relative', + height: 200, + [theme.breakpoints.down('xs')]: { + width: '100% !important', // Overrides inline-style + height: 100 + }, + '&:hover, &$focusVisible': { + zIndex: 1, + '& $imageBackdrop': { + opacity: 0.15 + }, + '& $imageMarked': { + opacity: 0 + }, + '& $imageTitle': { + backgroundColor: theme.palette.common.black, + opacity: 0.4 + } + } + }, + focusVisible: {}, + imageButton: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + color: theme.palette.common.white + }, + imageSrc: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + backgroundSize: 'cover', + backgroundPosition: 'center 40%' + }, + imageBackdrop: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + backgroundColor: theme.palette.common.black, + opacity: 0.4, + transition: theme.transitions.create('opacity') + }, + imageTitle: { + position: 'relative', + textTransform: 'uppercase', + fontWeight: 700, + padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 4}px ${theme.spacing.unit + 6}px` } }) -export const ImagePreview = ({ classes, handleChangeImage, image }) => ( +export const ImagePreview = ({ classes, handleChangeImage, image, imagePreview }) => ( - Existing Image Preview - + + + + + {imagePreview.title} + + + ) ImagePreview.propTypes = { classes: PropTypes.object.isRequired, handleChangeImage: PropTypes.func, - image: PropTypes.string + image: PropTypes.string, + imagePreview: PropTypes.object } export default withStyles(styles)(ImagePreview) diff --git a/src/image-upload/index.js b/src/image-upload/index.js index e8b7a8c..34c2986 100644 --- a/src/image-upload/index.js +++ b/src/image-upload/index.js @@ -23,6 +23,11 @@ const placeHolder = fileName => { return `data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3E${fileName}%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E` } +const imagePreviewDefault = { + width: 400, + title: 'Change Avatar' +} + const cropPreviewBoxDefault = { width: 350, height: 350 @@ -60,9 +65,12 @@ class ImageUpload extends Component { this.saveImage = this.saveImage.bind(this) this.debug = this.props.debug + let previewConfig = props.imagePreviewConfig !== undefined ? props.imagePreviewConfig : imagePreviewDefault let cropConfig = props.cropContainerConfig !== undefined ? props.cropContainerConfig : cropConfigDefault let saveConfig = props.saveImageConfig !== undefined ? props.saveImageConfig : saveImageConfigDefault let cropPreview = props.cropPreviewBox !== undefined ? props.cropPreviewBox : cropPreviewBoxDefault + this.previewConfig = previewConfig + this.cropConfig = cropConfig this.saveConfig = saveConfig this.cropPreview = cropPreview @@ -103,7 +111,7 @@ class ImageUpload extends Component {
{ (this.state.event === 'preview' || this.state.event === 'uploaded') && this.state.event !== 'choose' && ( - + )} { this.state.event === 'choose' && ( @@ -200,6 +208,7 @@ class ImageUpload extends Component { ImageUpload.propTypes = { classes: PropTypes.object.isRequired, + imagePreviewConfig: PropTypes.object, // { width: 400, title: 'Change Avatar'} cropContainerConfig: PropTypes.object, // { x: 10, y: 10, width: 200, height: 200 } (default) cropPreviewBox: PropTypes.object, // { width: 350, height: 350 } (default) cropRatio: PropTypes.number.isRequired, // ratio (width/height) image is cropped at eg. 1/1, 4/1, 16/9, 800/150 diff --git a/stories/index.stories.js b/stories/index.stories.js index 961e8dc..d5b05f1 100644 --- a/stories/index.stories.js +++ b/stories/index.stories.js @@ -38,7 +38,8 @@ storiesOf('ImageUpload', module) containerName={text('containerName', 'test-team')} existingImage={placeholder} cropRatio={1} - cropContainer={{ x: 10, y: 10, width: 200, height: 200 }} + imagePreviewConfig={{ width: 350, title: 'Change Avatar' }} + cropContainerConfig={{ x: 10, y: 10, width: 200, height: 200 }} cropPreviewBox={{ width: 350, height: 350 }} saveImageConfig={{ quality: 0.6, @@ -98,7 +99,7 @@ class LoadImage extends React.Component { storiesOf('ImageUpload Components', module) .addDecorator(withKnobs) .add('Image Preview component', () => ( - + )) .add('DropZone component', () => (