├── .babelrc
├── .eslintrc
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE.md
├── .gitignore
├── .npmignore
├── .prettierrc
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── __tests__
├── SimpleSlider.test.js
├── TestComponents.js
├── afterChange.test.js
├── arrows.js
├── beforeChange.test.js
├── lazyLoad.test.js
├── observations.json
├── regression
│ ├── fix-1813.test.js
│ ├── fix-1874.test.js
│ ├── fix-2315.test.js
│ └── fix-2414.test.js
├── sliderStyles.test.js
├── testUtils.js
└── utils
│ └── filterSettings.test.js
├── docs
├── api.md
├── common.md
├── demos.js
├── docs.css
├── docs.js
├── img
│ └── react-slick
│ │ ├── abstract01.jpg
│ │ ├── abstract02.jpg
│ │ ├── abstract03.jpg
│ │ └── abstract04.jpg
├── index.html
├── index.js
├── routes.js
├── scripts
│ ├── generateExampleConfigs.js
│ └── generateExamples.js
├── single-demo.js
├── slick-theme.css
└── slick.css
├── examples
├── AdaptiveHeight.js
├── AppendDots.js
├── AsNavFor.js
├── AutoPlay.js
├── AutoPlayMethods.js
├── CenterMode.js
├── CustomArrows.js
├── CustomPaging.js
├── CustomSlides.js
├── DynamicSlides.js
├── Fade.js
├── FocusOnSelect.js
├── LazyLoad.js
├── MultipleItems.js
├── MultipleRows.js
├── PauseOnHover.js
├── PreviousNextMethods.js
├── Resizable.js
├── Responsive.js
├── Rtl.js
├── SimpleSlider.js
├── SlickGoTo.js
├── SlideChangeHooks.js
├── SwipeToSlide.js
├── UnevenSetsFinite.js
├── UnevenSetsInfinite.js
├── VariableWidth.js
├── VerticalMode.js
├── VerticalSwipeToSlide.js
├── __tests__
│ ├── CentreMode.test.js
│ ├── Fade.js
│ ├── FocusOnSelect.test.js
│ ├── MultipleItems.test.js
│ ├── SimpleSlider.test.js
│ ├── SlickGoTo.test.js
│ ├── UnevenSets.test.js
│ └── sample.test.js
└── config.js
├── gulpfile.js
├── jest.config.js
├── package.json
├── playwright-ct.config.js
├── playwright-tests
├── features
│ └── responsive
│ │ ├── responsive.spec.tsx
│ │ └── responsive.story.tsx
├── regression
│ └── fix-1930
│ │ ├── fix-1930.spec.tsx
│ │ └── fix-1930.story.tsx
└── sample
│ ├── sample.spec.tsx
│ └── sample.story.tsx
├── playwright
├── index.html
└── index.jsx
├── src
├── arrows.js
├── default-props.js
├── dots.js
├── index.js
├── initial-state.js
├── inner-slider.js
├── slider.js
├── track.js
└── utils
│ └── innerSliderUtils.js
├── test-setup.js
├── test-utils.js
├── webpack.config.dist.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-extra-parens": 0,
4 | "react/jsx-uses-vars": 1,
5 | "strict": 0,
6 | "no-underscore-dangle": 0,
7 | "space-infix-ops": 0,
8 | "no-alert": 0,
9 | "react/prop-types": 0,
10 | "react/no-find-dom-node": 0,
11 | "react/display-name": 0,
12 | "no-console": 0,
13 | "no-prototype-builtins": 0
14 | },
15 | "env": {
16 | "node": true,
17 | "browser": true,
18 | "es6": true,
19 | "jasmine": true
20 | },
21 | "parser": "@babel/eslint-parser",
22 | "parserOptions": {
23 | "requireConfigFile": false
24 | },
25 | "plugins": [
26 | "react",
27 | "import"
28 | ],
29 | "extends": [
30 | "eslint:recommended",
31 | "plugin:import/errors",
32 | "plugin:react/recommended"
33 | ]
34 | }
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: akiran
2 | open_collective: react-slick
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
3 |
4 | ### Guidelines for posting a new issue
5 |
6 | * Please replicate your issue with this [CodeSandBox](https://codesandbox.io/s/ppwkk5l6xx) and provide a link to it along with the issue description
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bower_components
3 | .sass-cache
4 | build
5 | demos/*
6 | demos1
7 | TODO.md
8 | npm-debug.log
9 | lib
10 | *.sublime-*
11 | .idea
12 | dist
13 | yarn.lock
14 | .vscode
15 | exampleslib
16 | examples/scripts/configs.json
17 | jquery.html
18 | docs/fonts/
19 | docs/ajax-loader.gif
20 | package-lock.json
21 | .DS_Store
22 | /test-results/
23 | /playwright-report/
24 | /blob-report/
25 | /playwright/.cache/
26 | src-jsx
27 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | .sass-cache
3 | build
4 | demos
5 | demos1
6 | TODO.md
7 | test
8 | testlib
9 | bower.json
10 | gulpfile.js
11 | karma.conf.js
12 | LICENSE
13 | webpack.config.dist.js
14 | webpack.config.js
15 | ISSUE_TEMPLATE.md
16 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | trailingComma: none
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "stable"
5 |
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [Unreleased](https://github.com/akiran/react-slick/tree/HEAD)
4 |
5 | ## 0.22.0
6 |
7 | **Release Changes**
8 |
9 | - Internal Changes
10 | - converted InnerSlider from createReactClass object to ES6 class
11 | - removed all the mixins, created classMethods and pure utility functions instead
12 | - changed autoplay from setTimeout to setInterval
13 | - added images onload handlers to update dynamically
14 | - added autoplaying state for the betterment of autoplay and pause
15 | - removed usage of assign or Object.assign, using object spreading instead
16 | - implemented effects of touchMove props
17 | - fixed transition in opposite direction in case of continuous scrolling
18 | - added separate onclick event listener for images
19 | - added missing classes `regular` and `slider`
20 | - renamed events
21 | - edgeEvent => onEdge
22 | - init => onInit
23 | - reInit => onReInit
24 | - implemented `pauseOnDotsHover` property
25 | - implemented Progressive LazyLoad property, lazyLoad is now ondemand/progressive
26 | - implemented lazyloadError event
27 | - implemented useTransform property
28 | - implemented pauseOnFocus property
29 | - added resize observer to update on slider resize
30 |
31 | - Bug Fixes
32 | - dynamic track updates on image load
33 | - fixed slickPause and autoPlay issues (paused slider would resume autoplay sometime)
34 | - fixed trackStyle update on window resize
35 | - fixed NodeList forEach problem for chrome 51 or below
36 | - fixed bugs due to uncleared callback timers
37 | - fixed update issues on just slider resize
38 |
39 |
40 | ## 0.21.0
41 |
42 | **Release Changes**
43 |
44 | - Fixed issues
45 | - dataset undefined error in case of swipeToSlide but finite slides
46 | - slideWidth issue by transform scale
47 | - variableWidth + finite alignment problems
48 | - wrapper direction rtl issues
49 | - added onload update handler for images
50 | - fixed breaking of animation on setState
51 |
52 | - Mixins to Pure Functions
53 | - getWidth, getHeight
54 | - swipeDirection
55 | - initialize, update
56 |
57 | - Other Changes
58 | - removed sass, using pure CSS instead
59 | - enforced dir='ltr' in the slider, so dir='rtl' in wrapper doesn't break the slider
60 | - corrected up/down direction conventions
61 | - added more tests along with snapshots
62 |
63 | ## 0.20.0
64 |
65 | **Release Changes**
66 |
67 | - handled responsive breakpoint collision
68 | - renamed autoPlayTimer to autoplayTimer and removed it from state
69 | - changed es5 module.exports with es6 export default in src/index
70 | - implemented slider syncing with asNavFor prop
71 | - made all the slides untabbable
72 | - implemented getSlick method as in slick
73 | - implemented slickGetOption method
74 | - implemented lazyLoaded event
75 | - implemented reInit event
76 | - implemented onSwipe event and documented edgeEvent
77 |
78 |
79 | ## 0.19.0
80 |
81 | **Release Changes**
82 |
83 | Following are the changes to be mentioned:
84 |
85 | - fixed slideWidth calculation approximation
86 | - fixed unusual scrolls in focusOnSelect mode
87 | - added appendDots method for customization of dots
88 | - modified logic for handling odd/even cases where there were unusual scrolls in opposite direction
89 | - implemented unslick feature properly
90 | - fixed variableWidth issues like blank spaces at edges, improper alignment
91 | - handling focus loss in case of fade=true
92 | - responsive lazyloading bug fixed
93 | - increased verticalswiping resistance from 4 to 10
94 |
95 |
96 | ## 0.18.0
97 |
98 | **Major Changes:**
99 |
100 | - `centerPadding` prop now accepts % value as well
101 | - Fixed dots count in certain cases, where it was wrong
102 | - Fixed fade property mess-up on click
103 | - Fixed invisibility issue when fade & vertical are true
104 | - Modified logic for updating lazyLoadedList, earlier there were some whitespaces at ends, now they're gone
105 | - Fixed getTrackLeft issue for slideCount=1
106 |
107 |
108 | ## 0.17.1
109 |
110 | **Major Changes**
111 |
112 | * Enforced some settings in specific configurations like:
113 | - `slidesToScroll = 1` *when fade is true*
114 | - `slidesToScroll = 1` *when centerMode is true*
115 | - `slidesToShow = 1` *when fade is true*
116 |
117 | * Changed the number of clones (preclones and postclones), that fixed couple of issues like blank spaces after last slide and/or before first slide which occurred in several cases.
118 |
119 |
120 | **Minor Changes**
121 |
122 | - Rich amount of tests and test-utilities added
123 | - Additional documentation comments added
124 | - Refactored small snippets for betterment
125 | - Fixed several lazyload and centerMode bugs
126 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 |
3 | ## Introduction
4 |
5 | First, thank you for considering contributing to react-slick! It's people like you that make the open source community such a great community! 😊
6 |
7 | We welcome any type of contribution, not only code. You can help with
8 | - **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
9 | - **Marketing**: writing blog posts, howto's, printing stickers, ...
10 | - **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
11 | - **Code**: take a look at the [open issues](https://github.com/akiran/react-slick/issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them. To get started you can also [sign up to triage react-slick issues on CodeTriage](https://www.codetriage.com/akiran/react-slick).
12 | - **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-slick).
13 |
14 | ## Your First Contribution
15 |
16 | Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
17 |
18 | ## Submitting code
19 |
20 | Any code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests.
21 |
22 | ## Code review process
23 |
24 | The bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge.
25 | It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?
26 |
27 | ## Financial contributions
28 |
29 | We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-slick).
30 | Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
31 |
32 | ## Questions
33 |
34 | If you have any questions, create an [issue](https://github.com/akiran/react-slick/issues) (protip: do a quick search first to see if someone else didn't ask the same question before!).
35 | You can also reach us at hello@react-slick.opencollective.com.
36 |
37 | ## Credits
38 |
39 | ### Contributors
40 |
41 | Thank you to all the people who have already contributed to react-slick!
42 |
43 |
44 |
45 | ### Backers
46 |
47 | Thank you to all our backers! [[Become a backer](https://opencollective.com/react-slick#backer)]
48 |
49 |
50 |
51 |
52 | ### Sponsors
53 |
54 | Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/react-slick#sponsor))
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Kiran Abburi
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 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### react-slick
2 |
3 | [](#backers) [](#sponsors)
4 |
5 | ##### Carousel component built with React. It is a react port of [slick carousel](http://kenwheeler.github.io/slick/)
6 |
7 | ## [Documentation](http://react-slick.neostack.com)
8 |
9 | ### Installation
10 |
11 | **npm**
12 |
13 | ```bash
14 | npm install react-slick --save
15 | ```
16 |
17 | **yarn**
18 |
19 | ```bash
20 | yarn add react-slick
21 | ```
22 |
23 | **Also install slick-carousel for css and font**
24 |
25 | ```bash
26 | npm install slick-carousel
27 |
28 | // Import css files
29 | import "slick-carousel/slick/slick.css";
30 | import "slick-carousel/slick/slick-theme.css";
31 | ```
32 |
33 | or add cdn link in your html
34 |
35 | ```html
36 |
42 |
47 | ```
48 |
49 | ### [PlayGround](https://stackblitz.com/edit/vitejs-vite-ownrun?file=src%2FImageSlider.jsx)
50 |
51 | ### Example
52 |
53 | ```js
54 | import React from "react";
55 | import Slider from "react-slick";
56 |
57 | export default function SimpleSlider() {
58 | var settings = {
59 | dots: true,
60 | infinite: true,
61 | speed: 500,
62 | slidesToShow: 1,
63 | slidesToScroll: 1
64 | };
65 | return (
66 |
67 |
68 |
1
69 |
70 |
71 |
2
72 |
73 |
74 |
3
75 |
76 |
77 |
4
78 |
79 |
80 |
5
81 |
82 |
83 |
6
84 |
85 |
86 | );
87 | }
88 | ```
89 |
90 | ### Props
91 |
92 | For all available props, go [here](https://react-slick.neostack.com/docs/api/).
93 |
94 | ### Methods
95 |
96 | For all available methods, go [here](https://react-slick.neostack.com/docs/api#methods)
97 |
98 | ### Development
99 |
100 | Want to run demos locally
101 |
102 | ```bash
103 | git clone https://github.com/akiran/react-slick
104 | cd react-slick
105 | npm install
106 | npm start
107 | open http://localhost:8080
108 | ```
109 |
110 | ## Community
111 |
112 | Join our [discord channel](https://discord.gg/z7stRE4Cyb) to discuss react-slick bugs and ask for help
113 |
114 | ## Contributing
115 |
116 | Please see the [contributing guidelines](./CONTRIBUTING.md)
117 |
--------------------------------------------------------------------------------
/__tests__/SimpleSlider.test.js:
--------------------------------------------------------------------------------
1 | // includes tests of
2 | // SimpleSlider, MultipleItems
3 | import { testSlider } from "./testUtils";
4 |
5 | describe("SimpleSlider with combinations of possibilities", function() {
6 | // try around several possibilities
7 | let _noOfSlides = [2, 5, 12];
8 | let _slidesToShow = [2, 5, 10];
9 | let _slidesToScroll = [1, 2, 3, 10];
10 | if (true) {
11 | // for switching real quick to lesser/easier tests for simplicity
12 | _noOfSlides = [5];
13 | _slidesToShow = [2];
14 | _slidesToScroll = [1, 2];
15 | }
16 |
17 | for (let noOfSlides of _noOfSlides) {
18 | for (let slidesToShow of _slidesToShow) {
19 | for (let slidesToScroll of _slidesToScroll) {
20 | // following restrictions may not be 100% correct, and there may be more restrictions
21 | if (slidesToShow > noOfSlides || slidesToScroll > slidesToShow) {
22 | continue;
23 | }
24 | if (noOfSlides === slidesToShow) {
25 | // temporary, jquery slick disables arrows in this case, so the tests fail
26 | continue;
27 | }
28 | if (slidesToShow === slidesToScroll) {
29 | // temporary, active-class is not being assigned properly, so tests fail
30 | continue;
31 | }
32 | const settings1 = {
33 | infinite: true,
34 | speed: 0,
35 | noOfSlides,
36 | slidesToShow,
37 | slidesToScroll,
38 | useCSS: false
39 | };
40 | test(`Test with settings => noOfSlides: ${noOfSlides}, slidesToShow: ${slidesToShow}, slidesToScroll: ${slidesToScroll}`, function() {
41 | testSlider(settings1);
42 | });
43 | }
44 | }
45 | }
46 | });
47 |
--------------------------------------------------------------------------------
/__tests__/TestComponents.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "../src/index";
3 |
4 | export function GenericSliderComponent({ slidesCount, settings }) {
5 | const slides = [...Array(slidesCount).keys()].map(item => (
6 | {item + 1}
7 | ));
8 | return {slides} ;
9 | }
10 |
11 | test("fake test", () => {
12 | expect(1).toBe(1);
13 | });
14 |
--------------------------------------------------------------------------------
/__tests__/afterChange.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, fireEvent } from "@testing-library/react";
3 | import Slider from "../src/index";
4 | import {
5 | getActiveSlide,
6 | clickNext,
7 | clickPrevious,
8 | getCurrentSlide
9 | } from "../test-utils";
10 |
11 | class SliderWithAfterChange extends React.Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | currentSlide: null
16 | };
17 | this.afterChange = this.afterChange.bind(this);
18 | }
19 |
20 | afterChange(currentSlide) {
21 | console.log(currentSlide, "afterChange");
22 | this.setState({
23 | currentSlide
24 | });
25 | }
26 | render() {
27 | return (
28 |
29 | slide1
30 | slide2
31 | slide3
32 | slide4
33 |
34 | );
35 | }
36 | }
37 |
38 | describe("After change Slider", function() {
39 | it("should render", function() {
40 | const { container } = render( );
41 | clickNext(container);
42 | setTimeout(() => {
43 | expect(getActiveSlide(container).textContent).toEqual("slide2");
44 | }, 1000);
45 | clickNext(container);
46 | setTimeout(() => {
47 | expect(getActiveSlide(container).textContent).toEqual("slide3");
48 | }, 1000);
49 | clickPrevious(container);
50 | setTimeout(() => {
51 | expect(getActiveSlide(container).textContent).toEqual("slide2");
52 | }, 1000);
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/__tests__/arrows.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Arrow component tests
3 | */
4 |
5 | sinon.stub(console, "error");
6 |
7 | import { render } from "@testing-library/react";
8 | import React from "react";
9 | import sinon from "sinon";
10 |
11 | import { NextArrow, PrevArrow } from "../src/arrows";
12 |
13 | function CustomArrow(props) {
14 | return (
15 |
20 | );
21 | }
22 |
23 | describe("Previous arrows", () => {
24 | it("should render arrow", () => {
25 | const { container } = render( );
26 | expect(Array.from(container.getElementsByTagName("button"))).toHaveLength(
27 | 1
28 | );
29 | });
30 |
31 | it("should not result in errors", () => {
32 | render( );
33 |
34 | expect(console.error.called).toBe(false);
35 | });
36 |
37 | // it('should pass slide data to custom arrow', () => {
38 | // let elAttributes;
39 | // let arr =
40 |
41 | // const {container}= render( );
42 |
43 | // elAttributes =x=> container.querySelectorAll('.sample')[0].getAttribute(x);
44 | // expect(elAttributes('data-currentslide')).toBe('3');
45 | // expect(elAttributes('data-slidecount')).toBe('5');
46 | // });
47 | });
48 |
49 | describe("Next arrows", () => {
50 | it("should render arrow", () => {
51 | const { container } = render( );
52 | expect(Array.from(container.getElementsByTagName("button"))).toHaveLength(
53 | 1
54 | );
55 | });
56 |
57 | // it('should not result in errors', () => {
58 | // render( );
59 |
60 | // expect(console.error.called).toBe(false);
61 | // });
62 |
63 | // it('should pass slide data to custom arrow', () => {
64 | // let elAttributes;
65 | // let arr =
66 |
67 | // const {container} = render( );
68 |
69 | // elAttributes =(x)=> container.querySelectorAll('.sample')[0].getAttribute(x);
70 | // expect(elAttributes('data-currentslide')).toBe('6');
71 | // expect(elAttributes('data-slidecount')).toBe('9');
72 | // });
73 | });
74 |
--------------------------------------------------------------------------------
/__tests__/beforeChange.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render } from "@testing-library/react";
3 | import Slider from "../src/index";
4 | import {
5 | getActiveSlide,
6 | clickNext,
7 | clickPrevious,
8 | getCurrentSlide
9 | } from "../test-utils";
10 |
11 | class SliderWithBeforeChange extends React.Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | currentSlide: null,
16 | nextSlide: null
17 | };
18 | this.beforeChange = this.beforeChange.bind(this);
19 | }
20 | beforeChange(currentSlide, nextSlide) {
21 | this.setState({
22 | currentSlide,
23 | nextSlide
24 | });
25 | }
26 | render() {
27 | return (
28 |
29 | slide1
30 | slide2
31 | slide3
32 | slide4
33 |
34 | );
35 | }
36 | }
37 |
38 | describe("Slider", function() {
39 | it("should render", function() {
40 | const { container } = render( );
41 | clickNext(container);
42 | expect(getActiveSlide(container).textContent).toEqual("slide2");
43 | clickNext(container);
44 | expect(getActiveSlide(container).textContent).toEqual("slide3");
45 | clickPrevious(container);
46 | expect(getActiveSlide(container).textContent).toEqual("slide2");
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/__tests__/lazyLoad.test.js:
--------------------------------------------------------------------------------
1 | import { render } from "@testing-library/react";
2 | import assign from "object-assign";
3 | import { getRequiredLazySlides } from "../src/utils/innerSliderUtils";
4 | import {
5 | createInnerSliderWrapper,
6 | clickNext,
7 | clickPrev,
8 | tryAllConfigs
9 | } from "./testUtils";
10 |
11 | // const testSettings = settings => {
12 | // let {container} = createInnerSliderWrapper(settings);
13 | // for (let click = 0; click < settings.noOfSlides + 2; click++) {
14 | // let lazyLoadedList = slider.state().lazyLoadedList;
15 | // let expectedLazyLoadedList = getRequiredLazySlides(
16 | // assign({}, slider.props(), slider.state())
17 | // );
18 | // expectedLazyLoadedList.forEach(slide => {
19 | // expect(lazyLoadedList.indexOf(slide) >= 0).toEqual(true);
20 | // });
21 | // clickNext(slider);
22 | // }
23 |
24 | // slider = createInnerSliderWrapper(settings);
25 | // for (let click = 0; click < settings.noOfSlides + 2; click++) {
26 | // let lazyLoadedList = slider.state().lazyLoadedList;
27 | // let expectedLazyLoadedList = getRequiredLazySlides(
28 | // assign({}, slider.props(), slider.state())
29 | // );
30 | // expectedLazyLoadedList.forEach(slide => {
31 | // expect(lazyLoadedList.indexOf(slide) >= 0).toEqual(true);
32 | // });
33 | // clickPrev(slider);
34 | // }
35 |
36 | // slider = createInnerSliderWrapper(settings);
37 | // for (let click = 0; click < settings.noOfSlides + 2; click++) {
38 | // let lazyLoadedList = slider.state().lazyLoadedList;
39 | // lazyLoadedList.forEach(slideIndex => {
40 | // expect(
41 | // slider.find(`[data-index=${slideIndex}]`).props().children !== undefined
42 | // ).toBe(true);
43 | // });
44 | // }
45 | // };
46 |
47 | // describe("LazyLoad test", () => {
48 | // let settings = {
49 | // lazyLoad: true,
50 | // useCSS: false,
51 | // speed: 0,
52 | // noOfSlides: [7, 8],
53 | // initialSlide: [0, 5],
54 | // slidesToShow: [1, 3, 4],
55 | // slidesToScroll: [1, 3],
56 | // centerMode: [true, false]
57 | // };
58 | // let settingsList = [];
59 | // tryAllConfigs(settings, settingsList);
60 | // // shuffle the list
61 | // settingsList.sort(() => 0.5 - Math.random());
62 | // settingsList.forEach((settings, index) => {
63 | // if (Math.random() < 0.5) {
64 | // test(`Testing config no. ${index}`, () => testSettings(settings));
65 | // }
66 | // });
67 | // });
68 |
--------------------------------------------------------------------------------
/__tests__/observations.json:
--------------------------------------------------------------------------------
1 | {
2 | "jQueryTest": [
3 | {
4 | "observation": "Clicks on arrows are not working properly",
5 | "possibleCause": "Animation effects are taking effects somehow",
6 | "solutions": [
7 | {
8 | "description": "set useCSS property to false",
9 | "status": "did not work"
10 | },
11 | {
12 | "description": "set speed property to 0",
13 | "status": "worked, now the clicks are working as of now"
14 | }
15 | ]
16 | },
17 | {
18 | "observation": "arrows are disabled when slidesToShow are equal to noOfSlides",
19 | "status": "causes few tests to fail"
20 | },
21 | {
22 | "observation": "tests are very slow",
23 | "possibleCause": "synchronous click event simulation and slow DOM api",
24 | "status": "not tried yet"
25 | }
26 | ],
27 | "reactTest": [
28 | {
29 | "observation": "Clicks on arrows are not working properly",
30 | "possibleCause": "Animation effects are taking effects somehow",
31 | "solutions": [
32 | {
33 | "description": "set useCSS property to false",
34 | "status": "worked, now the clicks are working as of now"
35 | }
36 | ]
37 | }
38 | ],
39 | "misc": [
40 | {
41 | "observation": "In case of reverse scrolling, slick-active class is not being assigned properly.",
42 | "example": {
43 | "settings": {
44 | "noOfSlides": 5,
45 | "slidesToShow": 2,
46 | "slidesToScroll": 2
47 | },
48 | "jqueryBehaviour": "after one prev click, current-slide is 5th and active-class is assigned to slide 4th and 5th while the same are displayed in frame",
49 | "reactBehaviour": "after one prev click, current-slide is 5th and active-class is assigned to slide 5th and 1st(cloned) while 4th and 5th are displayed in frame",
50 | "status": "several tests are failing due to this property"
51 | }
52 | }
53 | ]
54 | }
55 |
--------------------------------------------------------------------------------
/__tests__/regression/fix-1813.test.js:
--------------------------------------------------------------------------------
1 | //Test fix of #1813: In infinite mode, when slidesToShow equal to the length of slides, infinite functionality is not working.
2 | // Reversed the fix for #1813 to match the slick carousel functionality. When slides <= slidesToShow, unslick will be activated
3 |
4 | import React from "react";
5 | import { render, fireEvent } from "@testing-library/react";
6 |
7 | import {
8 | clickNext,
9 | clickPrevious,
10 | getActiveButton,
11 | getActiveSlidesCount,
12 | getActiveSlidesText,
13 | getButtons,
14 | getButtonsLength,
15 | getClonesCount,
16 | getCurrentSlide,
17 | getSlidesCount,
18 | hasArrows,
19 | hasDots
20 | } from "../../test-utils";
21 | import { GenericSliderComponent } from "../TestComponents";
22 |
23 | function MultipleItems() {
24 | const settings = {
25 | dots: true,
26 | infinite: true,
27 | speed: 500,
28 | slidesToShow: 9,
29 | slidesToScroll: 3
30 | };
31 | return ;
32 | }
33 |
34 | describe("Multiple Items with slidesToShow = slides count in infinite mode", function() {
35 | it("should have 9 active slides", function() {
36 | const { container } = render( );
37 | expect(getActiveSlidesCount(container)).toEqual(9);
38 | });
39 | it("should show first 9 slides", function() {
40 | const { container } = render( );
41 | //expect(getActiveButton(container)).toEqual(["1"]);
42 | expect(getActiveSlidesText(container)).toEqual([
43 | "1",
44 | "2",
45 | "3",
46 | "4",
47 | "5",
48 | "6",
49 | "7",
50 | "8",
51 | "9"
52 | ]);
53 | });
54 | it("shouldn't have any arrows", () => {
55 | const { container } = render( );
56 | expect(hasArrows(container)).toEqual(false);
57 | });
58 | it("shouldn't have any dots", () => {
59 | const { container } = render( );
60 | expect(hasDots(container)).toEqual(false);
61 | });
62 | // it("should have 0 dots", function() {
63 | // const { container } = render( );
64 | // expect(getButtonsLength(container)).toEqual(0);
65 | // });
66 | // it("should show slides from 4 when next button is clicked", function() {
67 | // const { container } = render( );
68 | // clickNext(container);
69 | // expect(getActiveButton(container)).toEqual(["2"]);
70 | // expect(getActiveSlidesText(container)).toEqual([
71 | // "4",
72 | // "5",
73 | // "6",
74 | // "7",
75 | // "8",
76 | // "9",
77 | // "1",
78 | // "2",
79 | // "3"
80 | // ]);
81 | // });
82 | // it("should show slides from 7 when previous button is clicked", function() {
83 | // const { container } = render( );
84 | // clickPrevious(container);
85 | // expect(getActiveButton(container)).toEqual(["3"]);
86 | // expect(getActiveSlidesText(container)).toEqual([
87 | // "7",
88 | // "8",
89 | // "9",
90 | // "1",
91 | // "2",
92 | // "3",
93 | // "4",
94 | // "5",
95 | // "6"
96 | // ]);
97 | // });
98 | // it("should show slides first 9 slides when first dot is clicked", function() {
99 | // const { container } = render( );
100 | // fireEvent(
101 | // getButtons(container)[0],
102 | // new MouseEvent("click", {
103 | // bubbles: true,
104 | // cancelable: true
105 | // })
106 | // );
107 | // expect(getActiveButton(container)).toEqual(["1"]);
108 | // expect(getActiveSlidesText(container)).toEqual([
109 | // "1",
110 | // "2",
111 | // "3",
112 | // "4",
113 | // "5",
114 | // "6",
115 | // "7",
116 | // "8",
117 | // "9"
118 | // ]);
119 | // });
120 | // it("should show slides from 4 when middle dot is clicked", function() {
121 | // const { container } = render( );
122 | // fireEvent(
123 | // getButtons(container)[1],
124 | // new MouseEvent("click", {
125 | // bubbles: true,
126 | // cancelable: true
127 | // })
128 | // );
129 | // expect(getActiveButton(container)).toEqual(["2"]);
130 | // expect(getActiveSlidesText(container)).toEqual([
131 | // "4",
132 | // "5",
133 | // "6",
134 | // "7",
135 | // "8",
136 | // "9",
137 | // "1",
138 | // "2",
139 | // "3"
140 | // ]);
141 | // });
142 | // it("should show slides from 7 when last dot is clicked", function() {
143 | // const { container } = render( );
144 | // fireEvent(
145 | // getButtons(container)[2],
146 | // new MouseEvent("click", {
147 | // bubbles: true,
148 | // cancelable: true
149 | // })
150 | // );
151 | // expect(getActiveButton(container)).toEqual(["3"]);
152 | // expect(getActiveSlidesText(container)).toEqual([
153 | // "7",
154 | // "8",
155 | // "9",
156 | // "1",
157 | // "2",
158 | // "3",
159 | // "4",
160 | // "5",
161 | // "6"
162 | // ]);
163 | // });
164 | });
165 |
--------------------------------------------------------------------------------
/__tests__/regression/fix-1874.test.js:
--------------------------------------------------------------------------------
1 | // Test fix of#1874: "slick-current" is always on first slide despite initialSlide != 0
2 |
3 | import React from "react";
4 | import { render } from "@testing-library/react";
5 |
6 | import { getCurrentSlideContent, clickNext } from "../../test-utils";
7 | import { GenericSliderComponent } from "../TestComponents";
8 |
9 | describe("currentSlide test with different initialSlide values", () => {
10 | it("currentSlide is 0 when initialSlide is 0", function() {
11 | const { container } = render( );
12 | expect(getCurrentSlideContent(container)).toEqual("1");
13 | clickNext(container);
14 | expect(getCurrentSlideContent(container)).toEqual("2");
15 | });
16 |
17 | it("currentSlide is 2 when initialSlide is 2", function() {
18 | const { container } = render(
19 |
20 | );
21 | expect(getCurrentSlideContent(container)).toEqual("3");
22 | clickNext(container);
23 | expect(getCurrentSlideContent(container)).toEqual("4");
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/__tests__/regression/fix-2315.test.js:
--------------------------------------------------------------------------------
1 | // Test fix of #2315: Slider crashing after a state change in parent component
2 | import React from "react";
3 | import { render, fireEvent } from "@testing-library/react";
4 |
5 | import { getCurrentSlideContent, getSlidesCount } from "../../test-utils";
6 | import { GenericSliderComponent } from "../TestComponents";
7 |
8 | function TestSlider() {
9 | const [count, setCount] = React.useState();
10 |
11 | return (
12 |
13 | setCount(count + 1)}>
14 | Increment {count}
15 |
16 |
17 |
18 | );
19 | }
20 |
21 | describe("State change in parent component of slider", () => {
22 | it("Slider shoud work afer clicking on Increment button", function() {
23 | const { container } = render( );
24 | fireEvent(
25 | container.getElementsByClassName("increment-button")[0],
26 | new MouseEvent("click", {
27 | bubbles: true,
28 | cancelable: true
29 | })
30 | );
31 | // Throws an error "Maximum update depth exceeded." if the bug exists
32 | expect(getCurrentSlideContent(container)).toEqual("1");
33 | expect(getSlidesCount(container)).toEqual(8);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/__tests__/regression/fix-2414.test.js:
--------------------------------------------------------------------------------
1 | // Test fix of #2414: Extra clones in infinite mode when there is only one slide or unslick is true
2 | import React from "react";
3 | import { render, fireEvent } from "@testing-library/react";
4 |
5 | import {
6 | getCurrentSlideContent,
7 | getSlidesCount,
8 | getActiveSlidesCount,
9 | getClonesCount,
10 | hasArrows,
11 | hasDots
12 | } from "../../test-utils";
13 | import { GenericSliderComponent } from "../TestComponents";
14 |
15 | function SliderWithOneSlide() {
16 | const settings = {
17 | dots: true,
18 | infinite: true
19 | };
20 | return ;
21 | }
22 |
23 | function SliderWithUnslick() {
24 | const settings = {
25 | dots: true,
26 | infinite: true,
27 | unslick: true
28 | };
29 | return ;
30 | }
31 |
32 | describe("Slider with one slide", function() {
33 | it("should have 1 active slide", function() {
34 | const { container } = render( );
35 | expect(getActiveSlidesCount(container)).toEqual(1);
36 | });
37 | it("should not have any clones", function() {
38 | const { container } = render( );
39 | expect(getClonesCount(container)).toEqual(0);
40 | });
41 | it("should no have dots and arrows", function() {
42 | const { container } = render( );
43 | expect(hasArrows(container)).toEqual(false);
44 | expect(hasDots(container)).toEqual(false);
45 | });
46 | });
47 |
48 | describe("Slider with unslick=true", function() {
49 | it("should have one active slide", function() {
50 | const { container } = render( );
51 | expect(getActiveSlidesCount(container)).toEqual(1);
52 | });
53 | it("should not have any clones", function() {
54 | const { container } = render( );
55 | expect(getClonesCount(container)).toEqual(0);
56 | });
57 | it("should no have dots and arrows", function() {
58 | const { container } = render( );
59 | expect(hasArrows(container)).toEqual(false);
60 | expect(hasDots(container)).toEqual(false);
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/__tests__/sliderStyles.test.js:
--------------------------------------------------------------------------------
1 | import assign from "object-assign";
2 | import { getRequiredLazySlides } from "../src/utils/innerSliderUtils";
3 | import {
4 | createInnerSliderWrapper,
5 | clickNext,
6 | clickPrev,
7 | tryAllConfigs,
8 | actualTrackLeft,
9 | testTrackLeft
10 | } from "./testUtils";
11 | import { getTrackLeft } from "../src/utils/innerSliderUtils";
12 |
13 | const testSettings = settings => {
14 | let slider = createInnerSliderWrapper(settings);
15 | for (let click = 0; click < settings.noOfSlides + 2; click++) {
16 | testTrackLeft(slider);
17 | clickNext(slider);
18 | }
19 | slider = createInnerSliderWrapper(settings);
20 | for (let click = 0; click < settings.noOfSlides + 2; click++) {
21 | testTrackLeft(slider);
22 | clickPrev(slider);
23 | }
24 | };
25 |
26 | describe("Slider Styles Tests", () => {
27 | let settings = {
28 | useCSS: false,
29 | speed: 0,
30 | centerMode: [true, false],
31 | noOfSlides: [7, 8],
32 | initialSlide: [0, 5],
33 | slidesToShow: [1, 3, 4]
34 | };
35 | let settingsList = [];
36 | tryAllConfigs(settings, settingsList);
37 | // shuffle the list
38 | settingsList.sort(() => 0.5 - Math.random());
39 | settingsList.forEach((settings, index) => {
40 | // if (Math.random() < 0.5) {
41 | // test(`Testing config no. ${index}`, () => testSettings(settings));
42 | // }
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/__tests__/testUtils.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import $ from "jquery";
3 | import assign from "object-assign";
4 | import { render } from "@testing-library/react";
5 | import Slider from "../src/slider";
6 | import { InnerSlider } from "../src/inner-slider";
7 | import defaultProps from "../src/default-props";
8 | import * as slickCarousel from "slick-carousel"; // defining slick in global environment
9 | import { getTrackLeft } from "../src/utils/innerSliderUtils";
10 | import {
11 | getActiveSlides,
12 | getActiveSlidesCount,
13 | clickNext,
14 | clickPrevious
15 | } from "../test-utils";
16 |
17 | // finds active slide number in the last transition in the forward direction
18 | export function activeSlideInLastTransition(
19 | noOfSlides,
20 | slidesToShow,
21 | slidesToScroll
22 | ) {
23 | let currentSlide = 0;
24 | while (currentSlide < noOfSlides) {
25 | currentSlide += slidesToScroll;
26 | }
27 | return currentSlide - slidesToScroll;
28 | }
29 |
30 | // create jsx-form children for react slider
31 | export function createReactSliderChildren(noOfSlides) {
32 | return Array.from(Array(noOfSlides).keys()).map(i => (
33 |
34 |
{i + 1}
35 |
36 | ));
37 | }
38 |
39 | // create a react-slider with given noOfSlides and other props
40 | // variable widths are ignored for now for simplicity
41 | export function createReactSlider({ noOfSlides, ...props }) {
42 | return {createReactSliderChildren(noOfSlides)} ;
43 | }
44 |
45 | // create a react inner-slider with given noOfSlides and other props
46 | // performs most operations like the ones when mounted inside Slider component
47 | export function createInnerSlider({ noOfSlides, ...settings }) {
48 | if (settings.centerMode) {
49 | settings.slidesToScroll = 1; // always scroll by one when centerMode is enabled
50 | }
51 | settings = assign({}, defaultProps, settings);
52 | const children = React.Children.toArray(
53 | createReactSliderChildren(noOfSlides)
54 | );
55 | return {children} ;
56 | }
57 |
58 | export function createInnerSliderWrapper(settings) {
59 | return render(createInnerSlider(settings)).container;
60 | }
61 |
62 | // creates a dom string, containing children of slick children
63 | export function createJQuerySliderChildren(noOfSlides) {
64 | let children = [];
65 | for (let i = 0; i < noOfSlides; i++) {
66 | children.push(`
${i + 1} `);
67 | }
68 | return children.join("");
69 | }
70 |
71 | // performs the very basic tests while clicking next or prev
72 | export function testSliderScroll({ direction, ...settings }) {
73 | const { noOfSlides, slidesToShow, slidesToScroll, initialSlide } = settings;
74 | // initialize react slider
75 | const { container } = render(createReactSlider(settings));
76 | // initialize jquery slider
77 | document.body.innerHTML = `
78 |
79 | ${createJQuerySliderChildren(noOfSlides)}
80 |
81 | `;
82 | $(".regular.slider").slick({
83 | ...settings
84 | });
85 | // console.log('setings:', settings)
86 |
87 | let expectedSlideIndex = initialSlide || 0;
88 | for (let click = 0; click < 2 * noOfSlides + 2; click++) {
89 | let activeslides = getActiveSlides(container);
90 | let $activeSlides = $(".regular.slider").find("div.slick-active");
91 | expect(getActiveSlidesCount(container)).toEqual(slidesToShow || 1);
92 | expect($activeSlides.length).toEqual(slidesToShow || 1);
93 | let firstActiveSlide = activeslides[0];
94 | let $firstActiveSlide = $activeSlides.first();
95 | // console.log('classes', $firstActiveSlide.attr('data-slick-index'))
96 | // console.warn('currentSlide:', firstActiveSlide.prop('data-index'), 'expected slide', expectedSlideIndex)
97 | expect(parseInt(firstActiveSlide.getAttribute("data-index"))).toEqual(
98 | expectedSlideIndex % noOfSlides
99 | );
100 | expect(parseInt($firstActiveSlide.attr("data-slick-index"))).toEqual(
101 | expectedSlideIndex % noOfSlides
102 | );
103 | if (direction === "next") {
104 | // click the next arrow button
105 | clickNext(container);
106 | $("button.slick-next").click();
107 | expectedSlideIndex += slidesToScroll || 1;
108 | if (expectedSlideIndex >= noOfSlides) {
109 | expectedSlideIndex = 0;
110 | }
111 | } else {
112 | // click on the prev arrow button
113 | clickPrevious(container);
114 | $("button.slick-prev").click();
115 | expectedSlideIndex -= slidesToScroll || 1;
116 | if (expectedSlideIndex < 0) {
117 | expectedSlideIndex = activeSlideInLastTransition(
118 | noOfSlides,
119 | slidesToShow,
120 | slidesToScroll
121 | );
122 | }
123 | }
124 | }
125 | }
126 |
127 | // function to run tests on a slider,
128 | // scrolls slider to the right by clicking right arrow several times
129 | // scrolls slider to the left by clicking left arrow several times
130 | export function testSlider(settings) {
131 | const settings1 = { direction: "next", ...settings };
132 | const settings2 = { direction: "prev", ...settings };
133 | testSliderScroll(settings1);
134 | testSliderScroll(settings2);
135 | }
136 |
137 | export const tryAllConfigs = (settings, settingsList) => {
138 | let leaf = true;
139 | for (let key of Object.keys(settings)) {
140 | if (Array.isArray(settings[key])) {
141 | leaf = false;
142 | for (let val of settings[key]) {
143 | tryAllConfigs({ ...settings, [key]: val }, settingsList);
144 | }
145 | }
146 | }
147 | if (leaf) {
148 | if (
149 | settingsList
150 | .map(setting => JSON.stringify(setting))
151 | .indexOf(JSON.stringify(settings)) < 0
152 | ) {
153 | settingsList.push(settings);
154 | }
155 | }
156 | };
157 |
158 | export const actualTrackLeft = container =>
159 | container
160 | .querySelector(".slick-track")
161 | .style.transform.match(/translate3d\((\d+)px/i)[1];
162 |
163 | export const testTrackLeft = container => {
164 | let trackLeft = parseInt(actualTrackLeft(container));
165 | let spec = assign({}, wrapper.props(), wrapper.state(), {
166 | slideIndex: wrapper.state().currentSlide,
167 | trackRef: null
168 | });
169 | let expectedTrackLeft = getTrackLeft(spec);
170 | expect(trackLeft).toEqual(parseInt(expectedTrackLeft));
171 | };
172 | test("fake test", () => {
173 | expect(1).toBe(1);
174 | });
175 |
--------------------------------------------------------------------------------
/__tests__/utils/filterSettings.test.js:
--------------------------------------------------------------------------------
1 | import { filterSettings } from "../../src/utils/innerSliderUtils";
2 |
3 | describe("filterSettings", () => {
4 | it("returns empty object if there are no valid settings", () => {
5 | expect(filterSettings({})).toEqual({});
6 | expect(filterSettings({ age: 10 })).toEqual({});
7 | });
8 | it("return an object with valid settings and omits extra properties", () => {
9 | expect(filterSettings({ arrows: true, dots: true })).toEqual({
10 | arrows: true,
11 | dots: true
12 | });
13 | expect(filterSettings({ arrows: true, dots: true, age: 10 })).toEqual({
14 | arrows: true,
15 | dots: true
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | ### Methods
2 |
3 | | Name | Arguments | Description |
4 | | ------------ | ------------------ | --------------------------- |
5 | | `slickPrev` | None | go to previous slide |
6 | | `slickNext` | None | go to next slide |
7 | | `slickGoTo` | index, dontAnimate | go to the given slide index |
8 | | `slickPause` | None | pause the autoplay |
9 | | `slickPlay` | None | start the autoplay |
10 |
11 | #### Followings are not going to be implemented
12 |
13 | | Name | type | Reason |
14 | | ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
15 | | `unslick` | method | same functionality can be achieved with `unslick` prop |
16 | | `slickSetOption` | method | same functionality can be achieved via props and managing state for them in wrapper |
17 | | `slickFilter` | method | same functionality can be achieved as with dynamic slides, look at dynamic slides [example](https://github.com/akiran/react-slick/blob/master/examples/DynamicSlides.js) |
18 | | `slickUnfilter` | method | same functionality can be achieved as with dynamic slides, look at dynamic slides [example](https://github.com/akiran/react-slick/blob/master/examples/DynamicSlides.js) |
19 | | `slickAdd` | method | same functionality can be achieved as with dynamic slides, look at dynamic slides [example](https://github.com/akiran/react-slick/blob/master/examples/DynamicSlides.js) |
20 | | `slickRemove` | method | same functionality can be achieved as with dynamic slides, look at dynamic slides [example](https://github.com/akiran/react-slick/blob/master/examples/DynamicSlides.js) |
21 | | `slickCurrentSlide` | method | same functionality can be achieved with `beforeChange hook` |
22 | | `slickGetOption` | method | manage wrapper state for desired options |
23 | | `getSlick` | method | a simple ref will do |
24 |
--------------------------------------------------------------------------------
/docs/common.md:
--------------------------------------------------------------------------------
1 | #### `responsive` property
2 |
3 | Array of objects in the form of `{ breakpoint: int, settings: { ... } }` The breakpoint _int_ is the `maxWidth` so the settings will be applied when resolution is below this value. Breakpoints in the array should be ordered from smallest to greatest. Use 'unslick' in place of the settings object to disable rendering the carousel at that breakpoint. Example: `[ { breakpoint: 768, settings: { slidesToShow: 3 } }, { breakpoint: 1024, settings: { slidesToShow: 5 } }, { breakpoint: 100000, settings: 'unslick' } ]`
4 |
5 | ### Custom next/prev arrows
6 |
7 | To customize the next/prev arrow elements, simply create new React components and set them
8 | as the values of nextArrow and prevArrow.
9 |
10 | ```js
11 | class LeftNavButton extends React.Component {
12 | render() {
13 | return Next ;
14 | }
15 | }
16 | ```
17 |
18 | Important: be sure that you pass your component's props to your clickable element
19 | like the example above. If you don't, your custom component won't trigger the click handler.
20 |
21 | You can also set `onClick={this.props.onClick}` if you only want to set the click handler.
22 |
23 | ### Flexbox support
24 |
25 | If you have flex property on container div of slider, add below css
26 |
27 | ```css
28 | * {
29 | min-height: 0;
30 | min-width: 0;
31 | }
32 | ```
33 |
34 | ### Test Setup
35 |
36 | If you try to run tests with jest in a project that uses react-slick, you may run into this error
37 |
38 | ```
39 | matchMedia not present, legacy browsers require a polyfill
40 | ```
41 |
42 | To fix this issue add below snippet in test-setup.js
43 |
44 | ```js
45 | window.matchMedia =
46 | window.matchMedia ||
47 | function() {
48 | return {
49 | matches: false,
50 | addListener: function() {},
51 | removeListener: function() {}
52 | };
53 | };
54 | ```
55 |
56 | and add below jest config in package.json
57 |
58 | ```json
59 | "jest": {
60 | "setupFiles": ["test-setup.js"]
61 | }
62 | ```
63 |
64 | ### Polyfills for old IE support
65 |
66 | `matchMedia` support from [media-match](https://github.com/weblinc/media-match)
67 |
--------------------------------------------------------------------------------
/docs/demos.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import Slider from "../src/slider";
5 |
6 | import SimpleSlider from "../examples/SimpleSlider";
7 | import SlideChangeHooks from "../examples/SlideChangeHooks";
8 | import MultipleItems from "../examples/MultipleItems";
9 | import MultipleRows from "../examples/MultipleRows";
10 | import Responsive from "../examples/Responsive";
11 | import Resizable from "../examples/Resizable";
12 | import UnevenSetsInfinite from "../examples/UnevenSetsInfinite";
13 | import UnevenSetsFinite from "../examples/UnevenSetsFinite";
14 | import CenterMode from "../examples/CenterMode";
15 | import FocusOnSelect from "../examples/FocusOnSelect";
16 | import AutoPlay from "../examples/AutoPlay";
17 | import AutoPlayMethods from "../examples/AutoPlayMethods";
18 | import PauseOnHover from "../examples/PauseOnHover";
19 | import Rtl from "../examples/Rtl";
20 | import VariableWidth from "../examples/VariableWidth";
21 | import AdaptiveHeight from "../examples/AdaptiveHeight";
22 | import LazyLoad from "../examples/LazyLoad";
23 | import Fade from "../examples/Fade";
24 | import SlickGoTo from "../examples/SlickGoTo";
25 | import CustomArrows from "../examples/CustomArrows";
26 | import PreviousNextMethods from "../examples/PreviousNextMethods";
27 | import DynamicSlides from "../examples/DynamicSlides";
28 | import VerticalMode from "../examples/VerticalMode";
29 | import SwipeToSlide from "../examples/SwipeToSlide";
30 | import VerticalSwipeToSlide from "../examples/VerticalSwipeToSlide";
31 | import CustomPaging from "../examples/CustomPaging";
32 | import CustomSlides from "../examples/CustomSlides";
33 | import AsNavFor from "../examples/AsNavFor";
34 | import AppendDots from "../examples/AppendDots";
35 |
36 | export default class App extends React.Component {
37 | render() {
38 | return (
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/docs/docs.css:
--------------------------------------------------------------------------------
1 |
2 | h3 {
3 | background: #00558B;
4 | color: #fff;
5 | font-size: 36px;
6 | line-height: 100px;
7 | margin: 10px;
8 | padding: 2%;
9 | position: relative;
10 | text-align: center;
11 | }
12 | .variable-width .slick-slide p {
13 | background: #00558B;
14 | height: 100px;
15 | color: #fff;
16 | margin: 5px;
17 | line-height: 100px;
18 | text-align: center;
19 | }
20 | .center .slick-center h3 {
21 | color: #e67e22;
22 | opacity: 1;
23 | transform: scale(1.08);
24 | }
25 | .center h3{
26 | opacity: 0.8;
27 | transition: all 300ms ease;
28 | }
29 | .content {
30 | padding: 20px;
31 | margin: auto;
32 | }
33 | @media (min-width: 701px) {
34 | .content {
35 | width: 80%;
36 | }
37 | }
38 | @media (max-width: 700px) {
39 | .content {
40 | width: 70%;
41 | }
42 | }
43 | .slick-slide .image {
44 | padding: 10px;
45 | }
46 | .slick-slide img {
47 | border: 5px solid #FFF;
48 | display: block;
49 | margin: auto;
50 | max-width: 80%;
51 | }
52 | .slick-slide img.slick-loading {
53 | border: 0
54 | }
55 | .slick-slider {
56 | margin: 30px auto 50px;
57 | }
58 | .slick-dots {
59 | margin-left: 0;
60 | }
61 | .slick-thumb {
62 | bottom: -45px;
63 | }
64 | .slick-thumb li {
65 | width: 60px;
66 | height: 45px;
67 | }
68 | .slick-thumb li img {
69 | width: 100%;
70 | height: 100%;
71 | filter: grayscale(100%);
72 | }
73 | .slick-thumb li.slick-active img{
74 | filter: grayscale(0%);
75 | }
76 | @media (max-width: 768px) {
77 | h3 {
78 | font-size:24px;
79 | }
80 | .center {
81 | margin-left: -40px;
82 | margin-right: -40px;
83 | }
84 | .center .slick-center h3 {
85 | color: #e67e22;
86 | opacity: 1;
87 | transform: scale(1);
88 | }
89 | .center h3 {
90 | opacity: 0.8;
91 | transform: scale(0.95);
92 | transition: all 300ms ease;
93 | }
94 | }
95 | .slick-vertical .slick-slide {
96 | height: 180px;
97 | }
98 | .slick-arrow {
99 | background-color: grey;
100 | }
101 | .slick-arrow:hover {
102 | background-color: grey;
103 | }
104 | .slick-arrow:focus {
105 | background-color: grey;
106 | }
107 | .button {
108 | background-color: #00558B;
109 | padding: 10px 20px;
110 | margin: 0px 20px;
111 | border: none;
112 | color: white;
113 | font-size: 20px;
114 | border-radius: 5px;
115 | min-height: 45px
116 | }
117 |
--------------------------------------------------------------------------------
/docs/docs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import Demos from "./demos";
5 |
6 | export default class Docs extends React.Component {
7 | render() {
8 | return (
9 |
10 |
11 | React Slick
12 |
13 |
18 |
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docs/img/react-slick/abstract01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akiran/react-slick/a5a3cbe69abf4254713989f480e43480d3efdfe4/docs/img/react-slick/abstract01.jpg
--------------------------------------------------------------------------------
/docs/img/react-slick/abstract02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akiran/react-slick/a5a3cbe69abf4254713989f480e43480d3efdfe4/docs/img/react-slick/abstract02.jpg
--------------------------------------------------------------------------------
/docs/img/react-slick/abstract03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akiran/react-slick/a5a3cbe69abf4254713989f480e43480d3efdfe4/docs/img/react-slick/abstract03.jpg
--------------------------------------------------------------------------------
/docs/img/react-slick/abstract04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akiran/react-slick/a5a3cbe69abf4254713989f480e43480d3efdfe4/docs/img/react-slick/abstract04.jpg
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import { createRoot } from "react-dom/client";
5 | import Docs from "./docs";
6 |
7 | const container = document.getElementById("rapp");
8 | const root = createRoot(container);
9 |
10 | React.initializeTouchEvents && React.initializeTouchEvents(true);
11 | root.render(
12 |
13 |
14 |
15 | );
16 |
--------------------------------------------------------------------------------
/docs/routes.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var React = require("react");
4 | var Router = require("react-router");
5 | var Route = Router.Route;
6 | var Docs = require("./docs");
7 |
8 | var path =
9 | process.env.NODE_ENV === "dev_docs" ? "/" : "/opensource/react-slick";
10 | var routes = ;
11 |
12 | module.exports = routes;
13 |
--------------------------------------------------------------------------------
/docs/scripts/generateExampleConfigs.js:
--------------------------------------------------------------------------------
1 | const React = require("react");
2 | const fs = require("fs");
3 | const babel = require("babel-core");
4 | const ReactDOMServer = require("react-dom/server");
5 |
6 | let configsObject;
7 | if (fs.existsSync("./configs.json")) {
8 | configsObject = require("./configs.json");
9 | } else {
10 | configsObject = {};
11 | }
12 |
13 | const fetchExampleString = exampleName => {
14 | const exampleString = fs.readFileSync(`examples/${exampleName}.js`, "utf-8");
15 | return exampleString;
16 | };
17 |
18 | const extractConfig = exampleString => {
19 | const pattern = /(var|const)\s+settings\s*=\s*(\{(.|\n)+?\n\s*\};)/;
20 | let extraction = exampleString.match(pattern);
21 | if (extraction) extraction = extraction[2];
22 | else return null;
23 | const propPattern = /(\w+)\:((?:.|\n)+?)(?=(,\n)|(\n\s*};))/g;
24 | let match;
25 | let matchObject = {};
26 | do {
27 | match = propPattern.exec(extraction);
28 | if (!match) break;
29 | if (!matchObject[match[1]]) {
30 | matchObject[match[1]] = match[2].trim();
31 | }
32 | } while (match);
33 | return matchObject;
34 | };
35 |
36 | const extractChildren = exampleString => {
37 | const pattern = /\((.|\n)*?)\<\/Slider\>/;
38 | return exampleString.match(pattern)[1];
39 | };
40 |
41 | const transpile = exampleString =>
42 | babel.transform(exampleString, {
43 | plugins: [
44 | "transform-react-jsx",
45 | "babel-plugin-transform-object-rest-spread",
46 | "babel-plugin-transform-class-properties",
47 | "babel-plugin-transform-es2015-arrow-functions"
48 | ]
49 | }).code;
50 |
51 | const fetchExampleConfigs = (fileName, index) => {
52 | const exampleName = fileName.substring(0, fileName.length - 3);
53 | const exampleString = fetchExampleString(exampleName);
54 | const transformedString = transpile(exampleString);
55 | let childrenString = extractChildren(exampleString.replace(/\=\>/g, "$$$")); // jsx type string
56 | try {
57 | // react string without jsx
58 | childrenString = eval(
59 | transpile(
60 | `` + childrenString + "
"
61 | ).replace(/baseUrl/g, "'./img/react-slick'")
62 | );
63 | console.log("success");
64 | } catch (error) {
65 | childrenString = "";
66 | console.error("children error:", fileName);
67 | }
68 | childrenString = ReactDOMServer.renderToString(childrenString); // pure html string
69 | let config = extractConfig(transformedString);
70 | if (config) {
71 | configsObject[exampleName] = {
72 | props: config,
73 | children: childrenString
74 | };
75 | } else {
76 | console.log("config error:", fileName);
77 | }
78 | };
79 |
80 | const exampleFiles = fs
81 | .readdirSync("examples")
82 | .filter(file => file.endsWith(".js") && file[0] === file[0].toUpperCase())
83 | .forEach((fileName, index) => fetchExampleConfigs(fileName, index));
84 | fs.writeFileSync(
85 | "examples/scripts/configs.json",
86 | JSON.stringify(configsObject, null, 4)
87 | );
88 |
--------------------------------------------------------------------------------
/docs/scripts/generateExamples.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const exampleConfigs = require("./configs.json");
3 | const exec = require("child_process").exec;
4 |
5 | var procCode = exec(
6 | "cp -r node_modules/slick-carousel/slick/fonts node_modules/slick-carousel/slick/ajax-loader.gif docs/"
7 | );
8 |
9 | const toString = obj => {
10 | let ret = "{\n";
11 | Object.keys(obj).forEach(key => {
12 | if (
13 | obj[key].match("function") ||
14 | obj[key].match("React.createElement" || obj[key].match("\n"))
15 | ) {
16 | return;
17 | }
18 | if (
19 | key.match("style") ||
20 | key.match("src") ||
21 | key.match("border") ||
22 | key.match("settings") ||
23 | key.match("responsive")
24 | )
25 | return;
26 | ret += "\t" + key + ": " + obj[key] + ",\n";
27 | });
28 | ret += "}\n";
29 | return ret;
30 | };
31 |
32 | let bodyHTML = "";
33 | let bodyScript = "";
34 | Object.keys(exampleConfigs).forEach(key => {
35 | const props = exampleConfigs[key]["props"];
36 | const children = exampleConfigs[key]["children"];
37 | if (!props || !children) return;
38 | bodyHTML += `
39 |
40 |
${key}
41 | ${children}
42 |
43 | `;
44 | bodyScript += `
45 | $('[name="${key}"').slick(${toString(props)})
46 | `;
47 | });
48 |
49 | let HTMLString = `
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
70 |
71 |
72 |
73 |
74 | ${bodyHTML}
75 |
76 |
81 |
82 |
83 | `;
84 |
85 | fs.writeFileSync("docs/jquery.html", HTMLString);
86 |
--------------------------------------------------------------------------------
/docs/single-demo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import { createRoot } from "react-dom/client";
5 | import Slider from "../src/slider";
6 | import MultipleItems from "../examples/MultipleItems";
7 | function SimpleSlider() {
8 | const settings = {
9 | dots: true,
10 | infinite: true,
11 | speed: 500,
12 | slidesToShow: 1,
13 | slidesToScroll: 1
14 | };
15 | return (
16 |
17 |
Single Item
18 |
19 |
20 |
1
21 |
22 |
23 |
2
24 |
25 |
26 |
3
27 |
28 |
29 |
4
30 |
31 |
32 |
5
33 |
34 |
35 |
6
36 |
37 |
38 |
39 | );
40 | }
41 |
42 | function App() {
43 | return (
44 |
45 | {/* */}
46 |
47 |
48 | );
49 | }
50 |
51 | const container = document.getElementById("rapp");
52 | const root = createRoot(container);
53 |
54 | React.initializeTouchEvents && React.initializeTouchEvents(true);
55 | root.render(
56 |
57 |
58 |
59 | );
60 |
--------------------------------------------------------------------------------
/docs/slick-theme.css:
--------------------------------------------------------------------------------
1 | @charset 'UTF-8';
2 | /* Slider */
3 | .slick-loading .slick-list
4 | {
5 | background: #fff url('./ajax-loader.gif') center center no-repeat;
6 | }
7 |
8 | /* Icons */
9 | @font-face
10 | {
11 | font-family: 'slick';
12 | font-weight: normal;
13 | font-style: normal;
14 |
15 | src: url('./fonts/slick.eot');
16 | src: url('./fonts/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick.woff') format('woff'), url('./fonts/slick.ttf') format('truetype'), url('./fonts/slick.svg#slick') format('svg');
17 | }
18 | /* Arrows */
19 | .slick-prev,
20 | .slick-next
21 | {
22 | font-size: 0;
23 | line-height: 0;
24 |
25 | position: absolute;
26 | top: 50%;
27 |
28 | display: block;
29 |
30 | width: 20px;
31 | height: 20px;
32 | padding: 0;
33 | -webkit-transform: translate(0, -50%);
34 | -ms-transform: translate(0, -50%);
35 | transform: translate(0, -50%);
36 |
37 | cursor: pointer;
38 |
39 | color: transparent;
40 | border: none;
41 | outline: none;
42 | background: transparent;
43 | }
44 | .slick-prev:hover,
45 | .slick-prev:focus,
46 | .slick-next:hover,
47 | .slick-next:focus
48 | {
49 | color: transparent;
50 | outline: none;
51 | background: transparent;
52 | }
53 | .slick-prev:hover:before,
54 | .slick-prev:focus:before,
55 | .slick-next:hover:before,
56 | .slick-next:focus:before
57 | {
58 | opacity: 1;
59 | }
60 | .slick-prev.slick-disabled:before,
61 | .slick-next.slick-disabled:before
62 | {
63 | opacity: .25;
64 | }
65 |
66 | .slick-prev:before,
67 | .slick-next:before
68 | {
69 | font-family: 'slick';
70 | font-size: 20px;
71 | line-height: 1;
72 |
73 | opacity: .75;
74 | color: white;
75 |
76 | -webkit-font-smoothing: antialiased;
77 | -moz-osx-font-smoothing: grayscale;
78 | }
79 |
80 | .slick-prev
81 | {
82 | left: -25px;
83 | }
84 | [dir='rtl'] .slick-prev
85 | {
86 | right: -25px;
87 | left: auto;
88 | }
89 | .slick-prev:before
90 | {
91 | content: '←';
92 | }
93 | [dir='rtl'] .slick-prev:before
94 | {
95 | content: '→';
96 | }
97 |
98 | .slick-next
99 | {
100 | right: -25px;
101 | }
102 | [dir='rtl'] .slick-next
103 | {
104 | right: auto;
105 | left: -25px;
106 | }
107 | .slick-next:before
108 | {
109 | content: '→';
110 | }
111 | [dir='rtl'] .slick-next:before
112 | {
113 | content: '←';
114 | }
115 |
116 | /* Dots */
117 | .slick-dotted.slick-slider
118 | {
119 | margin-bottom: 30px;
120 | }
121 |
122 | .slick-dots
123 | {
124 | position: absolute;
125 | bottom: -25px;
126 |
127 | display: block;
128 |
129 | width: 100%;
130 | padding: 0;
131 | margin: 0;
132 |
133 | list-style: none;
134 |
135 | text-align: center;
136 | }
137 | .slick-dots li
138 | {
139 | position: relative;
140 |
141 | display: inline-block;
142 |
143 | width: 20px;
144 | height: 20px;
145 | margin: 0 5px;
146 | padding: 0;
147 |
148 | cursor: pointer;
149 | }
150 | .slick-dots li button
151 | {
152 | font-size: 0;
153 | line-height: 0;
154 |
155 | display: block;
156 |
157 | width: 20px;
158 | height: 20px;
159 | padding: 5px;
160 |
161 | cursor: pointer;
162 |
163 | color: transparent;
164 | border: 0;
165 | outline: none;
166 | background: transparent;
167 | }
168 | .slick-dots li button:hover,
169 | .slick-dots li button:focus
170 | {
171 | outline: none;
172 | }
173 | .slick-dots li button:hover:before,
174 | .slick-dots li button:focus:before
175 | {
176 | opacity: 1;
177 | }
178 | .slick-dots li button:before
179 | {
180 | font-family: 'slick';
181 | font-size: 6px;
182 | line-height: 20px;
183 |
184 | position: absolute;
185 | top: 0;
186 | left: 0;
187 |
188 | width: 20px;
189 | height: 20px;
190 |
191 | content: '•';
192 | text-align: center;
193 |
194 | opacity: .25;
195 | color: black;
196 |
197 | -webkit-font-smoothing: antialiased;
198 | -moz-osx-font-smoothing: grayscale;
199 | }
200 | .slick-dots li.slick-active button:before
201 | {
202 | opacity: .75;
203 | color: black;
204 | }
205 |
--------------------------------------------------------------------------------
/docs/slick.css:
--------------------------------------------------------------------------------
1 | /* Slider */
2 | .slick-slider
3 | {
4 | position: relative;
5 |
6 | display: block;
7 | box-sizing: border-box;
8 |
9 | -webkit-user-select: none;
10 | -moz-user-select: none;
11 | -ms-user-select: none;
12 | user-select: none;
13 |
14 | -webkit-touch-callout: none;
15 | -khtml-user-select: none;
16 | -ms-touch-action: pan-y;
17 | touch-action: pan-y;
18 | -webkit-tap-highlight-color: transparent;
19 | }
20 |
21 | .slick-list
22 | {
23 | position: relative;
24 |
25 | display: block;
26 | overflow: hidden;
27 |
28 | margin: 0;
29 | padding: 0;
30 | }
31 | .slick-list:focus
32 | {
33 | outline: none;
34 | }
35 | .slick-list.dragging
36 | {
37 | cursor: pointer;
38 | cursor: hand;
39 | }
40 |
41 | .slick-slider .slick-track,
42 | .slick-slider .slick-list
43 | {
44 | -webkit-transform: translate3d(0, 0, 0);
45 | -moz-transform: translate3d(0, 0, 0);
46 | -ms-transform: translate3d(0, 0, 0);
47 | -o-transform: translate3d(0, 0, 0);
48 | transform: translate3d(0, 0, 0);
49 | }
50 |
51 | .slick-track
52 | {
53 | position: relative;
54 | top: 0;
55 | left: 0;
56 |
57 | display: block;
58 | margin-left: auto;
59 | margin-right: auto;
60 | }
61 | .slick-track:before,
62 | .slick-track:after
63 | {
64 | display: table;
65 |
66 | content: '';
67 | }
68 | .slick-track:after
69 | {
70 | clear: both;
71 | }
72 | .slick-loading .slick-track
73 | {
74 | visibility: hidden;
75 | }
76 |
77 | .slick-slide
78 | {
79 | display: none;
80 | float: left;
81 |
82 | height: 100%;
83 | min-height: 1px;
84 | }
85 | [dir='rtl'] .slick-slide
86 | {
87 | float: right;
88 | }
89 | .slick-slide img
90 | {
91 | display: block;
92 | }
93 | .slick-slide.slick-loading img
94 | {
95 | display: none;
96 | }
97 | .slick-slide.dragging img
98 | {
99 | pointer-events: none;
100 | }
101 | .slick-initialized .slick-slide
102 | {
103 | display: block;
104 | }
105 | .slick-loading .slick-slide
106 | {
107 | visibility: hidden;
108 | }
109 | .slick-vertical .slick-slide
110 | {
111 | display: block;
112 |
113 | height: auto;
114 |
115 | border: 1px solid transparent;
116 | }
117 | .slick-arrow.slick-hidden {
118 | display: none;
119 | }
120 |
--------------------------------------------------------------------------------
/examples/AdaptiveHeight.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function AdaptiveHeight() {
5 | const settings = {
6 | className: "",
7 | dots: true,
8 | infinite: true,
9 | slidesToShow: 1,
10 | slidesToScroll: 1,
11 | adaptiveHeight: true
12 | };
13 |
14 | return (
15 |
16 |
17 |
18 |
1
19 |
20 |
24 |
25 |
3
26 |
See ....
27 |
Height is adaptive
28 |
29 |
30 |
4
31 |
32 |
33 |
5
34 |
35 |
36 |
6
37 |
38 |
39 |
40 | );
41 | }
42 |
43 | export default AdaptiveHeight;
44 |
--------------------------------------------------------------------------------
/examples/AppendDots.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function AppendDots() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | speed: 500,
9 | slidesToShow: 1,
10 | slidesToScroll: 1,
11 | appendDots: dots => (
12 |
21 | ),
22 | customPaging: i => (
23 |
30 | {i + 1}
31 |
32 | )
33 | };
34 | return (
35 |
36 |
37 |
38 |
1
39 |
40 |
41 |
2
42 |
43 |
44 |
3
45 |
46 |
47 |
4
48 |
49 |
50 |
5
51 |
52 |
53 |
6
54 |
55 |
56 |
57 | );
58 | }
59 | export default AppendDots;
60 |
--------------------------------------------------------------------------------
/examples/AsNavFor.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useRef } from "react";
2 | import Slider from "react-slick";
3 |
4 | function AsNavFor() {
5 | const [nav1, setNav1] = useState(null);
6 | const [nav2, setNav2] = useState(null);
7 | let sliderRef1 = useRef(null);
8 | let sliderRef2 = useRef(null);
9 |
10 | useEffect(() => {
11 | setNav1(sliderRef1);
12 | setNav2(sliderRef2);
13 | }, []);
14 | return (
15 |
16 |
Slider Syncing (AsNavFor)
17 |
First Slider
18 |
(sliderRef1 = slider)}>
19 |
20 |
1
21 |
22 |
23 |
2
24 |
25 |
26 |
3
27 |
28 |
29 |
4
30 |
31 |
32 |
5
33 |
34 |
35 |
6
36 |
37 |
38 |
Second Slider
39 |
(sliderRef2 = slider)}
42 | slidesToShow={3}
43 | swipeToSlide={true}
44 | focusOnSelect={true}
45 | >
46 |
47 |
1
48 |
49 |
50 |
2
51 |
52 |
53 |
3
54 |
55 |
56 |
4
57 |
58 |
59 |
5
60 |
61 |
62 |
6
63 |
64 |
65 |
66 | );
67 | }
68 |
69 | export default AsNavFor;
70 |
--------------------------------------------------------------------------------
/examples/AutoPlay.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function AutoPlay() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | autoplay: true,
11 | speed: 2000,
12 | autoplaySpeed: 2000,
13 | cssEase: "linear"
14 | };
15 | return (
16 |
17 |
18 |
19 |
1
20 |
21 |
22 |
2
23 |
24 |
25 |
3
26 |
27 |
28 |
4
29 |
30 |
31 |
5
32 |
33 |
34 |
6
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | export default AutoPlay;
42 |
--------------------------------------------------------------------------------
/examples/AutoPlayMethods.js:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import Slider from "react-slick";
3 |
4 | function AutoPlayMethods() {
5 | let sliderRef = useRef(null);
6 | const play = () => {
7 | sliderRef.slickPlay();
8 | };
9 | const pause = () => {
10 | sliderRef.slickPause();
11 | };
12 |
13 | const settings = {
14 | dots: true,
15 | infinite: true,
16 | slidesToShow: 3,
17 | slidesToScroll: 1,
18 | autoplay: true,
19 | autoplaySpeed: 2000
20 | };
21 | return (
22 |
23 |
Auto Play {"&"} Pause with buttons
24 |
(sliderRef = slider)} {...settings}>
25 |
26 |
1
27 |
28 |
29 |
2
30 |
31 |
32 |
3
33 |
34 |
35 |
4
36 |
37 |
38 |
5
39 |
40 |
41 |
6
42 |
43 |
44 |
45 |
46 | Play
47 |
48 |
49 | Pause
50 |
51 |
52 |
53 | );
54 | }
55 | export default AutoPlayMethods;
56 |
--------------------------------------------------------------------------------
/examples/CenterMode.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function CenterMode() {
5 | const settings = {
6 | className: "center",
7 | centerMode: true,
8 | infinite: true,
9 | centerPadding: "60px",
10 | slidesToShow: 3,
11 | speed: 500
12 | };
13 | return (
14 |
15 |
16 |
17 |
1
18 |
19 |
20 |
2
21 |
22 |
23 |
3
24 |
25 |
26 |
4
27 |
28 |
29 |
5
30 |
31 |
32 |
6
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default CenterMode;
40 |
--------------------------------------------------------------------------------
/examples/CustomArrows.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function SampleNextArrow(props) {
5 | const { className, style, onClick } = props;
6 | return (
7 |
12 | );
13 | }
14 |
15 | function SamplePrevArrow(props) {
16 | const { className, style, onClick } = props;
17 | return (
18 |
23 | );
24 | }
25 |
26 | function CustomArrows() {
27 | const settings = {
28 | dots: true,
29 | infinite: true,
30 | slidesToShow: 3,
31 | slidesToScroll: 1,
32 | nextArrow: ,
33 | prevArrow:
34 | };
35 | return (
36 |
37 |
38 |
39 |
1
40 |
41 |
42 |
2
43 |
44 |
45 |
3
46 |
47 |
48 |
4
49 |
50 |
51 |
5
52 |
53 |
54 |
6
55 |
56 |
57 |
58 | );
59 | }
60 |
61 | export default CustomArrows;
62 |
--------------------------------------------------------------------------------
/examples/CustomPaging.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 | import { baseUrl } from "./config";
4 |
5 | function CustomPaging() {
6 | const settings = {
7 | customPaging: function(i) {
8 | return (
9 |
10 |
11 |
12 | );
13 | },
14 | dots: true,
15 | dotsClass: "slick-dots slick-thumb",
16 | infinite: true,
17 | speed: 500,
18 | slidesToShow: 1,
19 | slidesToScroll: 1
20 | };
21 | return (
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | export default CustomPaging;
42 |
--------------------------------------------------------------------------------
/examples/CustomSlides.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function CustomSlide(props) {
5 | const { index, ...otherProps } = props;
6 | return (
7 |
8 |
{index}
9 |
10 | );
11 | }
12 |
13 | function CustomSlides() {
14 | const settings = {
15 | dots: true,
16 | infinite: true,
17 | speed: 500,
18 | slidesToShow: 1,
19 | slidesToScroll: 1
20 | };
21 | return (
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | );
33 | }
34 |
35 | export default CustomSlides;
36 |
--------------------------------------------------------------------------------
/examples/DynamicSlides.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Slider from "react-slick";
3 |
4 | function DynamicSlides() {
5 | const [slides, setSlides] = useState([1, 2, 3, 4, 5, 6]);
6 | const handleClick = () => {
7 | setSlides(
8 | slides.length === 6 ? [1, 2, 3, 4, 5, 6, 7, 8, 9] : [1, 2, 3, 4, 5, 6]
9 | );
10 | };
11 | const settings = {
12 | dots: true,
13 | infinite: true,
14 | speed: 500,
15 | slidesToShow: 3,
16 | slidesToScroll: 3
17 | };
18 | return (
19 |
20 |
21 | Click to change slide count
22 |
23 |
24 | {slides.map(slide => {
25 | return (
26 |
27 |
{slide}
28 |
29 | );
30 | })}
31 |
32 |
33 | );
34 | }
35 |
36 | export default DynamicSlides;
37 |
--------------------------------------------------------------------------------
/examples/Fade.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 | import { baseUrl } from "./config";
4 |
5 | function Fade() {
6 | const settings = {
7 | dots: true,
8 | fade: true,
9 | infinite: true,
10 | speed: 500,
11 | slidesToShow: 1,
12 | slidesToScroll: 1,
13 | waitForAnimate: false
14 | };
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | );
33 | }
34 |
35 | export default Fade;
36 |
--------------------------------------------------------------------------------
/examples/FocusOnSelect.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function FocusOnSelect() {
5 | const settings = {
6 | focusOnSelect: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | speed: 500
11 | };
12 | return (
13 |
14 |
Click on any slide to select and make it current slide
15 |
16 |
17 |
1
18 |
19 |
20 |
2
21 |
22 |
23 |
3
24 |
25 |
26 |
4
27 |
28 |
29 |
5
30 |
31 |
32 |
6
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default FocusOnSelect;
40 |
--------------------------------------------------------------------------------
/examples/LazyLoad.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 | import { baseUrl } from "./config";
4 |
5 | function LazyLoad() {
6 | const settings = {
7 | dots: true,
8 | lazyLoad: true,
9 | infinite: true,
10 | speed: 500,
11 | slidesToShow: 1,
12 | slidesToScroll: 1,
13 | initialSlide: 2
14 | };
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | );
33 | }
34 |
35 | export default LazyLoad;
36 |
--------------------------------------------------------------------------------
/examples/MultipleItems.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function MultipleItems() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | speed: 500,
9 | slidesToShow: 3,
10 | slidesToScroll: 3
11 | };
12 | return (
13 |
14 |
15 |
16 |
1
17 |
18 |
19 |
2
20 |
21 |
22 |
3
23 |
24 |
25 |
4
26 |
27 |
28 |
5
29 |
30 |
31 |
6
32 |
33 |
34 |
7
35 |
36 |
37 |
8
38 |
39 |
40 |
9
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default MultipleItems;
48 |
--------------------------------------------------------------------------------
/examples/MultipleRows.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function MultipleRows() {
5 | const settings = {
6 | className: "center",
7 | centerMode: true,
8 | infinite: true,
9 | centerPadding: "60px",
10 | slidesToShow: 3,
11 | speed: 500,
12 | rows: 2,
13 | slidesPerRow: 2
14 | };
15 | return (
16 |
17 |
18 |
19 |
1
20 |
21 |
22 |
2
23 |
24 |
25 |
3
26 |
27 |
28 |
4
29 |
30 |
31 |
5
32 |
33 |
34 |
6
35 |
36 |
37 |
7
38 |
39 |
40 |
8
41 |
42 |
43 |
9
44 |
45 |
46 |
10
47 |
48 |
49 |
11
50 |
51 |
52 |
12
53 |
54 |
55 |
13
56 |
57 |
58 |
14
59 |
60 |
61 |
15
62 |
63 |
64 |
16
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default MultipleRows;
72 |
--------------------------------------------------------------------------------
/examples/PauseOnHover.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function PauseOnHover() {
5 | var settings = {
6 | dots: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | autoplay: true,
11 | autoplaySpeed: 2000,
12 | pauseOnHover: true
13 | };
14 | return (
15 |
16 |
17 |
18 |
1
19 |
20 |
21 |
2
22 |
23 |
24 |
3
25 |
26 |
27 |
4
28 |
29 |
30 |
5
31 |
32 |
33 |
6
34 |
35 |
36 |
37 | );
38 | }
39 |
40 | export default PauseOnHover;
41 |
--------------------------------------------------------------------------------
/examples/PreviousNextMethods.js:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import Slider from "react-slick";
3 |
4 | function PreviousNextMethods() {
5 | let sliderRef = useRef(null);
6 | const next = () => {
7 | sliderRef.slickNext();
8 | };
9 | const previous = () => {
10 | sliderRef.slickPrev();
11 | };
12 | const settings = {
13 | dots: true,
14 | infinite: true,
15 | speed: 500,
16 | slidesToShow: 1,
17 | slidesToScroll: 1
18 | };
19 | return (
20 |
21 |
{
23 | sliderRef = slider;
24 | }}
25 | {...settings}
26 | >
27 |
28 |
1
29 |
30 |
31 |
2
32 |
33 |
34 |
3
35 |
36 |
37 |
4
38 |
39 |
40 |
5
41 |
42 |
43 |
6
44 |
45 |
46 |
47 |
48 | Previous
49 |
50 |
51 | Next
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | export default PreviousNextMethods;
59 |
--------------------------------------------------------------------------------
/examples/Resizable.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Slider from "react-slick";
3 |
4 | function Resizable() {
5 | const [display, setDisplay] = useState(true);
6 | const [width, setWidth] = useState(600);
7 |
8 | const settings = {
9 | dots: true,
10 | infinite: true,
11 | speed: 500,
12 | slidesToShow: 3,
13 | slidesToScroll: 1
14 | };
15 | return (
16 |
17 |
Resizable Collapsible
18 |
setWidth(width + 100)}>
19 | {" "}
20 | increase{" "}
21 |
22 |
setWidth(width - 100)}>
23 | {" "}
24 | decrease{" "}
25 |
26 |
setDisplay(!display)}>
27 | {" "}
28 | toggle{" "}
29 |
30 |
36 |
37 |
38 |
1
39 |
40 |
41 |
2
42 |
43 |
44 |
3
45 |
46 |
47 |
4
48 |
49 |
50 |
5
51 |
52 |
53 |
6
54 |
55 |
56 |
57 |
58 | );
59 | }
60 |
61 | export default Resizable;
62 |
--------------------------------------------------------------------------------
/examples/Responsive.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function Responsive() {
5 | var settings = {
6 | dots: true,
7 | infinite: false,
8 | speed: 500,
9 | slidesToShow: 4,
10 | slidesToScroll: 4,
11 | initialSlide: 0,
12 | responsive: [
13 | {
14 | breakpoint: 1024,
15 | settings: {
16 | slidesToShow: 3,
17 | slidesToScroll: 3,
18 | infinite: true,
19 | dots: true
20 | }
21 | },
22 | {
23 | breakpoint: 600,
24 | settings: {
25 | slidesToShow: 2,
26 | slidesToScroll: 2,
27 | initialSlide: 2
28 | }
29 | },
30 | {
31 | breakpoint: 480,
32 | settings: {
33 | slidesToShow: 1,
34 | slidesToScroll: 1
35 | }
36 | }
37 | ]
38 | };
39 | return (
40 |
41 |
42 |
43 |
1
44 |
45 |
46 |
2
47 |
48 |
49 |
3
50 |
51 |
52 |
4
53 |
54 |
55 |
5
56 |
57 |
58 |
6
59 |
60 |
61 |
7
62 |
63 |
64 |
8
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default Responsive;
72 |
--------------------------------------------------------------------------------
/examples/Rtl.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function Rtl() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | autoplay: true,
11 | autoplaySpeed: 2000,
12 | rtl: true
13 | };
14 | return (
15 |
16 |
Right to Left
17 |
18 |
19 |
1
20 |
21 |
22 |
2
23 |
24 |
25 |
3
26 |
27 |
28 |
4
29 |
30 |
31 |
5
32 |
33 |
34 |
6
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | export default Rtl;
42 |
--------------------------------------------------------------------------------
/examples/SimpleSlider.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function SimpleSlider() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | speed: 500,
9 | slidesToShow: 1,
10 | slidesToScroll: 1
11 | };
12 | return (
13 |
14 |
15 |
16 |
1
17 |
18 |
19 |
2
20 |
21 |
22 |
3
23 |
24 |
25 |
4
26 |
27 |
28 |
5
29 |
30 |
31 |
6
32 |
33 |
34 |
35 | );
36 | }
37 |
38 | export default SimpleSlider;
39 |
--------------------------------------------------------------------------------
/examples/SlickGoTo.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef } from "react";
2 | import Slider from "react-slick";
3 | import { baseUrl } from "./config";
4 |
5 | function SlickGoTo() {
6 | const [slideIndex, setSlideIndex] = useState(0);
7 | const [updateCount, setUpdateCount] = useState(0);
8 | let sliderRef = useRef(null);
9 | const settings = {
10 | dots: false,
11 | infinite: true,
12 | speed: 500,
13 | slidesToShow: 1,
14 | slidesToScroll: 1,
15 | afterChange: () => setUpdateCount(updateCount + 1),
16 | beforeChange: (current, next) => setSlideIndex(next)
17 | };
18 | return (
19 |
20 |
Total updates: {updateCount}
21 |
sliderRef.slickGoTo(e.target.value)}
23 | value={slideIndex}
24 | type="range"
25 | min={0}
26 | max={3}
27 | />
28 |
{
30 | sliderRef = slider;
31 | }}
32 | {...settings}
33 | >
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | );
49 | }
50 |
51 | export default SlickGoTo;
52 |
--------------------------------------------------------------------------------
/examples/SlideChangeHooks.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Slider from "react-slick";
3 |
4 | function SlideChangeHooks() {
5 | const [oldSlide, setOldSlide] = useState(0);
6 | const [activeSlide, setActiveSlide] = useState(0);
7 | const [activeSlide2, setActiveSlide2] = useState(0);
8 |
9 | const settings = {
10 | dots: true,
11 | infinite: true,
12 | speed: 1000,
13 | slidesToShow: 1,
14 | slidesToScroll: 1,
15 | beforeChange: (current, next) => {
16 | setOldSlide(current);
17 | setActiveSlide(next);
18 | },
19 | afterChange: current => setActiveSlide2(current)
20 | };
21 | return (
22 |
23 |
beforeChange and afterChange hooks
24 |
25 | BeforeChange {"=>"} oldSlide: {oldSlide}
26 |
27 |
28 | BeforeChange {"=>"} activeSlide: {activeSlide}
29 |
30 |
31 | AfterChange {"=>"} activeSlide: {activeSlide2}
32 |
33 |
34 |
35 |
1
36 |
37 |
38 |
2
39 |
40 |
41 |
3
42 |
43 |
44 |
4
45 |
46 |
47 |
5
48 |
49 |
50 |
6
51 |
52 |
53 |
54 | );
55 | }
56 |
57 | export default SlideChangeHooks;
58 |
--------------------------------------------------------------------------------
/examples/SwipeToSlide.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function SwipeToSlide() {
5 | const settings = {
6 | className: "center",
7 | infinite: true,
8 | centerPadding: "60px",
9 | slidesToShow: 5,
10 | swipeToSlide: true,
11 | afterChange: function(index) {
12 | console.log(
13 | `Slider Changed to: ${index + 1}, background: #222; color: #bada55`
14 | );
15 | }
16 | };
17 | return (
18 |
19 |
20 |
21 |
1
22 |
23 |
24 |
2
25 |
26 |
27 |
3
28 |
29 |
30 |
4
31 |
32 |
33 |
5
34 |
35 |
36 |
6
37 |
38 |
39 |
7
40 |
41 |
42 |
8
43 |
44 |
45 |
9
46 |
47 |
48 |
49 | );
50 | }
51 |
52 | export default SwipeToSlide;
53 |
--------------------------------------------------------------------------------
/examples/UnevenSetsFinite.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function UnevenSetsFinite() {
5 | var settings = {
6 | dots: true,
7 | infinite: false,
8 | speed: 500,
9 | slidesToScroll: 4,
10 | slidesToShow: 4
11 | };
12 | return (
13 |
14 |
15 |
16 |
1
17 |
18 |
19 |
2
20 |
21 |
22 |
3
23 |
24 |
25 |
4
26 |
27 |
28 |
5
29 |
30 |
31 |
6
32 |
33 |
34 |
35 | );
36 | }
37 |
38 | export default UnevenSetsFinite;
39 |
--------------------------------------------------------------------------------
/examples/UnevenSetsInfinite.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function UnevenSetsInfinite() {
5 | var settings = {
6 | dots: true,
7 | infinite: true,
8 | speed: 500,
9 | slidesToScroll: 4,
10 | slidesToShow: 4
11 | };
12 | return (
13 |
14 |
15 |
16 |
1
17 |
18 |
19 |
2
20 |
21 |
22 |
3
23 |
24 |
25 |
4
26 |
27 |
28 |
5
29 |
30 |
31 |
6
32 |
33 |
34 |
35 | );
36 | }
37 |
38 | export default UnevenSetsInfinite;
39 |
--------------------------------------------------------------------------------
/examples/VariableWidth.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "react-slick";
3 |
4 | function VariableWidth() {
5 | const settings = {
6 | className: "slider variable-width",
7 | dots: true,
8 | infinite: true,
9 | centerMode: true,
10 | slidesToShow: 1,
11 | slidesToScroll: 1,
12 | variableWidth: true
13 | };
14 | return (
15 |
16 |
17 |
20 |
23 |
26 |
29 |
32 |
35 |
36 |
37 | );
38 | }
39 |
40 | export default VariableWidth;
41 |
--------------------------------------------------------------------------------
/examples/VerticalMode.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function VerticalMode() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | vertical: true,
11 | verticalSwiping: true,
12 | beforeChange: function(currentSlide, nextSlide) {
13 | console.log("before change", currentSlide, nextSlide);
14 | },
15 | afterChange: function(currentSlide) {
16 | console.log("after change", currentSlide);
17 | }
18 | };
19 | return (
20 |
21 |
22 |
23 |
1
24 |
25 |
26 |
2
27 |
28 |
29 |
3
30 |
31 |
32 |
4
33 |
34 |
35 |
5
36 |
37 |
38 |
6
39 |
40 |
41 |
42 | );
43 | }
44 |
45 | export default VerticalMode;
46 |
--------------------------------------------------------------------------------
/examples/VerticalSwipeToSlide.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Slider from "react-slick";
3 |
4 | function VerticalSwipeToSlide() {
5 | const settings = {
6 | dots: true,
7 | infinite: true,
8 | slidesToShow: 3,
9 | slidesToScroll: 1,
10 | vertical: true,
11 | verticalSwiping: true,
12 | swipeToSlide: true,
13 | beforeChange: function(currentSlide, nextSlide) {
14 | console.log("before change", currentSlide, nextSlide);
15 | },
16 | afterChange: function(currentSlide) {
17 | console.log("after change", currentSlide);
18 | }
19 | };
20 | return (
21 |
22 |
23 |
24 |
1
25 |
26 |
27 |
2
28 |
29 |
30 |
3
31 |
32 |
33 |
4
34 |
35 |
36 |
5
37 |
38 |
39 |
6
40 |
41 |
42 |
43 | );
44 | }
45 |
46 | export default VerticalSwipeToSlide;
47 |
--------------------------------------------------------------------------------
/examples/__tests__/CentreMode.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import CenterMode from "../CenterMode";
3 | import { render } from "@testing-library/react";
4 | import { html as beautify_html } from "js-beautify";
5 | import {
6 | getActiveSlides,
7 | getActiveSlidesCount,
8 | getClonesCount,
9 | getCurrentSlide,
10 | getSlidesCount,
11 | clickNext
12 | } from "../../test-utils";
13 |
14 | describe("CenterMode Tests", () => {
15 | test("Counting test", () => {
16 | const { container } = render( );
17 | let totalSlides = getSlidesCount(container);
18 | let clonedSlides = getClonesCount(container);
19 | let activeSlides = getActiveSlidesCount(container);
20 | expect(totalSlides).toEqual(16);
21 | expect(clonedSlides).toEqual(10);
22 | expect(activeSlides).toEqual(3);
23 | //expect(beautify_html(toString(container))).toMatchSnapshot();
24 | });
25 | test("Positioning test", () => {
26 | const { container } = render( );
27 | let currentSlide = getCurrentSlide(container);
28 | let activeslides = getActiveSlides(container);
29 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
30 | expect(
31 | Array.from(activeslides).map(e => parseInt(e.getAttribute("data-index")))
32 | ).toEqual([-1, 0, 1]);
33 | //expect(beautify_html(toString(container))).toMatchSnapshot();
34 | });
35 | test("Activity test", () => {
36 | const { container } = render( );
37 | let currentSlide = getCurrentSlide(container);
38 | let activeslides = getActiveSlides(container);
39 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
40 | expect(
41 | Array.from(activeslides).map(e => parseInt(e.getAttribute("data-index")))
42 | ).toEqual([-1, 0, 1]);
43 | clickNext(container);
44 |
45 | currentSlide = getCurrentSlide(container);
46 | activeslides = getActiveSlides(container);
47 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(1);
48 | expect(
49 | Array.from(activeslides).map(e => parseInt(e.getAttribute("data-index")))
50 | ).toEqual([0, 1, 2]);
51 |
52 | // expect(beautify_html(toString(container))).toMatchSnapshot();
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/examples/__tests__/Fade.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render } from "@testing-library/react";
3 | import Fade from "../Fade";
4 | import { getActiveSlide, clickNext, clickPrevious } from "../../test-utils";
5 |
6 | describe("Fade", () => {
7 | it("should change slides when clicked on next & prev buttons", () => {
8 | const { container } = render( );
9 | let activeslide = getActiveSlide(container);
10 | expect(parseInt(activeslide.getAttribute("data-index"))).toEqual(0);
11 | clickNext(container);
12 | activeslide = getActiveSlide(container);
13 | expect(parseInt(activeslide.getAttribute("data-index"))).toEqual(1);
14 | clickPrevious(container);
15 | activeslide = getActiveSlide(container);
16 | expect(parseInt(activeslide.getAttribute("data-index"))).toEqual(0);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/examples/__tests__/FocusOnSelect.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, fireEvent } from "@testing-library/react";
3 | import { html as beautify_html } from "js-beautify";
4 | import {
5 | activeSlide,
6 | clickNext,
7 | clickPrevious,
8 | getButtons,
9 | getCurrentSlide
10 | } from "../../test-utils";
11 | import FocusOnSelect from "../FocusOnSelect";
12 |
13 | describe("FocusOnSelect Tests", () => {
14 | test("Activity Test", () => {
15 | const { container } = render( );
16 | expect(
17 | parseInt(getCurrentSlide(container).getAttribute("data-index"))
18 | ).toEqual(0);
19 | // expect(beautify_html(toString(container))).toMatchSnapshot();
20 | Array.from(container.getElementsByClassName("slick-slide")).map(e =>
21 | e.getAttribute("data-index") == "2"
22 | ? fireEvent(
23 | e,
24 | new MouseEvent("click", { bubbles: true, cancelable: true })
25 | )
26 | : null
27 | );
28 | expect(
29 | parseInt(getCurrentSlide(container).getAttribute("data-index"))
30 | ).toEqual(2);
31 | //expect(beautify_html(toString(container))).toMatchSnapshot();
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/examples/__tests__/MultipleItems.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, fireEvent } from "@testing-library/react";
3 | import { html as beautify_html } from "js-beautify";
4 | import {
5 | activeSlide,
6 | activeSlides,
7 | clickNext,
8 | clickPrevious,
9 | getActiveButton,
10 | getActiveSlidesCount,
11 | getActiveSlidesText,
12 | getButtons,
13 | getButtonsLength,
14 | getButtonsListItem,
15 | getClonesCount,
16 | getCurrentSlide,
17 | getSlidesCount,
18 | hasClass
19 | } from "../../test-utils";
20 | import MultipleItems from "../MultipleItems";
21 |
22 | describe("Multiple Items", function() {
23 | it("should have 9 actual slides and (3(pre) + 9(post)) clone slides", function() {
24 | const { container } = render( );
25 | expect(getSlidesCount(container)).toEqual(21);
26 | expect(getClonesCount(container)).toEqual(12);
27 | //expect(beautify_html(toString(container))).toMatchSnapshot();
28 | });
29 | it("should have 3 active slides", function() {
30 | const { container } = render( );
31 | expect(getActiveSlidesCount(container)).toEqual(3);
32 | // expect(beautify_html(toString(container))).toMatchSnapshot();
33 | });
34 | it("should have 3 dots", function() {
35 | const { container } = render( );
36 | expect(getButtonsLength(container)).toEqual(3);
37 | // expect(beautify_html(toString(container))).toMatchSnapshot();
38 | });
39 | it("should show first 3 slides", function() {
40 | const { container } = render( );
41 | expect(getActiveButton(container)).toEqual(["1"]);
42 | expect(getActiveSlidesText(container)).toEqual(["1", "2", "3"]);
43 | // expect(beautify_html(toString(container))).toMatchSnapshot();
44 | });
45 | it("should show slides from 4 to 6 when next button is clicked", function() {
46 | const { container } = render( );
47 | clickNext(container);
48 | // Array.from(container.querySelectorAll(".slick-current")).map(e=>console.log(e.textContent))
49 | expect(getActiveButton(container)).toEqual(["2"]);
50 | expect(getActiveSlidesText(container)).toEqual(["4", "5", "6"]);
51 | // expect(beautify_html(toString(container))).toMatchSnapshot();
52 | });
53 | it("should show last 3 slides when previous button is clicked", function() {
54 | const { container } = render( );
55 | clickPrevious(container);
56 | expect(getActiveButton(container)).toEqual(["3"]);
57 | expect(getActiveSlidesText(container)).toEqual(["7", "8", "9"]);
58 | // expect(beautify_html(toString(container))).toMatchSnapshot();
59 | });
60 | it("should show slides first 3 slides when first dot is clicked", function() {
61 | const { container } = render( );
62 | fireEvent(
63 | getButtons(container)[0],
64 | new MouseEvent("click", {
65 | bubbles: true,
66 | cancelable: true
67 | })
68 | );
69 | expect(getActiveButton(container)).toEqual(["1"]);
70 | expect(getActiveSlidesText(container)).toEqual(["1", "2", "3"]);
71 | // expect(beautify_html(toString(container))).toMatchSnapshot();
72 | });
73 | it("should show slides from 4 to 6 when middle dot is clicked", function() {
74 | const { container } = render( );
75 | fireEvent(
76 | getButtons(container)[1],
77 | new MouseEvent("click", {
78 | bubbles: true,
79 | cancelable: true
80 | })
81 | );
82 | expect(getActiveButton(container)).toEqual(["2"]);
83 | expect(getActiveSlidesText(container)).toEqual(["4", "5", "6"]);
84 | // expect(beautify_html(toString(container))).toMatchSnapshot();
85 | });
86 | it("should show last 3 slides when last dot is clicked", function() {
87 | const { container } = render( );
88 | fireEvent(
89 | getButtons(container)[2],
90 | new MouseEvent("click", {
91 | bubbles: true,
92 | cancelable: true
93 | })
94 | );
95 | expect(getActiveButton(container)).toEqual(["3"]);
96 | expect(getActiveSlidesText(container)).toEqual(["7", "8", "9"]);
97 | // expect(beautify_html(toString(container))).toMatchSnapshot();
98 | });
99 | });
100 |
--------------------------------------------------------------------------------
/examples/__tests__/SimpleSlider.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SimpleSlider from "../SimpleSlider";
3 | import { render, fireEvent, waitFor, screen } from "@testing-library/react";
4 | import { html as beautify_html } from "js-beautify";
5 | import {
6 | getActiveSlide,
7 | clickNext,
8 | clickPrevious,
9 | hasClass,
10 | getActiveSlides,
11 | getActiveSlidesCount,
12 | getActiveSlidesText,
13 | getButtons,
14 | getButtonsListItem,
15 | getCurrentSlide
16 | } from "../../test-utils";
17 |
18 | describe("SimpleSlider example", () => {
19 | it("should have 13 slides (1(preclone) + 6(actual) + 6(postclone))", function() {
20 | const { container } = render( );
21 | expect(container.getElementsByClassName("slick-slide").length).toBe(13);
22 | });
23 | it("should have 7 clone slides", function() {
24 | const { container } = render( );
25 | expect(container.getElementsByClassName("slick-cloned").length).toBe(7);
26 | });
27 | it("should have 1 current slide", function() {
28 | const { container } = render( );
29 | expect(
30 | container.querySelectorAll(".slick-slide.slick-current").length
31 | ).toBe(1);
32 | expect(parseInt(getCurrentSlide(container).textContent) - 1).toBe(0);
33 | });
34 | it("should have 1 active slide", function() {
35 | const { container } = render( );
36 | expect(container.querySelectorAll(".slick-slide.slick-active").length).toBe(
37 | 1
38 | );
39 | expect(
40 | Array.from(getActiveSlide(container).children).map(
41 | e => parseInt(e.textContent) - 1
42 | )[0]
43 | ).toBe(0);
44 | });
45 | it("should have 6 dots", function() {
46 | const { container } = render( );
47 | expect(
48 | container.getElementsByClassName("slick-dots")[0].children.length
49 | ).toBe(6);
50 | });
51 | it("should have 1 active dot", function() {
52 | const { container } = render( );
53 |
54 | expect(container.querySelectorAll(".slick-dots .slick-active").length).toBe(
55 | 1
56 | );
57 | });
58 | it("should have a prev arrow", function() {
59 | const { container } = render( );
60 | expect(container.getElementsByClassName("slick-prev").length).toBe(1);
61 | });
62 | it("should have a next arrow", function() {
63 | const { container } = render( );
64 | expect(container.getElementsByClassName("slick-next").length).toBe(1);
65 | });
66 | it("should got to next slide when next button is clicked", function() {
67 | const { container } = render( );
68 | clickNext(container);
69 | expect(
70 | container.querySelectorAll(".slick-slide.slick-active")[0].textContent
71 | ).toBe("2");
72 | expect(container.querySelectorAll(".slick-dots .slick-active").length).toBe(
73 | 1
74 | );
75 | expect(
76 | container.querySelectorAll(".slick-dots")[0].children[1]
77 | ).toHaveClass("slick-active");
78 | });
79 | it("should goto previous slide when prev button is clicked", function() {
80 | const { container } = render( );
81 | clickPrevious(container);
82 | expect(
83 | container.querySelectorAll(".slick-slide.slick-active")[0].textContent
84 | ).toBe("6");
85 | expect(container.querySelectorAll(".slick-dots .slick-active").length).toBe(
86 | 1
87 | );
88 | expect(
89 | container.querySelectorAll(".slick-dots")[0].children[5]
90 | ).toHaveClass("slick-active");
91 | });
92 | it("should goto 4th slide when 4th dot is clicked", function() {
93 | const { container } = render( );
94 | fireEvent(
95 | container.querySelectorAll(".slick-dots button")[3],
96 | new MouseEvent("click", {
97 | bubbles: true,
98 | cancelable: true
99 | })
100 | );
101 | expect(getActiveSlidesText(container)[0]).toEqual("4");
102 | expect(getActiveSlidesCount(container)).toEqual(1);
103 | expect(hasClass(getButtonsListItem(container)[3], "slick-active")).toEqual(
104 | true
105 | );
106 | });
107 | });
108 |
109 | describe("Simple Slider Snapshots", function() {
110 | it("slider initial state", function() {
111 | const { container } = render( );
112 | // expect(beautify_html(toString(container))).toMatchSnapshot();
113 | });
114 | it("click on next button", function() {
115 | const { container } = render( );
116 | clickNext(container);
117 | //expect(beautify_html(toString(container))).toMatchSnapshot();
118 | });
119 | it("click on prev button", function() {
120 | const { container } = render( );
121 | clickPrevious(container);
122 | // expect(beautify_html(toString(container))).toMatchSnapshot();
123 | });
124 | it("click on 3rd dot", function() {
125 | const { container } = render( );
126 | fireEvent(
127 | getButtons(container)[2],
128 | new MouseEvent("click", {
129 | bubbles: true,
130 | cancelable: true
131 | })
132 | );
133 | // expect(beautify_html(toString(container))).toMatchSnapshot();
134 | });
135 | });
136 |
--------------------------------------------------------------------------------
/examples/__tests__/SlickGoTo.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { fireEvent, getRoles, render } from "@testing-library/react";
3 | import SlickGoTo from "../SlickGoTo";
4 | import { activeSlide, getActiveSlides, getSlidesCount } from "../../test-utils";
5 |
6 | describe.skip("SlickGoTo", () => {
7 | it("should goto 2nd slide", () => {
8 | const { container } = render( );
9 | fireEvent.change(container.getElementsByTagName("input")[0], {
10 | target: { value: 1 }
11 | });
12 | let currentImg = Array.from(
13 | getActiveSlide(container).getElementsByTagName("img")
14 | )[0];
15 | expect(currentImg.getAttribute("src")).toEqual(
16 | "/img/react-slick/abstract02.jpg"
17 | );
18 | });
19 | it("should goto 2nd slide, even if input is number in string format", () => {
20 | const { container } = render( );
21 | fireEvent.change(container.getElementsByTagName("input")[0], {
22 | target: { value: "1" }
23 | });
24 | let currentImg = Array.from(
25 | getActiveSlide(container).getElementsByTagName("img")
26 | )[0];
27 | expect(currentImg.getAttribute("src")).toEqual(
28 | "/img/react-slick/abstract02.jpg"
29 | );
30 | });
31 | it("should remain at 1st slide", () => {
32 | const { container } = render( );
33 | fireEvent.change(container.getElementsByTagName("input")[0], {
34 | target: { value: 0 }
35 | });
36 | let currentImg = Array.from(
37 | getActiveSlide(container).getElementsByTagName("img")
38 | )[0];
39 | expect(currentImg.getAttribute("src")).toEqual(
40 | "/img/react-slick/abstract01.jpg"
41 | );
42 | });
43 | it.skip("should go to 1st slide from another 3rd slide", () => {
44 | // skipped because two simultaneous clicks dont' work with css and speed>0
45 | const wrapper = render( );
46 | wrapper.find("input").simulate("change", { target: { value: 3 } });
47 | wrapper.find("input").simulate("change", { target: { value: 0 } });
48 | expect(wrapper.find(".slick-slide.slick-active img").props().src).toEqual(
49 | "/img/react-slick/abstract01.jpg"
50 | );
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/examples/__tests__/UnevenSets.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, fireEvent } from "@testing-library/react";
3 | import UnevenSetsFinite from "../UnevenSetsFinite";
4 | import UnevenSetsInfinite from "../UnevenSetsInfinite";
5 | import { html as beautify_html } from "js-beautify";
6 | import {
7 | getActiveSlides,
8 | clickNext,
9 | getActiveSlidesCount,
10 | getButtonsLength,
11 | getClonesCount,
12 | getCurrentSlide,
13 | getSlidesCount
14 | } from "../../test-utils";
15 |
16 | describe("UnevenSets Finite", () => {
17 | test("Counting test", () => {
18 | const { container } = render( );
19 | let totalSlides = getSlidesCount(container);
20 | let clonedSlides = getClonesCount(container);
21 | let activeSlides = getActiveSlidesCount(container);
22 | let dots = getButtonsLength(container);
23 | expect(totalSlides).toEqual(6);
24 | expect(clonedSlides).toEqual(0);
25 | expect(activeSlides).toEqual(4);
26 | expect(dots).toEqual(2);
27 | // expect(beautify_html(toString(container))).toMatchSnapshot();
28 | });
29 | test("Positioning test", () => {
30 | const { container } = render( );
31 | let currentSlide = getCurrentSlide(container);
32 | let activeslides = getActiveSlides(container);
33 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
34 | expect(
35 | Array.from(activeslides).map(slide =>
36 | parseInt(slide.getAttribute("data-index"))
37 | )
38 | ).toEqual([0, 1, 2, 3]);
39 | //expect(beautify_html(toString(container))).toMatchSnapshot();
40 | });
41 | test("Activity test", () => {
42 | const { container } = render( );
43 | let currentSlide = getCurrentSlide(container);
44 | let activeslides = getActiveSlides(container);
45 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
46 | expect(
47 | Array.from(activeslides).map(slide =>
48 | parseInt(slide.getAttribute("data-index"))
49 | )
50 | ).toEqual([0, 1, 2, 3]);
51 |
52 | clickNext(container);
53 |
54 | currentSlide = getCurrentSlide(container);
55 | activeslides = getActiveSlides(container);
56 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(4);
57 | expect(
58 | Array.from(activeslides).map(slide =>
59 | parseInt(slide.getAttribute("data-index"))
60 | )
61 | ).toEqual([2, 3, 4, 5]);
62 |
63 | clickNext(container);
64 |
65 | currentSlide = getCurrentSlide(container);
66 | activeslides = getActiveSlides(container);
67 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(4);
68 | expect(
69 | Array.from(activeslides).map(slide =>
70 | parseInt(slide.getAttribute("data-index"))
71 | )
72 | ).toEqual([2, 3, 4, 5]);
73 |
74 | // expect(beautify_html(toString(container))).toMatchSnapshot();
75 | });
76 | });
77 |
78 | describe("UnevenSets Infinite", () => {
79 | test("Counting test", () => {
80 | const { container } = render( );
81 | let totalSlides = getSlidesCount(container);
82 | let clonedSlides = getClonesCount(container);
83 | let activeSlides = getActiveSlidesCount(container);
84 | let dots = getButtonsLength(container);
85 | expect(totalSlides).toEqual(16);
86 | expect(clonedSlides).toEqual(10);
87 | expect(activeSlides).toEqual(4);
88 | expect(dots).toEqual(2);
89 | // expect(beautify_html(toString(container))).toMatchSnapshot();
90 | });
91 | test("Positioning test", () => {
92 | const { container } = render( );
93 | let currentSlide = getCurrentSlide(container);
94 | let activeslides = getActiveSlides(container);
95 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
96 | expect(
97 | Array.from(activeslides).map(slide =>
98 | parseInt(slide.getAttribute("data-index"))
99 | )
100 | ).toEqual([0, 1, 2, 3]);
101 | // expect(beautify_html(toString(container))).toMatchSnapshot();
102 | });
103 | test("Activity test", () => {
104 | const { container } = render( );
105 | let currentSlide = getCurrentSlide(container);
106 | let activeslides = getActiveSlides(container);
107 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(0);
108 | expect(
109 | Array.from(activeslides).map(slide =>
110 | parseInt(slide.getAttribute("data-index"))
111 | )
112 | ).toEqual([0, 1, 2, 3]);
113 |
114 | clickNext(container);
115 |
116 | currentSlide = getCurrentSlide(container);
117 | activeslides = getActiveSlides(container);
118 | expect(parseInt(currentSlide.getAttribute("data-index"))).toEqual(4);
119 | expect(
120 | Array.from(activeslides).map(slide =>
121 | parseInt(slide.getAttribute("data-index"))
122 | )
123 | ).toEqual([4, 5, 6, 7]);
124 | // expect(beautify_html(toString(container))).toMatchSnapshot();
125 | });
126 | });
127 |
--------------------------------------------------------------------------------
/examples/__tests__/sample.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { fireEvent, render } from "@testing-library/react";
3 |
4 | export default class Counter extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | count: 0
9 | };
10 | }
11 | render() {
12 | return (
13 | this.setState({ count: this.state.count + 1 })}>
14 | Count {this.state.count}
15 |
16 | );
17 | }
18 | }
19 |
20 | describe("sample counter test", function() {
21 | it("mutliple counts", function() {
22 | const { container } = render( );
23 | const button = container.getElementsByTagName("Button")[0];
24 | fireEvent(
25 | button,
26 | new MouseEvent("click", {
27 | bubbles: true,
28 | cancelable: true
29 | })
30 | );
31 | fireEvent(
32 | button,
33 | new MouseEvent("click", {
34 | bubbles: true,
35 | cancelable: true
36 | })
37 | );
38 | expect(button.textContent).toEqual("Count 2");
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/examples/config.js:
--------------------------------------------------------------------------------
1 | // export const baseUrl =
2 | // process.env.NODE_ENV === "production"
3 | // ? "https://s3.amazonaws.com/static.neostack.com/img/react-slick"
4 | // : "/img/react-slick";
5 |
6 | export const baseUrl = "/img/react-slick";
7 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var gulp = require("gulp");
4 | var del = require("del");
5 | var rename = require("gulp-rename");
6 | var webpack = require("webpack");
7 | var WebpackDevServer = require("webpack-dev-server");
8 | var assign = require("object-assign");
9 | var opn = require("opn");
10 |
11 | var UglifyJsPlugin = require("uglifyjs-webpack-plugin");
12 |
13 | const DEV_PORT = process.env.DEV_PORT || 8080;
14 |
15 | gulp.task("clean", function() {
16 | return del(["./build/*"]);
17 | });
18 |
19 | gulp.task("copy", function() {
20 | gulp.src("./docs/index.html").pipe(gulp.dest("./build"));
21 | gulp.src("./docs/docs.css").pipe(gulp.dest("./build"));
22 | gulp.src("./docs/slick.css").pipe(gulp.dest("./build"));
23 | gulp.src("./docs/slick-theme.css").pipe(gulp.dest("./build"));
24 | gulp.src("./docs/img/**/*").pipe(gulp.dest("./build/img"));
25 | gulp
26 | .src("./node_modules/slick-carousel/slick/fonts/*")
27 | .pipe(gulp.dest("./build/fonts"));
28 | return gulp
29 | .src("./node_modules/slick-carousel/slick/ajax-loader.gif")
30 | .pipe(gulp.dest("./build"));
31 | });
32 |
33 | gulp.task("prepare-playwright", function() {
34 | // Copy files to src-jsx directory with jsx extension
35 | return gulp
36 | .src("./src/**/*.js")
37 | .pipe(rename({ extname: ".jsx" }))
38 | .pipe(gulp.dest("./src-jsx"));
39 | });
40 |
41 | gulp.task(
42 | "watch",
43 | gulp.series(["copy"], function(done) {
44 | gulp.watch(["./docs/index.html"], gulp.parallel(["copy"]));
45 | gulp.watch(["./docs/docs.css"], gulp.parallel(["copy"]));
46 | gulp.watch(["./docs/slick.css"], gulp.parallel(["copy"]));
47 | gulp.watch(["./docs/slick-theme.css"], gulp.parallel(["copy"]));
48 | done();
49 | })
50 | );
51 |
52 | gulp.task(
53 | "server",
54 | gulp.series(["watch", "copy"], function() {
55 | console.log("Start");
56 | var myConfig = require("./webpack.config");
57 | if (process.env.SINGLE_DEMO) {
58 | myConfig.entry = {
59 | "docs.js": "./docs/single-demo.js"
60 | };
61 | }
62 | myConfig.plugins = myConfig.plugins.concat(
63 | new webpack.DefinePlugin({
64 | "process.env": {
65 | NODE_ENV: JSON.stringify("dev_docs")
66 | }
67 | })
68 | );
69 |
70 | new WebpackDevServer(webpack(myConfig), {
71 | contentBase: "./build",
72 | hot: true,
73 | stats: {
74 | colors: true
75 | }
76 | }).listen(DEV_PORT, "0.0.0.0", function(err, result) {
77 | if (err) {
78 | console.log(err);
79 | } else {
80 | const server_url = `http://0.0.0.0:${DEV_PORT}`;
81 | console.log(`> Dev Server started at ${server_url}`);
82 | opn(server_url);
83 | }
84 | });
85 | })
86 | );
87 |
88 | // gulp tasks for building dist files
89 | gulp.task("dist-clean", function() {
90 | return del(["./dist/*"]);
91 | });
92 |
93 | var distConfig = require("./webpack.config.dist.js");
94 | gulp.task("dist-unmin", function(cb) {
95 | var unminConfig = assign({}, distConfig);
96 | unminConfig.output.filename = "react-slick.js";
97 | unminConfig.mode = "none";
98 | return webpack(unminConfig, function(err, stat) {
99 | console.error(err);
100 | cb();
101 | });
102 | });
103 |
104 | gulp.task("dist-min", function(cb) {
105 | var minConfig = assign({}, distConfig);
106 | minConfig.output.filename = "react-slick.min.js";
107 | minConfig.plugins = minConfig.plugins.concat(
108 | new UglifyJsPlugin({
109 | cache: true,
110 | parallel: true,
111 | sourceMap: true,
112 | uglifyOptions: {
113 | warnings: false
114 | }
115 | })
116 | );
117 | return webpack(minConfig, function(err, stat) {
118 | console.error(err);
119 | cb();
120 | });
121 | });
122 |
123 | gulp.task(
124 | "dist",
125 | gulp.series(["dist-clean", "dist-unmin", "dist-min"], function(done) {
126 | done();
127 | })
128 | );
129 |
130 | gulp.task("default", gulp.series(["watch", "server"]));
131 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | testEnvironment: "jsdom",
3 | setupFilesAfterEnv: ["/test-setup.js"],
4 | testPathIgnorePatterns: ["/node_modules/", "playwright-tests"]
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-slick",
3 | "version": "0.30.3",
4 | "description": " React port of slick carousel",
5 | "main": "./lib",
6 | "files": [
7 | "dist",
8 | "lib"
9 | ],
10 | "scripts": {
11 | "start": "NODE_OPTIONS=--openssl-legacy-provider gulp server",
12 | "demo": "SINGLE_DEMO=true DEV_PORT=8000 NODE_OPTIONS=--openssl-legacy-provider gulp server",
13 | "build-dev": "gulp clean && gulp copy && webpack",
14 | "lib": "babel ./src --out-dir ./lib",
15 | "build": "NODE_OPTIONS=--openssl-legacy-provider npm run lib && NODE_OPTIONS=--openssl-legacy-provider gulp dist",
16 | "prepublishOnly": "npm run build",
17 | "lint": "eslint src",
18 | "gen": "node docs/scripts/generateExampleConfigs.js && node docs/scripts/generateExamples.js && xdg-open docs/jquery.html",
19 | "precommit": "lint-staged",
20 | "test": "jest",
21 | "test-watch": "jest --watch",
22 | "clear-jest": "jest --clearCache",
23 | "test-ct": "npm run prepare-playwright && playwright test -c playwright-ct.config.js",
24 | "test-clear": "jest --clearCache && rm -rf ./playwright/.cache",
25 | "prepare-playwright": "rm -rf ./src-jsx && gulp prepare-playwright"
26 | },
27 | "author": "Kiran Abburi",
28 | "license": "MIT",
29 | "repository": {
30 | "type": "git",
31 | "url": "git+https://github.com/akiran/react-slick.git"
32 | },
33 | "keywords": [
34 | "slick",
35 | "carousel",
36 | "Image slider",
37 | "orbit",
38 | "slider",
39 | "react-component"
40 | ],
41 | "devDependencies": {
42 | "@babel/cli": "^7.0.0",
43 | "@babel/core": "^7.16.0",
44 | "@babel/eslint-parser": "^7.16.3",
45 | "@babel/plugin-proposal-class-properties": "^7.1.0",
46 | "@babel/polyfill": "^7.0.0",
47 | "@babel/preset-env": "^7.1.0",
48 | "@babel/preset-react": "^7.0.0",
49 | "@playwright/experimental-ct-react": "^1.49.1",
50 | "@testing-library/jest-dom": "^5.16.4",
51 | "@testing-library/react": "^16.1.0",
52 | "@testing-library/user-event": "^14.3.0",
53 | "@types/node": "^22.10.2",
54 | "autoprefixer": "^7.1.2",
55 | "babel-core": "^7.0.0-bridge.0",
56 | "babel-jest": "^24.8.0",
57 | "babel-loader": "^8.0.4",
58 | "babel-preset-airbnb": "^2.1.1",
59 | "css-loader": "^2.1.1",
60 | "deepmerge": "^1.1.0",
61 | "del": "^2.2.2",
62 | "es5-shim": "^4.5.9",
63 | "eslint": "^8.4.1",
64 | "eslint-plugin-import": "^2.25.3",
65 | "eslint-plugin-react": "^7.27.1",
66 | "express": "^4.14.0",
67 | "foundation-apps": "^1.2.0",
68 | "gulp": "^4.0.0",
69 | "gulp-rename": "^2.0.0",
70 | "husky": "^0.14.3",
71 | "jest": "^28.1.3",
72 | "jest-environment-jsdom": "^28.1.3",
73 | "js-beautify": "^1.7.5",
74 | "json-loader": "^0.5.4",
75 | "lint-staged": "^12.1.2",
76 | "opn": "^5.4.0",
77 | "postcss-loader": "^1.3.3",
78 | "prettier": "^1.14.3",
79 | "raf": "^3.4.0",
80 | "react": "^19.0.0",
81 | "react-dom": "^19.0.0",
82 | "regenerator-runtime": "^0.14.1",
83 | "sinon": "^2.1.0",
84 | "slick-carousel": "^1.8.1",
85 | "style-loader": "^0.16.1",
86 | "uglifyjs-webpack-plugin": "^2.0.1",
87 | "webpack": "^4.21.0",
88 | "webpack-cli": "^3.1.2",
89 | "webpack-dev-server": "^3.1.9",
90 | "why-did-you-update": "^0.1.1"
91 | },
92 | "dependencies": {
93 | "classnames": "^2.2.5",
94 | "json2mq": "^0.2.0",
95 | "lodash.debounce": "^4.0.8",
96 | "resize-observer-polyfill": "^1.5.0"
97 | },
98 | "peerDependencies": {
99 | "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
100 | "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
101 | },
102 | "lint-staged": {
103 | "*.{js,json,md}": [
104 | "prettier --write",
105 | "git add"
106 | ]
107 | },
108 | "npmName": "react-slick",
109 | "npmFileMap": [
110 | {
111 | "basePath": "/dist/",
112 | "files": [
113 | "*.js"
114 | ]
115 | }
116 | ],
117 | "bugs": {
118 | "url": "https://github.com/akiran/react-slick/issues"
119 | },
120 | "homepage": "https://react-slick.neostack.com",
121 | "collective": {
122 | "type": "opencollective",
123 | "url": "https://opencollective.com/react-slick",
124 | "logo": "https://opencollective.com/opencollective/logo.txt"
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/playwright-ct.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const { defineConfig, devices } = require("@playwright/experimental-ct-react");
3 | /**
4 | * @see https://playwright.dev/docs/test-configuration
5 | */
6 | module.exports = defineConfig({
7 | testDir: "./playwright-tests",
8 | // testDir: "./tests-out",
9 | /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
10 | snapshotDir: "./__snapshots__",
11 | /* Maximum time one test can run for. */
12 | timeout: 10 * 1000,
13 | /* Run tests in files in parallel */
14 | fullyParallel: true,
15 | /* Fail the build on CI if you accidentally left test.only in the source code. */
16 | forbidOnly: !!process.env.CI,
17 | /* Retry on CI only */
18 | retries: process.env.CI ? 2 : 0,
19 | /* Opt out of parallel tests on CI. */
20 | workers: process.env.CI ? 1 : undefined,
21 | /* Reporter to use. See https://playwright.dev/docs/test-reporters */
22 | reporter: "html",
23 | /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
24 | use: {
25 | /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
26 | trace: "on-first-retry",
27 |
28 | /* Port to use for Playwright component endpoint. */
29 | ctPort: 3100
30 | },
31 |
32 | /* Configure projects for major browsers */
33 | projects: [
34 | {
35 | name: "chromium",
36 | use: { ...devices["Desktop Chrome"] }
37 | }
38 | // {
39 | // name: "firefox",
40 | // use: { ...devices["Desktop Firefox"] }
41 | // },
42 | // {
43 | // name: "webkit",
44 | // use: { ...devices["Desktop Safari"] }
45 | // }
46 | ]
47 | });
48 |
--------------------------------------------------------------------------------
/playwright-tests/features/responsive/responsive.spec.tsx:
--------------------------------------------------------------------------------
1 | import { test, expect } from "@playwright/experimental-ct-react";
2 | import Responsive from "./responsive.story";
3 |
4 | test.use({ viewport: { width: 1200, height: 500 } });
5 |
6 | async function activeSlidesCount(component) {
7 | return await component.locator(".slick-slide.slick-active").count();
8 | }
9 |
10 | test("Responsive settings", async ({ mount, page }) => {
11 | const component = await mount( );
12 |
13 | await expect(await activeSlidesCount(component)).toEqual(4);
14 |
15 | await page.setViewportSize({ width: 1000, height: 500 });
16 | await page.waitForTimeout(10);
17 | await expect(await activeSlidesCount(component)).toEqual(3);
18 |
19 | await page.setViewportSize({ width: 600, height: 500 });
20 | await page.waitForTimeout(10);
21 | await expect(await activeSlidesCount(component)).toEqual(2);
22 |
23 | await page.setViewportSize({ width: 400, height: 500 });
24 | await page.waitForTimeout(10);
25 | await expect(await activeSlidesCount(component)).toEqual(1);
26 |
27 | await page.setViewportSize({ width: 600, height: 500 });
28 | await page.waitForTimeout(10);
29 | await expect(await activeSlidesCount(component)).toEqual(2);
30 |
31 | await page.setViewportSize({ width: 1000, height: 500 });
32 | await page.waitForTimeout(10);
33 | await expect(await activeSlidesCount(component)).toEqual(3);
34 |
35 | await page.setViewportSize({ width: 1500, height: 500 });
36 | await page.waitForTimeout(10);
37 | await expect(await activeSlidesCount(component)).toEqual(4);
38 | });
39 |
--------------------------------------------------------------------------------
/playwright-tests/features/responsive/responsive.story.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Slider from "../../../src-jsx";
3 |
4 | function Responsive() {
5 | var settings = {
6 | dots: true,
7 | infinite: false,
8 | speed: 500,
9 | slidesToShow: 4,
10 | slidesToScroll: 4,
11 | initialSlide: 0,
12 | responsive: [
13 | {
14 | breakpoint: 1024,
15 | settings: {
16 | slidesToShow: 3,
17 | slidesToScroll: 3,
18 | infinite: true,
19 | dots: true
20 | }
21 | },
22 | {
23 | breakpoint: 600,
24 | settings: {
25 | slidesToShow: 2,
26 | slidesToScroll: 2,
27 | initialSlide: 2
28 | }
29 | },
30 | {
31 | breakpoint: 480,
32 | settings: {
33 | slidesToShow: 1,
34 | slidesToScroll: 1
35 | }
36 | }
37 | ]
38 | };
39 | return (
40 |
41 |
42 |
43 |
1
44 |
45 |
46 |
2
47 |
48 |
49 |
3
50 |
51 |
52 |
4
53 |
54 |
55 |
5
56 |
57 |
58 |
6
59 |
60 |
61 |
7
62 |
63 |
64 |
8
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default Responsive;
72 |
--------------------------------------------------------------------------------
/playwright-tests/regression/fix-1930/fix-1930.spec.tsx:
--------------------------------------------------------------------------------
1 | // Test fix of #1930: Extra height of slider in vertical mode when number of slides is less than or equal to slidesToShow
2 |
3 | import { test, expect } from "@playwright/experimental-ct-react";
4 | import { VerticalModeFinite, VerticalModeInfinite } from "./fix-1930.story";
5 |
6 | test.use({ viewport: { width: 500, height: 500 } });
7 |
8 | test("height check in vertical mode when slides < slidesToShow and finite", async ({
9 | mount
10 | }) => {
11 | const component = await mount( );
12 |
13 | const track = component.locator(".slick-track").first();
14 | const box = await track.boundingBox();
15 | await expect(box.height).toEqual(200);
16 | });
17 |
18 | test("height check in vertical mode when slides < slidesToShow and infinite", async ({
19 | mount
20 | }) => {
21 | const component = await mount( );
22 |
23 | const track = component.locator(".slick-track").first();
24 | const box = await track.boundingBox();
25 | await expect(box.height).toEqual(200);
26 | });
27 |
--------------------------------------------------------------------------------
/playwright-tests/regression/fix-1930/fix-1930.story.tsx:
--------------------------------------------------------------------------------
1 | import Slider from "../../../src-jsx";
2 | import React from "react";
3 |
4 | export function VerticalModeFinite() {
5 | const settings = {
6 | dots: true,
7 | infinite: false,
8 | vertical: true,
9 | slidesToShow: 3
10 | };
11 | return (
12 |
13 |
16 |
19 |
20 | );
21 | }
22 |
23 | export function VerticalModeInfinite() {
24 | const settings = {
25 | dots: true,
26 | infinite: true,
27 | vertical: true,
28 | slidesToShow: 3
29 | };
30 | return (
31 |
32 |
35 |
38 |
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/playwright-tests/sample/sample.spec.tsx:
--------------------------------------------------------------------------------
1 | //Imports the test and expect functions from the Playwright ct-react module
2 | import { test, expect } from "@playwright/experimental-ct-react";
3 | //Imports the App component to test from the relative ../App path
4 | import App from "./sample.story";
5 |
6 | //Configures the viewport to a 500x500 size
7 | test.use({ viewport: { width: 500, height: 500 } });
8 | //Starts a test case named "should work" which will run asynchronously,
9 | //mount function binding is destructured from test parameter
10 | test("Sample playwright test", async ({ mount }) => {
11 | //Uses mount() to instantiate the component in isolation
12 | const component = await mount( );
13 | //Asserts that component contains expected "Learn React" text on it verifying basic render.
14 | await expect(component).toContainText("Learn React");
15 | });
16 |
--------------------------------------------------------------------------------
/playwright-tests/sample/sample.story.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default function App() {
4 | return Learn React
;
5 | }
6 |
--------------------------------------------------------------------------------
/playwright/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Testing Page
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/playwright/index.jsx:
--------------------------------------------------------------------------------
1 | // Import styles, initialize component theme here.
2 | // import '../src/common.css';
3 |
--------------------------------------------------------------------------------
/src/arrows.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import classnames from "classnames";
5 | import { canGoNext } from "./utils/innerSliderUtils";
6 |
7 | export class PrevArrow extends React.PureComponent {
8 | clickHandler(options, e) {
9 | if (e) {
10 | e.preventDefault();
11 | }
12 | this.props.clickHandler(options, e);
13 | }
14 | render() {
15 | let prevClasses = { "slick-arrow": true, "slick-prev": true };
16 | let prevHandler = this.clickHandler.bind(this, { message: "previous" });
17 |
18 | if (
19 | !this.props.infinite &&
20 | (this.props.currentSlide === 0 ||
21 | this.props.slideCount <= this.props.slidesToShow)
22 | ) {
23 | prevClasses["slick-disabled"] = true;
24 | prevHandler = null;
25 | }
26 |
27 | let prevArrowProps = {
28 | key: "0",
29 | "data-role": "none",
30 | className: classnames(prevClasses),
31 | style: { display: "block" },
32 | onClick: prevHandler
33 | };
34 | let customProps = {
35 | currentSlide: this.props.currentSlide,
36 | slideCount: this.props.slideCount
37 | };
38 | let prevArrow;
39 |
40 | if (this.props.prevArrow) {
41 | prevArrow = React.cloneElement(this.props.prevArrow, {
42 | ...prevArrowProps,
43 | ...customProps
44 | });
45 | } else {
46 | prevArrow = (
47 |
48 | {" "}
49 | Previous
50 |
51 | );
52 | }
53 |
54 | return prevArrow;
55 | }
56 | }
57 |
58 | export class NextArrow extends React.PureComponent {
59 | clickHandler(options, e) {
60 | if (e) {
61 | e.preventDefault();
62 | }
63 | this.props.clickHandler(options, e);
64 | }
65 | render() {
66 | let nextClasses = { "slick-arrow": true, "slick-next": true };
67 | let nextHandler = this.clickHandler.bind(this, { message: "next" });
68 |
69 | if (!canGoNext(this.props)) {
70 | nextClasses["slick-disabled"] = true;
71 | nextHandler = null;
72 | }
73 |
74 | let nextArrowProps = {
75 | key: "1",
76 | "data-role": "none",
77 | className: classnames(nextClasses),
78 | style: { display: "block" },
79 | onClick: nextHandler
80 | };
81 | let customProps = {
82 | currentSlide: this.props.currentSlide,
83 | slideCount: this.props.slideCount
84 | };
85 | let nextArrow;
86 |
87 | if (this.props.nextArrow) {
88 | nextArrow = React.cloneElement(this.props.nextArrow, {
89 | ...nextArrowProps,
90 | ...customProps
91 | });
92 | } else {
93 | nextArrow = (
94 |
95 | {" "}
96 | Next
97 |
98 | );
99 | }
100 |
101 | return nextArrow;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/default-props.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | let defaultProps = {
4 | accessibility: true,
5 | adaptiveHeight: false,
6 | afterChange: null,
7 | appendDots: dots => ,
8 | arrows: true,
9 | autoplay: false,
10 | autoplaySpeed: 3000,
11 | beforeChange: null,
12 | centerMode: false,
13 | centerPadding: "50px",
14 | className: "",
15 | cssEase: "ease",
16 | customPaging: i => {i + 1} ,
17 | dots: false,
18 | dotsClass: "slick-dots",
19 | draggable: true,
20 | easing: "linear",
21 | edgeFriction: 0.35,
22 | fade: false,
23 | focusOnSelect: false,
24 | infinite: true,
25 | initialSlide: 0,
26 | lazyLoad: null,
27 | nextArrow: null,
28 | onEdge: null,
29 | onInit: null,
30 | onLazyLoadError: null,
31 | onReInit: null,
32 | pauseOnDotsHover: false,
33 | pauseOnFocus: false,
34 | pauseOnHover: true,
35 | prevArrow: null,
36 | responsive: null,
37 | rows: 1,
38 | rtl: false,
39 | slide: "div",
40 | slidesPerRow: 1,
41 | slidesToScroll: 1,
42 | slidesToShow: 1,
43 | speed: 500,
44 | swipe: true,
45 | swipeEvent: null,
46 | swipeToSlide: false,
47 | touchMove: true,
48 | touchThreshold: 5,
49 | useCSS: true,
50 | useTransform: true,
51 | variableWidth: false,
52 | vertical: false,
53 | verticalSwiping: false,
54 | waitForAnimate: true,
55 | asNavFor: null,
56 | unslick: false
57 | };
58 |
59 | export default defaultProps;
60 |
--------------------------------------------------------------------------------
/src/dots.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import classnames from "classnames";
5 | import { clamp } from "./utils/innerSliderUtils";
6 |
7 | const getDotCount = spec => {
8 | let dots;
9 |
10 | if (spec.infinite) {
11 | dots = Math.ceil(spec.slideCount / spec.slidesToScroll);
12 | } else {
13 | dots =
14 | Math.ceil((spec.slideCount - spec.slidesToShow) / spec.slidesToScroll) +
15 | 1;
16 | }
17 |
18 | return dots;
19 | };
20 |
21 | export class Dots extends React.PureComponent {
22 | clickHandler(options, e) {
23 | // In Autoplay the focus stays on clicked button even after transition
24 | // to next slide. That only goes away by click somewhere outside
25 | e.preventDefault();
26 | this.props.clickHandler(options);
27 | }
28 | render() {
29 | const {
30 | onMouseEnter,
31 | onMouseOver,
32 | onMouseLeave,
33 | infinite,
34 | slidesToScroll,
35 | slidesToShow,
36 | slideCount,
37 | currentSlide
38 | } = this.props;
39 | let dotCount = getDotCount({
40 | slideCount,
41 | slidesToScroll,
42 | slidesToShow,
43 | infinite
44 | });
45 |
46 | const mouseEvents = { onMouseEnter, onMouseOver, onMouseLeave };
47 | let dots = [];
48 | for (let i = 0; i < dotCount; i++) {
49 | let _rightBound = (i + 1) * slidesToScroll - 1;
50 | let rightBound = infinite
51 | ? _rightBound
52 | : clamp(_rightBound, 0, slideCount - 1);
53 | let _leftBound = rightBound - (slidesToScroll - 1);
54 | let leftBound = infinite
55 | ? _leftBound
56 | : clamp(_leftBound, 0, slideCount - 1);
57 |
58 | let className = classnames({
59 | "slick-active": infinite
60 | ? currentSlide >= leftBound && currentSlide <= rightBound
61 | : currentSlide === leftBound
62 | });
63 |
64 | let dotOptions = {
65 | message: "dots",
66 | index: i,
67 | slidesToScroll,
68 | currentSlide
69 | };
70 |
71 | let onClick = this.clickHandler.bind(this, dotOptions);
72 | dots = dots.concat(
73 |
74 | {React.cloneElement(this.props.customPaging(i), { onClick })}
75 |
76 | );
77 | }
78 |
79 | return React.cloneElement(this.props.appendDots(dots), {
80 | className: this.props.dotsClass,
81 | ...mouseEvents
82 | });
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Slider from "./slider";
2 |
3 | export default Slider;
4 |
--------------------------------------------------------------------------------
/src/initial-state.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | animating: false,
3 | autoplaying: null,
4 | currentDirection: 0,
5 | currentLeft: null,
6 | currentSlide: 0,
7 | direction: 1,
8 | dragging: false,
9 | edgeDragged: false,
10 | initialized: false,
11 | lazyLoadedList: [],
12 | listHeight: null,
13 | listWidth: null,
14 | scrolling: false,
15 | slideCount: null,
16 | slideHeight: null,
17 | slideWidth: null,
18 | swipeLeft: null,
19 | swiped: false, // used by swipeEvent. differentites between touch and swipe.
20 | swiping: false,
21 | touchObject: { startX: 0, startY: 0, curX: 0, curY: 0 },
22 | trackStyle: {},
23 | trackWidth: 0,
24 | targetSlide: 0
25 | };
26 |
27 | export default initialState;
28 |
--------------------------------------------------------------------------------
/src/inner-slider.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import initialState from "./initial-state";
5 | import debounce from "lodash.debounce";
6 | import classnames from "classnames";
7 | import {
8 | getOnDemandLazySlides,
9 | extractObject,
10 | initializedState,
11 | getHeight,
12 | canGoNext,
13 | slideHandler,
14 | changeSlide,
15 | keyHandler,
16 | swipeStart,
17 | swipeMove,
18 | swipeEnd,
19 | getPreClones,
20 | getPostClones,
21 | getTrackLeft,
22 | getTrackCSS
23 | } from "./utils/innerSliderUtils";
24 |
25 | import { Track } from "./track";
26 | import { Dots } from "./dots";
27 | import { PrevArrow, NextArrow } from "./arrows";
28 | import ResizeObserver from "resize-observer-polyfill";
29 |
30 | export class InnerSlider extends React.Component {
31 | constructor(props) {
32 | super(props);
33 | this.list = null;
34 | this.track = null;
35 | this.state = {
36 | ...initialState,
37 | currentSlide: this.props.initialSlide,
38 | targetSlide: this.props.initialSlide ? this.props.initialSlide : 0,
39 | slideCount: React.Children.count(this.props.children)
40 | };
41 | this.callbackTimers = [];
42 | this.clickable = true;
43 | this.debouncedResize = null;
44 | const ssrState = this.ssrInit();
45 | this.state = { ...this.state, ...ssrState };
46 | }
47 | listRefHandler = ref => (this.list = ref);
48 | trackRefHandler = ref => (this.track = ref);
49 | adaptHeight = () => {
50 | if (this.props.adaptiveHeight && this.list) {
51 | const elem = this.list.querySelector(
52 | `[data-index="${this.state.currentSlide}"]`
53 | );
54 | this.list.style.height = getHeight(elem) + "px";
55 | }
56 | };
57 | componentDidMount = () => {
58 | this.props.onInit && this.props.onInit();
59 | if (this.props.lazyLoad) {
60 | let slidesToLoad = getOnDemandLazySlides({
61 | ...this.props,
62 | ...this.state
63 | });
64 | if (slidesToLoad.length > 0) {
65 | this.setState(prevState => ({
66 | lazyLoadedList: prevState.lazyLoadedList.concat(slidesToLoad)
67 | }));
68 | if (this.props.onLazyLoad) {
69 | this.props.onLazyLoad(slidesToLoad);
70 | }
71 | }
72 | }
73 | let spec = { listRef: this.list, trackRef: this.track, ...this.props };
74 | this.updateState(spec, true, () => {
75 | this.adaptHeight();
76 | this.props.autoplay && this.autoPlay("update");
77 | });
78 | if (this.props.lazyLoad === "progressive") {
79 | this.lazyLoadTimer = setInterval(this.progressiveLazyLoad, 1000);
80 | }
81 | this.ro = new ResizeObserver(() => {
82 | if (this.state.animating) {
83 | this.onWindowResized(false); // don't set trackStyle hence don't break animation
84 | this.callbackTimers.push(
85 | setTimeout(() => this.onWindowResized(), this.props.speed)
86 | );
87 | } else {
88 | this.onWindowResized();
89 | }
90 | });
91 | this.ro.observe(this.list);
92 | document.querySelectorAll &&
93 | Array.prototype.forEach.call(
94 | document.querySelectorAll(".slick-slide"),
95 | slide => {
96 | slide.onfocus = this.props.pauseOnFocus ? this.onSlideFocus : null;
97 | slide.onblur = this.props.pauseOnFocus ? this.onSlideBlur : null;
98 | }
99 | );
100 | if (window.addEventListener) {
101 | window.addEventListener("resize", this.onWindowResized);
102 | } else {
103 | window.attachEvent("onresize", this.onWindowResized);
104 | }
105 | };
106 | componentWillUnmount = () => {
107 | if (this.animationEndCallback) {
108 | clearTimeout(this.animationEndCallback);
109 | }
110 | if (this.lazyLoadTimer) {
111 | clearInterval(this.lazyLoadTimer);
112 | }
113 | if (this.callbackTimers.length) {
114 | this.callbackTimers.forEach(timer => clearTimeout(timer));
115 | this.callbackTimers = [];
116 | }
117 | if (window.addEventListener) {
118 | window.removeEventListener("resize", this.onWindowResized);
119 | } else {
120 | window.detachEvent("onresize", this.onWindowResized);
121 | }
122 | if (this.autoplayTimer) {
123 | clearInterval(this.autoplayTimer);
124 | }
125 | this.ro.disconnect();
126 | };
127 |
128 | didPropsChange(prevProps) {
129 | let setTrackStyle = false;
130 | for (let key of Object.keys(this.props)) {
131 | if (!prevProps.hasOwnProperty(key)) {
132 | setTrackStyle = true;
133 | break;
134 | }
135 | if (
136 | typeof prevProps[key] === "object" ||
137 | typeof prevProps[key] === "function" ||
138 | isNaN(prevProps[key])
139 | ) {
140 | continue;
141 | }
142 | if (prevProps[key] !== this.props[key]) {
143 | setTrackStyle = true;
144 | break;
145 | }
146 | }
147 | return (
148 | setTrackStyle ||
149 | React.Children.count(this.props.children) !==
150 | React.Children.count(prevProps.children)
151 | );
152 | }
153 |
154 | componentDidUpdate = prevProps => {
155 | this.checkImagesLoad();
156 | this.props.onReInit && this.props.onReInit();
157 | if (this.props.lazyLoad) {
158 | let slidesToLoad = getOnDemandLazySlides({
159 | ...this.props,
160 | ...this.state
161 | });
162 | if (slidesToLoad.length > 0) {
163 | this.setState(prevState => ({
164 | lazyLoadedList: prevState.lazyLoadedList.concat(slidesToLoad)
165 | }));
166 | if (this.props.onLazyLoad) {
167 | this.props.onLazyLoad(slidesToLoad);
168 | }
169 | }
170 | }
171 | // if (this.props.onLazyLoad) {
172 | // this.props.onLazyLoad([leftMostSlide])
173 | // }
174 | this.adaptHeight();
175 | let spec = {
176 | listRef: this.list,
177 | trackRef: this.track,
178 | ...this.props,
179 | ...this.state
180 | };
181 | const setTrackStyle = this.didPropsChange(prevProps);
182 | setTrackStyle &&
183 | this.updateState(spec, setTrackStyle, () => {
184 | if (
185 | this.state.currentSlide >= React.Children.count(this.props.children)
186 | ) {
187 | this.changeSlide({
188 | message: "index",
189 | index:
190 | React.Children.count(this.props.children) -
191 | this.props.slidesToShow,
192 | currentSlide: this.state.currentSlide
193 | });
194 | }
195 | if (this.props.autoplay) {
196 | this.autoPlay("update");
197 | } else {
198 | this.pause("paused");
199 | }
200 | });
201 | };
202 | onWindowResized = setTrackStyle => {
203 | if (this.debouncedResize) this.debouncedResize.cancel();
204 | this.debouncedResize = debounce(() => this.resizeWindow(setTrackStyle), 50);
205 | this.debouncedResize();
206 | };
207 | resizeWindow = (setTrackStyle = true) => {
208 | const isTrackMounted = Boolean(this.track && this.track.node);
209 | // prevent warning: setting state on unmounted component (server side rendering)
210 | if (!isTrackMounted) return;
211 | let spec = {
212 | listRef: this.list,
213 | trackRef: this.track,
214 | ...this.props,
215 | ...this.state
216 | };
217 | this.updateState(spec, setTrackStyle, () => {
218 | if (this.props.autoplay) this.autoPlay("update");
219 | else this.pause("paused");
220 | });
221 | // animating state should be cleared while resizing, otherwise autoplay stops working
222 | this.setState({
223 | animating: false
224 | });
225 | clearTimeout(this.animationEndCallback);
226 | delete this.animationEndCallback;
227 | };
228 | updateState = (spec, setTrackStyle, callback) => {
229 | let updatedState = initializedState(spec);
230 | spec = { ...spec, ...updatedState, slideIndex: updatedState.currentSlide };
231 | let targetLeft = getTrackLeft(spec);
232 | spec = { ...spec, left: targetLeft };
233 | let trackStyle = getTrackCSS(spec);
234 | if (
235 | setTrackStyle ||
236 | React.Children.count(this.props.children) !==
237 | React.Children.count(spec.children)
238 | ) {
239 | updatedState["trackStyle"] = trackStyle;
240 | }
241 | this.setState(updatedState, callback);
242 | };
243 |
244 | ssrInit = () => {
245 | if (this.props.variableWidth) {
246 | let trackWidth = 0,
247 | trackLeft = 0;
248 | let childrenWidths = [];
249 | let preClones = getPreClones({
250 | ...this.props,
251 | ...this.state,
252 | slideCount: this.props.children.length
253 | });
254 | let postClones = getPostClones({
255 | ...this.props,
256 | ...this.state,
257 | slideCount: this.props.children.length
258 | });
259 | this.props.children.forEach(child => {
260 | childrenWidths.push(child.props.style.width);
261 | trackWidth += child.props.style.width;
262 | });
263 | for (let i = 0; i < preClones; i++) {
264 | trackLeft += childrenWidths[childrenWidths.length - 1 - i];
265 | trackWidth += childrenWidths[childrenWidths.length - 1 - i];
266 | }
267 | for (let i = 0; i < postClones; i++) {
268 | trackWidth += childrenWidths[i];
269 | }
270 | for (let i = 0; i < this.state.currentSlide; i++) {
271 | trackLeft += childrenWidths[i];
272 | }
273 | let trackStyle = {
274 | width: trackWidth + "px",
275 | left: -trackLeft + "px"
276 | };
277 | if (this.props.centerMode) {
278 | let currentWidth = `${childrenWidths[this.state.currentSlide]}px`;
279 | trackStyle.left = `calc(${trackStyle.left} + (100% - ${currentWidth}) / 2 ) `;
280 | }
281 | return {
282 | trackStyle
283 | };
284 | }
285 | let childrenCount = React.Children.count(this.props.children);
286 | const spec = { ...this.props, ...this.state, slideCount: childrenCount };
287 | let slideCount = getPreClones(spec) + getPostClones(spec) + childrenCount;
288 | let trackWidth = (100 / this.props.slidesToShow) * slideCount;
289 | let slideWidth = 100 / slideCount;
290 | let trackLeft =
291 | (-slideWidth *
292 | (getPreClones(spec) + this.state.currentSlide) *
293 | trackWidth) /
294 | 100;
295 | if (this.props.centerMode) {
296 | trackLeft += (100 - (slideWidth * trackWidth) / 100) / 2;
297 | }
298 | let trackStyle = {
299 | width: trackWidth + "%",
300 | left: trackLeft + "%"
301 | };
302 | return {
303 | slideWidth: slideWidth + "%",
304 | trackStyle: trackStyle
305 | };
306 | };
307 | checkImagesLoad = () => {
308 | let images =
309 | (this.list &&
310 | this.list.querySelectorAll &&
311 | this.list.querySelectorAll(".slick-slide img")) ||
312 | [];
313 | let imagesCount = images.length,
314 | loadedCount = 0;
315 | Array.prototype.forEach.call(images, image => {
316 | const handler = () =>
317 | ++loadedCount && loadedCount >= imagesCount && this.onWindowResized();
318 | if (!image.onclick) {
319 | image.onclick = () => image.parentNode.focus();
320 | } else {
321 | const prevClickHandler = image.onclick;
322 | image.onclick = e => {
323 | prevClickHandler(e);
324 | image.parentNode.focus();
325 | };
326 | }
327 | if (!image.onload) {
328 | if (this.props.lazyLoad) {
329 | image.onload = () => {
330 | this.adaptHeight();
331 | this.callbackTimers.push(
332 | setTimeout(this.onWindowResized, this.props.speed)
333 | );
334 | };
335 | } else {
336 | image.onload = handler;
337 | image.onerror = () => {
338 | handler();
339 | this.props.onLazyLoadError && this.props.onLazyLoadError();
340 | };
341 | }
342 | }
343 | });
344 | };
345 | progressiveLazyLoad = () => {
346 | let slidesToLoad = [];
347 | const spec = { ...this.props, ...this.state };
348 | for (
349 | let index = this.state.currentSlide;
350 | index < this.state.slideCount + getPostClones(spec);
351 | index++
352 | ) {
353 | if (this.state.lazyLoadedList.indexOf(index) < 0) {
354 | slidesToLoad.push(index);
355 | break;
356 | }
357 | }
358 | for (
359 | let index = this.state.currentSlide - 1;
360 | index >= -getPreClones(spec);
361 | index--
362 | ) {
363 | if (this.state.lazyLoadedList.indexOf(index) < 0) {
364 | slidesToLoad.push(index);
365 | break;
366 | }
367 | }
368 | if (slidesToLoad.length > 0) {
369 | this.setState(state => ({
370 | lazyLoadedList: state.lazyLoadedList.concat(slidesToLoad)
371 | }));
372 | if (this.props.onLazyLoad) {
373 | this.props.onLazyLoad(slidesToLoad);
374 | }
375 | } else {
376 | if (this.lazyLoadTimer) {
377 | clearInterval(this.lazyLoadTimer);
378 | delete this.lazyLoadTimer;
379 | }
380 | }
381 | };
382 | slideHandler = (index, dontAnimate = false) => {
383 | const {
384 | asNavFor,
385 | beforeChange,
386 | onLazyLoad,
387 | speed,
388 | afterChange
389 | } = this.props;
390 | // capture currentslide before state is updated
391 | const currentSlide = this.state.currentSlide;
392 | let { state, nextState } = slideHandler({
393 | index,
394 | ...this.props,
395 | ...this.state,
396 | trackRef: this.track,
397 | useCSS: this.props.useCSS && !dontAnimate
398 | });
399 | if (!state) return;
400 | beforeChange && beforeChange(currentSlide, state.currentSlide);
401 | let slidesToLoad = state.lazyLoadedList.filter(
402 | value => this.state.lazyLoadedList.indexOf(value) < 0
403 | );
404 | onLazyLoad && slidesToLoad.length > 0 && onLazyLoad(slidesToLoad);
405 | if (!this.props.waitForAnimate && this.animationEndCallback) {
406 | clearTimeout(this.animationEndCallback);
407 | afterChange && afterChange(currentSlide);
408 | delete this.animationEndCallback;
409 | }
410 | this.setState(state, () => {
411 | // asNavForIndex check is to avoid recursive calls of slideHandler in waitForAnimate=false mode
412 | if (asNavFor && this.asNavForIndex !== index) {
413 | this.asNavForIndex = index;
414 | asNavFor.innerSlider.slideHandler(index);
415 | }
416 | if (!nextState) return;
417 | this.animationEndCallback = setTimeout(() => {
418 | const { animating, ...firstBatch } = nextState;
419 | this.setState(firstBatch, () => {
420 | this.callbackTimers.push(
421 | setTimeout(() => this.setState({ animating }), 10)
422 | );
423 | afterChange && afterChange(state.currentSlide);
424 | delete this.animationEndCallback;
425 | });
426 | }, speed);
427 | });
428 | };
429 | changeSlide = (options, dontAnimate = false) => {
430 | const spec = { ...this.props, ...this.state };
431 | let targetSlide = changeSlide(spec, options);
432 | if (targetSlide !== 0 && !targetSlide) return;
433 | if (dontAnimate === true) {
434 | this.slideHandler(targetSlide, dontAnimate);
435 | } else {
436 | this.slideHandler(targetSlide);
437 | }
438 | this.props.autoplay && this.autoPlay("update");
439 | if (this.props.focusOnSelect) {
440 | const nodes = this.list.querySelectorAll(".slick-current");
441 | nodes[0] && nodes[0].focus();
442 | }
443 | };
444 | clickHandler = e => {
445 | if (this.clickable === false) {
446 | e.stopPropagation();
447 | e.preventDefault();
448 | }
449 | this.clickable = true;
450 | };
451 | keyHandler = e => {
452 | let dir = keyHandler(e, this.props.accessibility, this.props.rtl);
453 | dir !== "" && this.changeSlide({ message: dir });
454 | };
455 | selectHandler = options => {
456 | this.changeSlide(options);
457 | };
458 | disableBodyScroll = () => {
459 | const preventDefault = e => {
460 | e = e || window.event;
461 | if (e.preventDefault) e.preventDefault();
462 | e.returnValue = false;
463 | };
464 | window.ontouchmove = preventDefault;
465 | };
466 | enableBodyScroll = () => {
467 | window.ontouchmove = null;
468 | };
469 | swipeStart = e => {
470 | if (this.props.verticalSwiping) {
471 | this.disableBodyScroll();
472 | }
473 | let state = swipeStart(e, this.props.swipe, this.props.draggable);
474 | state !== "" && this.setState(state);
475 | };
476 | swipeMove = e => {
477 | let state = swipeMove(e, {
478 | ...this.props,
479 | ...this.state,
480 | trackRef: this.track,
481 | listRef: this.list,
482 | slideIndex: this.state.currentSlide
483 | });
484 | if (!state) return;
485 | if (state["swiping"]) {
486 | this.clickable = false;
487 | }
488 | this.setState(state);
489 | };
490 | swipeEnd = e => {
491 | let state = swipeEnd(e, {
492 | ...this.props,
493 | ...this.state,
494 | trackRef: this.track,
495 | listRef: this.list,
496 | slideIndex: this.state.currentSlide
497 | });
498 | if (!state) return;
499 | let triggerSlideHandler = state["triggerSlideHandler"];
500 | delete state["triggerSlideHandler"];
501 | this.setState(state);
502 | if (triggerSlideHandler === undefined) return;
503 | this.slideHandler(triggerSlideHandler);
504 | if (this.props.verticalSwiping) {
505 | this.enableBodyScroll();
506 | }
507 | };
508 | touchEnd = e => {
509 | this.swipeEnd(e);
510 | this.clickable = true;
511 | };
512 | slickPrev = () => {
513 | // this and fellow methods are wrapped in setTimeout
514 | // to make sure initialize setState has happened before
515 | // any of such methods are called
516 | this.callbackTimers.push(
517 | setTimeout(() => this.changeSlide({ message: "previous" }), 0)
518 | );
519 | };
520 | slickNext = () => {
521 | this.callbackTimers.push(
522 | setTimeout(() => this.changeSlide({ message: "next" }), 0)
523 | );
524 | };
525 | slickGoTo = (slide, dontAnimate = false) => {
526 | slide = Number(slide);
527 | if (isNaN(slide)) return "";
528 | this.callbackTimers.push(
529 | setTimeout(
530 | () =>
531 | this.changeSlide(
532 | {
533 | message: "index",
534 | index: slide,
535 | currentSlide: this.state.currentSlide
536 | },
537 | dontAnimate
538 | ),
539 | 0
540 | )
541 | );
542 | };
543 | play = () => {
544 | var nextIndex;
545 | if (this.props.rtl) {
546 | nextIndex = this.state.currentSlide - this.props.slidesToScroll;
547 | } else {
548 | if (canGoNext({ ...this.props, ...this.state })) {
549 | nextIndex = this.state.currentSlide + this.props.slidesToScroll;
550 | } else {
551 | return false;
552 | }
553 | }
554 |
555 | this.slideHandler(nextIndex);
556 | };
557 |
558 | autoPlay = playType => {
559 | if (this.autoplayTimer) {
560 | clearInterval(this.autoplayTimer);
561 | }
562 | const autoplaying = this.state.autoplaying;
563 | if (playType === "update") {
564 | if (
565 | autoplaying === "hovered" ||
566 | autoplaying === "focused" ||
567 | autoplaying === "paused"
568 | ) {
569 | return;
570 | }
571 | } else if (playType === "leave") {
572 | if (autoplaying === "paused" || autoplaying === "focused") {
573 | return;
574 | }
575 | } else if (playType === "blur") {
576 | if (autoplaying === "paused" || autoplaying === "hovered") {
577 | return;
578 | }
579 | }
580 | this.autoplayTimer = setInterval(this.play, this.props.autoplaySpeed + 50);
581 | this.setState({ autoplaying: "playing" });
582 | };
583 | pause = pauseType => {
584 | if (this.autoplayTimer) {
585 | clearInterval(this.autoplayTimer);
586 | this.autoplayTimer = null;
587 | }
588 | const autoplaying = this.state.autoplaying;
589 | if (pauseType === "paused") {
590 | this.setState({ autoplaying: "paused" });
591 | } else if (pauseType === "focused") {
592 | if (autoplaying === "hovered" || autoplaying === "playing") {
593 | this.setState({ autoplaying: "focused" });
594 | }
595 | } else {
596 | // pauseType is 'hovered'
597 | if (autoplaying === "playing") {
598 | this.setState({ autoplaying: "hovered" });
599 | }
600 | }
601 | };
602 | onDotsOver = () => this.props.autoplay && this.pause("hovered");
603 | onDotsLeave = () =>
604 | this.props.autoplay &&
605 | this.state.autoplaying === "hovered" &&
606 | this.autoPlay("leave");
607 | onTrackOver = () => this.props.autoplay && this.pause("hovered");
608 | onTrackLeave = () =>
609 | this.props.autoplay &&
610 | this.state.autoplaying === "hovered" &&
611 | this.autoPlay("leave");
612 | onSlideFocus = () => this.props.autoplay && this.pause("focused");
613 | onSlideBlur = () =>
614 | this.props.autoplay &&
615 | this.state.autoplaying === "focused" &&
616 | this.autoPlay("blur");
617 |
618 | render = () => {
619 | var className = classnames("slick-slider", this.props.className, {
620 | "slick-vertical": this.props.vertical,
621 | "slick-initialized": true
622 | });
623 | let spec = { ...this.props, ...this.state };
624 | let trackProps = extractObject(spec, [
625 | "fade",
626 | "cssEase",
627 | "speed",
628 | "infinite",
629 | "centerMode",
630 | "focusOnSelect",
631 | "currentSlide",
632 | "lazyLoad",
633 | "lazyLoadedList",
634 | "rtl",
635 | "slideWidth",
636 | "slideHeight",
637 | "listHeight",
638 | "vertical",
639 | "slidesToShow",
640 | "slidesToScroll",
641 | "slideCount",
642 | "trackStyle",
643 | "variableWidth",
644 | "unslick",
645 | "centerPadding",
646 | "targetSlide",
647 | "useCSS"
648 | ]);
649 | const { pauseOnHover } = this.props;
650 | trackProps = {
651 | ...trackProps,
652 | onMouseEnter: pauseOnHover ? this.onTrackOver : null,
653 | onMouseLeave: pauseOnHover ? this.onTrackLeave : null,
654 | onMouseOver: pauseOnHover ? this.onTrackOver : null,
655 | focusOnSelect:
656 | this.props.focusOnSelect && this.clickable ? this.selectHandler : null
657 | };
658 |
659 | var dots;
660 | if (
661 | this.props.dots === true &&
662 | this.state.slideCount >= this.props.slidesToShow
663 | ) {
664 | let dotProps = extractObject(spec, [
665 | "dotsClass",
666 | "slideCount",
667 | "slidesToShow",
668 | "currentSlide",
669 | "slidesToScroll",
670 | "clickHandler",
671 | "children",
672 | "customPaging",
673 | "infinite",
674 | "appendDots"
675 | ]);
676 | const { pauseOnDotsHover } = this.props;
677 | dotProps = {
678 | ...dotProps,
679 | clickHandler: this.changeSlide,
680 | onMouseEnter: pauseOnDotsHover ? this.onDotsLeave : null,
681 | onMouseOver: pauseOnDotsHover ? this.onDotsOver : null,
682 | onMouseLeave: pauseOnDotsHover ? this.onDotsLeave : null
683 | };
684 | dots = ;
685 | }
686 |
687 | var prevArrow, nextArrow;
688 | let arrowProps = extractObject(spec, [
689 | "infinite",
690 | "centerMode",
691 | "currentSlide",
692 | "slideCount",
693 | "slidesToShow",
694 | "prevArrow",
695 | "nextArrow"
696 | ]);
697 | arrowProps.clickHandler = this.changeSlide;
698 |
699 | if (this.props.arrows) {
700 | prevArrow = ;
701 | nextArrow = ;
702 | }
703 |
704 | var verticalHeightStyle = null;
705 |
706 | if (this.props.vertical) {
707 | verticalHeightStyle = {
708 | height: this.state.listHeight
709 | };
710 | }
711 |
712 | var centerPaddingStyle = null;
713 |
714 | if (this.props.vertical === false) {
715 | if (this.props.centerMode === true) {
716 | centerPaddingStyle = {
717 | padding: "0px " + this.props.centerPadding
718 | };
719 | }
720 | } else {
721 | if (this.props.centerMode === true) {
722 | centerPaddingStyle = {
723 | padding: this.props.centerPadding + " 0px"
724 | };
725 | }
726 | }
727 |
728 | const listStyle = { ...verticalHeightStyle, ...centerPaddingStyle };
729 | const touchMove = this.props.touchMove;
730 | let listProps = {
731 | className: "slick-list",
732 | style: listStyle,
733 | onClick: this.clickHandler,
734 | onMouseDown: touchMove ? this.swipeStart : null,
735 | onMouseMove: this.state.dragging && touchMove ? this.swipeMove : null,
736 | onMouseUp: touchMove ? this.swipeEnd : null,
737 | onMouseLeave: this.state.dragging && touchMove ? this.swipeEnd : null,
738 | onTouchStart: touchMove ? this.swipeStart : null,
739 | onTouchMove: this.state.dragging && touchMove ? this.swipeMove : null,
740 | onTouchEnd: touchMove ? this.touchEnd : null,
741 | onTouchCancel: this.state.dragging && touchMove ? this.swipeEnd : null,
742 | onKeyDown: this.props.accessibility ? this.keyHandler : null
743 | };
744 |
745 | let innerSliderProps = {
746 | className: className,
747 | dir: "ltr",
748 | style: this.props.style
749 | };
750 |
751 | if (this.props.unslick) {
752 | listProps = { className: "slick-list" };
753 | innerSliderProps = { className, style: this.props.style };
754 | }
755 | return (
756 |
757 | {!this.props.unslick ? prevArrow : ""}
758 |
759 |
760 | {this.props.children}
761 |
762 |
763 | {!this.props.unslick ? nextArrow : ""}
764 | {!this.props.unslick ? dots : ""}
765 |
766 | );
767 | };
768 | }
769 |
--------------------------------------------------------------------------------
/src/slider.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import { InnerSlider } from "./inner-slider";
5 | import json2mq from "json2mq";
6 | import defaultProps from "./default-props";
7 | import { canUseDOM, filterSettings } from "./utils/innerSliderUtils";
8 |
9 | export default class Slider extends React.Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | breakpoint: null
14 | };
15 | this._responsiveMediaHandlers = [];
16 | }
17 |
18 | innerSliderRefHandler = ref => (this.innerSlider = ref);
19 |
20 | media(query, handler) {
21 | // javascript handler for css media query
22 | const mql = window.matchMedia(query);
23 | const listener = ({ matches }) => {
24 | if (matches) {
25 | handler();
26 | }
27 | };
28 | mql.addListener(listener);
29 | this._responsiveMediaHandlers.push({ mql, query, listener });
30 | }
31 |
32 | // handles responsive breakpoints
33 | componentDidMount() {
34 | // performance monitoring
35 | //if (process.env.NODE_ENV !== 'production') {
36 | //const { whyDidYouUpdate } = require('why-did-you-update')
37 | //whyDidYouUpdate(React)
38 | //}
39 | if (this.props.responsive) {
40 | let breakpoints = this.props.responsive.map(
41 | breakpt => breakpt.breakpoint
42 | );
43 | // sort them in increasing order of their numerical value
44 | breakpoints.sort((x, y) => x - y);
45 |
46 | breakpoints.forEach((breakpoint, index) => {
47 | // media query for each breakpoint
48 | let bQuery;
49 | if (index === 0) {
50 | bQuery = json2mq({ minWidth: 0, maxWidth: breakpoint });
51 | } else {
52 | bQuery = json2mq({
53 | minWidth: breakpoints[index - 1] + 1,
54 | maxWidth: breakpoint
55 | });
56 | }
57 | // when not using server side rendering
58 | canUseDOM() &&
59 | this.media(bQuery, () => {
60 | this.setState({ breakpoint: breakpoint });
61 | });
62 | });
63 |
64 | // Register media query for full screen. Need to support resize from small to large
65 | // convert javascript object to media query string
66 | let query = json2mq({ minWidth: breakpoints.slice(-1)[0] });
67 |
68 | canUseDOM() &&
69 | this.media(query, () => {
70 | this.setState({ breakpoint: null });
71 | });
72 | }
73 | }
74 |
75 | componentWillUnmount() {
76 | this._responsiveMediaHandlers.forEach(function(obj) {
77 | obj.mql.removeListener(obj.listener);
78 | });
79 | }
80 |
81 | slickPrev = () => this.innerSlider.slickPrev();
82 |
83 | slickNext = () => this.innerSlider.slickNext();
84 |
85 | slickGoTo = (slide, dontAnimate = false) =>
86 | this.innerSlider.slickGoTo(slide, dontAnimate);
87 |
88 | slickPause = () => this.innerSlider.pause("paused");
89 |
90 | slickPlay = () => this.innerSlider.autoPlay("play");
91 |
92 | render() {
93 | var settings;
94 | var newProps;
95 | if (this.state.breakpoint) {
96 | newProps = this.props.responsive.filter(
97 | resp => resp.breakpoint === this.state.breakpoint
98 | );
99 | settings =
100 | newProps[0].settings === "unslick"
101 | ? "unslick"
102 | : { ...defaultProps, ...this.props, ...newProps[0].settings };
103 | } else {
104 | settings = { ...defaultProps, ...this.props };
105 | }
106 |
107 | // force scrolling by one if centerMode is on
108 | if (settings.centerMode) {
109 | if (
110 | settings.slidesToScroll > 1 &&
111 | process.env.NODE_ENV !== "production"
112 | ) {
113 | console.warn(
114 | `slidesToScroll should be equal to 1 in centerMode, you are using ${settings.slidesToScroll}`
115 | );
116 | }
117 | settings.slidesToScroll = 1;
118 | }
119 | // force showing one slide and scrolling by one if the fade mode is on
120 | if (settings.fade) {
121 | if (settings.slidesToShow > 1 && process.env.NODE_ENV !== "production") {
122 | console.warn(
123 | `slidesToShow should be equal to 1 when fade is true, you're using ${settings.slidesToShow}`
124 | );
125 | }
126 | if (
127 | settings.slidesToScroll > 1 &&
128 | process.env.NODE_ENV !== "production"
129 | ) {
130 | console.warn(
131 | `slidesToScroll should be equal to 1 when fade is true, you're using ${settings.slidesToScroll}`
132 | );
133 | }
134 | settings.slidesToShow = 1;
135 | settings.slidesToScroll = 1;
136 | }
137 |
138 | // makes sure that children is an array, even when there is only 1 child
139 | let children = React.Children.toArray(this.props.children);
140 |
141 | // Children may contain false or null, so we should filter them
142 | // children may also contain string filled with spaces (in certain cases where we use jsx strings)
143 | children = children.filter(child => {
144 | if (typeof child === "string") {
145 | return !!child.trim();
146 | }
147 | return !!child;
148 | });
149 |
150 | // rows and slidesPerRow logic is handled here
151 | if (
152 | settings.variableWidth &&
153 | (settings.rows > 1 || settings.slidesPerRow > 1)
154 | ) {
155 | console.warn(
156 | `variableWidth is not supported in case of rows > 1 or slidesPerRow > 1`
157 | );
158 | settings.variableWidth = false;
159 | }
160 | let newChildren = [];
161 | let currentWidth = null;
162 | for (
163 | let i = 0;
164 | i < children.length;
165 | i += settings.rows * settings.slidesPerRow
166 | ) {
167 | let newSlide = [];
168 | for (
169 | let j = i;
170 | j < i + settings.rows * settings.slidesPerRow;
171 | j += settings.slidesPerRow
172 | ) {
173 | let row = [];
174 | for (let k = j; k < j + settings.slidesPerRow; k += 1) {
175 | if (settings.variableWidth && children[k].props.style) {
176 | currentWidth = children[k].props.style.width;
177 | }
178 | if (k >= children.length) break;
179 | row.push(
180 | React.cloneElement(children[k], {
181 | key: 100 * i + 10 * j + k,
182 | tabIndex: -1,
183 | style: {
184 | width: `${100 / settings.slidesPerRow}%`,
185 | display: "inline-block"
186 | }
187 | })
188 | );
189 | }
190 | newSlide.push({row}
);
191 | }
192 | if (settings.variableWidth) {
193 | newChildren.push(
194 |
195 | {newSlide}
196 |
197 | );
198 | } else {
199 | newChildren.push({newSlide}
);
200 | }
201 | }
202 |
203 | if (settings === "unslick") {
204 | const className = "regular slider " + (this.props.className || "");
205 | return {children}
;
206 | } else if (newChildren.length <= settings.slidesToShow) {
207 | settings.unslick = true;
208 | }
209 | return (
210 |
215 | {newChildren}
216 |
217 | );
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/track.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from "react";
4 | import classnames from "classnames";
5 | import {
6 | lazyStartIndex,
7 | lazyEndIndex,
8 | getPreClones,
9 | getPostClones
10 | } from "./utils/innerSliderUtils";
11 |
12 | // given specifications/props for a slide, fetch all the classes that need to be applied to the slide
13 | const getSlideClasses = spec => {
14 | let slickActive, slickCenter, slickCloned;
15 | let centerOffset, index;
16 |
17 | if (spec.rtl) {
18 | index = spec.slideCount - 1 - spec.index;
19 | } else {
20 | index = spec.index;
21 | }
22 | slickCloned = index < 0 || index >= spec.slideCount;
23 | if (spec.centerMode) {
24 | centerOffset = Math.floor(spec.slidesToShow / 2);
25 | slickCenter = (index - spec.currentSlide) % spec.slideCount === 0;
26 | if (
27 | index > spec.currentSlide - centerOffset - 1 &&
28 | index <= spec.currentSlide + centerOffset
29 | ) {
30 | slickActive = true;
31 | }
32 | } else {
33 | slickActive =
34 | spec.currentSlide <= index &&
35 | index < spec.currentSlide + spec.slidesToShow;
36 | }
37 |
38 | let focusedSlide;
39 | if (spec.targetSlide < 0) {
40 | focusedSlide = spec.targetSlide + spec.slideCount;
41 | } else if (spec.targetSlide >= spec.slideCount) {
42 | focusedSlide = spec.targetSlide - spec.slideCount;
43 | } else {
44 | focusedSlide = spec.targetSlide;
45 | }
46 | let slickCurrent = index === focusedSlide;
47 | return {
48 | "slick-slide": true,
49 | "slick-active": slickActive,
50 | "slick-center": slickCenter,
51 | "slick-cloned": slickCloned,
52 | "slick-current": slickCurrent // dubious in case of RTL
53 | };
54 | };
55 |
56 | const getSlideStyle = spec => {
57 | let style = {};
58 |
59 | if (spec.variableWidth === undefined || spec.variableWidth === false) {
60 | style.width = spec.slideWidth;
61 | }
62 |
63 | if (spec.fade) {
64 | style.position = "relative";
65 | if (spec.vertical) {
66 | style.top = -spec.index * parseInt(spec.slideHeight);
67 | } else {
68 | style.left = -spec.index * parseInt(spec.slideWidth);
69 | }
70 | style.opacity = spec.currentSlide === spec.index ? 1 : 0;
71 | style.zIndex = spec.currentSlide === spec.index ? 999 : 998;
72 | if (spec.useCSS) {
73 | style.transition =
74 | "opacity " +
75 | spec.speed +
76 | "ms " +
77 | spec.cssEase +
78 | ", " +
79 | "visibility " +
80 | spec.speed +
81 | "ms " +
82 | spec.cssEase;
83 | }
84 | }
85 |
86 | return style;
87 | };
88 |
89 | const getKey = (child, fallbackKey) => child.key || fallbackKey;
90 |
91 | const renderSlides = spec => {
92 | let key;
93 | let slides = [];
94 | let preCloneSlides = [];
95 | let postCloneSlides = [];
96 | let childrenCount = React.Children.count(spec.children);
97 | let startIndex = lazyStartIndex(spec);
98 | let endIndex = lazyEndIndex(spec);
99 |
100 | React.Children.forEach(spec.children, (elem, index) => {
101 | let child;
102 | let childOnClickOptions = {
103 | message: "children",
104 | index: index,
105 | slidesToScroll: spec.slidesToScroll,
106 | currentSlide: spec.currentSlide
107 | };
108 |
109 | // in case of lazyLoad, whether or not we want to fetch the slide
110 | if (
111 | !spec.lazyLoad ||
112 | (spec.lazyLoad && spec.lazyLoadedList.indexOf(index) >= 0)
113 | ) {
114 | child = elem;
115 | } else {
116 | child =
;
117 | }
118 | let childStyle = getSlideStyle({ ...spec, index });
119 | let slideClass = child.props.className || "";
120 | let slideClasses = getSlideClasses({ ...spec, index });
121 | // push a cloned element of the desired slide
122 | slides.push(
123 | React.cloneElement(child, {
124 | key: "original" + getKey(child, index),
125 | "data-index": index,
126 | className: classnames(slideClasses, slideClass),
127 | tabIndex: "-1",
128 | "aria-hidden": !slideClasses["slick-active"],
129 | style: { outline: "none", ...(child.props.style || {}), ...childStyle },
130 | onClick: e => {
131 | child.props && child.props.onClick && child.props.onClick(e);
132 | if (spec.focusOnSelect) {
133 | spec.focusOnSelect(childOnClickOptions);
134 | }
135 | }
136 | })
137 | );
138 |
139 | // if slide needs to be precloned or postcloned
140 | if (
141 | spec.infinite &&
142 | childrenCount > 1 &&
143 | spec.fade === false &&
144 | !spec.unslick
145 | ) {
146 | let preCloneNo = childrenCount - index;
147 | if (preCloneNo <= getPreClones(spec)) {
148 | key = -preCloneNo;
149 | if (key >= startIndex) {
150 | child = elem;
151 | }
152 | slideClasses = getSlideClasses({ ...spec, index: key });
153 | preCloneSlides.push(
154 | React.cloneElement(child, {
155 | key: "precloned" + getKey(child, key),
156 | "data-index": key,
157 | tabIndex: "-1",
158 | className: classnames(slideClasses, slideClass),
159 | "aria-hidden": !slideClasses["slick-active"],
160 | style: { ...(child.props.style || {}), ...childStyle },
161 | onClick: e => {
162 | child.props && child.props.onClick && child.props.onClick(e);
163 | if (spec.focusOnSelect) {
164 | spec.focusOnSelect(childOnClickOptions);
165 | }
166 | }
167 | })
168 | );
169 | }
170 | if (index < getPostClones(spec)) {
171 | key = childrenCount + index;
172 | if (key < endIndex) {
173 | child = elem;
174 | }
175 | slideClasses = getSlideClasses({ ...spec, index: key });
176 | postCloneSlides.push(
177 | React.cloneElement(child, {
178 | key: "postcloned" + getKey(child, key),
179 | "data-index": key,
180 | tabIndex: "-1",
181 | className: classnames(slideClasses, slideClass),
182 | "aria-hidden": !slideClasses["slick-active"],
183 | style: { ...(child.props.style || {}), ...childStyle },
184 | onClick: e => {
185 | child.props && child.props.onClick && child.props.onClick(e);
186 | if (spec.focusOnSelect) {
187 | spec.focusOnSelect(childOnClickOptions);
188 | }
189 | }
190 | })
191 | );
192 | }
193 | }
194 | });
195 |
196 | if (spec.rtl) {
197 | return preCloneSlides.concat(slides, postCloneSlides).reverse();
198 | } else {
199 | return preCloneSlides.concat(slides, postCloneSlides);
200 | }
201 | };
202 |
203 | export class Track extends React.PureComponent {
204 | node = null;
205 |
206 | handleRef = ref => {
207 | this.node = ref;
208 | };
209 |
210 | render() {
211 | const slides = renderSlides(this.props);
212 | const { onMouseEnter, onMouseOver, onMouseLeave } = this.props;
213 | const mouseEvents = { onMouseEnter, onMouseOver, onMouseLeave };
214 | return (
215 |
221 | {slides}
222 |
223 | );
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/test-setup.js:
--------------------------------------------------------------------------------
1 | import "@testing-library/jest-dom/extend-expect";
2 | import "regenerator-runtime/runtime";
3 |
4 | //Fix for "matchMedia not present, legacy browsers require a polyfill jest" error
5 | window.matchMedia =
6 | window.matchMedia ||
7 | function() {
8 | return {
9 | matches: false,
10 | addListener: function() {},
11 | removeListener: function() {}
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/test-utils.js:
--------------------------------------------------------------------------------
1 | import { render, fireEvent, waitFor, screen } from "@testing-library/react";
2 |
3 | export function getSlidesCount(container) {
4 | return container.getElementsByClassName("slick-slide").length;
5 | }
6 |
7 | export function getSlides(container) {
8 | return container.getElementsByClassName("slick-slide");
9 | }
10 |
11 | export function getClonesCount(container) {
12 | return container.getElementsByClassName("slick-cloned").length;
13 | }
14 |
15 | export function getActiveSlidesCount(container) {
16 | return container.querySelectorAll(".slick-slide.slick-active").length;
17 | }
18 |
19 | export function getCurrentSlide(container) {
20 | return container.querySelector(".slick-current");
21 | }
22 |
23 | export function getCurrentSlideContent(container) {
24 | const slide = container.querySelector(".slick-current");
25 | return slide.textContent;
26 | }
27 |
28 | export function getButtons(container) {
29 | return container.querySelectorAll(".slick-dots button");
30 | }
31 |
32 | export function getButtonsListItem(container) {
33 | return container.querySelectorAll(".slick-dots")[0].children;
34 | }
35 | export function getButtonsLength(container) {
36 | return container.querySelectorAll(".slick-dots")[0].children.length;
37 | }
38 | export function hasClass(element, classname) {
39 | if (element.className != undefined) {
40 | return element.classList.contains(classname);
41 | }
42 | return false;
43 | }
44 | export function getActiveButton(container) {
45 | return Array.from(
46 | container.querySelectorAll(".slick-dots .slick-active button")
47 | ).map(e => e.textContent);
48 | }
49 | // export function getCurrentSlideIdState(container) {
50 | // return parseInt(getCurrentSlide(container).getAttribute("data-index")) + 1;
51 | // }
52 | // export function activeSlides(container) {
53 | // return container.querySelectorAll(".slick-slide.slick-active");
54 | // }
55 | export function getActiveSlide(container) {
56 | return container.querySelector(".slick-slide.slick-active");
57 | }
58 |
59 | export function getActiveSlides(container) {
60 | return container.querySelectorAll(".slick-slide.slick-active");
61 | }
62 |
63 | export function getActiveSlidesText(container) {
64 | const slides = getActiveSlides(container);
65 | return Array.from(slides).map(e => e.textContent);
66 | }
67 |
68 | export function clickNext(container) {
69 | fireEvent(
70 | container.getElementsByClassName("slick-next")[0],
71 | new MouseEvent("click", {
72 | bubbles: true,
73 | cancelable: true
74 | })
75 | );
76 | }
77 |
78 | export function clickPrevious(container) {
79 | fireEvent(
80 | container.getElementsByClassName("slick-prev")[0],
81 | new MouseEvent("click", {
82 | bubbles: true,
83 | cancelable: true
84 | })
85 | );
86 | }
87 |
88 | export function hasDots(container) {
89 | return Boolean(container.querySelectorAll(".slick-dots")[0]);
90 | }
91 |
92 | export function hasArrows(container) {
93 | return Boolean(
94 | container.getElementsByClassName("slick-next")[0] ||
95 | container.getElementsByClassName("slick-prev")[0]
96 | );
97 | }
98 |
--------------------------------------------------------------------------------
/webpack.config.dist.js:
--------------------------------------------------------------------------------
1 | var webpack = require("webpack");
2 | var path = require("path");
3 |
4 | module.exports = {
5 | mode: "production",
6 |
7 | entry: "./src/index",
8 |
9 | output: {
10 | library: "Slider",
11 | libraryTarget: "umd",
12 | path: path.join(__dirname, "dist")
13 | },
14 |
15 | module: {
16 | rules: [
17 | {
18 | test: /\.js/,
19 | exclude: /(node_modules)/,
20 | use: {
21 | loader: "babel-loader"
22 | }
23 | }
24 | ]
25 | },
26 |
27 | resolve: {
28 | extensions: [".js", ".jsx"]
29 | },
30 |
31 | externals: {
32 | react: {
33 | root: "React",
34 | commonjs2: "react",
35 | commonjs: "react",
36 | amd: "react"
37 | },
38 | "react-dom": {
39 | root: "ReactDOM",
40 | commonjs2: "react-dom",
41 | commonjs: "react-dom",
42 | amd: "react-dom"
43 | }
44 | },
45 |
46 | node: {
47 | Buffer: false
48 | },
49 |
50 | devtool: "source-map",
51 |
52 | performance: {
53 | hints: "warning"
54 | },
55 |
56 | plugins: []
57 | };
58 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require("webpack");
2 | var path = require("path");
3 |
4 | module.exports = {
5 | mode: "production",
6 | devtool: "source-map",
7 | entry: {
8 | "docs.js": "./docs/index.js"
9 | },
10 | output: {
11 | path: path.join(__dirname, "build"),
12 | filename: "[name]"
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.jsx?/,
18 | exclude: /(node_modules)/,
19 | use: {
20 | loader: "babel-loader"
21 | }
22 | },
23 | {
24 | test: /\.md$/,
25 | loader: "html!markdown"
26 | }
27 | ]
28 | },
29 | resolve: {
30 | extensions: [".js", ".jsx"],
31 | alias: {
32 | "react-slick": path.resolve(__dirname, "src/index.js")
33 | }
34 | },
35 | plugins: [new webpack.IgnorePlugin(/vertx/)],
36 | devServer: {
37 | contentBase: path.join(__dirname, "./build"),
38 | port: 8080,
39 | hot: true
40 | }
41 | };
42 |
--------------------------------------------------------------------------------