Repository: react-materialize/react-materialize
Pull request #649 (2018-09-22 14:04:28)

3.0.0-Carousel
# Description

This Pull Request is for #587.

Dropping support of `jQuery`.

Added two new options as per materialize-css documentation: 

- numVisible
- onCycleTo

Added an handy prop `centerImages` to make each image centered in the slider using `valign-wrapper` CSS helper.

## Type of change

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

# How Has This Been Tested?

`npm test` and in a side project.

# Checklist:

- [x] I have commented my code, particularly in hard-to-understand areas
- [x] My changes generate no new warnings
- [x] I have not generated a new package version. (the maintainers will handle that)



Patch:
diff --git a/src/Carousel.js b/src/Carousel.js
index 69dbb6c..ba65f68 100644
--- a/src/Carousel.js
+++ b/src/Carousel.js
@@ -12,15 +12,23 @@ class Carousel extends React.Component {
   componentDidMount() {
     const { options = {} } = this.props;
 
-    if (typeof $ !== 'undefined') {
-      $(this._carousel).carousel(options);
+    this.instance = M.Carousel.init(this._carousel, options);
+  }
+
+  componentWillUnmount() {
+    if (this.instance) {
+      this.instance.destroy();
     }
   }
 
-  renderItems(child, idx) {
+  renderItems(child, centerImages) {
     if (typeof child === 'string') {
       return (
-        <a className="carousel-item">
+        <a
+          className={cx('carousel-item', {
+            'valign-wrapper': centerImages
+          })}
+        >
           <img src={child} />
         </a>
       );
@@ -43,6 +51,7 @@ class Carousel extends React.Component {
       className,
       carouselId,
       images,
+      centerImages,
       options = {}
     } = this.props;
     const elemsToRender = children || images || [];
@@ -61,7 +70,9 @@ class Carousel extends React.Component {
           )}
         >
           {this.renderFixedItem()}
-          {React.Children.map(elemsToRender, this.renderItems)}
+          {React.Children.map(elemsToRender, child =>
+            this.renderItems(child, centerImages)
+          )}
         </div>
       )
     );
@@ -78,6 +89,10 @@ Carousel.propTypes = {
   */
   images: PropTypes.arrayOf(PropTypes.string),
   /*
+  * Makes the images centered inside the carousel using '.valign-wrapper' CSS helper
+  */
+  centerImages: PropTypes.bool,
+  /*
   * Fixed element on slider
   */
   fixedItem: PropTypes.node,
@@ -111,7 +126,11 @@ Carousel.propTypes = {
     */
     padding: PropTypes.number,
     /*
-    * Make the carousel a full width slider like the second example. (Default: false)
+    * Set the number of visible items. (Default: 5)
+    */
+    numVisible: PropTypes.number,
+    /*
+    * Make the carousel a full width slider. (Default: false)
     */
     fullWidth: PropTypes.bool,
     /*
@@ -121,7 +140,11 @@ Carousel.propTypes = {
     /*
      * Don't wrap around and cycle through items. (Default: false)
     */
-    noWrap: PropTypes.bool
+    noWrap: PropTypes.bool,
+    /*
+    * Callback for when a new slide is cycled to. (Default: null)
+    */
+    onCycleTo: PropTypes.func
   })
 };
 


Test patch:
diff --git a/test/Carousel.spec.js b/test/Carousel.spec.js
index 2d250d5..49d0b0f 100644
--- a/test/Carousel.spec.js
+++ b/test/Carousel.spec.js
@@ -1,16 +1,10 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import Carousel from '../src/Carousel';
-import mocker from './helper/mocker';
+import mocker from './helper/new-mocker';
 
 describe('<Carousel />', () => {
   let wrapper;
-  const carouselMock = jest.fn();
-  const restore = mocker('carousel', carouselMock);
-
-  afterAll(() => {
-    restore();
-  });
 
   const images = [
     'https://lorempixel.com/250/250/nature/1',
@@ -52,17 +46,41 @@ describe('<Carousel />', () => {
     expect(wrapper).toMatchSnapshot();
   });
 
-  test('handles full width sliders', () => {
-    wrapper = shallow(
-      <Carousel images={images} options={{ fullWidth: true }} />
-    );
-    expect(wrapper).toMatchSnapshot();
-    expect(carouselMock).toHaveBeenCalledWith({ fullWidth: true });
-  });
+  describe('initialises', () => {
+    const carouselInitMock = jest.fn();
+    const carouselInstanceDestroyMock = jest.fn();
+    const carouselMock = {
+      init: (el, options) => {
+        carouselInitMock(options);
+        return {
+          destroy: carouselInstanceDestroyMock
+        };
+      }
+    };
+
+    const restore = mocker('Carousel', carouselMock);
+
+    beforeEach(() => {
+      carouselInitMock.mockClear();
+      carouselInstanceDestroyMock.mockClear();
+    });
+
+    afterAll(() => {
+      restore();
+    });
+
+    test('handles full width sliders', () => {
+      wrapper = shallow(
+        <Carousel images={images} options={{ fullWidth: true }} />
+      );
+      expect(wrapper).toMatchSnapshot();
+      expect(carouselInitMock).toHaveBeenCalledWith({ fullWidth: true });
+    });
 
-  test('more options', () => {
-    const options = { padding: 12, fullWidth: true, indicators: false };
-    wrapper = shallow(<Carousel images={images} options={options} />);
-    expect(carouselMock).toHaveBeenCalledWith(options);
+    test('more options', () => {
+      const options = { padding: 12, fullWidth: true, indicators: false };
+      wrapper = shallow(<Carousel images={images} options={options} />);
+      expect(carouselInitMock).toHaveBeenCalledWith(options);
+    });
   });
 });
diff --git a/test/__snapshots__/Carousel.spec.js.snap b/test/__snapshots__/Carousel.spec.js.snap
index 69b0b4c..43273b6 100644
--- a/test/__snapshots__/Carousel.spec.js.snap
+++ b/test/__snapshots__/Carousel.spec.js.snap
@@ -97,7 +97,7 @@ exports[`<Carousel /> handles content slides 1`] = `
 </div>
 `;
 
-exports[`<Carousel /> handles full width sliders 1`] = `
+exports[`<Carousel /> initialises handles full width sliders 1`] = `
 <div
   className="carousel carousel-slider"
 >