├── .babelrc ├── .github └── FUNDING.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── demo.gif ├── package-lock.json ├── package.json ├── src ├── AutoRotatingCarousel.js ├── AutoRotatingCarousel.md ├── Slide.js ├── Slide.md ├── SwipableCarouselView.js ├── index.js └── util.js ├── styleguide.config.js └── styleguide └── Wrapper.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react", "@babel/preset-env"], 3 | "plugins": ["@babel/plugin-proposal-class-properties"] 4 | } 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [leMaik,saschb2b] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | build 4 | lib -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "6.1" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2018 Team Wertarbyte and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Material AutoRotatingCarousel 2 | 3 | [![Build Status](https://travis-ci.org/TeamWertarbyte/material-auto-rotating-carousel.svg?branch=next)](https://travis-ci.org/TeamWertarbyte/material-auto-rotating-carousel) 4 | [![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 5 | 6 | So you wrote a great app and deployed it and everything. But how do you introduce new users to your app? Well, the Material design guidelines have a solution: Displaying the top benefits in a beautiful [auto-rotating carousel](https://material.io/design/communication/onboarding.html#top-user-benefits-model)! 7 | 8 | This project implements such a carousel for [Material-UI](https://material-ui-next.com). Visit [the styleguide](https://mui.wertarbyte.com/#material-auto-rotating-carousel) for an interactive demo. 9 | 10 | ![Demo](demo.gif) 11 | 12 | ## Installation 13 | ```shell 14 | npm i --save material-auto-rotating-carousel 15 | npm i --save react-swipeable-views 16 | ``` 17 | 18 | **Note:** This is the version for Material-UI 1.0.0 or later. If you are using Material-UI 1.0.0-beta, you should update to the latest version. If you are still using Material-UI 0.x, you can use our [legacy version][legacy]. 19 | 20 | ### AutoRotatingCarousel Properties 21 | 22 | |Name |Type |Default |Description 23 | |----------------|------------|------------|-------------------------------- 24 | |autoplay | `bool` | `true` | If `false`, the auto play behavior is disabled. 25 | |ButtonProps | `object` | | Properties applied to the [Button](https://material-ui.com/api/button/) element. 26 | |classes | `object` | | Object for customizing the CSS classes. 27 | |containerStyle | `object` | | Override the inline-styles of the carousel container. 28 | |hideArrows | `function` | | If `true`, the left and right arrows are hidden in the desktop version. 29 | |interval | `integer` | `3000` | Delay between auto play transitions (in ms). 30 | |label | `string` | | Button text. If not supplied, the button will be hidden. 31 | |landscape | `bool` | | If `true`, slide will adjust content for wide mobile screens. 32 | |mobile | `bool` | `false` | If `true`, the screen width and height is filled. 33 | |ModalProps | `object` | | Properties applied to the [Modal](https://material-ui.com/api/modal/) element. 34 | |open | `bool` | `false` | Controls whether the AutoRotatingCarousel is opened or not. 35 | |onChange | `function` | | Fired when the index changed. Returns current index. 36 | |onClose | `function` | | Fired when the gray background of the popup is pressed when it is open. 37 | |onStart | `function` | | Fired when the user clicks the getting started button. 38 | 39 | ### Slide Properties 40 | 41 | |Name |Type |Default |Description 42 | |-----------------------|-----------|-------------|-------------------------------- 43 | |classes | `object` | | Object for customizing the CSS classes. 44 | |landscape | `bool` | | If `true`, slide will adjust content for wide mobile screens (automatically set by `AutoRotatingCarousel`). 45 | |media* | `node` | | Object to display in the upper half. 46 | |mediaBackgroundStyle | `object` | | Override the inline-styles of the media container. 47 | |mobile | `bool` | | If `true`, the screen width and height is filled (automatically set by `AutoRotatingCarousel`). 48 | |style | `object` | | Override the inline-styles of the slide. 49 | |subtitle* | `string` | | Subtitle for the slide. 50 | |title* | `string` | | Title for the slide. 51 | 52 | \* required property 53 | 54 | ## Example 55 | [![Edit material-auto-rotating-carousel example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mystifying-varahamihira-dphsr?fontsize=14) 56 | 57 | ## License 58 | 59 | The files included in this repository are licensed under the MIT license. 60 | 61 | [legacy]: https://github.com/TeamWertarbyte/material-auto-rotating-carousel/tree/legacy 62 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamWertarbyte/material-auto-rotating-carousel/bdd2a9c239e7c934c75fd3e1245e597c2fba6339/demo.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-auto-rotating-carousel", 3 | "version": "3.0.2", 4 | "description": "Introduce new users to your app with this material style carousel", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "babel src -d lib", 8 | "prepublish": "npm run build", 9 | "styleguide": "styleguidist server", 10 | "styleguide:build": "styleguidist build", 11 | "test": "standard" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/TeamWertarbyte/material-auto-rotating-carousel.git" 16 | }, 17 | "keywords": [ 18 | "react", 19 | "material-ui", 20 | "rotate", 21 | "intro", 22 | "react-component" 23 | ], 24 | "author": "Wertarbyte (https://wertarbyte.com)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/TeamWertarbyte/material-auto-rotating-carousel/issues" 28 | }, 29 | "homepage": "https://github.com/TeamWertarbyte/material-auto-rotating-carousel#readme", 30 | "devDependencies": { 31 | "@babel/cli": "^7.11.6", 32 | "@babel/core": "^7.11.6", 33 | "@babel/plugin-proposal-class-properties": "^7.10.4", 34 | "@babel/preset-env": "^7.11.5", 35 | "@babel/preset-react": "^7.10.4", 36 | "@material-ui/core": "^4.3.2", 37 | "@material-ui/icons": "^4.2.1", 38 | "babel-eslint": "^7.2.3", 39 | "babel-loader": "^8.1.0", 40 | "react": "^16.9.0", 41 | "react-dom": "^16.9.0", 42 | "react-styleguidist": "^11.1.0", 43 | "react-swipeable-views": "^0.13.3", 44 | "standard": "^10.0.2", 45 | "webpack": "^4.44.2" 46 | }, 47 | "peerDependencies": { 48 | "@material-ui/core": "^3.6.0 || ^4.0.0", 49 | "@material-ui/icons": "^3.0.0 || ^4.0.0", 50 | "react": "^16.3.0", 51 | "react-dom": "^16.3.0", 52 | "react-swipeable-views": "^0.13.3", 53 | "react-swipeable-views-utils": "^0.13.3" 54 | }, 55 | "dependencies": { 56 | "classnames": "^2.2.5", 57 | "material-ui-dots": "^2.0.0", 58 | "prop-types": "^15.5.8" 59 | }, 60 | "standard": { 61 | "parser": "babel-eslint" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/AutoRotatingCarousel.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from 'prop-types' 3 | import Button from '@material-ui/core/Button' 4 | import Paper from '@material-ui/core/Paper' 5 | import { grey } from '@material-ui/core/colors' 6 | import withStyles from '@material-ui/core/styles/withStyles' 7 | import { duration } from '@material-ui/core/styles/transitions' 8 | import Fab from '@material-ui/core/Fab' 9 | import ArrowBackIcon from '@material-ui/icons/ArrowBack' 10 | import ArrowForwardIcon from '@material-ui/icons/ArrowForward' 11 | import Modal from '@material-ui/core/Modal' 12 | import Fade from '@material-ui/core/Fade' 13 | import Backdrop from '@material-ui/core/Backdrop' 14 | import Dots from 'material-ui-dots' 15 | import classNames from 'classnames' 16 | import Carousel from './SwipableCarouselView' 17 | import { modulo } from './util' 18 | 19 | const styles = { 20 | root: { 21 | '& > *:focus': { 22 | outline: 'none' 23 | } 24 | }, 25 | content: { 26 | width: '60%', 27 | maxWidth: 700, 28 | height: 'calc(100% - 96px)', 29 | maxHeight: 600, 30 | margin: '-16px auto 0', 31 | position: 'relative', 32 | top: '50%', 33 | transform: 'translateY(-50%)' 34 | }, 35 | contentMobile: { 36 | width: '100%', 37 | height: '100%', 38 | maxWidth: 'initial', 39 | maxHeight: 'initial', 40 | margin: 0, 41 | top: 0, 42 | transform: 'none', 43 | 44 | '& > $carouselWrapper': { 45 | borderRadius: 0 46 | } 47 | }, 48 | arrow: { 49 | width: 48, 50 | height: 48, 51 | position: 'absolute', 52 | top: 'calc((100% - 96px) / 2 + 24px)' 53 | }, 54 | arrowLeft: { 55 | left: -96 56 | }, 57 | arrowRight: { 58 | right: -96 59 | }, 60 | arrowIcon: { 61 | color: grey[700] 62 | }, 63 | carouselWrapper: { 64 | overflow: 'hidden', 65 | borderRadius: 14, 66 | transform: 'scale(1.0)', 67 | background: 'transparent', 68 | height: '100%' 69 | }, 70 | dots: { 71 | paddingTop: 36, 72 | margin: '0 auto' 73 | }, 74 | dotsMobile: { 75 | paddingTop: 0 76 | }, 77 | dotsMobileLandscape: { 78 | paddingTop: 20 79 | }, 80 | footer: { 81 | marginTop: -72, 82 | width: '100%', 83 | position: 'relative', 84 | textAlign: 'center' 85 | }, 86 | footerMobile: { 87 | marginTop: -92 88 | }, 89 | footerMobileLandscape: { 90 | marginTop: -3, 91 | transform: 'translateY(-50vh)', 92 | display: 'inline-block', 93 | width: 'auto' 94 | }, 95 | slide: { 96 | width: '100%', 97 | height: '100%' 98 | }, 99 | slideMobile: { 100 | width: '100%', 101 | height: '100%' 102 | }, 103 | carousel: { 104 | height: '100%' 105 | }, 106 | carouselContainer: { 107 | height: '100%' 108 | }, 109 | closed: {} 110 | } 111 | 112 | class AutoRotatingCarousel extends Component { 113 | state = { 114 | slideIndex: 0 115 | } 116 | 117 | handleContentClick = (e) => e.stopPropagation() || e.preventDefault() 118 | 119 | handleChange = (slideIndex) => { 120 | this.setState({ 121 | slideIndex 122 | }, this.onChange(slideIndex)) 123 | } 124 | 125 | decreaseIndex () { 126 | const slideIndex = this.state.slideIndex - 1 127 | this.setState({ 128 | slideIndex 129 | }, this.onChange(slideIndex)) 130 | } 131 | 132 | increaseIndex () { 133 | const slideIndex = this.state.slideIndex + 1 134 | this.setState({ 135 | slideIndex 136 | }, this.onChange(slideIndex)) 137 | } 138 | 139 | onChange (slideIndex) { 140 | if (this.props.onChange) { 141 | this.props.onChange(modulo(slideIndex, this.props.children.length)) 142 | } 143 | } 144 | 145 | render () { 146 | const { 147 | autoplay, 148 | ButtonProps, 149 | children, 150 | classes, 151 | containerStyle, 152 | hideArrows, 153 | interval, 154 | label, 155 | landscape: landscapeProp, 156 | mobile, 157 | ModalProps, 158 | open, 159 | onClose, 160 | onStart 161 | } = this.props 162 | const landscape = mobile && landscapeProp 163 | const transitionDuration = { enter: duration.enteringScreen, exit: duration.leavingScreen } 164 | const hasMultipleChildren = children.length != null 165 | 166 | const carousel = ( 167 | 176 | { 177 | React.Children.map(children, c => React.cloneElement(c, { 178 | mobile, 179 | landscape 180 | })) 181 | } 182 | 183 | ) 184 | 185 | return ( 186 | 196 | 201 |
207 | 210 | {carousel} 211 | 212 |
213 |
219 | {label && } 226 | { 227 | hasMultipleChildren && 228 | 237 | } 238 |
239 |
240 | {!mobile && !hideArrows && hasMultipleChildren && ( 241 |
242 | this.decreaseIndex()} 245 | > 246 | 247 | 248 | this.increaseIndex()} 251 | > 252 | 253 | 254 |
255 | )} 256 |
257 |
258 |
259 | ) 260 | } 261 | } 262 | 263 | AutoRotatingCarousel.defaultProps = { 264 | autoplay: true, 265 | interval: 3000, 266 | mobile: false, 267 | open: false, 268 | hideArrows: false 269 | } 270 | 271 | AutoRotatingCarousel.propTypes = { 272 | /** If `false`, the auto play behavior is disabled. */ 273 | autoplay: PropTypes.bool, 274 | /** Properties applied to the [Button](https://material-ui.com/api/button/) element. */ 275 | ButtonProps: PropTypes.object, 276 | /** Object for customizing the CSS classes. */ 277 | classes: PropTypes.object.isRequired, 278 | /** Override the inline-styles of the carousel container. */ 279 | containerStyle: PropTypes.object, 280 | /** Delay between auto play transitions (in ms). */ 281 | interval: PropTypes.number, 282 | /** Button text. If not supplied, the button will be hidden. */ 283 | label: PropTypes.string, 284 | /** If `true`, slide will adjust content for wide mobile screens. */ 285 | landscape: PropTypes.bool, 286 | /** If `true`, the screen width and height is filled. */ 287 | mobile: PropTypes.bool, 288 | /** Properties applied to the [Modal](https://material-ui.com/api/modal/) element. */ 289 | ModalProps: PropTypes.object, 290 | /** Fired when the index changed. Returns current index. */ 291 | onChange: PropTypes.func, 292 | /** Fired when the gray background of the popup is pressed when it is open. */ 293 | onClose: PropTypes.func, 294 | /** Fired when the user clicks the getting started button. */ 295 | onStart: PropTypes.func, 296 | /** Controls whether the AutoRotatingCarousel is opened or not. */ 297 | open: PropTypes.bool, 298 | /** If `true`, the left and right arrows are hidden in the desktop version. */ 299 | hideArrows: PropTypes.bool 300 | } 301 | 302 | export default withStyles(styles)(AutoRotatingCarousel) 303 | -------------------------------------------------------------------------------- /src/AutoRotatingCarousel.md: -------------------------------------------------------------------------------- 1 | ### Desktop mode 2 | 3 | ``` 4 | const Slide = require('./Slide').default; 5 | const { red, blue, green } = require('@material-ui/core/colors'); 6 | const Button = require('@material-ui/core/Button').default; 7 | 8 | const [open, setOpen] = React.useState(false); 9 | 10 |
11 | 12 | setOpen(false)} 16 | onStart={() => setOpen(false)} 17 | style={{ position: 'absolute' }} 18 | > 19 | } 21 | mediaBackgroundStyle={{ backgroundColor: red[400] }} 22 | style={{ backgroundColor: red[600] }} 23 | title='This is a very cool feature' 24 | subtitle='Just using this will blow your mind.' 25 | /> 26 | } 28 | mediaBackgroundStyle={{ backgroundColor: blue[400] }} 29 | style={{ backgroundColor: blue[600] }} 30 | title='Ever wanted to be popular?' 31 | subtitle='Well just mix two colors and your are good to go!' 32 | /> 33 | } 35 | mediaBackgroundStyle={{ backgroundColor: green[400] }} 36 | style={{ backgroundColor: green[600] }} 37 | title='May the force be with you' 38 | subtitle='The Force is a metaphysical and ubiquitous power in the Star Wars fictional universe.' 39 | /> 40 | 41 |
42 | ``` 43 | 44 | ### Mobile mode (no autoplay) 45 | 46 | ``` 47 | const Slide = require('./Slide').default; 48 | const { red, blue, green } = require('@material-ui/core/colors'); 49 | const Button = require('@material-ui/core/Button').default; 50 | 51 | const [open, setOpen] = React.useState(false); 52 | 53 |
54 | 55 | setOpen(false)} 59 | onStart={() => setOpen(false)} 60 | mobile 61 | autoplay={false} 62 | style={{ position: 'absolute' }} 63 | > 64 | } 66 | mediaBackgroundStyle={{ backgroundColor: red[400] }} 67 | style={{ backgroundColor: red[600] }} 68 | title='1 This is a very cool feature' 69 | subtitle='Just using this will blow your mind.' 70 | /> 71 | } 73 | mediaBackgroundStyle={{ backgroundColor: blue[400] }} 74 | style={{ backgroundColor: blue[600] }} 75 | title='2 Ever wanted to be popular?' 76 | subtitle='Well just mix two colors and your are good to go!' 77 | /> 78 | } 80 | mediaBackgroundStyle={{ backgroundColor: green[400] }} 81 | style={{ backgroundColor: green[600] }} 82 | title='3 May the force be with you' 83 | subtitle='The Force is a metaphysical and ubiquitous power in the Star Wars fictional universe.' 84 | /> 85 | } 87 | mediaBackgroundStyle={{ backgroundColor: green[400] }} 88 | style={{ backgroundColor: green[600] }} 89 | title='4 May the force be with you' 90 | subtitle='The Force is a metaphysical and ubiquitous power in the Star Wars fictional universe.' 91 | /> 92 | } 94 | mediaBackgroundStyle={{ backgroundColor: green[400] }} 95 | style={{ backgroundColor: green[600] }} 96 | title='5 May the force be with you' 97 | subtitle='The Force is a metaphysical and ubiquitous power in the Star Wars fictional universe.' 98 | /> 99 | } 101 | mediaBackgroundStyle={{ backgroundColor: green[400] }} 102 | style={{ backgroundColor: green[600] }} 103 | title='6 May the force be with you' 104 | subtitle='The Force is a metaphysical and ubiquitous power in the Star Wars fictional universe.' 105 | /> 106 | 107 |
108 | ``` 109 | -------------------------------------------------------------------------------- /src/Slide.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import Typography from '@material-ui/core/Typography' 4 | import blue from '@material-ui/core/colors/blue' 5 | import withStyles from '@material-ui/core/styles/withStyles' 6 | import classNames from 'classnames' 7 | 8 | const styles = { 9 | root: { 10 | backgroundColor: blue[500], 11 | height: '100%' 12 | }, 13 | rootMobileLandscape: { 14 | width: '100%', 15 | display: 'flex', 16 | flexDirection: 'row' 17 | }, 18 | media: { 19 | height: '100%', 20 | display: 'flex', 21 | justifyContent: 'center', 22 | alignItems: 'center', 23 | '& > *': { 24 | maxHeight: '100%' 25 | } 26 | }, 27 | mediaMobile: { 28 | position: 'relative', 29 | top: '50%', 30 | transform: 'translateY(-50%)' 31 | }, 32 | mediaMobileLandscape: {}, 33 | mediaBackground: { 34 | backgroundColor: blue[700], 35 | height: 'calc(100% - 216px)', 36 | textAlign: 'center' 37 | }, 38 | mediaBackgroundMobile: { 39 | height: 'calc(100% - 241px)' 40 | }, 41 | mediaBackgroundMobileLandscape: { 42 | height: '100%', 43 | flex: '1 1', 44 | alignSelf: 'stretch' 45 | }, 46 | text: { 47 | textAlign: 'center', 48 | maxWidth: '80%', 49 | margin: '0 auto', 50 | paddingTop: 32 51 | }, 52 | textMobile: { 53 | paddingTop: 30, 54 | '& $title': { 55 | marginBottom: 8 56 | } 57 | }, 58 | textMobileLandscape: { 59 | minWidth: 300, 60 | maxWidth: 'calc(50% - 48px)', 61 | padding: '24px 24px 128px', 62 | flex: '0 1', 63 | alignSelf: 'center', 64 | textAlign: 'left', 65 | margin: 0 66 | }, 67 | title: { 68 | fontSize: '24px', 69 | fontWeight: 700, 70 | lineHeight: '32px', 71 | marginBottom: 12, 72 | textOverflow: 'ellipsis', 73 | whiteSpace: 'nowrap', 74 | overflow: 'hidden', 75 | color: '#fff' 76 | }, 77 | subtitle: { 78 | fontSize: '15px', 79 | fontWeight: 400, 80 | lineHeight: '18px', 81 | margin: 0, 82 | color: '#fff' 83 | } 84 | } 85 | 86 | function Slide (props) { 87 | const { 88 | classes, 89 | media, 90 | mediaBackgroundStyle, 91 | subtitle, 92 | title, 93 | mobile, 94 | landscape, 95 | ...other 96 | } = props 97 | 98 | const mobileLandscape = mobile && landscape 99 | 100 | return ( 101 |
108 |
115 |
119 | {media} 120 |
121 |
122 |
128 | 129 | {title} 130 | 131 | 132 | {subtitle} 133 | 134 |
135 |
136 | ) 137 | } 138 | 139 | Slide.propTypes = { 140 | /** 141 | * Useful to extend the style applied to components. 142 | */ 143 | classes: PropTypes.object.isRequired, 144 | /** 145 | * Object to display in the upper half. 146 | */ 147 | media: PropTypes.node.isRequired, 148 | /** 149 | * Override the inline-styles of the media container. 150 | */ 151 | mediaBackgroundStyle: PropTypes.object, 152 | /** 153 | * Subtitle of the slide. 154 | */ 155 | subtitle: PropTypes.string.isRequired, 156 | /** 157 | * Title of the slide. 158 | */ 159 | title: PropTypes.string.isRequired, 160 | /** 161 | * If `true`, the screen width and height is filled. 162 | * @ignore 163 | */ 164 | mobile: PropTypes.bool, 165 | /** 166 | * If `true`, slide will adjust content for wide mobile screens. 167 | * @ignore 168 | */ 169 | landscape: PropTypes.bool 170 | } 171 | 172 | export default withStyles(styles)(Slide) 173 | -------------------------------------------------------------------------------- /src/Slide.md: -------------------------------------------------------------------------------- 1 | The `Slide` supports landscape and portrait mode, which will be selected automatically depending to the `landscape` prop of the `AutoRotatingCarousel` that contains it. 2 | 3 | ### Portrait mode 4 | ``` 5 | const { red } = require('@material-ui/core/colors'); 6 | const { withStyles } = require('@material-ui/core/styles'); 7 | 8 | const styles = { 9 | root: { 10 | backgroundColor: red[600], 11 | height: 500, 12 | width: 400 13 | }, 14 | media: { 15 | backgroundColor: red[400] 16 | } 17 | } 18 | 19 | const StyledSlide = withStyles(styles)(Slide); 20 | 21 | } 23 | title='This is a very cool feature' 24 | subtitle='Just using this will blow your mind.' 25 | /> 26 | ``` 27 | 28 | ### Landscape mode 29 | ``` 30 | const { red } = require('@material-ui/core/colors'); 31 | const { withStyles } = require('@material-ui/core/styles'); 32 | 33 | const styles = { 34 | root: { 35 | backgroundColor: red[600], 36 | height: 400, 37 | width: 800 38 | }, 39 | media: { 40 | backgroundColor: red[400] 41 | } 42 | } 43 | 44 | const StyledSlide = withStyles(styles)(Slide); 45 | 46 | } 48 | title='This is a very cool feature' 49 | subtitle='Just using this will blow your mind.' 50 | mobile 51 | landscape 52 | /> 53 | ``` 54 | -------------------------------------------------------------------------------- /src/SwipableCarouselView.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import autoPlay from 'react-swipeable-views-utils/lib/autoPlay' 3 | import virtualize from 'react-swipeable-views-utils/lib/virtualize' 4 | import bindKeyboard from 'react-swipeable-views-utils/lib/bindKeyboard' 5 | import SwipeableViews from 'react-swipeable-views' 6 | import { modulo } from './util' 7 | 8 | const VirtualizeSwipeViews = bindKeyboard(virtualize(SwipeableViews)) 9 | const VirtualizeAutoPlaySwipeViews = autoPlay(VirtualizeSwipeViews) 10 | 11 | const carouselSlideRenderer = (children) => 12 | ({index, key}) => React.cloneElement(children[modulo(index, children.length)], {key}) 13 | 14 | export default function Carousel ({children, autoplay, ...other}) { 15 | const slideRenderer = carouselSlideRenderer(children) 16 | return autoplay ? ( 17 | 21 | ) : ( 22 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as AutoRotatingCarousel } from './AutoRotatingCarousel' 2 | export { default as Slide } from './Slide' 3 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | // modulo that supports negative numbers (so that e.g. -5 % 4 = 3) 2 | export const modulo = (a, n) => ((a % n) + n) % n 3 | -------------------------------------------------------------------------------- /styleguide.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | skipComponentsWithoutExample: true, 5 | components: 'src/**/[A-Z]*.js', 6 | webpackConfig: { 7 | resolve: { 8 | alias: { 9 | 'rsg-components/Wrapper': path.join(__dirname, 'styleguide', 'Wrapper') 10 | } 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?$/, 16 | exclude: /node_modules/, 17 | loader: 'babel-loader' 18 | } 19 | ] 20 | } 21 | }, 22 | getComponentPathLine: (componentPath) => { 23 | const name = path.basename(componentPath, '.js') 24 | return `import { ${name} } from 'material-auto-rotating-carousel';` 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /styleguide/Wrapper.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class Wrapper extends Component { 4 | render () { 5 | return ( 6 |
7 | {this.props.children} 8 |
9 | ) 10 | } 11 | } 12 | --------------------------------------------------------------------------------