├── .circleci
└── config.yml
├── .dockerignore
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── pull-request-template.md
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .releaserc
├── Dockerfile.e2e
├── LICENSE.md
├── README.md
├── commitlint.config.js
├── cypress.json
├── cypress
├── integration
│ ├── Arrows.test.js
│ ├── ClickToChange.test.js
│ ├── ControlledInput.test.js
│ ├── Dots.test.js
│ ├── Infinite.test.js
│ ├── MoveSlides.test.js
│ └── Thumbnails.test.js
├── plugins
│ └── index.js
└── support
│ ├── commands.js
│ └── index.js
├── dangerfile.js
├── docker-compose.e2e.yml
├── docs-www
├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── gatsby-config.js
├── gatsby-docs-kit.yml
├── package.json
├── src
│ ├── globalReferences.js
│ ├── layouts
│ │ └── .gitkeep
│ ├── pages
│ │ ├── 404.js
│ │ ├── landing.js
│ │ ├── landing.module.scss
│ │ └── variables.scss
│ ├── static
│ │ ├── favicon.png
│ │ ├── mona.jpg
│ │ ├── mona_thumbnail.jpg
│ │ ├── scream.jpg
│ │ ├── scream_thumbnail.jpg
│ │ ├── starry-night.jpg
│ │ └── starry-night_thumbnail.jpg
│ ├── styles
│ │ └── carousel.scss
│ └── templates
│ │ └── .gitkeep
└── tools
│ ├── deploy-github.sh
│ ├── seed.sh
│ └── seed
│ └── example.md
├── docs
├── CHANGELOG.md
├── api
│ ├── carousel.md
│ ├── dots.md
│ └── plugins.md
├── contributions-guide
│ ├── decision-log.md
│ ├── labels.md
│ └── workflow.md
├── examples
│ ├── animation.md
│ ├── centered.md
│ ├── clickToChange.md
│ ├── controlled.md
│ ├── customArrows.md
│ ├── defaultArrows.md
│ ├── dots.md
│ ├── flexContainer.md
│ ├── infinite.md
│ ├── lazyload.md
│ ├── multipleSlides.md
│ ├── resizableCarousel.md
│ ├── responsive.md
│ ├── rtl.md
│ ├── simpleUsage.md
│ ├── slidesToScroll.md
│ ├── swipingSlides.md
│ └── thumbnails.md
├── gettingStarted.md
├── migrationGuide.md
└── plugins
│ └── plugins.md
├── license
├── blacklist.js
├── licenses.js
└── whitelist.js
├── package.json
├── react-carousel
├── .babelrc
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── jest.config.js
├── jest.setup.js
├── package.json
├── src
│ ├── components
│ │ ├── Carousel.js
│ │ ├── CarouselDots.js
│ │ ├── CarouselSlide.js
│ │ └── CarouselWrapper.js
│ ├── constants
│ │ ├── carouselStrategies.js
│ │ ├── config.js
│ │ ├── plugins.js
│ │ └── pluginsOrder.js
│ ├── hooks
│ │ ├── useEventListener.js
│ │ └── useOnResize.js
│ ├── index.js
│ ├── plugins
│ │ ├── arrows.js
│ │ ├── arrows.scss
│ │ ├── autoplay.js
│ │ ├── centered.js
│ │ ├── clickToChange.js
│ │ ├── fastSwipe.js
│ │ ├── index.js
│ │ ├── infinite.js
│ │ ├── rtl.js
│ │ ├── rtl.scss
│ │ ├── slidesToScroll.js
│ │ └── slidesToShow.js
│ ├── state
│ │ ├── atoms
│ │ │ ├── carouselAtoms.js
│ │ │ └── slideAtoms.js
│ │ └── selectors
│ │ │ └── carouselSelectors.js
│ ├── styles
│ │ ├── Arrows.scss
│ │ ├── Carousel.scss
│ │ ├── CarouselDots.scss
│ │ └── CarouselItem.scss
│ └── tools
│ │ ├── carouselPluginResolver.js
│ │ ├── clamp.js
│ │ ├── getChildren.js
│ │ └── simulateEvent.js
├── test
│ ├── __mocks__
│ │ └── styleMock.js
│ ├── carousel.test.js
│ ├── plugins
│ │ ├── arrows.test.js
│ │ ├── autoplay.test.js
│ │ ├── dots.test.js
│ │ ├── infinite.test.js
│ │ ├── rtl.test.js
│ │ └── slidesPerScroll.test.js
│ └── tools
│ │ └── setupCarousel.js
├── tools
│ ├── build.js
│ └── chalkConfig.js
└── webpack.config.prod.js
├── readme
└── assets
│ ├── carousel.gif
│ ├── logo.gif
│ └── thumbnails.gif
├── renovate.json
├── tools
├── deploy-gh-pages-pr.sh
├── deploy-gh-pages.sh
├── skip-all-e2e-tests.sh
└── unskip-all-e2e-tests.sh
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 | executors:
3 | node-executor:
4 | docker:
5 | - image: circleci/node:12.18.2
6 | working_directory: ~/app
7 |
8 | jobs:
9 | deploy_test_environment:
10 | docker:
11 | - image: circleci/node:12.18.2
12 | working_directory: ~/app
13 | steps:
14 | - checkout
15 | - run:
16 | name: publish gh pages to one of the test environments
17 | command: ./tools/deploy-gh-pages-pr.sh
18 | test:
19 | executor: node-executor
20 | steps:
21 | - checkout
22 | - run: yarn install --non-interactive
23 | - run: yarn danger ci --failOnErrors --id @brainhubeu/react-carousel
24 | - run: yarn lint
25 | - run: yarn test:unit:coverage
26 | - run:
27 | name: Generate coveralls config
28 | command: "echo repo_token: $COVERALLS_REPO_TOKEN > ./react-carousel/.coveralls.yml"
29 | - run: yarn build
30 | - persist_to_workspace:
31 | root: ~/app
32 | paths:
33 | - .git
34 | - node_modules
35 | - react-carousel/node_modules
36 | - react-carousel/lib
37 | - docs-www/node_modules
38 | - react-carousel/.coveralls.yml
39 | - react-carousel/coverage
40 | test-e2e:
41 | docker:
42 | - image: circleci/node:12.18.2
43 | working_directory: ~/app
44 | steps:
45 | - checkout
46 | - setup_remote_docker
47 | - run:
48 | name: Running E2E tests
49 | command: docker-compose -f ./docker-compose.e2e.yml up --build --exit-code-from e2e-test
50 |
51 | publish_package:
52 | executor: node-executor
53 | steps:
54 | - attach_workspace:
55 | at: ~/app
56 | - run: git checkout .
57 | - run:
58 | name: Upload coverage to coveralls
59 | command: |
60 | cd react-carousel
61 | cat ./coverage/lcov.info | ./node_modules/.bin/coveralls
62 | - run:
63 | name: configure GitHub user
64 | command: |
65 | git config --global user.email "robert@brainhub.pl"
66 | git config --global user.name "DevOps Brainhub"
67 | git remote -v
68 | git remote remove origin
69 | git remote add origin https://$GIT_TOKEN@github.com/brainhubeu/react-carousel
70 | git remote -v
71 | - run: git pull --no-edit origin $CIRCLE_BRANCH
72 | - run: git push origin $CIRCLE_BRANCH
73 | - run:
74 | name: npm publish
75 | command: npx semantic-release
76 | - run: sleep 10
77 | - run: git pull --no-edit origin $CIRCLE_BRANCH
78 | - run: git push origin $CIRCLE_BRANCH
79 | - run:
80 | name: publish gh pages
81 | command: ./tools/deploy-gh-pages.sh
82 |
83 | workflows:
84 | version: 2
85 | test_and_deploy:
86 | jobs:
87 | - test
88 | - test-e2e
89 | - deploy_test_environment:
90 | filters:
91 | branches:
92 | ignore:
93 | - master
94 | - rc
95 | - publish_package:
96 | requires:
97 | - test
98 | - test-e2e
99 | - deploy_test_environment
100 | filters:
101 | branches:
102 | only:
103 | - master
104 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .gitignore
3 | .editorconfig
4 | node_modules
5 | react-carousel/node_modules
6 | docs-www/node_modules
7 | *.DS_Store
8 | *.md
9 | *.log
10 | LICENSE.txt
11 | README.md
12 | screenshots
13 | coverage
14 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | docs-www/.cache
2 | docs-www/public
3 | react-carousel/coverage
4 | react-carousel/lib
5 | node_modules
6 | react-carousel/node_modules
7 | docs-www/node_modules
8 |
9 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": [
4 | "brainhub",
5 | "prettier"
6 | ],
7 | "plugins": [
8 | "cypress",
9 | "prettier"
10 | ],
11 | "env": {
12 | "jest": true,
13 | "browser": true,
14 | "cypress/globals": true
15 | },
16 | "settings": {
17 | "import/resolve": {
18 | "moduleDirectory": ["node_modules", "src"]
19 | }
20 | },
21 | "rules": {
22 | "prettier/prettier": "error"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Environment**
24 | - please paste the result of `npx envinfo --system --binaries --browsers --npmPackages '@brainhubeu/*'`
25 | - desktop or mobile (which device & OS if mobile)?
26 | - Browser [e.g. Chrome, Safari]
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/pull-request-template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | - [ ] an issue linked to the PR
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 |
3 | # Logs
4 | logs
5 | *.log*
6 |
7 | # Runtime data
8 | pids
9 | *.pid
10 | *.seed
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 | reports
18 |
19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
20 | .grunt
21 |
22 | # node-waf configuration
23 | .lock-wscript
24 |
25 | # Compiled binary addons (http://nodejs.org/api/addons.html)
26 | build/Release
27 |
28 | # Dependency directory
29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
30 | node_modules
31 |
32 | # IDEA/Webstorm project files
33 | .idea
34 | *.iml
35 |
36 | #VSCode metadata
37 | .vscode
38 |
39 | # Mac files
40 | .DS_Store
41 |
42 | # Debug files
43 | selenium-debug.log
44 | .npm.debug
45 | package-lock.json
46 |
47 | html-report/
48 | lib/
49 | test/cypress/screenshots/
50 | test/cypress/videos/
51 | docs-www/reduxcache*
52 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | docs-www/.cache
2 | docs-www/public
3 | react-carousel/coverage
4 | react-carousel/lib
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "trailingComma": "all",
8 | "jsxBracketSameLine": false
9 | }
10 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "branches": [
3 | "v1-legacy",
4 | { name: 'master', channel: latest },
5 | { name: 'v2-beta', prerelease: true },
6 | { name: 'rc', prerelease: true }
7 | ],
8 | "plugins": [
9 | "@semantic-release/commit-analyzer",
10 | "@semantic-release/release-notes-generator",
11 | ["@semantic-release/changelog", {
12 | "changelogFile": "docs/CHANGELOG.md",
13 | }],
14 | ["@semantic-release/npm", {
15 | "pkgRoot": "react-carousel"
16 | }],
17 | ["@semantic-release/git", {
18 | "assets": ["react-carousel/package.json", "docs/CHANGELOG.md"],
19 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
20 | }],
21 | "@semantic-release/github"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/Dockerfile.e2e:
--------------------------------------------------------------------------------
1 | FROM cypress/included:4.9.0
2 |
3 | WORKDIR /e2e
4 |
5 | COPY ./package.json ./yarn.lock docs /e2e/
6 |
7 | COPY . /e2e
8 |
9 | # limit output by setting CI environment variable
10 | # https://github.com/cypress-io/cypress/issues/1243
11 | ENV CI=true
12 | RUN yarn install --frozen-lockfile && \
13 | npx cypress verify
14 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018-2020 [Brainhub](https://brainhub.eu/?utm_source=github)
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 |
2 |
3 |
4 |
5 |
6 |
7 | react-carousel
8 |
9 |
10 |
11 | A pure extendable React carousel, powered by Brainhub (craftsmen who ❤️ JS)
12 |
13 |
14 |
15 |
16 | Live code demo |
17 | v1 migration guide |
18 | Hire us
19 |
20 |
21 |
22 |
23 |
24 | [](https://circleci.com/gh/brainhubeu/react-carousel)
25 | [](https://github.com/brainhubeu/react-carousel/commits/master)
26 | [](https://github.com/brainhubeu/react-carousel/blob/master/LICENSE.md)
27 | [](http://makeapullrequest.com)
28 | [](https://renovatebot.com/)
29 |
30 | [](https://coveralls.io/github/brainhubeu/react-carousel?branch=master)
31 | [](https://www.npmjs.com/package/@brainhubeu/react-carousel)
32 | [](https://github.com/brainhubeu/react-carousel/commits/master)
33 | [](https://www.npmjs.com/package/@brainhubeu/react-carousel)
34 | [](https://www.npmjs.com/package/@brainhubeu/react-carousel)
35 | [](https://github.com/brainhubeu/react-carousel/graphs/contributors)
36 |
37 |
38 | ## Table of Contents
39 | - 🔌 [Installation](#installation)
40 | - 🐥 [Usage](#usage)
41 | - 🔨 [Props](#props)
42 | - 🎠 [Carousel Props](#carousel-props)
43 | - 🐾 [Dots Props](#dots-props)
44 | - 😻 [Contributing](#contributing)
45 | - 💁 [Setting up local development](#setting-up-local-development-which-means-running-the-docsdemo-locally)
46 | - 🐞 [Tests](#tests)
47 | - 🏋️ [Workflow](#workflow)
48 | - 🏷 [Labels](#labels)
49 | - 📝 [Decision Log](#decision-log)
50 |
51 | ## Why?
52 | There are some great carousels (like slick) that do not have real React implementations. This library provides you with carousel that is not merely a wrapper for some jQuery solution, can be used as controlled or uncontrolled element (similar to [inputs](https://reactjs.org/docs/uncontrolled-components.html)), and has tons of useful features.
53 |
54 | ## Installation
55 | ### Basic
56 | ```
57 | npm i @brainhubeu/react-carousel
58 | ```
59 |
60 | ### Typescript
61 | ```
62 | npm i @types/brainhubeu__react-carousel -D
63 | ```
64 |
65 | ### SSR
66 | When using `@brainhubeu/react-carousel` with SSR (Server-side Rendering), we recommend [Next.js](https://github.com/zeit/next.js) as `@brainhubeu/react-carousel` currently doesn't work on the server side so it must be rendered on the client side (maybe we'll provide server-side working in the future).
67 | ```js
68 | import dynamic from 'next/dynamic';
69 |
70 | const { default: Carousel, Dots } = dynamic(
71 | () => require('@brainhubeu/react-carousel'),
72 | { ssr: false },
73 | );
74 | ```
75 |
76 | ## Usage
77 | By default, the component does not need anything except children to render a simple carousel.
78 | Remember that styles do not have to be imported every time you use carousel, you can do it once in an entry point of your bundle.
79 | ```javascript
80 | import React from 'react';
81 | import Carousel from '@brainhubeu/react-carousel';
82 | import '@brainhubeu/react-carousel/lib/style.css';
83 |
84 | const MyCarousel = () => (
85 |
86 |
87 |
88 |
89 |
90 | );
91 |
92 | export default MyCarousel;
93 | ```
94 |
95 | [](https://brainhubeu.github.io/react-carousel/docs/examples/simpleUsage)
96 |
97 | ### Showing dots or thumbnails
98 | There is a separate Dots component that can be used to fully control navigation dots or add thumbnails.
99 | ```javascript
100 | import Carousel, { Dots } from '@brainhubeu/react-carousel';
101 | import '@brainhubeu/react-carousel/lib/style.css'; import { useState } from 'react';
102 |
103 | const MyCarouselWithDots = () => {
104 | const [value, setValue] = useState(0);
105 |
106 | const onChange = value => {
107 | setValue(value);
108 | }
109 |
110 | return (
111 |
112 |
116 |
117 | ...
118 |
119 |
120 |
),
125 | ...
126 | (
),
127 | ]}
128 | />
129 |
130 | );
131 | };
132 |
133 | export default MyCarouselWithDots;
134 | ```
135 |
136 | [](https://brainhubeu.github.io/react-carousel/docs/examples/thumbnails)
137 |
138 | ## Props
139 | You can access a clickable demo with many examples and a [live code editor](https://brainhubeu.github.io/react-carousel/) by clicking on a Prop name.
140 |
141 | ### Carousel props
142 |
143 | | Prop | Type | Default | Description |
144 | | --- | --- | --- | --- |
145 | | [**value**](https://brainhubeu.github.io/react-carousel/docs/examples/controlled) | *Number* | `undefined` | Current slide's index (zero based, depends on the elements order) |
146 | | [**onChange**](https://brainhubeu.github.io/react-carousel/docs/examples/controlled) | *Function* | `undefined` | Handler triggered when current slide is about to change (e.g. on arrow click or on swipe) |
147 | | **slides** | *Array* | `undefined` | Alternative way to pass slides. This prop expects an array of JSX elements |
148 | | **itemWidth** | *Number* | `undefined` | Determines custom width for every slide in the carousel |
149 | | **offset** | *Number* | `0` | Padding between items |
150 | | [**animationSpeed**](https://brainhubeu.github.io/react-carousel/docs/examples/animation) | *Number* | `500` | Determines transition duration in milliseconds |
151 | | [**draggable**](https://brainhubeu.github.io/react-carousel/docs/examples/draggable) | *Boolean* | `true` | Makes it possible to drag to the next slide with mouse cursor |
152 | | [**breakpoints**](https://brainhubeu.github.io/react-carousel/docs/examples/responsive) | *Object* | `undefined` | All props can be set to different values on different screen resolutions |
153 |
154 | ### Plugins
155 | You can extend react-carousel default behavior by applying plugins shipped within carousel
156 |
157 | [**Plugins documentation**](https://brainhubeu.github.io/react-carousel/docs/plugins/plugins)
158 |
159 | ### Dots props
160 |
161 | | Prop | Type | Default | Description |
162 | | --- | --- | --- | --- |
163 | | [**value**](https://brainhubeu.github.io/react-carousel/docs/examples/dots) | *Number* | slide position in the slides Array | Current `Carousel` value |
164 | | [**onChange**](https://brainhubeu.github.io/react-carousel/docs/examples/dots) | *Function* | `undefined` | `onChange` callback (works the same way as `onChange` in `Carousel` component) |
165 | | [**number**](https://brainhubeu.github.io/react-carousel/docs/examples/dots) | *Number* | Amount of slides | Number of slides in the carousel you want to control |
166 | | [**thumbnails**](https://brainhubeu.github.io/react-carousel/docs/examples/thumbnails) | *Array of ReactElements* | `undefined` | Array of thumbnails to show. If not provided, default dots will be shown |
167 | | [**rtl**](https://brainhubeu.github.io/react-carousel/docs/examples/rtl) | *Boolean* | `false` | Indicating if the dots should have direction from Right to Left |
168 |
169 | ### Setting up local development which means running the docs/demo locally:
170 | - `git clone https://github.com/brainhubeu/react-carousel`
171 | - `cd react-carousel`
172 | - `yarn`
173 | - `yarn start-demo`
174 | - open http://localhost:8000/
175 |
176 | ### Tests
177 | Each test command should be run from the root directory.
178 |
179 | #### Unit tests
180 | ```
181 | yarn test:unit:coverage
182 | ```
183 |
184 | #### E2E tests
185 | ```
186 | yarn test:e2e
187 | ```
188 |
189 | ### Workflow
190 | See [the Workflow subsection in our docs](https://brainhubeu.github.io/react-carousel/docs/contributions-guide/workflow)
191 |
192 | ### Labels
193 | See [the Labels subsection in our docs](https://brainhubeu.github.io/react-carousel/docs/contributions-guide/labels)
194 |
195 | ### Decision log
196 | See [the Decision log subsection in our docs](https://brainhubeu.github.io/react-carousel/docs/contributions-guide/decision-log)
197 |
198 | ## License
199 |
200 | react-carousel is copyright © 2018-2020 [Brainhub](https://brainhub.eu/?utm_source=github). It is free software and may be redistributed under the terms specified in the [license](LICENSE.md).
201 |
202 | ## About
203 |
204 | react-carousel is maintained by the Brainhub development team. It is funded by Brainhub and the names and logos for Brainhub are trademarks of Brainhub Sp. z o.o.. You can check other open-source projects supported/developed by our teammates [here](https://github.com/brainhubeu).
205 |
206 | [](https://brainhub.eu/?utm_source=github)
207 |
208 | We love open-source JavaScript software! See our other projects or hire us to build your next web, desktop and mobile application with JavaScript.
209 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:8000"
3 | }
4 |
--------------------------------------------------------------------------------
/cypress/integration/Arrows.test.js:
--------------------------------------------------------------------------------
1 | describe('Arrows', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/controlled/');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('changes slide when clicks on the arrow', () => {
12 | cy.get('.BrainhubCarousel__arrowRight').trigger('click');
13 |
14 | cy.wait(1);
15 |
16 | cy.get('.BrainhubCarouselItem--active')
17 | .children('img')
18 | .should('have.attr', 'src')
19 | .and('contain', 'scream');
20 |
21 | cy.get('.BrainhubCarousel__arrowLeft').trigger('click');
22 |
23 | cy.wait(1);
24 |
25 | cy.get('.BrainhubCarouselItem--active')
26 | .children('img')
27 | .should('have.attr', 'src')
28 | .and('contain', 'mona');
29 | });
30 |
31 | it(`doesn't allow to click on the arrow if there is no more slides`, () => {
32 | for (let i = 0; i < 2; i++) {
33 | cy.get('.BrainhubCarousel__arrowRight').trigger('click');
34 | cy.wait(1);
35 | }
36 |
37 | cy.get('.BrainhubCarouselItem--active')
38 | .children('img')
39 | .should('have.attr', 'src')
40 | .and('contain', 'starry-night');
41 |
42 | cy.get('.BrainhubCarousel__arrowRight').should('be.disabled');
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/cypress/integration/ClickToChange.test.js:
--------------------------------------------------------------------------------
1 | // TODO find a better way
2 | Cypress.on('uncaught:exception', (error) => {
3 | console.error('an uncaught eaten exception', error);
4 | return false;
5 | });
6 |
7 | describe('Click to change', () => {
8 | beforeEach(() => {
9 | cy.visit('/docs/examples/clickToChange/');
10 |
11 | cy.get('.BrainhubCarouselItem--active')
12 | .children('img')
13 | .should('have.attr', 'src')
14 | .and('contain', 'mona');
15 | });
16 |
17 | it('allows to change slide when clicks on the next slide', () => {
18 | cy.get('.BrainhubCarouselItem')
19 | .eq(1)
20 | .trigger('mousedown')
21 | .wait(10)
22 | .trigger('mouseup', { force: true });
23 |
24 | cy.get('.BrainhubCarouselItem--active')
25 | .children('img')
26 | .should('have.attr', 'src')
27 | .and('contain', 'scream');
28 | });
29 |
30 | it('allows to change slide when clicks on the previous slide', () => {
31 | cy.get('.BrainhubCarouselItem')
32 | .eq(1)
33 | .trigger('mousedown')
34 | .wait(10)
35 | .trigger('mouseup', { force: true });
36 |
37 | cy.get('.BrainhubCarouselItem')
38 | .eq(0)
39 | .trigger('mousedown')
40 | .wait(10)
41 | .trigger('mouseup', { force: true });
42 |
43 | cy.get('.BrainhubCarouselItem--active')
44 | .children('img')
45 | .should('have.attr', 'src')
46 | .and('contain', 'mona');
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/cypress/integration/ControlledInput.test.js:
--------------------------------------------------------------------------------
1 | describe('Controlled input', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/controlled/');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('goes to the slide index provided in input', () => {
12 | cy.get('input').type('2');
13 |
14 | cy.get('.BrainhubCarouselItem--active')
15 | .children('img')
16 | .should('have.attr', 'src')
17 | .and('contain', 'starry-night');
18 | });
19 |
20 | it('stays at the last slide if the value in input is greater than number of slides', () => {
21 | cy.get('input').type('50');
22 |
23 | cy.get('.BrainhubCarouselItem--active')
24 | .children('img')
25 | .should('have.attr', 'src')
26 | .and('contain', 'starry-night');
27 | });
28 |
29 | it('stays at the first slide if the value in input is less than 0', () => {
30 | for (let i = 0; i < 5; i++) {
31 | cy.get('input:first').type('{downArrow}');
32 | }
33 |
34 | cy.get('.BrainhubCarouselItem--active')
35 | .children('img')
36 | .should('have.attr', 'src')
37 | .and('contain', 'mona');
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/cypress/integration/Dots.test.js:
--------------------------------------------------------------------------------
1 | describe('Dots', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/dots');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('changes slide on dot click', () => {
12 | cy.get('.BrainhubCarousel__dot').eq(2).click();
13 |
14 | cy.get('.BrainhubCarouselItem--active')
15 | .children('img')
16 | .should('have.attr', 'src')
17 | .and('contain', 'starry-night');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/cypress/integration/Infinite.test.js:
--------------------------------------------------------------------------------
1 | describe('Infinite', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/infinite');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('repeats slides when swipes right', () => {
12 | for (let i = 0; i < 17; i++) {
13 | cy.get('.BrainhubCarousel__arrowRight').trigger('click');
14 |
15 | cy.wait(5);
16 | }
17 |
18 | cy.wait(20);
19 |
20 | cy.get('.BrainhubCarouselItem--active')
21 | .children('img')
22 |
23 | .should('have.attr', 'src')
24 | .and('contain', 'starry-night');
25 | });
26 |
27 | it('repeats slides when swipes left', () => {
28 | for (let i = 0; i < 17; i++) {
29 | cy.get('.BrainhubCarousel__arrowLeft').trigger('click');
30 |
31 | cy.wait(5);
32 | }
33 |
34 | cy.wait(20);
35 |
36 | cy.get('.BrainhubCarouselItem--active')
37 | .children('img')
38 |
39 | .should('have.attr', 'src')
40 | .and('contain', 'scream');
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/cypress/integration/MoveSlides.test.js:
--------------------------------------------------------------------------------
1 | describe('Move slides', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/simpleUsage');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('moves slide to the right if the next slide exists', () => {
12 | cy.get('.BrainhubCarouselItem--active')
13 | .trigger('mousedown')
14 | .trigger('mousemove', { pageX: 100 })
15 | .wait(10)
16 | .trigger('mouseup', { force: true });
17 |
18 | cy.get('.BrainhubCarouselItem--active')
19 | .children('img')
20 | .should('have.attr', 'src')
21 | .and('contain', 'scream');
22 | });
23 |
24 | it(`stays at the same slide if the previous one doesn't exist`, () => {
25 | cy.get('.BrainhubCarouselItem--active')
26 | .trigger('mousedown')
27 | .trigger('mousemove', { pageX: 990 })
28 | .trigger('mouseup', { force: true });
29 |
30 | cy.get('.BrainhubCarouselItem--active')
31 | .children('img')
32 | .should('have.attr', 'src')
33 | .and('contain', 'mona');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/cypress/integration/Thumbnails.test.js:
--------------------------------------------------------------------------------
1 | describe('Thumbnails', () => {
2 | beforeEach(() => {
3 | cy.visit('/docs/examples/thumbnails');
4 |
5 | cy.get('.BrainhubCarouselItem--active')
6 | .children('img')
7 | .should('have.attr', 'src')
8 | .and('contain', 'mona');
9 | });
10 |
11 | it('changes slide on thumbnail click', () => {
12 | cy.get('.BrainhubCarousel__thumbnail').eq(2).click();
13 |
14 | cy.get('.BrainhubCarouselItem--active')
15 | .children('img')
16 | .should('have.attr', 'src')
17 | .and('contain', 'starry-night');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | // /
2 | // ***********************************************************
3 | // This example plugins/index.js can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | /**
16 | * @type {Cypress.PluginConfig}
17 | */
18 | module.exports = () => {
19 | // `on` is used to hook into various events Cypress emits
20 | // `config` is the resolved Cypress config
21 | };
22 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands';
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/dangerfile.js:
--------------------------------------------------------------------------------
1 | const licenseAuditor = require('@brainhubeu/license-auditor');
2 |
3 | const whitelist = require('./license/whitelist');
4 | const blacklist = require('./license/blacklist');
5 |
6 | licenseAuditor({
7 | whitelistedLicenses: whitelist,
8 | blacklistedLicenses: blacklist,
9 | projectPath: `.`,
10 | ciManager: {
11 | warn,
12 | fail,
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/docker-compose.e2e.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | e2e-test:
4 | build:
5 | context: .
6 | dockerfile: ./Dockerfile.e2e
7 | volumes:
8 | - ${SHARED_PATH:-.}/test-results:/e2e/test-results
9 | entrypoint: yarn test:e2e
10 |
--------------------------------------------------------------------------------
/docs-www/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "loose": true,
7 | "modules": false,
8 | "shippedProposals": true,
9 | "useBuiltIns": "usage"
10 | }
11 | ],
12 | "@babel/react"
13 | ],
14 | "plugins": [
15 | "@babel/plugin-proposal-class-properties"
16 | ],
17 | "env": {
18 | "production": {
19 | "plugins": [
20 | "@babel/plugin-transform-react-constant-elements",
21 | "transform-react-remove-prop-types"
22 | ]
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/docs-www/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log*
4 |
5 | # node-waf configuration
6 | .lock-wscript
7 |
8 | # Dependency directory
9 | node_modules
10 |
11 | # IDEA/Webstorm project files
12 | .idea
13 | *.iml
14 |
15 | #VSCode metadata
16 | .vscode
17 |
18 | # Mac files
19 | .DS_Store
20 |
21 | # Gatsby
22 | .cache
23 | public
24 |
--------------------------------------------------------------------------------
/docs-www/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018-2020 Brainhub
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 |
--------------------------------------------------------------------------------
/docs-www/README.md:
--------------------------------------------------------------------------------
1 | # Gatsby Docs Kit Starter
2 | The default Brainhub static docs starter.
3 |
4 | ## Try it out
5 |
6 | Ensure you have the latest version of [Node](https://nodejs.org/en/download/) installed. We also recommend you install [Yarn](https://yarnpkg.com/en/docs/install) as well.
7 | Then run:
8 |
9 | ```bash
10 | yarn install
11 | ```
12 |
13 | Seed documentation (if you don't have any yet):
14 |
15 | ```bash
16 | yarn seed
17 | ```
18 |
19 | Run the local webserver via `yarn develop`;
20 |
21 | The example site is available at http://localhost:8000. You should see the example site loaded in your web browser.
22 | Also visit http://localhost:8000/___graphql to explore your site's GraphiQL data and schema.
23 |
24 | Then go to `../docs` to edit and write awesome docs!.
25 |
26 | ## Deploy
27 |
28 | Ready to go? Want to deploy documentation to github pages? Run:
29 |
30 | ```bash
31 | yarn deploy:gh
32 | ```
--------------------------------------------------------------------------------
/docs-www/gatsby-config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const pluginConfigFactory = require('@brainhubeu/gatsby-docs-kit/plugins');
4 | const _ = require('lodash');
5 |
6 | const url = process.env.CIRCLE_PULL_REQUEST;
7 | const branch = process.env.CIRCLE_BRANCH;
8 | const githubUrl = 'https://github.com/brainhubeu/react-carousel';
9 | const getUrl = (url) => (url ? `★☂☀${_.last(url.split('/'))}♞♜♖` : 'local');
10 |
11 | const postfix = branch === 'master' ? 'master' : getUrl(url);
12 |
13 | module.exports = {
14 | siteMetadata: {
15 | title: `React-carousel ${postfix} built on ${new Date()}`,
16 | description: 'Feature-rich, react-way react component that does not suck',
17 | image:
18 | 'https://cdn-images-1.medium.com/max/1200/1*CLUFZFaXF6NG27NA3d_JkQ.jpeg',
19 | url: url || githubUrl,
20 | type: 'article',
21 | siteName: 'React-carousel',
22 | githubUrl: url || githubUrl,
23 | },
24 |
25 | // URL prefix on production environment. For more info see https://www.gatsbyjs.org/docs/path-prefix/
26 | pathPrefix: process.env.PATH_PREFIX || null,
27 |
28 | plugins: [
29 | ...pluginConfigFactory({
30 | config: `${__dirname}/gatsby-docs-kit.yml`,
31 | resources: path.resolve(__dirname, '../docs'),
32 | }),
33 | {
34 | resolve: `gatsby-plugin-google-analytics`,
35 | options: {
36 | trackingId: 'UA-62818184-6',
37 | head: false,
38 | anonymize: true,
39 | respectDNT: true,
40 | pageTransitionDelay: 0,
41 | cookieDomain: 'brainhubeu.github.io',
42 | },
43 | },
44 | ],
45 | };
46 |
--------------------------------------------------------------------------------
/docs-www/gatsby-docs-kit.yml:
--------------------------------------------------------------------------------
1 | - title: Home
2 | dir: ./src
3 | url: /
4 | file: pages/landing.js
5 |
6 | - title: "DOCS__BUILD_INFO__"
7 | dir: ../docs
8 | url: docs
9 | sidemenu:
10 | - title: Getting started
11 | file: gettingStarted.md
12 | - title: Migration guide
13 | file: migrationGuide.md
14 | - title: Api
15 | dir: api
16 | items:
17 | - title: Carousel props
18 | file: carousel.md
19 | - title: Dots props
20 | file: dots.md
21 | - title: Plugins
22 | dir: plugins
23 | items:
24 | - title: React-carousel plugins
25 | file: plugins.md
26 | - title: Examples
27 | dir: examples
28 | items:
29 | - title: Simple Usage
30 | file: simpleUsage.md
31 | - title: Controlled component
32 | file: controlled.md
33 | - title: Multiple slides to show
34 | file: multipleSlides.md
35 | - title: Click to change
36 | file: clickToChange.md
37 | - title: Default arrows
38 | file: defaultArrows.md
39 | - title: Custom arrows
40 | file: customArrows.md
41 | - title: Infinite
42 | file: infinite.md
43 | - title: RTL layout
44 | file: rtl.md
45 | - title: Centered
46 | file: centered.md
47 | - title: Slides to scroll
48 | file: slidesToScroll.md
49 | - title: Swiping slides
50 | file: swipingSlides.md
51 | - title: Responsive
52 | file: responsive.md
53 | - title: Autoplay & animation speed
54 | file: animation.md
55 | - title: Dots
56 | file: dots.md
57 | - title: Thumbnails
58 | file: thumbnails.md
59 | - title: Resizable carousel
60 | file: resizableCarousel.md
61 | - title: Flex Container
62 | file: flexContainer.md
63 | - title: Contributions Guide
64 | dir: contributions-guide
65 | items:
66 | - title: Workflow
67 | file: workflow.md
68 | - title: Decision log
69 | file: decision-log.md
70 | - title: Labels
71 | file: labels.md
72 |
--------------------------------------------------------------------------------
/docs-www/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-carousel-docs",
3 | "description": "Gatsby-Docs-Kit starter repository",
4 | "version": "0.0.52",
5 | "author": "Brainhub",
6 | "license": "MIT",
7 | "scripts": {
8 | "build": "rm -rf .cache && rm -rf public && gatsby build --prefix-paths",
9 | "develop": "rm -rf .cache && NODE_ENV=development gatsby develop",
10 | "seed": "bash tools/seed.sh",
11 | "serve": "export RC_ENV=__RC_ENV__; if [[ \"$RC_ENV\" == 'development' ]]; then yarn develop; else gatsby serve; fi",
12 | "lint": "eslint --ext .jsx,.js .",
13 | "lint:autofix": "eslint --ext .jsx,.js . --fix"
14 | },
15 | "dependencies": {
16 | "@brainhubeu/gatsby-docs-kit": "3.0.8",
17 | "gatsby": "^2.24.2",
18 | "gatsby-link": "2.3.1",
19 | "lodash": "^4.17.21",
20 | "react-fa": "^5.0.0"
21 | },
22 | "devDependencies": {
23 | "@babel/plugin-proposal-class-properties": "^7.10.4",
24 | "@babel/plugin-transform-react-constant-elements": "^7.10.4",
25 | "@babel/polyfill": "^7.10.4",
26 | "@babel/preset-env": "^7.10.4",
27 | "@babel/preset-react": "^7.10.4",
28 | "@babel/preset-stage-1": "^7.8.3",
29 | "@babel/register": "^7.10.4",
30 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
31 | "gatsby-plugin-google-analytics": "2.2.2",
32 | "gh-pages": "^3.1.0",
33 | "react": "^16.13.1",
34 | "react-dom": "^16.13.1"
35 | },
36 | "peerDependencies": {
37 | "@babel/core": "^7.10.4"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/docs-www/src/globalReferences.js:
--------------------------------------------------------------------------------
1 | import './styles/carousel.scss';
2 | import Icon from 'react-fa';
3 |
4 | import imageOne from './static/mona.jpg';
5 | import imageTwo from './static/scream.jpg';
6 | import imageThree from './static/starry-night.jpg';
7 | import thumbnailOne from './static/mona_thumbnail.jpg';
8 | import thumbnailTwo from './static/scream_thumbnail.jpg';
9 | import thumbnailThree from './static/starry-night_thumbnail.jpg';
10 |
11 | const {
12 | default: Carousel,
13 | Dots,
14 | slidesToShowPlugin,
15 | infinitePlugin,
16 | clickToChangePlugin,
17 | autoplayPlugin,
18 | rtlPlugin,
19 | centeredPlugin,
20 | slidesToScrollPlugin,
21 | arrowsPlugin,
22 | fastSwipePlugin,
23 | } = (() => {
24 | if (!global.window) {
25 | global.window = {};
26 | }
27 | console.log('connecting with local react-carousel source code');
28 | return require('../../react-carousel/src');
29 | })();
30 |
31 | export {
32 | Carousel,
33 | Dots,
34 | slidesToShowPlugin,
35 | infinitePlugin,
36 | clickToChangePlugin,
37 | autoplayPlugin,
38 | rtlPlugin,
39 | centeredPlugin,
40 | slidesToScrollPlugin,
41 | arrowsPlugin,
42 | fastSwipePlugin,
43 | Icon,
44 | imageOne,
45 | imageTwo,
46 | imageThree,
47 | thumbnailOne,
48 | thumbnailTwo,
49 | thumbnailThree,
50 | };
51 |
--------------------------------------------------------------------------------
/docs-www/src/layouts/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/layouts/.gitkeep
--------------------------------------------------------------------------------
/docs-www/src/pages/404.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const NotFoundPage = () => (
4 |
5 |
NOT FOUND
6 |
You just hit a route that doesn't exist... the sadness.
7 |
8 | );
9 |
10 | export default NotFoundPage;
11 |
--------------------------------------------------------------------------------
/docs-www/src/pages/landing.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Link from 'gatsby-link';
3 |
4 | import styles from './landing.module.scss';
5 |
6 | const LandingPage = () => (
7 |
8 |
9 |
React-carousel
10 |
11 | A pure extendable React carousel, powered by{' '}
12 | Brainhub (craftsmen who ❤️ JS)
13 |
14 |
15 |
16 | Get started!
17 |
18 |
19 |
20 |
21 | );
22 |
23 | export default LandingPage;
24 |
--------------------------------------------------------------------------------
/docs-www/src/pages/landing.module.scss:
--------------------------------------------------------------------------------
1 | @import './variables.scss';
2 |
3 | .landing {
4 | text-align: center;
5 | display: flex;
6 | align-items: center;
7 | justify-content: center;
8 | min-height: calc(100vh - 2*#{$mainNavHeight} - 64px);
9 | }
10 |
11 | .landing__header {
12 | text-transform: uppercase;
13 | font-size: 3rem;
14 | letter-spacing: 2px;
15 | margin-bottom: 1rem;
16 | margin-top: 0;
17 | }
18 |
19 | .btn__wrapper {
20 | display: flex;
21 | justify-content: center;
22 | }
23 |
24 | .landing__btn {
25 | display: inline-block;
26 | background-color: $colorBHBg;
27 | text-decoration: none;
28 | color: $white;
29 | padding: 1rem 2rem;
30 | margin: 2rem;
31 | position: relative;
32 | overflow: hidden;
33 |
34 | span {
35 | position: relative;
36 | z-index: 1;
37 | }
38 |
39 | &:after,
40 | &:before {
41 | content: '';
42 | position: absolute;
43 | top: 0;
44 | bottom: 0;
45 | width: 50%;
46 | background-color: $colorBHMain;
47 | transition: width .3s ease-out;
48 | }
49 |
50 | &:after {
51 | left: 0;
52 | }
53 |
54 | &:before {
55 | right: 0;
56 | }
57 |
58 | &:hover {
59 | color: $white;
60 |
61 | &:after,
62 | &:before {
63 | width: 0;
64 | }
65 | }
66 | }
67 |
68 | .landing__btn--alt {
69 | composes: landing__btn;
70 | background-color: transparent;
71 | color: rgba($colorBHBg, .7);
72 | transition: color .3s;
73 |
74 | &:after,
75 | &:before {
76 | background-color: transparent;
77 | border-style: solid;
78 | border-color: $colorBHMain;
79 | }
80 |
81 | &:after {
82 | border-width: 1px 0 1px 1px;
83 | }
84 |
85 | &:before {
86 | border-width: 1px 1px 1px 0;
87 | }
88 |
89 | &:hover {
90 | color: $colorBHMain;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/docs-www/src/pages/variables.scss:
--------------------------------------------------------------------------------
1 | $colorBHBg: #150940;
2 | $colorBHMain: #7b59ff;
3 | $white: #ffffff;
4 |
5 | $mainNavHeight: 80px;
6 |
--------------------------------------------------------------------------------
/docs-www/src/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/favicon.png
--------------------------------------------------------------------------------
/docs-www/src/static/mona.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/mona.jpg
--------------------------------------------------------------------------------
/docs-www/src/static/mona_thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/mona_thumbnail.jpg
--------------------------------------------------------------------------------
/docs-www/src/static/scream.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/scream.jpg
--------------------------------------------------------------------------------
/docs-www/src/static/scream_thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/scream_thumbnail.jpg
--------------------------------------------------------------------------------
/docs-www/src/static/starry-night.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/starry-night.jpg
--------------------------------------------------------------------------------
/docs-www/src/static/starry-night_thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/static/starry-night_thumbnail.jpg
--------------------------------------------------------------------------------
/docs-www/src/styles/carousel.scss:
--------------------------------------------------------------------------------
1 | h2 {
2 | text-align: center;
3 | }
--------------------------------------------------------------------------------
/docs-www/src/templates/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/docs-www/src/templates/.gitkeep
--------------------------------------------------------------------------------
/docs-www/tools/deploy-github.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | GITHUB_REPO_NAME=$(basename -s .git `git config --get remote.origin.url`);
4 |
5 | PATH_PREFIX="/$GITHUB_REPO_NAME" npm run build
6 |
7 | # deploy to github pags
8 | node ./node_modules/.bin/gh-pages -d public
9 |
--------------------------------------------------------------------------------
/docs-www/tools/seed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | CONFIG_FILE="gatsby-docs-kit.yml"
4 | DIR_NAME="docs"
5 |
6 | # Create docs directory
7 | if [ -d "../${DIR_NAME}" ]; then
8 | echo '"docs" directory already exists. Can not seed it. Remove it and try again.'
9 | exit 1;
10 | fi
11 |
12 | mkdir -p "../${DIR_NAME}"
13 |
14 | # Create gastsby docs kit config file if do not exists
15 | if [ ! -f "./${CONFIG_FILE}" ]; then
16 | echo "" > $CONFIG_FILE;
17 | fi
18 |
19 | # Create example Mk
20 | cp ./tools/seed/example.md ../${DIR_NAME}/example.md
21 |
22 | # Seeding gastsby docs kit config file
23 | echo "- title: Home
24 | dir: ../docs
25 | url: docs
26 | file: example.md" >> $CONFIG_FILE;
27 |
28 | # Done
29 | echo "Done!"
--------------------------------------------------------------------------------
/docs-www/tools/seed/example.md:
--------------------------------------------------------------------------------
1 | # CLI Commands
2 |
3 | ### Running an app
4 | 1. running an application on locally
5 | ```bash
6 | npm run develop # or yarn develop
7 | ```
8 |
9 | Gatsby will start a hot-reloading development environment accessible at [http://localhost:8000](http://localhost:8000)
10 |
11 | 2. preparing optimized production build
12 | ```bash
13 | npm run build
14 | ```
15 |
16 | 3. serving locally production build
17 | ```bash
18 | npm run serve
19 | ```
20 |
21 | > Note that your site by default will be available on [http://localhost:9000](http://localhost:9000)
22 |
23 | 4. deploying to github pages
24 | ```bash
25 | npm run deploy:gh
26 | ```
27 |
28 | > See more [HERE](../getting-started/publishing.md)
29 |
30 |
--------------------------------------------------------------------------------
/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [2.0.4](https://github.com/brainhubeu/react-carousel/compare/v2.0.3...v2.0.4) (2021-05-26)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * autoplay call onChange ([#694](https://github.com/brainhubeu/react-carousel/issues/694)) ([#713](https://github.com/brainhubeu/react-carousel/issues/713)) ([97ab35f](https://github.com/brainhubeu/react-carousel/commit/97ab35f00c8dbc37ac202d7957575039bc0291e1))
7 |
8 | ## [2.0.3](https://github.com/brainhubeu/react-carousel/compare/v2.0.2...v2.0.3) (2021-04-12)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * production builds using webpack ([0cb444b](https://github.com/brainhubeu/react-carousel/commit/0cb444b777558494c5790ade0dface85e66bacbe))
14 |
15 | ## [2.0.2](https://github.com/brainhubeu/react-carousel/compare/v2.0.1...v2.0.2) (2020-11-19)
16 |
17 |
18 | ### Bug Fixes
19 |
20 | * child re render ([b427cda](https://github.com/brainhubeu/react-carousel/commit/b427cda8d41e36045aaad92abbaa0f747480d110))
21 |
22 | ## [2.0.1](https://github.com/brainhubeu/react-carousel/compare/v2.0.0...v2.0.1) (2020-07-29)
23 |
24 |
25 | ### Bug Fixes
26 |
27 | * temporarily disable creating custom plugins functionality ([971a5ac](https://github.com/brainhubeu/react-carousel/commit/971a5ac3e3c50b920f61443bea368e1a4b89d959))
28 |
29 | # [2.0.0](https://github.com/brainhubeu/react-carousel/compare/v1.0.1...v2.0.0) (2020-07-27)
30 |
31 |
32 | * Carousel 2.0 introduce plugins (#622) ([f4774f1](https://github.com/brainhubeu/react-carousel/commit/f4774f14a7c746ab64afc942a9274bbd774010c7)), closes [#622](https://github.com/brainhubeu/react-carousel/issues/622) [#451](https://github.com/brainhubeu/react-carousel/issues/451) [#584](https://github.com/brainhubeu/react-carousel/issues/584) [#613](https://github.com/brainhubeu/react-carousel/issues/613) [#614](https://github.com/brainhubeu/react-carousel/issues/614) [#394](https://github.com/brainhubeu/react-carousel/issues/394) [#394](https://github.com/brainhubeu/react-carousel/issues/394) [#394](https://github.com/brainhubeu/react-carousel/issues/394) [#618](https://github.com/brainhubeu/react-carousel/issues/618) [#394](https://github.com/brainhubeu/react-carousel/issues/394) [#618](https://github.com/brainhubeu/react-carousel/issues/618)
33 |
34 |
35 | ### Bug Fixes
36 |
37 | * Setting offset breaks "centered" ([#394](https://github.com/brainhubeu/react-carousel/issues/394)) ([5f69446](https://github.com/brainhubeu/react-carousel/commit/5f694466442587eb09ca1e17ba61406bb77e8960))
38 |
39 | # [2.0.0-v2-beta.1](https://github.com/brainhubeu/react-carousel/compare/v1.0.1...v2.0.0-v2-beta.1) (2020-07-22)
40 |
41 | ### Bug Fixes
42 |
43 | * Adding 'rtl' to breakpoints prop-type shape ([6de56a9](https://github.com/brainhubeu/react-carousel/commit/6de56a90d7101f222c8c90bd2835b12b12f05832))
44 | * carousel breaks when one of the carousel children is an array of nodes ([88a6e0f](https://github.com/brainhubeu/react-carousel/commit/88a6e0f8d61f25c61f5a43c2fe8ac22124e11817))
45 | * pass null instead of boolean to drag event listener if disabled ([2a884bf](https://github.com/brainhubeu/react-carousel/commit/2a884bf1b7165ad53e8a1f678e1931982c44482f))
46 | * pkgRoot path ([1ce7ffd](https://github.com/brainhubeu/react-carousel/commit/1ce7ffd0360a942e98ed6a57532b777dadfe808f))
47 |
48 | # [2.0.0-rc.3](https://github.com/brainhubeu/react-carousel/compare/v2.0.0-rc.2...v2.0.0-rc.3) (2020-07-27)
49 |
50 |
51 | ### Bug Fixes
52 |
53 | * publish package with CHANGELOG.md LICENSE.md and README.md ([29f2016](https://github.com/brainhubeu/react-carousel/commit/29f201661bc9f2f20453387179b51caeea81dc5a))
54 |
55 | # [2.0.0-rc.2](https://github.com/brainhubeu/react-carousel/compare/v2.0.0-rc.1...v2.0.0-rc.2) (2020-07-24)
56 |
57 |
58 | ### Bug Fixes
59 |
60 | * setting offset breaks "centered" plugin [#394](https://github.com/brainhubeu/react-carousel/issues/394) ([#618](https://github.com/brainhubeu/react-carousel/issues/618)) ([cfae59f](https://github.com/brainhubeu/react-carousel/commit/cfae59f46609b26441ceba0d910b1ef02c1f1c5c))
61 |
--------------------------------------------------------------------------------
/docs/api/carousel.md:
--------------------------------------------------------------------------------
1 | ## Carousel component props
2 |
3 | * ```plugins: Func[]|String[]```: An array of plugins which will modify and extend carousel behavior. More details [**here**](https://brainhubeu.github.io/react-carousel/docs/plugins/plugins)
4 |
5 | * ```value: Number```: Current slide's index (zero based, depends on the elements order).
6 |
7 | * ```onChange: Function```: Handler triggered when current slide is about to change (e.g. on arrow click or on swipe).
8 |
9 | * ```slides: Array``` Alternative way to pass slides. This prop expects an array of JSX \ elements.
10 |
11 | * ```itemWidth: Number```: Determines custom width for every slide in the carousel.
12 |
13 | * ```offset: Number```: Padding between items.
14 |
15 | * ```animationSpeed: Number``` Determines transition duration in milliseconds.
16 |
17 | * ```draggable: Boolean``` Makes it possible to drag to the next slide with mouse cursor.
18 |
19 | * ```breakpoints: Object``` All props can be set to different values on different screen resolutions
20 |
21 | ## Default Properties:
22 |
23 | - ```offset: 0```
24 | - ```animationSpeed: 500```
25 | - ```draggable: true```
26 |
--------------------------------------------------------------------------------
/docs/api/dots.md:
--------------------------------------------------------------------------------
1 | ## Dots component props
2 |
3 | * ```value: Number```: Current Carousel value
4 |
5 | * ```onChange: PropTypes.func```: OnChange callback (works in the same way as onChange in Carousel component)
6 |
7 | * ```number: Number```: Number of slides in carousel you want to control. By default it will be set to the number of thumbnails (if provided).
8 |
9 | * ```thumbnails: Array```: Array of thumbnails to show. If not provided, default dots will be shown.
10 |
11 | * ```rtl: PropTypes.bool```: Indicating if the dots should have direction from Right to Left
12 |
--------------------------------------------------------------------------------
/docs/api/plugins.md:
--------------------------------------------------------------------------------
1 | ## plugins
2 |
3 | ### slidesToShow plugin
4 |
5 | options:
6 | * ```numberOfSlides: Number```: Number of slides visible at once.
7 |
8 | usage:
9 | ```jsx
10 |
20 | {/ *carousel items... */}
21 |
22 | ```
23 |
24 |
25 |
26 | ### slidesToScroll plugin
27 |
28 | options:
29 | * ```numberOfSlides: Number```: Number by which value will change on scroll (autoPlay, arrow click, drag).
30 |
31 | usage:
32 | ```jsx
33 |
43 | {/ *carousel items... */}
44 |
45 | ```
46 |
47 |
48 |
49 | ### arrows plugin
50 |
51 | options:
52 | * ```arrowLeft: React element```, ```arrowLeftDisabled: React element```, ```arrowRightDisabled: React element```, ```arrowRight: React element```: React elements to be used instead of default arrows.
53 |
54 | * ```addArrowClickHandler: Boolean``` Has to be added for arrowLeft and arrowRight to work.
55 |
56 | simple usage:
57 | ```jsx
58 |
61 | {/ *carousel items... */}
62 |
63 | ```
64 |
65 | advanced usage:
66 | ```jsx
67 | ,
73 | arrowLeftDisabled: ,
74 | arrowRight: ,
75 | arrowRightDisabled: ,
76 | addArrowClickHandler: true,
77 | }
78 | }
79 | ]}
80 | >
81 | {/ *carousel items... */}
82 |
83 | ```
84 |
85 |
86 |
87 | ### autoplay plugin
88 |
89 | options:
90 | * ```interval: Number```: Slide change interval in milliseconds. Defaults to 2000
91 |
92 | * ```stopAutoPlayOnHover: Boolean```: Determines if autoPlay should stop when mouse hover over carousel, defaults to `true`
93 |
94 | simple usage:
95 | ```jsx
96 |
99 | {/ *carousel items... */}
100 |
101 | ```
102 |
103 | advanced usage:
104 | ```jsx
105 |
116 | {/ *carousel items... */}
117 |
118 | ```
119 |
120 |
121 |
122 | ### clickToChange plugin
123 | Clicking on a slide changes current slide to the clicked one.
124 |
125 | usage:
126 | ```jsx
127 |
130 | {/ *carousel items... */}
131 |
132 | ```
133 |
134 |
135 |
136 | ### centered plugin
137 | Alignes active slide to the center of the carousel.
138 |
139 | usage:
140 | ```jsx
141 |
144 | {/ *carousel items... */}
145 |
146 | ```
147 |
148 |
149 |
150 | ### infinite plugin
151 | Creates an infinite carousel width.
152 |
153 | options:
154 | * ```numberOfInfiniteClones: Number```: Number of clones created before and after original carousel slides. Defaults to 1
155 |
156 | usage:
157 | ```jsx
158 |
161 | {/ *carousel items... */}
162 |
163 | ```
164 |
165 | advanced usage:
166 | ```jsx
167 |
177 | {/ *carousel items... */}
178 |
179 | ```
180 |
181 |
182 |
183 | ### fastSwipe plugin
184 | While dragging, it doesn't matter which slide is the nearest one, but in what direction you dragged.
185 |
186 | usage:
187 | ```jsx
188 |
191 | {/ *carousel items... */}
192 |
193 | ```
194 |
--------------------------------------------------------------------------------
/docs/contributions-guide/decision-log.md:
--------------------------------------------------------------------------------
1 | # Decision log
2 |
3 | ### React (2 January 2018)
4 | We love [React](https://github.com/facebook/react) so we'd like to focus on React only and in the nearest future, we don't plan to make this library working in another framework like [Vue.js](https://github.com/vuejs/vue).
5 |
6 | ### Renovate (18 February 2019)
7 | We've decided that [Renovate](https://github.com/renovatebot/renovate) is better than [Greenkeeper](https://github.com/greenkeeperio/greenkeeper) because Renovate is very configurable and has a great support.
8 |
9 | ### IssueHunt (7 January 2020)
10 | We've decided to use [IssueHunt](https://issuehunt.io/) to fund issues so we can get more contributors (more contributors, more popular a given project), assign a value to issues and reward active contributors.
11 |
12 | ### Testing environment deployment (31 January 2020)
13 | We've decided to use http://beghp.github.io/ domain to deploy each branch there because in a version deployed to [Netlify](https://www.netlify.com/) we've noticed broken fonts so deploying to GitHub Pages gives an environment the most possibly similar to the [production version](https://brainhubeu.github.io/react-carousel/). `beghp` is an acronym from Brainhub.eu GitHub Pages and we use this organization in order to keep only real repos in the `brainhubeu` organization.
14 |
15 | ### Cypress (13 March 2020)
16 | We've decided that [Cypress](https://github.com/cypress-io/cypress) is better than [Hermione](https://github.com/gemini-testing/hermione) (Hermione predecessor is [Gemini](https://github.com/gemini-testing/gemini)) because Hermione required setting a very large tolerance in order to pass both locally and in CI. Moreover, Cypress is much more popular.
17 |
18 | ### Recoil (14 July 2020)
19 | We've decided that [recoil](https://recoiljs.org/) will be used for managing state of the react-carousel component because of its simplicity to set up and maintain.
20 |
21 | ### Plugins (14 July 2020)
22 | We've decided to use plugins to make carousel easier to maintain and to allow users to extend carousel possibilities.
23 |
--------------------------------------------------------------------------------
/docs/contributions-guide/labels.md:
--------------------------------------------------------------------------------
1 | # Labels
2 |
3 | ### Issue labels:
4 | - issue type (mutually exclusive):
5 | - `bug`
6 | - `enhancement` - a feature request or a proposal to improve tests or to improve README or to improve anything beside fixing a bug
7 | - `question`
8 | - answering labels (mutually exclusive):
9 | - `answering: reported by brainhubeu` if the issue is created by any member of the `brainhubeu` organization with no comments by external contributors
10 | - otherwise `answering: answered` if the last comment is by a `brainhubeu` member
11 | - otherwise `answering: not answered`
12 | - severity (only for bugs, mutually exclusive):
13 | - `severity: blocked` - nothing is working
14 | - `severity: critical` - the most important features are often broken
15 | - `severity: major` - the most important features are sometimes broken or medium important features are often broken
16 | - `severity: medium` - medium important features are sometimes broken or less important features are often broken
17 | - `severity: minor` - less important features are sometimes broken
18 | - `severity: trivial` - it'd be nice to fix but we can live without fixing it
19 | - used by third-party GitHub apps:
20 | - `💵 Funded on Issuehunt` - funded on IssueHunt so you can earn money, fixing the given issue
21 | - `🎁 Rewarded on Issuehunt` - already rewarded on IssueHunt
22 | - other labels:
23 | - `duplicate` - if the given issue is a duplicate of another issue
24 | - `no reproduction details` - if we miss details needed to reproduce the given issue
25 | - `needs discussion` - if we need to discuss details of the given issue
26 | - `proposed issuehunt` if we consider the given issue to fund on IssueHunt
27 | - `hacktoberfest` - used in [Hacktoberfest](https://hacktoberfest.digitalocean.com/) during October, each year so you can obtain a T-shirt according to the Hacktoberfest rules
28 |
29 | ### PRs labels:
30 | - testing (mutually exclusive):
31 | - `tested & works`
32 | - `tested & fails`
33 | - used by third-party GitHub apps:
34 | - `renovate` for PRs opened by Renovate
35 | - `dependencies` for PRs opened by Dependabot
36 | - other labels:
37 | - `wip` - Work in Progress so don't merge
38 |
39 | ### Labels used for both issues and PRs:
40 | - `blocked` if a given issue or PR is blocked by another issue or PR
41 |
--------------------------------------------------------------------------------
/docs/contributions-guide/workflow.md:
--------------------------------------------------------------------------------
1 | # Workflow
2 |
3 | 1. A contributor opens a PR.
4 | 1. A `brainhubeu` organization member creates a new branch from `master` with one of the following prefixes:
5 | - `fix/` for a bug fix
6 | - `feature/` for a new feature
7 | - `breaking/` for breaking changes
8 | 1. A `brainhubeu` organization member changes the PR base branch.
9 | 1. If there are no vulnerabilities, a `brainhubeu` organization member merges the PR to the created branch (other than `master`) in the main repo.
10 | 1. The CI deploys the PR to one of the testing environments.
11 | 1. A `brainhubeu` organization member tests the PR:
12 | - what to test?
13 | - whether the bug is really fixed or the newly implemented feature is working correctly
14 | - whether it doesn't break anything (doesn't cause any new bug)
15 | - where?
16 | - if a manual code analysis tells the PR doesn't affect the mobile and it's a simple change, only desktop (the newest Chrome in any OS)
17 | - otherwise both desktop and mobile (Safari for iOS or the newest Chrome for Android)
18 | - which examples?
19 | - all the examples from the docs
20 | - make sure to resize the screen for the `Responsive` example, desktop
21 | - add `rtl` to the `Autoplay & Animation speed` example
22 | 1. Other `brainhubeu` organization members (at least one person other than the one who has opened the PR) review the PR (and test if they want to).
23 | 1. If the problem is correctly resolved, no breaking changes, and the code approved, a `brainhubeu` organization member merges the PR to the `master` branch.
24 | 1. The CI publishes to NPM.
25 | 1. The CI deploys the production version of docs.
26 | 1. If the issue resolved by the merged PR is funded on IssueHunt, a `brainhubeu` organization member rewards it for the PR author.
27 |
--------------------------------------------------------------------------------
/docs/examples/animation.md:
--------------------------------------------------------------------------------
1 | ## Autoplay & Animation speed
2 | You can set how often slides will change automatically using the `autoPlay` plugin and interval option. Animation speed can also be changed, using animationSpeed prop (which is actually animation duration in ms).
3 | ```jsx render
4 | // import Carousel, { autoplayPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
19 |
20 |
21 |
22 |
23 | ```
24 |
--------------------------------------------------------------------------------
/docs/examples/centered.md:
--------------------------------------------------------------------------------
1 | ## Centered
2 | By default, the current slide is aligned to the left. You can change that behaviour with the `centered` plugin.
3 | ```jsx render
4 | // import Carousel, { slidesToShowPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
20 |
21 |
22 |
23 |
24 | ```
25 |
--------------------------------------------------------------------------------
/docs/examples/clickToChange.md:
--------------------------------------------------------------------------------
1 | ## Click to change
2 | By default, clicking the slides does nothing. You can change that behavior with the `clickToChange` plugin.
3 | ```jsx render
4 | // import Carousel, { slidesToShowPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
19 |
20 |
21 |
22 |
23 | ```
24 |
--------------------------------------------------------------------------------
/docs/examples/controlled.md:
--------------------------------------------------------------------------------
1 | ## Controlled component
2 | You can use Carousel as a controlled component. Provided value will be clamped depending on the number of slides. E.g. if there are 3 slides, all values greater than 2 (index of the last element) will evaluate to 2.
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 | class MyCarousel extends React.Component {
8 | constructor() {
9 | super()
10 | this.state = { value: 0 };
11 | this.onChange = this.onChange.bind(this);
12 | }
13 |
14 | onChange(value) {
15 | this.setState({ value });
16 | }
17 |
18 | render() {
19 | return (
20 |
21 |
this.onChange(parseInt(e.target.value || 0))}
25 | />
26 |
),
31 | (
),
32 | (
),
33 | ]}
34 | plugins={[
35 | 'arrows',
36 | 'clickToChange'
37 | ]}
38 | />
39 |
40 | );
41 | }
42 | }
43 | ```
44 |
--------------------------------------------------------------------------------
/docs/examples/customArrows.md:
--------------------------------------------------------------------------------
1 | ## Custom arrows
2 | You can set custom arrows, using `arrowLeft` and arrowRight options in the `arrows` plugin. You can set custom arrows for the disabled state of `arrowLeft` and `arrowRight`, using `arrrowLeftDisabled` and `arrowRightDisabled` options. You can handle an arrow click event by yourself, or you can tell Carousel to do that for you (using `addArrowClickHandler` option).
3 | ```jsx render
4 | // import Carousel, { arrowsPlugin } from '@brainhubeu/react-carousel';
5 | // import Icon from 'react-fa';
6 |
7 | // import '@brainhubeu/react-carousel/lib/style.css';
8 |
9 | ,
15 | arrowLeftDisabled: ,
16 | arrowRight: ,
17 | arrowRightDisabled: ,
18 | addArrowClickHandler: true,
19 | }
20 | }
21 | ]}
22 |
23 | >
24 |
25 |
26 |
27 |
28 | ```
29 |
--------------------------------------------------------------------------------
/docs/examples/defaultArrows.md:
--------------------------------------------------------------------------------
1 | ## Default Arrows
2 | You can turn default arrows on, using the `arrows` plugin.
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
10 |
11 |
12 |
13 |
14 | ```
15 |
--------------------------------------------------------------------------------
/docs/examples/dots.md:
--------------------------------------------------------------------------------
1 | ## Dots
2 | Dots are a separate component which you can use with controlled carousel as well.
3 | ```jsx render
4 | // import Carousel, { Dots } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 | class MyCarousel extends React.Component {
8 | constructor() {
9 | super()
10 | this.state = {
11 | value: 0,
12 | slides: [
13 | ( ),
14 | ( ),
15 | ( ),
16 | ],
17 | }
18 | this.onchange = this.onchange.bind(this);
19 | }
20 |
21 |
22 | onchange(value) {
23 | this.setState({ value });
24 | }
25 |
26 | render() {
27 | return (
28 |
29 |
34 |
35 |
36 | );
37 | }
38 | }
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/examples/flexContainer.md:
--------------------------------------------------------------------------------
1 | ## Flex Container
2 | You can use a Carousel within a flex container
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
15 |
16 |
17 | ```
18 |
--------------------------------------------------------------------------------
/docs/examples/infinite.md:
--------------------------------------------------------------------------------
1 | ## Infinite
2 | ```jsx render
3 | // import Carousel from '@brainhubeu/react-carousel';
4 | // import '@brainhubeu/react-carousel/lib/style.css';
5 |
6 |
12 |
13 |
14 |
15 |
16 | ```
17 |
--------------------------------------------------------------------------------
/docs/examples/lazyload.md:
--------------------------------------------------------------------------------
1 | ## Lazy load slides
2 | Loads only the nearest next/prev slides to the current one based on the value of the slidesPerPage variable. Check network tab, to see that images are preloaded on demand.
3 | ```jsx render
4 | class MyCarousel extends React.Component {
5 | constructor() {
6 | super()
7 | this.state = { value: 0 };
8 | this.onChange = this.onChange.bind(this);
9 | }
10 |
11 | onChange(value) {
12 | this.setState({ value });
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
this.onChange(parseInt(e.target.value || 0))}
22 | />
23 |
),
39 | (
),
40 | (
),
41 | (
),
42 | (
),
43 | (
),
44 | (
),
45 | (
),
46 | (
),
47 | (
),
48 | (
),
49 | ]}
50 | />
51 |
52 | );
53 | }
54 | }
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/examples/multipleSlides.md:
--------------------------------------------------------------------------------
1 | ## Multiple slides
2 | You can show more than one slide per page, using the `slidesToShow` plugin.
3 | ```jsx render
4 | // import Carousel, { slidesToShowPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
19 |
20 |
21 |
22 |
23 | ```
24 |
--------------------------------------------------------------------------------
/docs/examples/resizableCarousel.md:
--------------------------------------------------------------------------------
1 | ## Resizable carousel
2 | You can surround the Carousel by a container, which can be resized
3 | independently of the window. You should only make sure,
4 | that the container doesn't exceed the viewport.
5 | ```jsx render
6 | // import Carousel from '@brainhubeu/react-carousel';
7 | // import '@brainhubeu/react-carousel/lib/style.css';
8 |
9 | class MyCarousel extends React.Component {
10 |
11 | resizeSurrounding() {
12 | const width = document.querySelector('#width').value;
13 | document.querySelector('#surrounding').style.width = `${width}px`;
14 | }
15 |
16 | render() {
17 | return (
18 |
19 |
Width (px)
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | );
36 | }
37 | }
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/examples/responsive.md:
--------------------------------------------------------------------------------
1 | ## Responsive
2 | You can set all props and plugins to different values on different screen resolutions. The props set will override the existing prop (if already set).
3 |
4 | ```jsx render
5 | // import Carousel, { slidesToShowPlugin } from '@brainhubeu/react-carousel';
6 | // import '@brainhubeu/react-carousel/lib/style.css';
7 |
8 |
41 |
42 |
43 |
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/examples/rtl.md:
--------------------------------------------------------------------------------
1 | ## RTL layout
2 | Carousel supports the right to left layout.
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
10 |
11 |
12 |
13 |
14 | ```
15 |
--------------------------------------------------------------------------------
/docs/examples/simpleUsage.md:
--------------------------------------------------------------------------------
1 | ## Simple slide
2 | For simple usage, just pass slides as children. You don't need any configuration!
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
8 |
9 |
10 |
11 |
12 | ```
13 |
--------------------------------------------------------------------------------
/docs/examples/slidesToScroll.md:
--------------------------------------------------------------------------------
1 | ## Slides to scroll
2 | You can change how far the carousel should move when you click arrow or swipe, using the `slidesToScroll` plugin. The default value is 3.
3 | ```jsx render
4 | // import Carousel, { slidesToShowPlugin, slidesToScrollPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
26 |
27 |
28 |
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/docs/examples/swipingSlides.md:
--------------------------------------------------------------------------------
1 | ## Swiping slides
2 | You can change the swiping behaviour with the `fastSwipe` plugin, and you can disable swiping by setting props `draggable={false}`.
3 | ```jsx render
4 | // import Carousel, { slidesToShowPlugin } from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 |
19 |
20 |
21 |
22 |
23 | ```
24 |
--------------------------------------------------------------------------------
/docs/examples/thumbnails.md:
--------------------------------------------------------------------------------
1 | ## Thumbnails
2 | You can use Dots component to show thumbnails.
3 | ```jsx render
4 | // import Carousel from '@brainhubeu/react-carousel';
5 | // import '@brainhubeu/react-carousel/lib/style.css';
6 |
7 | class MyCarousel extends React.Component {
8 | constructor() {
9 | super()
10 | this.state = {
11 | value: 0,
12 | slides: [
13 | ( ),
14 | ( ),
15 | ( ),
16 | ],
17 | thumbnails: [
18 | ( ),
19 | ( ),
20 | ( ),
21 | ],
22 | }
23 | this.onchange = this.onchange.bind(this);
24 | }
25 |
26 |
27 | onchange(value) {
28 | this.setState({ value });
29 | }
30 |
31 | render() {
32 | return (
33 |
34 |
39 |
40 |
41 | );
42 | }
43 | }
44 | ```
45 |
--------------------------------------------------------------------------------
/docs/gettingStarted.md:
--------------------------------------------------------------------------------
1 | ## Why?
2 | There are some great carousels (like slick) that do not have real React implementations. This library provides you with carousel that is not merely a wrapper for some jQuery solution, can be used as controlled or uncontrolled element (similar to [inputs](https://reactjs.org/docs/uncontrolled-components.html)), and has tons of useful features.
3 |
4 | ## Installation
5 | Install the library:
6 | ```
7 | $ npm i @brainhubeu/react-carousel
8 | ```
9 |
10 | And then you can import Carousel and Dots components:
11 | ```
12 | import Carousel, { Dots } from '@brainhubeu/react-carousel';
13 | import '@brainhubeu/react-carousel/lib/style.css';
14 | ```
15 |
16 | You can find usage examples [here](/docs/examples/simpleUsage/)
17 |
--------------------------------------------------------------------------------
/docs/migrationGuide.md:
--------------------------------------------------------------------------------
1 | ## Migration guide
2 | In the carousel v2 in order to make carousel more maintainable, many props have been replaced with the plugins. In the following section, you can find out how to migrate the carousel v1 props into plugins.
3 |
4 | ### slidesPerPage
5 |
6 | ####v1
7 | ```jsx
8 |
11 |
12 |
13 |
14 |
15 | ```
16 |
17 | ####v2
18 | ```jsx
19 | import { slidesToShowPlugin } from '@brainhubeu/react-carousel';
20 |
21 |
31 |
32 |
33 |
34 |
35 | ```
36 |
37 | ### clickToChange
38 |
39 | ####v1
40 | ```jsx
41 |
44 |
45 |
46 |
47 |
48 | ```
49 |
50 | ####v2
51 | ```jsx
52 |
57 |
58 |
59 |
60 |
61 | ```
62 |
63 | ### arrows
64 |
65 | ####v1
66 | ```jsx
67 |
70 |
71 |
72 |
73 |
74 | ```
75 |
76 | ####v2
77 | ```jsx
78 |
81 |
82 |
83 |
84 |
85 | ```
86 |
87 | ### infinite
88 |
89 | ####v1
90 | ```jsx
91 |
94 |
95 |
96 |
97 |
98 | ```
99 |
100 | ####v2
101 | ```jsx
102 |
107 |
108 |
109 |
110 |
111 | ```
112 |
113 |
114 | ### rtl
115 |
116 | ####v1
117 | ```jsx
118 |
119 |
120 |
121 |
122 |
123 | ```
124 |
125 | ####v2
126 | ```jsx
127 |
132 |
133 |
134 |
135 |
136 | ```
137 |
138 | ### centered
139 |
140 | ####v1
141 | ```jsx
142 |
143 |
144 |
145 |
146 |
147 | ```
148 |
149 | ####v2
150 | ```jsx
151 |
156 |
157 |
158 |
159 |
160 | ```
161 |
162 | ### slidesPerScroll
163 |
164 | ####v1
165 | ```jsx
166 |
169 |
170 |
171 |
172 |
173 | ```
174 |
175 | ####v2
176 | ```jsx
177 | import { slidesToScrollPlugin } from '@brainhubeu/react-carousel';
178 |
179 |
189 |
190 |
191 |
192 |
193 | ```
194 |
195 | ### keepDirectionWhenDragging
196 |
197 | ####v1
198 | ```jsx
199 |
202 |
203 |
204 |
205 |
206 | ```
207 |
208 | ####v2
209 | ```jsx
210 |
215 |
216 |
217 |
218 |
219 | ```
220 |
221 | ### autoplay
222 |
223 | ####v1
224 | ```jsx
225 |
229 |
230 |
231 |
232 |
233 | ```
234 |
235 | ####v2
236 | ```jsx
237 | import { autoplayPlugin } from '@brainhubeu/react-carousel';
238 |
239 |
250 |
251 |
252 |
253 |
254 | ```
255 |
256 | ### dots
257 |
258 | In v2, the dots property has been removed. Please use [**dots component**](https://brainhubeu.github.io/react-carousel/docs/examples/dots) instead.
259 |
260 | ### lazyLoad
261 |
262 | We are working on implementing this feature in the carousel v2. Stay tuned...
263 |
--------------------------------------------------------------------------------
/docs/plugins/plugins.md:
--------------------------------------------------------------------------------
1 | ## plugins
2 |
3 | ### slidesToShow plugin
4 |
5 | options:
6 | * ```numberOfSlides: Number```: Number of slides visible at once.
7 |
8 | usage:
9 | ```jsx
10 |
20 | {/ *carousel items... */}
21 |
22 | ```
23 |
24 |
25 |
26 | ### slidesToScroll plugin
27 |
28 | options:
29 | * ```numberOfSlides: Number```: Number by which value will change on scroll (autoPlay, arrow click, drag).
30 |
31 | usage:
32 | ```jsx
33 |
43 | {/ *carousel items... */}
44 |
45 | ```
46 |
47 |
48 |
49 | ### arrows plugin
50 |
51 | options:
52 | * ```arrowLeft: React element```, ```arrowLeftDisabled: React element```, ```arrowRightDisabled: React element```, ```arrowRight: React element```: React elements to be used instead of default arrows.
53 |
54 | * ```addArrowClickHandler: Boolean``` Has to be added for arrowLeft and arrowRight to work.
55 |
56 | simple usage:
57 | ```jsx
58 |
61 | {/ *carousel items... */}
62 |
63 | ```
64 |
65 | advanced usage:
66 | ```jsx
67 | ,
73 | arrowLeftDisabled: ,
74 | arrowRight: ,
75 | arrowRightDisabled: ,
76 | addArrowClickHandler: true,
77 | }
78 | }
79 | ]}
80 | >
81 | {/ *carousel items... */}
82 |
83 | ```
84 |
85 |
86 |
87 | ### autoplay plugin
88 |
89 | options:
90 | * ```interval: Number```: Slide change interval in milliseconds. Defaults to 2000
91 |
92 | * ```stopAutoPlayOnHover: Boolean```: Determines if autoPlay should stop when mouse hover over carousel, defaults to `true`
93 |
94 | * ```direction: 'right' | 'left'```: Determines direction of changing slides, defaults to `right`
95 |
96 | simple usage:
97 | ```jsx
98 |
101 | {/ *carousel items... */}
102 |
103 | ```
104 |
105 | advanced usage:
106 | ```jsx
107 |
118 | {/ *carousel items... */}
119 |
120 | ```
121 |
122 |
123 |
124 | ### clickToChange plugin
125 | Clicking on a slide changes current slide to the clicked one.
126 |
127 | usage:
128 | ```jsx
129 |
132 | {/ *carousel items... */}
133 |
134 | ```
135 |
136 |
137 |
138 | ### centered plugin
139 | Alignes active slide to the center of the carousel.
140 |
141 | usage:
142 | ```jsx
143 |
146 | {/ *carousel items... */}
147 |
148 | ```
149 |
150 |
151 |
152 | ### infinite plugin
153 | Creates an infinite carousel width.
154 |
155 | options:
156 | * ```numberOfInfiniteClones: Number```: Number of clones created before and after original carousel slides. Defaults to 1
157 |
158 | usage:
159 | ```jsx
160 |
163 | {/ *carousel items... */}
164 |
165 | ```
166 |
167 | advanced usage:
168 | ```jsx
169 |
179 | {/ *carousel items... */}
180 |
181 | ```
182 |
183 |
184 |
185 | ### fastSwipe plugin
186 | While dragging, it doesn't matter which slide is the nearest one, but in what direction you drag.
187 |
188 | usage:
189 | ```jsx
190 |
193 | {/ *carousel items... */}
194 |
195 | ```
196 |
--------------------------------------------------------------------------------
/license/blacklist.js:
--------------------------------------------------------------------------------
1 | /* Provide a list of blacklisted licenses for the project below */
2 | const blacklist = [
3 | 'UNKNOWN',
4 | '389-exception',
5 | 'AAL',
6 | 'ADSL',
7 | 'AFL-1.1',
8 | 'AFL-1.2',
9 | 'AFL-2.0',
10 | 'AFL-2.1',
11 | 'AFL-3.0',
12 | 'AGPL-1.0-only',
13 | 'AGPL-1.0-or-later',
14 | 'AGPL-3.0-only',
15 | 'AGPL-3.0-or-later',
16 | 'AMDPLPA',
17 | 'AML',
18 | 'AMPAS',
19 | 'ANTLR-PD',
20 | 'APAFML',
21 | 'APL-1.0',
22 | 'APSL-1.0',
23 | 'APSL-1.1',
24 | 'APSL-1.2',
25 | 'APSL-2.0',
26 | 'Abstyles',
27 | 'Adobe-2006',
28 | 'Adobe-Glyph',
29 | 'Afmparse',
30 | 'Aladdin',
31 | 'Apache-1.0',
32 | 'Apache-1.1',
33 | 'Artistic-1.0-Perl',
34 | 'Artistic-1.0-cl8',
35 | 'Artistic-1.0',
36 | 'Autoconf-exception-2.0',
37 | 'Autoconf-exception-3.0',
38 | 'BSD-1-Clause',
39 | 'BSD-2-Clause-FreeBSD',
40 | 'BSD-2-Clause-NetBSD',
41 | 'BSD-2-Clause-Patent',
42 | 'BSD-3-Clause-Attribution',
43 | 'BSD-3-Clause-Clear',
44 | 'BSD-3-Clause-LBNL',
45 | 'BSD-3-Clause-No-Nuclear-License-2014',
46 | 'BSD-3-Clause-No-Nuclear-License',
47 | 'BSD-3-Clause-No-Nuclear-Warranty',
48 | 'BSD-3-Clause-Open-MPI',
49 | 'BSD-4-Clause-UC',
50 | 'BSD-4-Clause',
51 | 'BSD-Protection',
52 | 'BSD-Source-Code',
53 | 'BSL-1.0',
54 | 'Bahyph',
55 | 'Barr',
56 | 'Beerware',
57 | 'Bison-exception-2.2',
58 | 'BitTorrent-1.0',
59 | 'BitTorrent-1.1',
60 | 'BlueOak-1.0.0',
61 | 'Bootloader-exception',
62 | 'Borceux',
63 | 'CATOSL-1.1',
64 | 'CC-BY-1.0',
65 | 'CC-BY-2.0',
66 | 'CC-BY-2.5',
67 | 'CC-BY-NC-1.0',
68 | 'CC-BY-NC-2.0',
69 | 'CC-BY-NC-2.5',
70 | 'CC-BY-NC-3.0',
71 | 'CC-BY-NC-4.0',
72 | 'CC-BY-NC-ND-1.0',
73 | 'CC-BY-NC-ND-2.0',
74 | 'CC-BY-NC-ND-2.5',
75 | 'CC-BY-NC-ND-3.0',
76 | 'CC-BY-NC-ND-4.0',
77 | 'CC-BY-NC-SA-1.0',
78 | 'CC-BY-NC-SA-2.0',
79 | 'CC-BY-NC-SA-2.5',
80 | 'CC-BY-NC-SA-3.0',
81 | 'CC-BY-NC-SA-4.0',
82 | 'CC-BY-ND-1.0',
83 | 'CC-BY-ND-2.0',
84 | 'CC-BY-ND-2.5',
85 | 'CC-BY-ND-3.0',
86 | 'CC-BY-ND-4.0',
87 | 'CC-BY-SA-1.0',
88 | 'CC-BY-SA-2.0',
89 | 'CC-BY-SA-2.5',
90 | 'CC-BY-SA-3.0',
91 | 'CC-BY-SA-4.0',
92 | 'CC-PDDC',
93 | 'CDDL-1.0',
94 | 'CDDL-1.1',
95 | 'CDLA-Permissive-1.0',
96 | 'CDLA-Sharing-1.0',
97 | 'CECILL-1.0',
98 | 'CECILL-1.1',
99 | 'CECILL-2.0',
100 | 'CECILL-2.1',
101 | 'CECILL-B',
102 | 'CECILL-C',
103 | 'CERN-OHL-1.1',
104 | 'CERN-OHL-1.2',
105 | 'CLISP-exception-2.0',
106 | 'CNRI-Jython',
107 | 'CNRI-Python-GPL-Compatible',
108 | 'CNRI-Python',
109 | 'CPAL-1.0',
110 | 'CPL-1.0',
111 | 'CPOL-1.02',
112 | 'CUA-OPL-1.0',
113 | 'Caldera',
114 | 'ClArtistic',
115 | 'Classpath-exception-2.0',
116 | 'Condor-1.1',
117 | 'Crossword',
118 | 'CrystalStacker',
119 | 'Cube',
120 | 'D-FSL-1.0',
121 | 'DOC',
122 | 'DSDP',
123 | 'DigiRule-FOSS-exception',
124 | 'Dotseqn',
125 | 'ECL-1.0',
126 | 'ECL-2.0',
127 | 'EFL-1.0',
128 | 'EFL-2.0',
129 | 'EPL-1.0',
130 | 'EPL-2.0',
131 | 'EUDatagrid',
132 | 'EUPL-1.0',
133 | 'EUPL-1.1',
134 | 'EUPL-1.2',
135 | 'Entessa',
136 | 'ErlPL-1.1',
137 | 'Eurosym',
138 | 'FLTK-exception',
139 | 'FSFAP',
140 | 'FSFUL',
141 | 'FSFULLR',
142 | 'FTL',
143 | 'Fair',
144 | 'Fawkes-Runtime-exception',
145 | 'Font-exception-2.0',
146 | 'Frameworx-1.0',
147 | 'FreeImage',
148 | 'GCC-exception-2.0',
149 | 'GCC-exception-3.1',
150 | 'GFDL-1.1-only',
151 | 'GFDL-1.1-or-later',
152 | 'GFDL-1.2-only',
153 | 'GFDL-1.2-or-later',
154 | 'GFDL-1.3-only',
155 | 'GFDL-1.3-or-later',
156 | 'GL2PS',
157 | 'GPL-1.0-only',
158 | 'GPL-1.0-or-later',
159 | 'GPL-2.0-only',
160 | 'GPL-2.0-or-later',
161 | 'GPL-3.0-linking-exception',
162 | 'GPL-3.0-linking-source-exception',
163 | 'GPL-3.0-only',
164 | 'GPL-3.0-or-later',
165 | 'GPL-CC-1.0',
166 | 'Giftware',
167 | 'Glide',
168 | 'Glulxe',
169 | 'HPND-sell-variant',
170 | 'HPND',
171 | 'HaskellReport',
172 | 'IBM-pibs',
173 | 'ICU',
174 | 'IJG',
175 | 'IPA',
176 | 'IPL-1.0',
177 | 'ImageMagick',
178 | 'Imlib2',
179 | 'Info-ZIP',
180 | 'Intel-ACPI',
181 | 'Intel',
182 | 'Interbase-1.0',
183 | 'JPNIC',
184 | 'JSON',
185 | 'JasPer-2.0',
186 | 'LAL-1.2',
187 | 'LAL-1.3',
188 | 'LGPL-2.0-only',
189 | 'LGPL-2.0-or-later',
190 | 'LGPL-2.1-only',
191 | 'LGPL-2.1-or-later',
192 | 'LGPL-3.0-only',
193 | 'LGPL-3.0-or-later',
194 | 'LGPLLR',
195 | 'LLVM-exception',
196 | 'LPL-1.0',
197 | 'LPL-1.02',
198 | 'LPPL-1.0',
199 | 'LPPL-1.1',
200 | 'LPPL-1.2',
201 | 'LPPL-1.3a',
202 | 'LPPL-1.3c',
203 | 'LZMA-exception',
204 | 'Latex2e',
205 | 'Leptonica',
206 | 'LiLiQ-P-1.1',
207 | 'LiLiQ-R-1.1',
208 | 'LiLiQ-Rplus-1.1',
209 | 'Libpng',
210 | 'Libtool-exception',
211 | 'Linux-OpenIB',
212 | 'Linux-syscall-note',
213 | 'MIT-0',
214 | 'MIT-CMU',
215 | 'MIT-advertising',
216 | 'MIT-enna',
217 | 'MIT-feh',
218 | 'MITNFA',
219 | 'MS-PL',
220 | 'MS-RL',
221 | 'MTLL',
222 | 'MakeIndex',
223 | 'MirOS',
224 | 'Motosoto',
225 | 'MulanPSL-1.0',
226 | 'Multics',
227 | 'Mup',
228 | 'NASA-1.3',
229 | 'NBPL-1.0',
230 | 'NCSA',
231 | 'NGPL',
232 | 'NLOD-1.0',
233 | 'NLPL',
234 | 'NOSL',
235 | 'NPL-1.0',
236 | 'NPL-1.1',
237 | 'NPOSL-3.0',
238 | 'NRL',
239 | 'NTP-0',
240 | 'NTP',
241 | 'Naumen',
242 | 'Net-SNMP',
243 | 'NetCDF',
244 | 'Newsletr',
245 | 'Nokia-Qt-exception-1.1',
246 | 'Nokia',
247 | 'Noweb',
248 | 'OCCT-PL',
249 | 'OCCT-exception-1.0',
250 | 'OCLC-2.0',
251 | 'OCaml-LGPL-linking-exception',
252 | 'ODbL-1.0',
253 | 'OFL-1.0-RFN',
254 | 'OFL-1.0-no-RFN',
255 | 'OFL-1.0',
256 | 'OFL-1.1-RFN',
257 | 'OFL-1.1-no-RFN',
258 | 'OFL-1.1',
259 | 'OGL-Canada-2.0',
260 | 'OGL-UK-1.0',
261 | 'OGL-UK-2.0',
262 | 'OGL-UK-3.0',
263 | 'OGTSL',
264 | 'OLDAP-1.1',
265 | 'OLDAP-1.2',
266 | 'OLDAP-1.3',
267 | 'OLDAP-1.4',
268 | 'OLDAP-2.0.1',
269 | 'OLDAP-2.0',
270 | 'OLDAP-2.1',
271 | 'OLDAP-2.2.1',
272 | 'OLDAP-2.2.2',
273 | 'OLDAP-2.2',
274 | 'OLDAP-2.3',
275 | 'OLDAP-2.4',
276 | 'OLDAP-2.5',
277 | 'OLDAP-2.6',
278 | 'OLDAP-2.7',
279 | 'OLDAP-2.8',
280 | 'OML',
281 | 'OPL-1.0',
282 | 'OSET-PL-2.1',
283 | 'OSL-1.0',
284 | 'OSL-1.1',
285 | 'OSL-2.0',
286 | 'OSL-2.1',
287 | 'OSL-3.0',
288 | 'OpenJDK-assembly-exception-1.0',
289 | 'OpenSSL',
290 | 'PDDL-1.0',
291 | 'PHP-3.0',
292 | 'PHP-3.01',
293 | 'PS-or-PDF-font-exception-20170817',
294 | 'PSF-2.0',
295 | 'Parity-6.0.0',
296 | 'Plexus',
297 | 'PostgreSQL',
298 | 'Python-2.0',
299 | 'QPL-1.0',
300 | 'Qhull',
301 | 'Qt-GPL-exception-1.0',
302 | 'Qt-LGPL-exception-1.1',
303 | 'Qwt-exception-1.0',
304 | 'RHeCos-1.1',
305 | 'RPL-1.1',
306 | 'RPL-1.5',
307 | 'RPSL-1.0',
308 | 'RSA-MD',
309 | 'RSCPL',
310 | 'Rdisc',
311 | 'Ruby',
312 | 'SAX-PD',
313 | 'SCEA',
314 | 'SGI-B-1.0',
315 | 'SGI-B-1.1',
316 | 'SGI-B-2.0',
317 | 'SHL-0.5',
318 | 'SHL-0.51',
319 | 'SISSL-1.2',
320 | 'SISSL',
321 | 'SMLNJ',
322 | 'SMPPL',
323 | 'SNIA',
324 | 'SPL-1.0',
325 | 'SSH-OpenSSH',
326 | 'SSH-short',
327 | 'SSPL-1.0',
328 | 'SWL',
329 | 'Saxpath',
330 | 'Sendmail-8.23',
331 | 'Sendmail',
332 | 'SimPL-2.0',
333 | 'Sleepycat',
334 | 'Spencer-86',
335 | 'Spencer-94',
336 | 'Spencer-99',
337 | 'SugarCRM-1.1.3',
338 | 'Swift-exception',
339 | 'TAPR-OHL-1.0',
340 | 'TCL',
341 | 'TCP-wrappers',
342 | 'TMate',
343 | 'TORQUE-1.1',
344 | 'TOSL',
345 | 'TU-Berlin-1.0',
346 | 'TU-Berlin-2.0',
347 | 'UCL-1.0',
348 | 'UPL-1.0',
349 | 'Unicode-DFS-2015',
350 | 'Unicode-DFS-2016',
351 | 'Unicode-TOU',
352 | 'Universal-FOSS-exception-1.0',
353 | 'VOSTROM',
354 | 'VSL-1.0',
355 | 'Vim',
356 | 'W3C-19980720',
357 | 'W3C-20150513',
358 | 'W3C',
359 | 'Watcom-1.0',
360 | 'Wsuipa',
361 | 'WxWindows-exception-3.1',
362 | 'X11',
363 | 'XFree86-1.1',
364 | 'XSkat',
365 | 'Xerox',
366 | 'Xnet',
367 | 'YPL-1.0',
368 | 'YPL-1.1',
369 | 'ZPL-1.1',
370 | 'ZPL-2.0',
371 | 'ZPL-2.1',
372 | 'Zed',
373 | 'Zend-2.0',
374 | 'Zimbra-1.3',
375 | 'Zimbra-1.4',
376 | 'blessing',
377 | 'bzip2-1.0.5',
378 | 'bzip2-1.0.6',
379 | 'copyleft-next-0.3.0',
380 | 'copyleft-next-0.3.1',
381 | 'curl',
382 | 'deprecated_AGPL-1.0',
383 | 'deprecated_AGPL-3.0',
384 | 'deprecated_GFDL-1.1',
385 | 'deprecated_GFDL-1.2',
386 | 'deprecated_GFDL-1.3',
387 | 'deprecated_GPL-1.0+',
388 | 'deprecated_GPL-1.0',
389 | 'deprecated_GPL-2.0+',
390 | 'deprecated_GPL-2.0-with-GCC-exception',
391 | 'deprecated_GPL-2.0-with-autoconf-exception',
392 | 'deprecated_GPL-2.0-with-bison-exception',
393 | 'deprecated_GPL-2.0-with-classpath-exception',
394 | 'deprecated_GPL-2.0-with-font-exception',
395 | 'deprecated_GPL-2.0',
396 | 'deprecated_GPL-3.0+',
397 | 'deprecated_GPL-3.0-with-GCC-exception',
398 | 'deprecated_GPL-3.0-with-autoconf-exception',
399 | 'deprecated_GPL-3.0',
400 | 'deprecated_LGPL-2.0+',
401 | 'deprecated_LGPL-2.0',
402 | 'deprecated_LGPL-2.1+',
403 | 'deprecated_LGPL-2.1',
404 | 'deprecated_LGPL-3.0+',
405 | 'deprecated_LGPL-3.0',
406 | 'deprecated_Nunit',
407 | 'deprecated_StandardML-NJ',
408 | 'deprecated_eCos-2.0',
409 | 'deprecated_wxWindows',
410 | 'diffmark',
411 | 'dvipdfm',
412 | 'eCos-exception-2.0',
413 | 'eGenix',
414 | 'etalab-2.0',
415 | 'freertos-exception-2.0',
416 | 'gSOAP-1.3b',
417 | 'gnu-javamail-exception',
418 | 'gnuplot',
419 | 'i2p-gpl-java-exception',
420 | 'iMatix',
421 | 'libpng-2.0',
422 | 'libselinux-1.0',
423 | 'libtiff',
424 | 'mif-exception',
425 | 'mpich2',
426 | 'openvpn-openssl-exception',
427 | 'psfrag',
428 | 'psutils',
429 | 'u-boot-exception-2.0',
430 | 'xinetd',
431 | 'xpp',
432 | 'zlib-acknowledgement',
433 | ];
434 |
435 | module.exports = blacklist;
436 |
--------------------------------------------------------------------------------
/license/licenses.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-unused-vars
2 | const licenses = [
3 | '0BSD',
4 | '389-exception',
5 | 'AAL',
6 | 'ADSL',
7 | 'AFL-1.1',
8 | 'AFL-1.2',
9 | 'AFL-2.0',
10 | 'AFL-2.1',
11 | 'AFL-3.0',
12 | 'AGPL-1.0-only',
13 | 'AGPL-1.0-or-later',
14 | 'AGPL-3.0-only',
15 | 'AGPL-3.0-or-later',
16 | 'AMDPLPA',
17 | 'AML',
18 | 'AMPAS',
19 | 'ANTLR-PD',
20 | 'APAFML',
21 | 'APL-1.0',
22 | 'APSL-1.0',
23 | 'APSL-1.1',
24 | 'APSL-1.2',
25 | 'APSL-2.0',
26 | 'Abstyles',
27 | 'Adobe-2006',
28 | 'Adobe-Glyph',
29 | 'Afmparse',
30 | 'Aladdin',
31 | 'Apache-1.0',
32 | 'Apache-1.1',
33 | 'Apache-2.0',
34 | 'Artistic-1.0-Perl',
35 | 'Artistic-1.0-cl8',
36 | 'Artistic-1.0',
37 | 'Artistic-2.0',
38 | 'Autoconf-exception-2.0',
39 | 'Autoconf-exception-3.0',
40 | 'BSD-1-Clause',
41 | 'BSD-2-Clause-FreeBSD',
42 | 'BSD-2-Clause-NetBSD',
43 | 'BSD-2-Clause-Patent',
44 | 'BSD-2-Clause',
45 | 'BSD-3-Clause-Attribution',
46 | 'BSD-3-Clause-Clear',
47 | 'BSD-3-Clause-LBNL',
48 | 'BSD-3-Clause-No-Nuclear-License-2014',
49 | 'BSD-3-Clause-No-Nuclear-License',
50 | 'BSD-3-Clause-No-Nuclear-Warranty',
51 | 'BSD-3-Clause-Open-MPI',
52 | 'BSD-3-Clause',
53 | 'BSD-4-Clause-UC',
54 | 'BSD-4-Clause',
55 | 'BSD-Protection',
56 | 'BSD-Source-Code',
57 | 'BSL-1.0',
58 | 'Bahyph',
59 | 'Barr',
60 | 'Beerware',
61 | 'Bison-exception-2.2',
62 | 'BitTorrent-1.0',
63 | 'BitTorrent-1.1',
64 | 'BlueOak-1.0.0',
65 | 'Bootloader-exception',
66 | 'Borceux',
67 | 'CATOSL-1.1',
68 | 'CC-BY-1.0',
69 | 'CC-BY-2.0',
70 | 'CC-BY-2.5',
71 | 'CC-BY-3.0',
72 | 'CC-BY-4.0',
73 | 'CC-BY-NC-1.0',
74 | 'CC-BY-NC-2.0',
75 | 'CC-BY-NC-2.5',
76 | 'CC-BY-NC-3.0',
77 | 'CC-BY-NC-4.0',
78 | 'CC-BY-NC-ND-1.0',
79 | 'CC-BY-NC-ND-2.0',
80 | 'CC-BY-NC-ND-2.5',
81 | 'CC-BY-NC-ND-3.0',
82 | 'CC-BY-NC-ND-4.0',
83 | 'CC-BY-NC-SA-1.0',
84 | 'CC-BY-NC-SA-2.0',
85 | 'CC-BY-NC-SA-2.5',
86 | 'CC-BY-NC-SA-3.0',
87 | 'CC-BY-NC-SA-4.0',
88 | 'CC-BY-ND-1.0',
89 | 'CC-BY-ND-2.0',
90 | 'CC-BY-ND-2.5',
91 | 'CC-BY-ND-3.0',
92 | 'CC-BY-ND-4.0',
93 | 'CC-BY-SA-1.0',
94 | 'CC-BY-SA-2.0',
95 | 'CC-BY-SA-2.5',
96 | 'CC-BY-SA-3.0',
97 | 'CC-BY-SA-4.0',
98 | 'CC-PDDC',
99 | 'CC0-1.0',
100 | 'CDDL-1.0',
101 | 'CDDL-1.1',
102 | 'CDLA-Permissive-1.0',
103 | 'CDLA-Sharing-1.0',
104 | 'CECILL-1.0',
105 | 'CECILL-1.1',
106 | 'CECILL-2.0',
107 | 'CECILL-2.1',
108 | 'CECILL-B',
109 | 'CECILL-C',
110 | 'CERN-OHL-1.1',
111 | 'CERN-OHL-1.2',
112 | 'CLISP-exception-2.0',
113 | 'CNRI-Jython',
114 | 'CNRI-Python-GPL-Compatible',
115 | 'CNRI-Python',
116 | 'CPAL-1.0',
117 | 'CPL-1.0',
118 | 'CPOL-1.02',
119 | 'CUA-OPL-1.0',
120 | 'Caldera',
121 | 'ClArtistic',
122 | 'Classpath-exception-2.0',
123 | 'Condor-1.1',
124 | 'Crossword',
125 | 'CrystalStacker',
126 | 'Cube',
127 | 'D-FSL-1.0',
128 | 'DOC',
129 | 'DSDP',
130 | 'DigiRule-FOSS-exception',
131 | 'Dotseqn',
132 | 'ECL-1.0',
133 | 'ECL-2.0',
134 | 'EFL-1.0',
135 | 'EFL-2.0',
136 | 'EPL-1.0',
137 | 'EPL-2.0',
138 | 'EUDatagrid',
139 | 'EUPL-1.0',
140 | 'EUPL-1.1',
141 | 'EUPL-1.2',
142 | 'Entessa',
143 | 'ErlPL-1.1',
144 | 'Eurosym',
145 | 'FLTK-exception',
146 | 'FSFAP',
147 | 'FSFUL',
148 | 'FSFULLR',
149 | 'FTL',
150 | 'Fair',
151 | 'Fawkes-Runtime-exception',
152 | 'Font-exception-2.0',
153 | 'Frameworx-1.0',
154 | 'FreeImage',
155 | 'GCC-exception-2.0',
156 | 'GCC-exception-3.1',
157 | 'GFDL-1.1-only',
158 | 'GFDL-1.1-or-later',
159 | 'GFDL-1.2-only',
160 | 'GFDL-1.2-or-later',
161 | 'GFDL-1.3-only',
162 | 'GFDL-1.3-or-later',
163 | 'GL2PS',
164 | 'GPL-1.0-only',
165 | 'GPL-1.0-or-later',
166 | 'GPL-2.0-only',
167 | 'GPL-2.0-or-later',
168 | 'GPL-3.0-linking-exception',
169 | 'GPL-3.0-linking-source-exception',
170 | 'GPL-3.0-only',
171 | 'GPL-3.0-or-later',
172 | 'GPL-CC-1.0',
173 | 'Giftware',
174 | 'Glide',
175 | 'Glulxe',
176 | 'HPND-sell-variant',
177 | 'HPND',
178 | 'HaskellReport',
179 | 'IBM-pibs',
180 | 'ICU',
181 | 'IJG',
182 | 'IPA',
183 | 'IPL-1.0',
184 | 'ISC',
185 | 'ImageMagick',
186 | 'Imlib2',
187 | 'Info-ZIP',
188 | 'Intel-ACPI',
189 | 'Intel',
190 | 'Interbase-1.0',
191 | 'JPNIC',
192 | 'JSON',
193 | 'JasPer-2.0',
194 | 'LAL-1.2',
195 | 'LAL-1.3',
196 | 'LGPL-2.0-only',
197 | 'LGPL-2.0-or-later',
198 | 'LGPL-2.1-only',
199 | 'LGPL-2.1-or-later',
200 | 'LGPL-3.0-only',
201 | 'LGPL-3.0-or-later',
202 | 'LGPLLR',
203 | 'LLVM-exception',
204 | 'LPL-1.0',
205 | 'LPL-1.02',
206 | 'LPPL-1.0',
207 | 'LPPL-1.1',
208 | 'LPPL-1.2',
209 | 'LPPL-1.3a',
210 | 'LPPL-1.3c',
211 | 'LZMA-exception',
212 | 'Latex2e',
213 | 'Leptonica',
214 | 'LiLiQ-P-1.1',
215 | 'LiLiQ-R-1.1',
216 | 'LiLiQ-Rplus-1.1',
217 | 'Libpng',
218 | 'Libtool-exception',
219 | 'Linux-OpenIB',
220 | 'Linux-syscall-note',
221 | 'MIT-0',
222 | 'MIT-CMU',
223 | 'MIT-advertising',
224 | 'MIT-enna',
225 | 'MIT-feh',
226 | 'MIT',
227 | 'MITNFA',
228 | 'MPL-1.0',
229 | 'MPL-1.1',
230 | 'MPL-2.0-no-copyleft-exception',
231 | 'MPL-2.0',
232 | 'MS-PL',
233 | 'MS-RL',
234 | 'MTLL',
235 | 'MakeIndex',
236 | 'MirOS',
237 | 'Motosoto',
238 | 'MulanPSL-1.0',
239 | 'Multics',
240 | 'Mup',
241 | 'NASA-1.3',
242 | 'NBPL-1.0',
243 | 'NCSA',
244 | 'NGPL',
245 | 'NLOD-1.0',
246 | 'NLPL',
247 | 'NOSL',
248 | 'NPL-1.0',
249 | 'NPL-1.1',
250 | 'NPOSL-3.0',
251 | 'NRL',
252 | 'NTP-0',
253 | 'NTP',
254 | 'Naumen',
255 | 'Net-SNMP',
256 | 'NetCDF',
257 | 'Newsletr',
258 | 'Nokia-Qt-exception-1.1',
259 | 'Nokia',
260 | 'Noweb',
261 | 'OCCT-PL',
262 | 'OCCT-exception-1.0',
263 | 'OCLC-2.0',
264 | 'OCaml-LGPL-linking-exception',
265 | 'ODC-By-1.0',
266 | 'ODbL-1.0',
267 | 'OFL-1.0-RFN',
268 | 'OFL-1.0-no-RFN',
269 | 'OFL-1.0',
270 | 'OFL-1.1-RFN',
271 | 'OFL-1.1-no-RFN',
272 | 'OFL-1.1',
273 | 'OGL-Canada-2.0',
274 | 'OGL-UK-1.0',
275 | 'OGL-UK-2.0',
276 | 'OGL-UK-3.0',
277 | 'OGTSL',
278 | 'OLDAP-1.1',
279 | 'OLDAP-1.2',
280 | 'OLDAP-1.3',
281 | 'OLDAP-1.4',
282 | 'OLDAP-2.0.1',
283 | 'OLDAP-2.0',
284 | 'OLDAP-2.1',
285 | 'OLDAP-2.2.1',
286 | 'OLDAP-2.2.2',
287 | 'OLDAP-2.2',
288 | 'OLDAP-2.3',
289 | 'OLDAP-2.4',
290 | 'OLDAP-2.5',
291 | 'OLDAP-2.6',
292 | 'OLDAP-2.7',
293 | 'OLDAP-2.8',
294 | 'OML',
295 | 'OPL-1.0',
296 | 'OSET-PL-2.1',
297 | 'OSL-1.0',
298 | 'OSL-1.1',
299 | 'OSL-2.0',
300 | 'OSL-2.1',
301 | 'OSL-3.0',
302 | 'OpenJDK-assembly-exception-1.0',
303 | 'OpenSSL',
304 | 'PDDL-1.0',
305 | 'PHP-3.0',
306 | 'PHP-3.01',
307 | 'PS-or-PDF-font-exception-20170817',
308 | 'PSF-2.0',
309 | 'Parity-6.0.0',
310 | 'Plexus',
311 | 'PostgreSQL',
312 | 'Python-2.0',
313 | 'QPL-1.0',
314 | 'Qhull',
315 | 'Qt-GPL-exception-1.0',
316 | 'Qt-LGPL-exception-1.1',
317 | 'Qwt-exception-1.0',
318 | 'RHeCos-1.1',
319 | 'RPL-1.1',
320 | 'RPL-1.5',
321 | 'RPSL-1.0',
322 | 'RSA-MD',
323 | 'RSCPL',
324 | 'Rdisc',
325 | 'Ruby',
326 | 'SAX-PD',
327 | 'SCEA',
328 | 'SGI-B-1.0',
329 | 'SGI-B-1.1',
330 | 'SGI-B-2.0',
331 | 'SHL-0.5',
332 | 'SHL-0.51',
333 | 'SISSL-1.2',
334 | 'SISSL',
335 | 'SMLNJ',
336 | 'SMPPL',
337 | 'SNIA',
338 | 'SPL-1.0',
339 | 'SSH-OpenSSH',
340 | 'SSH-short',
341 | 'SSPL-1.0',
342 | 'SWL',
343 | 'Saxpath',
344 | 'Sendmail-8.23',
345 | 'Sendmail',
346 | 'SimPL-2.0',
347 | 'Sleepycat',
348 | 'Spencer-86',
349 | 'Spencer-94',
350 | 'Spencer-99',
351 | 'SugarCRM-1.1.3',
352 | 'Swift-exception',
353 | 'TAPR-OHL-1.0',
354 | 'TCL',
355 | 'TCP-wrappers',
356 | 'TMate',
357 | 'TORQUE-1.1',
358 | 'TOSL',
359 | 'TU-Berlin-1.0',
360 | 'TU-Berlin-2.0',
361 | 'UCL-1.0',
362 | 'UPL-1.0',
363 | 'Unicode-DFS-2015',
364 | 'Unicode-DFS-2016',
365 | 'Unicode-TOU',
366 | 'Universal-FOSS-exception-1.0',
367 | 'Unlicense',
368 | 'VOSTROM',
369 | 'VSL-1.0',
370 | 'Vim',
371 | 'W3C-19980720',
372 | 'W3C-20150513',
373 | 'W3C',
374 | 'WTFPL',
375 | 'Watcom-1.0',
376 | 'Wsuipa',
377 | 'WxWindows-exception-3.1',
378 | 'X11',
379 | 'XFree86-1.1',
380 | 'XSkat',
381 | 'Xerox',
382 | 'Xnet',
383 | 'YPL-1.0',
384 | 'YPL-1.1',
385 | 'ZPL-1.1',
386 | 'ZPL-2.0',
387 | 'ZPL-2.1',
388 | 'Zed',
389 | 'Zend-2.0',
390 | 'Zimbra-1.3',
391 | 'Zimbra-1.4',
392 | 'Zlib',
393 | 'blessing',
394 | 'bzip2-1.0.5',
395 | 'bzip2-1.0.6',
396 | 'copyleft-next-0.3.0',
397 | 'copyleft-next-0.3.1',
398 | 'curl',
399 | 'deprecated_AGPL-1.0',
400 | 'deprecated_AGPL-3.0',
401 | 'deprecated_GFDL-1.1',
402 | 'deprecated_GFDL-1.2',
403 | 'deprecated_GFDL-1.3',
404 | 'deprecated_GPL-1.0+',
405 | 'deprecated_GPL-1.0',
406 | 'deprecated_GPL-2.0+',
407 | 'deprecated_GPL-2.0-with-GCC-exception',
408 | 'deprecated_GPL-2.0-with-autoconf-exception',
409 | 'deprecated_GPL-2.0-with-bison-exception',
410 | 'deprecated_GPL-2.0-with-classpath-exception',
411 | 'deprecated_GPL-2.0-with-font-exception',
412 | 'deprecated_GPL-2.0',
413 | 'deprecated_GPL-3.0+',
414 | 'deprecated_GPL-3.0-with-GCC-exception',
415 | 'deprecated_GPL-3.0-with-autoconf-exception',
416 | 'deprecated_GPL-3.0',
417 | 'deprecated_LGPL-2.0+',
418 | 'deprecated_LGPL-2.0',
419 | 'deprecated_LGPL-2.1+',
420 | 'deprecated_LGPL-2.1',
421 | 'deprecated_LGPL-3.0+',
422 | 'deprecated_LGPL-3.0',
423 | 'deprecated_Nunit',
424 | 'deprecated_StandardML-NJ',
425 | 'deprecated_eCos-2.0',
426 | 'deprecated_wxWindows',
427 | 'diffmark',
428 | 'dvipdfm',
429 | 'eCos-exception-2.0',
430 | 'eGenix',
431 | 'etalab-2.0',
432 | 'freertos-exception-2.0',
433 | 'gSOAP-1.3b',
434 | 'gnu-javamail-exception',
435 | 'gnuplot',
436 | 'i2p-gpl-java-exception',
437 | 'iMatix',
438 | 'libpng-2.0',
439 | 'libselinux-1.0',
440 | 'libtiff',
441 | 'mif-exception',
442 | 'mpich2',
443 | 'openvpn-openssl-exception',
444 | 'psfrag',
445 | 'psutils',
446 | 'u-boot-exception-2.0',
447 | 'xinetd',
448 | 'xpp',
449 | 'zlib-acknowledgement',
450 | ];
451 |
--------------------------------------------------------------------------------
/license/whitelist.js:
--------------------------------------------------------------------------------
1 | /* Provide a list of whitelisted licenses for the project below */
2 | const whitelist = [
3 | '(MIT AND BSD-3-Clause)',
4 | '(MIT AND CC-BY-3.0)',
5 | '(MIT AND Zlib)',
6 | '(MIT OR Apache-2.0)',
7 | '(MIT OR CC0-1.0)',
8 | '(WTFPL OR MIT)',
9 | '0BSD',
10 | 'AFLv2.1',
11 | 'Apache-2.0',
12 | 'Apache2',
13 | 'Artistic-2.0',
14 | 'BSD-2-Clause',
15 | 'BSD-3-Clause OR MIT',
16 | 'BSD-3-Clause',
17 | 'CC-BY-3.0',
18 | 'CC-BY-4.0',
19 | 'CC0-1.0',
20 | 'ISC',
21 | 'MIT',
22 | 'MIT,Apache2',
23 | 'MPL-1.0',
24 | 'MPL-1.1',
25 | 'MPL-2.0-no-copyleft-exception',
26 | 'MPL-2.0',
27 | 'ODC-By-1.0',
28 | 'Unlicense',
29 | 'WTFPL',
30 | 'Zlib',
31 | ];
32 |
33 | module.exports = whitelist;
34 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "workspaces": [
4 | "docs-www",
5 | "react-carousel"
6 | ],
7 | "devDependencies": {
8 | "@brainhubeu/license-auditor": "^1.0.30",
9 | "@commitlint/cli": "^9.1.1",
10 | "@commitlint/config-conventional": "^9.1.1",
11 | "@commitlint/prompt": "^9.1.1",
12 | "@semantic-release/commit-analyzer": "^8.0.1",
13 | "@semantic-release/changelog": "^5.0.1",
14 | "@semantic-release/git": "^9.0.0",
15 | "@semantic-release/github": "^7.0.7",
16 | "@semantic-release/release-notes-generator": "^9.0.1",
17 | "@semantic-release/npm": "^7.0.5",
18 | "commitizen": "^4.1.2",
19 | "cypress": "^4.9.0",
20 | "danger": "^10.2.1",
21 | "eslint": "^6.8.0",
22 | "eslint-config-brainhub": "^1.12.0",
23 | "eslint-config-prettier": "^6.11.0",
24 | "eslint-plugin-babel": "^5.3.1",
25 | "eslint-plugin-cypress": "^2.10.3",
26 | "eslint-plugin-prettier": "^3.1.4",
27 | "eslint-watch": "^6.0.1",
28 | "husky": "^4.2.5",
29 | "lint-staged": "^10.2.11",
30 | "prettier": "^2.0.5",
31 | "semantic-release": "^17.1.1",
32 | "start-server-and-test": "^1.11.0"
33 | },
34 | "scripts": {
35 | "preinstall": "node -e \"if (process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('Use yarn for installing: https://yarnpkg.com/en/docs/install')\"",
36 | "start-demo": "yarn workspace react-carousel-docs develop",
37 | "format": "prettier --write \"./**/*.{js,json}\"",
38 | "lint": "eslint docs-www/ react-carousel/ cypress/ --color",
39 | "build": "yarn workspace @brainhubeu/react-carousel build",
40 | "test:e2e": "start-server-and-test start-demo http://localhost:8000 cypress:run",
41 | "test:unit:coverage": "yarn workspace @brainhubeu/react-carousel test:coverage",
42 | "test-dockerized:e2e": "docker-compose -f ./docker-compose.e2e.yml up --build --exit-code-from e2e-test",
43 | "cypress:run": "yarn cypress run",
44 | "commit": "yarn git-cz"
45 | },
46 | "husky": {
47 | "hooks": {
48 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
49 | "pre-commit": "lint-staged",
50 | "pre-push": "yarn test:unit:coverage"
51 | }
52 | },
53 | "lint-staged": {
54 | "**/*.+(js|jsx)": [
55 | "yarn format",
56 | "yarn lint --fix"
57 | ]
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/react-carousel/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties"
8 | ],
9 | "env": {
10 | "production": {
11 | "plugins": [
12 | "transform-react-constant-elements",
13 | "transform-react-remove-prop-types"
14 | ]
15 | },
16 | "test": {
17 | "plugins": ["@babel/plugin-transform-runtime"]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/react-carousel/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [2.0.0-rc.2](https://github.com/brainhubeu/react-carousel/compare/v2.0.0-rc.1...v2.0.0-rc.2) (2020-07-24)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * setting offset breaks "centered" plugin [#394](https://github.com/brainhubeu/react-carousel/issues/394) ([#618](https://github.com/brainhubeu/react-carousel/issues/618)) ([cfae59f](https://github.com/brainhubeu/react-carousel/commit/cfae59f46609b26441ceba0d910b1ef02c1f1c5c))
7 |
--------------------------------------------------------------------------------
/react-carousel/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018-2020 [Brainhub](https://brainhub.eu/?utm_source=github)
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 |
--------------------------------------------------------------------------------
/react-carousel/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | testEnvironment: 'jsdom',
3 | testMatch: ['/test/**/**.test.js'],
4 | moduleNameMapper: {
5 | '\\.(css|scss)$': '/test/__mocks__/styleMock.js',
6 | },
7 | setupFilesAfterEnv: ['/jest.setup.js'],
8 | };
9 |
--------------------------------------------------------------------------------
/react-carousel/jest.setup.js:
--------------------------------------------------------------------------------
1 | import { configure } from 'enzyme';
2 | import Adapter from 'enzyme-adapter-react-16';
3 |
4 | configure({ adapter: new Adapter() });
5 |
--------------------------------------------------------------------------------
/react-carousel/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@brainhubeu/react-carousel",
3 | "version": "2.0.4",
4 | "description": "Carousel component for React",
5 | "engines": {
6 | "npm": ">=6.14.3"
7 | },
8 | "files": [
9 | "/lib/*"
10 | ],
11 | "main": "./lib/react-carousel.js",
12 | "scripts": {
13 | "lint": "esw webpack.config.* src tools test --color",
14 | "clean-dist": "rimraf ./lib && mkdir lib",
15 | "prebuild": "npm run clean-dist",
16 | "build": "node tools/build.js",
17 | "prepack": "cp ../LICENSE.md ../README.md ../docs/CHANGELOG.md .",
18 | "test": "jest",
19 | "test:coverage": "yarn jest --coverage"
20 | },
21 | "author": "Brainhub",
22 | "license": "MIT",
23 | "devDependencies": {
24 | "@babel/cli": "^7.8.4",
25 | "@babel/core": "^7.8.7",
26 | "@babel/plugin-proposal-class-properties": "^7.8.3",
27 | "@babel/plugin-transform-runtime": "^7.10.4",
28 | "@babel/polyfill": "^7.8.7",
29 | "@babel/preset-env": "^7.8.7",
30 | "@babel/preset-react": "^7.8.3",
31 | "@babel/register": "^7.8.6",
32 | "autoprefixer": "^9.7.4",
33 | "babel-eslint": "^10.1.0",
34 | "babel-loader": "^8.0.6",
35 | "babel-plugin-transform-react-constant-elements": "^6.23.0",
36 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
37 | "chalk": "^3.0.0",
38 | "classnames": "^2.2.6",
39 | "coveralls": "^3.1.0",
40 | "css-loader": "^3.4.2",
41 | "enzyme": "^3.11.0",
42 | "enzyme-adapter-react-16": "^1.15.2",
43 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
44 | "file-loader": "^5.1.0",
45 | "html-webpack-plugin": "^3.2.0",
46 | "husky": "^4.2.3",
47 | "jest": "^26.1.0",
48 | "jest-enzyme": "^7.1.2",
49 | "jsdom": "^16.2.1",
50 | "lodash": "^4.17.21",
51 | "node-sass": "^4.13.1",
52 | "postcss-loader": "^3.0.0",
53 | "prop-types": "^15.7.2",
54 | "react-resize-detector": "^5.0.6",
55 | "react-test-renderer": "^16.13.1",
56 | "recoil": "^0.0.13",
57 | "resize-observer-polyfill": "^1.5.1",
58 | "rimraf": "3.0.2",
59 | "sass-loader": "^8.0.2",
60 | "style-loader": "^1.1.3",
61 | "terser-webpack-plugin": "^3.0.6",
62 | "url-loader": "^3.0.0",
63 | "webpack": "^4.42.0"
64 | },
65 | "peerDependencies": {
66 | "react": "^16.8.0",
67 | "react-dom": "^16.8.0"
68 | },
69 | "keywords": [
70 | "react",
71 | "carousel",
72 | "react-carousel",
73 | "react-component",
74 | "component",
75 | "image",
76 | "image-gallery",
77 | "image-slider",
78 | "responsive",
79 | "gallery",
80 | "rwd"
81 | ],
82 | "repository": {
83 | "type": "git",
84 | "url": "https://github.com/brainhubeu/react-carousel"
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/react-carousel/src/components/CarouselDots.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import classnames from 'classnames';
4 | import '../styles/CarouselDots.scss';
5 |
6 | const CarouselDots = ({
7 | value,
8 | thumbnails,
9 | number,
10 | onChange,
11 | rtl,
12 | className,
13 | }) => {
14 | const calculateButtonValue = () => {
15 | const numberOfSlides = number || thumbnails.length;
16 | return value >= 0
17 | ? value
18 | : value + numberOfSlides * Math.ceil(Math.abs(value / numberOfSlides));
19 | };
20 |
21 | const onDotClick = (index) => () => {
22 | const numberOfSlides = number || thumbnails.length;
23 | const moduloItem = calculateButtonValue() % numberOfSlides;
24 |
25 | return onChange(value - (moduloItem - index));
26 | };
27 |
28 | const renderCarouselDots = () => {
29 | if (thumbnails) {
30 | const dotsLength = isNaN(number) ? thumbnails.length : number;
31 |
32 | return thumbnails.slice(0, dotsLength).map((thumbnail, index) => (
33 |
34 |
42 | {thumbnail}
43 |
44 |
45 | ));
46 | }
47 |
48 | const dots = [];
49 | for (let i = 0; i < number; i++) {
50 | dots.push(
51 |
52 |
60 | {i + 1}
61 |
62 | ,
63 | );
64 | }
65 | return dots;
66 | };
67 |
68 | return (
69 |
76 | {renderCarouselDots()}
77 |
78 | );
79 | };
80 |
81 | CarouselDots.propTypes = {
82 | number: PropTypes.number,
83 | thumbnails: PropTypes.arrayOf(PropTypes.node),
84 | value: PropTypes.number,
85 | onChange: PropTypes.func,
86 | rtl: PropTypes.bool,
87 | className: PropTypes.string,
88 | };
89 |
90 | export default React.memo(CarouselDots);
91 |
--------------------------------------------------------------------------------
/react-carousel/src/components/CarouselSlide.js:
--------------------------------------------------------------------------------
1 | import React, { memo, useEffect, useRef } from 'react';
2 | import PropTypes from 'prop-types';
3 | import classname from 'classnames';
4 | import ResizeObserver from 'resize-observer-polyfill';
5 |
6 | import '../styles/CarouselItem.scss';
7 |
8 | const CarouselSlide = ({
9 | index,
10 | onMouseDown,
11 | onTouchStart,
12 | currentSlideIndex,
13 | isDraggingEnabled,
14 | itemClassNames,
15 | width,
16 | offset,
17 | isDragging,
18 | children,
19 | }) => {
20 | const childrenRef = useRef(null);
21 | const isInitialMount = useRef(true);
22 |
23 | const resizeChildren = () => {
24 | if (childrenRef.current) {
25 | childrenRef.current.style = null;
26 | if (childrenRef.current.offsetWidth > width) {
27 | childrenRef.current.style.width = `${width}px`;
28 | }
29 | }
30 | };
31 |
32 | const observeWidth = () => {
33 | const resizeObserver = new ResizeObserver(() => {
34 | resizeChildren();
35 | childrenRef.current && resizeObserver.unobserve(childrenRef.current);
36 | });
37 | childrenRef.current && resizeObserver.observe(childrenRef.current);
38 | };
39 |
40 | const getChildren = () =>
41 | childrenRef.current
42 | ? React.cloneElement(children, { ref: childrenRef })
43 | : children;
44 |
45 | const onItemMouseDown = (event) => {
46 | onMouseDown(event, index);
47 | };
48 |
49 | const onItemTouchStart = (event) => {
50 | onTouchStart(event, index);
51 | };
52 |
53 | useEffect(() => {
54 | if (isInitialMount.current) {
55 | isInitialMount.current = false;
56 | } else {
57 | observeWidth();
58 | }
59 | }, []);
60 |
61 | useEffect(() => {
62 | resizeChildren();
63 | }, [width]);
64 |
65 | return (
66 |
85 | {getChildren()}
86 |
87 | );
88 | };
89 |
90 | CarouselSlide.propTypes = {
91 | onMouseDown: PropTypes.func,
92 | onTouchStart: PropTypes.func,
93 | clickable: PropTypes.bool,
94 | children: PropTypes.node,
95 | width: PropTypes.number,
96 | offset: PropTypes.number,
97 | index: PropTypes.number,
98 | currentSlideIndex: PropTypes.number,
99 | isDragging: PropTypes.bool,
100 | isDraggingEnabled: PropTypes.bool,
101 | itemClassNames: PropTypes.arrayOf(PropTypes.string),
102 | };
103 |
104 | export default memo(CarouselSlide);
105 |
--------------------------------------------------------------------------------
/react-carousel/src/components/CarouselWrapper.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import { useRecoilValue, RecoilRoot, useSetRecoilState } from 'recoil';
3 | import _isNil from 'lodash/isNil';
4 | import _omit from 'lodash/omit';
5 | import PropTypes from 'prop-types';
6 |
7 | import {
8 | carouselValueState,
9 | transitionEnabledState,
10 | } from '../state/atoms/carouselAtoms';
11 | import {
12 | getCurrentValueSelector,
13 | nearestSlideSelector,
14 | transformOffsetSelector,
15 | } from '../state/selectors/carouselSelectors';
16 |
17 | import Carousel from './Carousel';
18 |
19 | const CarouselWrapper = (props) => {
20 | const changeSlide = useSetRecoilState(getCurrentValueSelector);
21 | const value = useRecoilValue(carouselValueState);
22 | const setTransitionEnabled = useSetRecoilState(transitionEnabledState);
23 |
24 | useEffect(() => {
25 | if (!_isNil(props.value)) {
26 | changeSlide(props.value);
27 | }
28 | }, [props.value, setTransitionEnabled]);
29 |
30 | const { onChange, value: customValue, ...rest } = props;
31 | const transformOffset = useRecoilValue(transformOffsetSelector);
32 | const nearestSlideIndex = useRecoilValue(nearestSlideSelector);
33 |
34 | const carouselProps = Object.entries(rest.breakpoints || {})
35 | .filter(([resolution]) => window.innerWidth <= resolution)
36 | .sort(([prevRes], [nextRes]) => nextRes - prevRes)
37 | .reduce(
38 | // eslint-disable-next-line no-unused-vars
39 | (prev, [_, props]) => ({
40 | ...prev,
41 | ...props,
42 | }),
43 | _omit(rest, ['breakpoints']),
44 | );
45 |
46 | const isControlled = !_isNil(customValue);
47 | return (
48 |
56 | );
57 | };
58 |
59 | CarouselWrapper.propTypes = {
60 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
61 | onChange: PropTypes.func,
62 | };
63 |
64 | const RecoiledComponent = (props) => (
65 |
66 |
67 |
68 | );
69 |
70 | export default RecoiledComponent;
71 |
--------------------------------------------------------------------------------
/react-carousel/src/constants/carouselStrategies.js:
--------------------------------------------------------------------------------
1 | const CAROUSEL_STRATEGIES = {
2 | CHANGE_SLIDE: 'CHANGE_SLIDE',
3 | GET_CURRENT_VALUE: 'GET_CURRENT_VALUE',
4 | GET_TRANSFORM_OFFSET: 'GET_TRANSFORM_OFFSET',
5 | GET_NEAREST_SLIDE: 'GET_NEAREST_SLIDE',
6 | };
7 |
8 | export default CAROUSEL_STRATEGIES;
9 |
--------------------------------------------------------------------------------
/react-carousel/src/constants/config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | resizeEventListenerThrottle: 300, // event listener onResize will not be triggered more frequently than once per given number of miliseconds
3 | clickDragThreshold: 10,
4 | };
5 |
--------------------------------------------------------------------------------
/react-carousel/src/constants/plugins.js:
--------------------------------------------------------------------------------
1 | import pluginsFunc from '../plugins';
2 |
3 | const {
4 | slidesToShow,
5 | infinite,
6 | clickToChange,
7 | autoplay,
8 | rtl,
9 | centered,
10 | slidesToScroll,
11 | arrows,
12 | fastSwipe,
13 | } = pluginsFunc;
14 |
15 | export const pluginNames = {
16 | SLIDES_TO_SHOW: 'SLIDESTOSHOW',
17 | CLICK_TO_CHANGE: 'CLICKTOCHANGE',
18 | INFINITE: 'INFINITE',
19 | AUTOPLAY: 'AUTOPLAY',
20 | RTL: 'RTL',
21 | CENTERED: 'CENTERED',
22 | SLIDES_TO_SCROLL: 'SLIDESTOSCROLL',
23 | ARROWS: 'ARROWS',
24 | FAST_SWIPE: 'FASTSWIPE',
25 | };
26 |
27 | export const plugins = {
28 | [pluginNames.SLIDES_TO_SHOW]: slidesToShow,
29 | [pluginNames.CLICK_TO_CHANGE]: clickToChange,
30 | [pluginNames.INFINITE]: infinite,
31 | [pluginNames.RTL]: rtl,
32 | [pluginNames.AUTOPLAY]: autoplay,
33 | [pluginNames.CENTERED]: centered,
34 | [pluginNames.SLIDES_TO_SCROLL]: slidesToScroll,
35 | [pluginNames.ARROWS]: arrows,
36 | [pluginNames.FAST_SWIPE]: fastSwipe,
37 | };
38 |
--------------------------------------------------------------------------------
/react-carousel/src/constants/pluginsOrder.js:
--------------------------------------------------------------------------------
1 | import { pluginNames } from './plugins';
2 |
3 | const pluginsOrder = [
4 | pluginNames.FAST_SWIPE,
5 | pluginNames.ARROWS,
6 | pluginNames.SLIDES_TO_SHOW,
7 | pluginNames.AUTOPLAY,
8 | pluginNames.INFINITE,
9 | pluginNames.RTL,
10 | pluginNames.CLICK_TO_CHANGE,
11 | pluginNames.CENTERED,
12 | pluginNames.SLIDES_TO_SCROLL,
13 | ];
14 |
15 | export default pluginsOrder;
16 |
--------------------------------------------------------------------------------
/react-carousel/src/hooks/useEventListener.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | function useEventListener(eventName, handler, options = {}, element = window) {
4 | // Create a ref that stores handler
5 | const savedHandler = useRef();
6 |
7 | // Update ref.current value if handler changes.
8 | // This allows our effect below to always get latest handler ...
9 | // ... without us needing to pass it in effect deps array ...
10 | // ... and potentially cause effect to re-run every render.
11 | useEffect(() => {
12 | savedHandler.current = handler;
13 | }, [handler]);
14 |
15 | useEffect(
16 | () => {
17 | // Make sure element supports addEventListener
18 | // On
19 | const isSupported = element && element.addEventListener;
20 | if (isSupported) {
21 | // Create event listener that calls handler function stored in ref
22 | const eventListener = (event) => savedHandler.current(event);
23 |
24 | // Add event listener
25 | element.addEventListener(eventName, eventListener, options);
26 |
27 | // Remove event listener on cleanup
28 | return () => {
29 | element.removeEventListener(eventName, eventListener);
30 | };
31 | }
32 | },
33 | [eventName, element], // Re-run if eventName or element changes
34 | );
35 | }
36 |
37 | export default useEventListener;
38 |
--------------------------------------------------------------------------------
/react-carousel/src/hooks/useOnResize.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 | import _throttle from 'lodash/throttle';
3 |
4 | import config from '../constants/config';
5 |
6 | /**
7 | * hook setting the carouselWidth value in state (used to set proper width of track and slides)
8 | * throttled to improve performance
9 | *
10 | * @param {node} carouselRef
11 | * @param {number} itemWidth
12 | * @param {function} setItemWidth
13 | * @param {node} trackContainerRef
14 | */
15 | const useOnResize = ({
16 | width,
17 | carouselRef,
18 | setItemWidth,
19 | trackContainerRef,
20 | }) => {
21 | const isInitialMount = useRef(true);
22 | const onResize = _throttle(() => {
23 | if (!carouselRef || !trackContainerRef) {
24 | return;
25 | }
26 |
27 | setItemWidth(trackContainerRef.current.offsetWidth);
28 | }, config.resizeEventListenerThrottle);
29 |
30 | useEffect(() => {
31 | if (isInitialMount.current) {
32 | isInitialMount.current = false;
33 | } else {
34 | onResize();
35 | }
36 | }, [width, trackContainerRef.current]);
37 | };
38 |
39 | export default useOnResize;
40 |
--------------------------------------------------------------------------------
/react-carousel/src/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-namespace */
2 | import Carousel from './components/CarouselWrapper';
3 | import CarouselDots from './components/CarouselDots';
4 | import slidesToShow from './plugins/slidesToShow';
5 | import infinite from './plugins/infinite';
6 | import clickToChange from './plugins/clickToChange';
7 | import autoplay from './plugins/autoplay';
8 | import rtl from './plugins/rtl';
9 | import centered from './plugins/centered';
10 | import slidesToScroll from './plugins/slidesToScroll';
11 | import arrows from './plugins/arrows';
12 | import fastSwipe from './plugins/fastSwipe';
13 |
14 | export const slidesToShowPlugin = slidesToShow;
15 | export const infinitePlugin = infinite;
16 | export const clickToChangePlugin = clickToChange;
17 | export const autoplayPlugin = autoplay;
18 | export const rtlPlugin = rtl;
19 | export const centeredPlugin = centered;
20 | export const slidesToScrollPlugin = slidesToScroll;
21 | export const arrowsPlugin = arrows;
22 | export const fastSwipePlugin = fastSwipe;
23 |
24 | export const Dots = CarouselDots;
25 | export default Carousel;
26 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/arrows.js:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from 'react';
2 | import { useRecoilValue } from 'recoil';
3 | import classnames from 'classnames';
4 |
5 | import { pluginNames } from '../constants/plugins';
6 | import { slidesState } from '../state/atoms/slideAtoms';
7 |
8 | import './arrows.scss';
9 |
10 | /**
11 | * Adds onClick handler to the arrow if possible (if it does not already have one)
12 | * @param {ReactElement} element to render
13 | * @param {function} onClick handler to be added to element
14 | * @param {string} name of an element
15 | * @param {boolean} addArrowClickHandler decide whether to add action to onClick
16 | * @param {string} key unique element key
17 | * @param {boolean} disable info whether the arrow is disabled
18 | * @return {ReactElement} element with added handler
19 | */
20 | const renderArrowWithAddedHandler = (
21 | element,
22 | onClick,
23 | name,
24 | addArrowClickHandler,
25 | key,
26 | disable = false,
27 | ) => (
28 |
39 | {element}
40 |
41 | );
42 |
43 | const arrows = ({ carouselProps, options = {} }) => ({
44 | name: pluginNames.ARROWS,
45 | // eslint-disable-next-line react/display-name
46 | beforeCarouselItems: () => {
47 | const slides = useRecoilValue(slidesState);
48 |
49 | const prevSlide = useCallback(
50 | () => carouselProps.onChange(carouselProps.value - 1),
51 | [carouselProps.value, carouselProps.onChange],
52 | );
53 |
54 | const disabled =
55 | carouselProps.value <= 0 &&
56 | carouselProps?.children?.length === slides.length;
57 |
58 | if (options.arrowLeft) {
59 | if (!disabled) {
60 | return renderArrowWithAddedHandler(
61 | options.arrowLeft,
62 | prevSlide,
63 | 'arrowLeft',
64 | options.addArrowClickHandler,
65 | '@brainhubeu/react-carousel/custom-arrow-left',
66 | );
67 | }
68 | const arrow = options.arrowLeftDisabled
69 | ? options.arrowLeftDisabled
70 | : options.arrowLeft;
71 | return renderArrowWithAddedHandler(
72 | arrow,
73 | prevSlide,
74 | 'arrowLeft',
75 | options.addArrowClickHandler,
76 | '@brainhubeu/react-carousel/custom-arrow-left',
77 | disabled,
78 | );
79 | }
80 | return (
81 |
87 | prev
88 |
89 | );
90 | },
91 | // eslint-disable-next-line react/display-name
92 | afterCarouselItems: () => {
93 | const slides = useRecoilValue(slidesState);
94 |
95 | const nextSlide = useCallback(
96 | () => carouselProps.onChange(carouselProps.value + 1),
97 | [carouselProps.value, carouselProps.onChange],
98 | );
99 |
100 | const disabled =
101 | carouselProps.value >= slides.length - 1 &&
102 | carouselProps?.children?.length === slides.length;
103 |
104 | if (options.arrowRight) {
105 | if (!disabled) {
106 | return renderArrowWithAddedHandler(
107 | options.arrowRight,
108 | nextSlide,
109 | 'arrowLeft',
110 | options.addArrowClickHandler,
111 | '@brainhubeu/react-carousel/custom-arrow-right',
112 | );
113 | }
114 | const arrow = options.arrowRightDisabled
115 | ? options.arrowRightDisabled
116 | : options.arrowRight;
117 | return renderArrowWithAddedHandler(
118 | arrow,
119 | nextSlide,
120 | 'arrowLeft',
121 | options.addArrowClickHandler,
122 | '@brainhubeu/react-carousel/custom-arrow-right',
123 | disabled,
124 | );
125 | }
126 | return (
127 |
133 | next
134 |
135 | );
136 | },
137 | });
138 |
139 | export default arrows;
140 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/arrows.scss:
--------------------------------------------------------------------------------
1 |
2 | $clickableAreaSize: 42px;
3 | $clickableAreaColor: #7b59ff;
4 | $clickableAreaColor__hover: lighten(#7b59ff, 3%);
5 | $disabledButtonColor: #cccccc;
6 |
7 | $arrowColor: #fff;
8 | $arrowColor__hover: #fff;
9 | $arrowSize: 10px;
10 | $arrowWeight: 3px;
11 |
12 | .BrainhubCarousel__arrows {
13 | position: relative;
14 | padding: $clickableAreaSize/2;
15 | border: none;
16 | overflow: hidden;
17 | outline: 0;
18 | font-size: 0;
19 | line-height: 0;
20 | background-color: $clickableAreaColor;
21 |
22 | span {
23 | display: block;
24 | position: absolute;
25 | top: 50%;
26 | left: 50%;
27 | border-style: solid;
28 | border-color: $arrowColor;
29 | border-width: $arrowWeight $arrowWeight 0 0;
30 | padding: $arrowSize/2;
31 | transition: 0.3s;
32 | font-size: 0;
33 | }
34 |
35 | &:hover {
36 | background-color: $clickableAreaColor__hover;
37 | span {
38 | display: block;
39 | position: absolute;
40 | top: 50%;
41 | left: 50%;
42 | border-style: solid;
43 | border-color: $arrowColor;
44 | border-width: $arrowWeight $arrowWeight 0 0;
45 | padding: $arrowSize/2;
46 | transition: 0.3s;
47 | font-size: 0;
48 | }
49 |
50 | &:enabled {
51 | background-color: $clickableAreaColor__hover;
52 | span {
53 | border-color: $arrowColor__hover;
54 | margin: 0;
55 | }
56 | }
57 | }
58 |
59 | &:disabled {
60 | background-color: $disabledButtonColor;
61 | }
62 | }
63 |
64 | .BrainhubCarousel__arrowLeft {
65 | span {
66 | transform: translate(-50%, -50%) rotate(-135deg);
67 | margin-left: 0.35 * ($arrowSize - $arrowWeight);
68 | }
69 | }
70 |
71 | .BrainhubCarousel__arrowRight {
72 | span {
73 | transform: translate(-50%, -50%) rotate(45deg);
74 | margin-left: -0.35 * ($arrowSize - $arrowWeight);
75 | }
76 | }
77 |
78 | .BrainhubCarousel--isRTL {
79 | .BrainhubCarousel__arrowLeft {
80 | span {
81 | transform: translate(-50%, -50%) rotate(45deg);
82 | margin-left: -0.35 * ($arrowSize - $arrowWeight);
83 | }
84 | }
85 |
86 | .BrainhubCarousel__custom-arrowLeft {
87 | span {
88 | transform: rotate(180deg);
89 | }
90 | }
91 |
92 | .BrainhubCarousel__arrowRight {
93 | span {
94 | transform: translate(-50%, -50%) rotate(-135deg);
95 | margin-left: 0.35 * ($arrowSize - $arrowWeight);
96 | }
97 | }
98 |
99 | .BrainhubCarousel__custom-arrowRight {
100 | span {
101 | transform: rotate(-180deg);
102 | }
103 | }
104 |
105 | .BrainhubCarousel__arrows {
106 | &:hover {
107 | span {
108 | margin: 0;
109 | }
110 | }
111 | }
112 | }
113 |
114 | .BrainhubCarousel__arrow--disable {
115 | pointer-events: none;
116 | }
117 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/autoplay.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { useSetRecoilState } from 'recoil';
3 |
4 | import { pluginNames } from '../constants/plugins';
5 | import { getCurrentValueSelector } from '../state/selectors/carouselSelectors';
6 |
7 | let interval = null;
8 |
9 | const DIRECTION = {
10 | LEFT: 'LEFT',
11 | RIGHT: 'RIGHT',
12 | };
13 |
14 | const getDirection = (direction) => {
15 | if (direction === DIRECTION.LEFT) {
16 | return -1;
17 | } else if (direction === DIRECTION.RIGHT) {
18 | return 1;
19 | }
20 | return 0;
21 | };
22 |
23 | const defaultOptions = {
24 | interval: 2000,
25 | stopAutoPlayOnHover: true,
26 | direction: DIRECTION.RIGHT,
27 | };
28 |
29 | const autoplay = ({ carouselProps, options = {} }) => {
30 | const pluginOptions = { ...defaultOptions, ...options };
31 |
32 | return {
33 | name: pluginNames.AUTOPLAY,
34 | trackCustomProps: () => {
35 | const changeSlide = useSetRecoilState(getCurrentValueSelector);
36 | const [autoPlayStopped, setAutoPlayStopped] = useState(false);
37 |
38 | const resetInterval = () => {
39 | if (interval) {
40 | clearInterval(interval);
41 | }
42 | interval = setInterval(() => {
43 | if (!document.hidden && !autoPlayStopped) {
44 | const newSlide =
45 | carouselProps.value +
46 | getDirection(pluginOptions.direction.toUpperCase());
47 | carouselProps.onChange(newSlide);
48 | changeSlide(newSlide);
49 | }
50 | }, pluginOptions.interval);
51 | };
52 |
53 | // setting autoplay interval
54 | resetInterval();
55 |
56 | /**
57 | * Function handling mouse hover over element
58 | * Stops auto play
59 | */
60 | const onMouseEnter = () => {
61 | setAutoPlayStopped(true);
62 | };
63 |
64 | /**
65 | * Function handling mouse leaving element
66 | * Resumes auto play
67 | */
68 | const onMouseLeave = () => {
69 | setAutoPlayStopped(false);
70 | resetInterval();
71 | };
72 |
73 | return {
74 | onMouseEnter: pluginOptions.stopAutoPlayOnHover ? onMouseEnter : null,
75 | onMouseLeave: pluginOptions.stopAutoPlayOnHover ? onMouseLeave : null,
76 | };
77 | },
78 | };
79 | };
80 |
81 | export default autoplay;
82 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/centered.js:
--------------------------------------------------------------------------------
1 | import { useRecoilValue } from 'recoil';
2 |
3 | import { pluginNames } from '../constants/plugins';
4 | import { slideOffsetState, slideWidthState } from '../state/atoms/slideAtoms';
5 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
6 |
7 | const centered = ({ refs }) => ({
8 | name: pluginNames.CENTERED,
9 | strategies: () => {
10 | const itemWidth = useRecoilValue(slideWidthState);
11 | const itemOffset = useRecoilValue(slideOffsetState);
12 | const trackContainerWidth = refs.trackContainerRef?.current?.offsetWidth;
13 |
14 | return {
15 | [CAROUSEL_STRATEGIES.GET_TRANSFORM_OFFSET]: (
16 | originalValue,
17 | prevValue,
18 | ) => {
19 | const elementWidthWithOffset = itemWidth + itemOffset;
20 | const additionalOffset =
21 | trackContainerWidth / 2 - elementWidthWithOffset / 2;
22 | return prevValue + additionalOffset;
23 | },
24 | };
25 | },
26 | });
27 |
28 | export default centered;
29 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/clickToChange.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from 'react';
2 | import { useRecoilState, useSetRecoilState, useRecoilValue } from 'recoil';
3 |
4 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
5 | import { pluginNames } from '../constants/plugins';
6 | import {
7 | slideMovementState,
8 | transitionEnabledState,
9 | } from '../state/atoms/carouselAtoms';
10 | import { activeSlideIndexState } from '../state/atoms/slideAtoms';
11 |
12 | let previousClicked = 0;
13 |
14 | const DIRECTION = {
15 | LEFT: 'LEFT',
16 | RIGHT: 'RIGHT',
17 | NONE: 'NONE',
18 | };
19 |
20 | const getDirection = (dragStart, dragOffset) => {
21 | if (dragStart < dragOffset) {
22 | return DIRECTION.LEFT;
23 | } else if (dragStart > dragOffset) {
24 | return DIRECTION.RIGHT;
25 | }
26 | return DIRECTION.NONE;
27 | };
28 |
29 | const clickToChange = ({ carouselProps }) => ({
30 | name: pluginNames.CLICK_TO_CHANGE,
31 | strategies: () => {
32 | const slideMovement = useRecoilValue(slideMovementState);
33 | const activeSlideIndex = useRecoilValue(activeSlideIndexState);
34 |
35 | return {
36 | [CAROUSEL_STRATEGIES.CHANGE_SLIDE]: (originalValue, prevValue) => {
37 | const direction = getDirection(
38 | Math.abs(slideMovement.dragStart),
39 | Math.abs(slideMovement.dragEnd) || 0,
40 | );
41 |
42 | if (direction === DIRECTION.NONE) {
43 | return prevValue;
44 | }
45 |
46 | if (previousClicked !== slideMovement.clicked) {
47 | if (
48 | direction === DIRECTION.LEFT &&
49 | prevValue <= slideMovement.clicked
50 | ) {
51 | previousClicked = prevValue;
52 | return prevValue;
53 | }
54 |
55 | previousClicked = slideMovement.clicked;
56 | if (activeSlideIndex) {
57 | return (
58 | carouselProps.value + slideMovement.clicked - activeSlideIndex
59 | );
60 | }
61 | return slideMovement.clicked;
62 | }
63 | previousClicked = prevValue || originalValue;
64 | return prevValue || originalValue;
65 | },
66 | };
67 | },
68 | slideCustomProps: () => {
69 | const setTransitionEnabled = useSetRecoilState(transitionEnabledState);
70 | const [slideMovement, setSlideMovement] = useRecoilState(
71 | slideMovementState,
72 | );
73 |
74 | const onMouseDown = useCallback(
75 | (event, index) => {
76 | event.preventDefault();
77 | event.stopPropagation();
78 | setTransitionEnabled(true);
79 | const { pageX } = event;
80 |
81 | setSlideMovement({
82 | ...slideMovement,
83 | clicked: index,
84 | dragStart: pageX,
85 | });
86 | },
87 | [slideMovement, setTransitionEnabled],
88 | );
89 | return {
90 | onMouseDown,
91 | };
92 | },
93 | itemClassNames: () => ['BrainhubCarouselItem--clickable'],
94 | });
95 |
96 | export default clickToChange;
97 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/fastSwipe.js:
--------------------------------------------------------------------------------
1 | import { useRecoilValue } from 'recoil';
2 |
3 | import { pluginNames } from '../constants/plugins';
4 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
5 | import {
6 | carouselValueState,
7 | slideMovementState,
8 | } from '../state/atoms/carouselAtoms';
9 |
10 | import './rtl.scss';
11 |
12 | const fastSwipe = ({ carouselProps }) => ({
13 | name: pluginNames.FAST_SWIPE,
14 | strategies: () => {
15 | const dragOffset = useRecoilValue(slideMovementState).dragOffset;
16 | const value = useRecoilValue(carouselValueState);
17 |
18 | return {
19 | [CAROUSEL_STRATEGIES.GET_NEAREST_SLIDE]: () => {
20 | const slideIndexOffset =
21 | dragOffset > 0
22 | ? -Math.ceil(dragOffset / carouselProps.width)
23 | : -Math.floor(dragOffset / carouselProps.width);
24 |
25 | return value + slideIndexOffset;
26 | },
27 | };
28 | },
29 | });
30 |
31 | export default fastSwipe;
32 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/index.js:
--------------------------------------------------------------------------------
1 | import slidesToShow from './slidesToShow';
2 | import infinite from './infinite';
3 | import clickToChange from './clickToChange';
4 | import autoplay from './autoplay';
5 | import rtl from './rtl';
6 | import centered from './centered';
7 | import slidesToScroll from './slidesToScroll';
8 | import arrows from './arrows';
9 | import fastSwipe from './fastSwipe';
10 |
11 | export default {
12 | slidesToShow,
13 | infinite,
14 | clickToChange,
15 | autoplay,
16 | rtl,
17 | centered,
18 | slidesToScroll,
19 | arrows,
20 | fastSwipe,
21 | };
22 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/infinite.js:
--------------------------------------------------------------------------------
1 | import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
2 | import _isNil from 'lodash/isNil';
3 | import _times from 'lodash/times';
4 | import _concat from 'lodash/concat';
5 | import { useEffect } from 'react';
6 |
7 | import getChildren from '../tools/getChildren';
8 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
9 | import { pluginNames } from '../constants/plugins';
10 | import {
11 | activeSlideIndexState,
12 | slideWidthState,
13 | slidesState,
14 | } from '../state/atoms/slideAtoms';
15 | import {
16 | slideMovementState,
17 | trackStylesState,
18 | trackWidthState,
19 | } from '../state/atoms/carouselAtoms';
20 |
21 | export const defaultOptions = {
22 | numberOfInfiniteClones: 2,
23 | };
24 |
25 | const infinite = ({ options = defaultOptions, carouselProps }) => {
26 | const itemWidth = useRecoilValue(slideWidthState);
27 | const children = getChildren(carouselProps.children, carouselProps.slides);
28 |
29 | const getTargetMod = (customValue = null) => {
30 | const value = _isNil(customValue) ? carouselProps.value : customValue;
31 | const length = children.length;
32 |
33 | return value >= 0
34 | ? value % length
35 | : (length - Math.abs(value % length)) % length;
36 | };
37 |
38 | const getTargetSlide = () => {
39 | const mod = getTargetMod(0);
40 |
41 | return mod + carouselProps.value;
42 | };
43 |
44 | const getNeededAdditionalClones = () => {
45 | if (Math.abs(carouselProps.value) > children.length) {
46 | return Math.ceil(carouselProps.value / children.length);
47 | }
48 | return 0;
49 | };
50 |
51 | const getAdditionalClonesLeft = () => {
52 | const additionalClones = getNeededAdditionalClones();
53 | return additionalClones < 0 ? -additionalClones : 0;
54 | };
55 |
56 | const getAdditionalClonesOffset = () =>
57 | -children.length * itemWidth * getAdditionalClonesLeft();
58 |
59 | return {
60 | name: pluginNames.INFINITE,
61 | plugin: () => {
62 | const setTrackWidth = useSetRecoilState(trackWidthState);
63 | const setActiveSlideIndex = useSetRecoilState(activeSlideIndexState);
64 | const [trackStyles, setTrackStyles] = useRecoilState(trackStylesState);
65 | const setSlides = useSetRecoilState(slidesState);
66 |
67 | const numberOfInfiniteClones = options.numberOfInfiniteClones;
68 |
69 | const getAdditionalClonesRight = () => {
70 | const additionalClones = getNeededAdditionalClones();
71 | return additionalClones > 0 ? additionalClones : 0;
72 | };
73 | const getClonesLeft = () =>
74 | numberOfInfiniteClones + getAdditionalClonesLeft();
75 | const getClonesRight = () =>
76 | numberOfInfiniteClones + getAdditionalClonesRight();
77 |
78 | useEffect(() => {
79 | setActiveSlideIndex(
80 | getTargetSlide() + getClonesLeft() * children.length,
81 | );
82 |
83 | setTrackStyles({
84 | ...trackStyles,
85 | marginLeft: getAdditionalClonesOffset(),
86 | });
87 | }, [carouselProps.value]);
88 |
89 | useEffect(() => {
90 | const trackLengthMultiplier = 1 + getClonesLeft() + getClonesRight();
91 |
92 | const clonesLeft = _times(getClonesLeft(), () => children);
93 | const clonesRight = _times(getClonesRight(), () => children);
94 |
95 | setTrackWidth(
96 | carouselProps.width * children.length * trackLengthMultiplier,
97 | );
98 | setSlides(_concat(...clonesLeft, children, ...clonesRight));
99 | }, [carouselProps.width, children.length, carouselProps.value]);
100 | },
101 |
102 | strategies: () => {
103 | const slideMovement = useRecoilValue(slideMovementState);
104 | const activeSlideIndex = useRecoilValue(activeSlideIndexState);
105 | const slideWidth = useRecoilValue(slideWidthState);
106 |
107 | const marginLeft = (slideMovement.marginLeft || '0')
108 | .match(/\d/g)
109 | .join('');
110 |
111 | return {
112 | [CAROUSEL_STRATEGIES.CHANGE_SLIDE]: (originalValue) => originalValue,
113 | [CAROUSEL_STRATEGIES.GET_NEAREST_SLIDE]: (originalValue) => {
114 | const slideIndexOffset = -Math.round(
115 | slideMovement.dragOffset / slideWidth,
116 | );
117 |
118 | return originalValue + slideIndexOffset;
119 | },
120 | [CAROUSEL_STRATEGIES.GET_CURRENT_VALUE]: () => carouselProps.value,
121 | [CAROUSEL_STRATEGIES.GET_TRANSFORM_OFFSET]: () => {
122 | const elementWidthWithOffset = itemWidth;
123 | const dragOffset = slideMovement.dragOffset;
124 |
125 | return (
126 | dragOffset -
127 | activeSlideIndex * elementWidthWithOffset -
128 | marginLeft -
129 | getAdditionalClonesOffset()
130 | );
131 | },
132 | };
133 | },
134 | };
135 | };
136 |
137 | export default infinite;
138 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/rtl.js:
--------------------------------------------------------------------------------
1 | import { useCallback, useEffect } from 'react';
2 | import { useRecoilState, useRecoilValue } from 'recoil';
3 |
4 | import { pluginNames } from '../constants/plugins';
5 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
6 | import clamp from '../tools/clamp';
7 | import { slidesState } from '../state/atoms/slideAtoms';
8 | import {
9 | carouselValueState,
10 | slideMovementState,
11 | trackStylesState,
12 | } from '../state/atoms/carouselAtoms';
13 |
14 | import './rtl.scss';
15 |
16 | const rtl = ({ carouselProps }) => ({
17 | name: pluginNames.RTL,
18 | plugin: () => {
19 | const [trackStyles, setTrackStyles] = useRecoilState(trackStylesState);
20 | const slides = useRecoilValue(slidesState);
21 |
22 | useEffect(() => {
23 | if (carouselProps?.children?.length !== slides.length) {
24 | setTrackStyles({
25 | ...trackStyles,
26 | transform: -carouselProps.transformOffset,
27 | });
28 | }
29 | }, [carouselProps.transformOffset]);
30 | },
31 | strategies: () => {
32 | const slides = useRecoilValue(slidesState);
33 | const slideMovement = useRecoilValue(slideMovementState);
34 | const value = useRecoilValue(carouselValueState);
35 |
36 | return {
37 | [CAROUSEL_STRATEGIES.CHANGE_SLIDE]: (originalValue, prevValue) => {
38 | if (slideMovement.dragOffset) {
39 | return clamp(originalValue, slides);
40 | }
41 | const slidesDiff = prevValue - value;
42 |
43 | // if prev and original are the same, we assume we use the infinite plugin
44 | const rtlValue = value + slidesDiff;
45 | if (originalValue !== prevValue) {
46 | return clamp(rtlValue, slides);
47 | }
48 | return rtlValue;
49 | },
50 | [CAROUSEL_STRATEGIES.GET_TRANSFORM_OFFSET]: (originalValue, prevValue) =>
51 | -prevValue,
52 | };
53 | },
54 | carouselClassNames: () => {
55 | const slides = useRecoilValue(slidesState);
56 | const rtlClassName = 'BrainhubCarousel--isRTL';
57 | const classNames = [];
58 |
59 | if (carouselProps.children.length === slides.length) {
60 | classNames.push(rtlClassName);
61 | }
62 |
63 | return classNames;
64 | },
65 | carouselCustomProps: () => {
66 | const [slideMovement, setSlideMovement] = useRecoilState(
67 | slideMovementState,
68 | );
69 |
70 | /**
71 | * Function handling mouse move if drag has started. Sets dragOffset in the state.
72 | * @param {event} event event
73 | */
74 | const onMouseMove = useCallback(
75 | (event) => {
76 | const { pageX } = event;
77 | if (slideMovement.dragStart !== null) {
78 | setSlideMovement((previousState) => ({
79 | ...slideMovement,
80 | dragOffset: previousState.dragStart - pageX,
81 | dragEnd: pageX,
82 | }));
83 | }
84 | },
85 | [slideMovement],
86 | );
87 |
88 | return {
89 | onMouseMove,
90 | };
91 | },
92 | });
93 |
94 | export default rtl;
95 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/rtl.scss:
--------------------------------------------------------------------------------
1 | .BrainhubCarousel {
2 |
3 | &.BrainhubCarousel--isRTL {
4 | direction: rtl;
5 |
6 | .BrainhubCarousel__trackContainer {
7 | .BrainhubCarousel__track {
8 | direction: rtl;
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/slidesToScroll.js:
--------------------------------------------------------------------------------
1 | import { useRecoilValue } from 'recoil';
2 |
3 | import { pluginNames } from '../constants/plugins';
4 | import CAROUSEL_STRATEGIES from '../constants/carouselStrategies';
5 | import clamp from '../tools/clamp';
6 | import { carouselValueState } from '../state/atoms/carouselAtoms';
7 | import { slidesState } from '../state/atoms/slideAtoms';
8 |
9 | const getAdditionalScroll = (baseToScroll, customToScroll) => {
10 | if (baseToScroll < 0) {
11 | return -baseToScroll - customToScroll;
12 | } else if (baseToScroll > 0) {
13 | return customToScroll - baseToScroll;
14 | }
15 | return 0;
16 | };
17 |
18 | const defaultOptions = {
19 | numberOfSlides: 3,
20 | };
21 |
22 | const slidesToScroll = ({ carouselProps, options = defaultOptions }) => ({
23 | name: pluginNames.SLIDES_TO_SCROLL,
24 | strategies: () => {
25 | const currentValue = useRecoilValue(carouselValueState);
26 | const slides = useRecoilValue(slidesState);
27 | return {
28 | [CAROUSEL_STRATEGIES.CHANGE_SLIDE]: (originalValue, prevValue) => {
29 | const baseToScroll = prevValue - currentValue;
30 |
31 | const additionalToScroll = getAdditionalScroll(
32 | baseToScroll,
33 | options.numberOfSlides,
34 | );
35 |
36 | if (carouselProps?.children?.length !== slides.length) {
37 | return prevValue + additionalToScroll;
38 | }
39 | return clamp(prevValue + additionalToScroll, slides);
40 | },
41 | };
42 | },
43 | });
44 |
45 | export default slidesToScroll;
46 |
--------------------------------------------------------------------------------
/react-carousel/src/plugins/slidesToShow.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 | import { useSetRecoilState } from 'recoil';
3 |
4 | import useEventListener from '../hooks/useEventListener';
5 | import { pluginNames } from '../constants/plugins';
6 | import { slideWidthState } from '../state/atoms/slideAtoms';
7 |
8 | const defaultOptions = {
9 | numberOfSlides: 3,
10 | };
11 |
12 | const slidesToShow = ({ carouselProps, refs, options = defaultOptions }) => ({
13 | name: pluginNames.SLIDES_TO_SHOW,
14 | plugin: () => {
15 | const isInitialMount = useRef(true);
16 |
17 | const setItemWidth = useSetRecoilState(slideWidthState);
18 |
19 | const onResize = () => {
20 | setItemWidth(
21 | refs.trackContainerRef.current.offsetWidth / options.numberOfSlides,
22 | );
23 | };
24 |
25 | useEffect(() => {
26 | if (isInitialMount.current) {
27 | isInitialMount.current = false;
28 | } else {
29 | onResize();
30 | }
31 | }, [carouselProps.width, refs.trackContainerRef.current]);
32 |
33 | useEventListener('resize', onResize);
34 | useEventListener('load', onResize);
35 | },
36 | });
37 |
38 | export default slidesToShow;
39 |
--------------------------------------------------------------------------------
/react-carousel/src/state/atoms/carouselAtoms.js:
--------------------------------------------------------------------------------
1 | import { atom } from 'recoil';
2 |
3 | export const slideMovementState = atom({
4 | key: '@brainhubeu/react-carousel/slideMovementState',
5 | default: {
6 | clicked: null, // index of the clicked slide
7 | dragStart: null, // X position of drag event start
8 | dragEnd: null, // X position of drag event end
9 | dragOffset: 0, // distance of the drag
10 | },
11 | });
12 |
13 | export const transitionEnabledState = atom({
14 | key: '@brainhubeu/react-carousel/transitionEnabledState',
15 | default: false,
16 | });
17 |
18 | export const trackWidthState = atom({
19 | key: '@brainhubeu/react-carousel/trackWidthState',
20 | default: 0,
21 | });
22 |
23 | export const trackStylesState = atom({
24 | key: '@brainhubeu/react-carousel/trackStylesState',
25 | default: {
26 | marginLeft: 0,
27 | transform: 0,
28 | },
29 | });
30 |
31 | export const carouselStrategiesState = atom({
32 | key: '@brainhubeu/react-carousel/carouselStrategiesState',
33 | default: [],
34 | });
35 |
36 | export const carouselValueState = atom({
37 | key: '@brainhubeu/react-carousel/carouselValueState',
38 | default: 0,
39 | });
40 |
--------------------------------------------------------------------------------
/react-carousel/src/state/atoms/slideAtoms.js:
--------------------------------------------------------------------------------
1 | import { atom } from 'recoil';
2 |
3 | export const activeSlideIndexState = atom({
4 | key: '@brainhubeu/react-carousel/activeSlideIndexState',
5 | default: 0,
6 | });
7 |
8 | export const slideWidthState = atom({
9 | key: '@brainhubeu/react-carousel/itemWidthState',
10 | default: 0,
11 | });
12 |
13 | export const slideOffsetState = atom({
14 | key: '@brainhubeu/react-carousel/itemOffsetState',
15 | default: 0,
16 | });
17 |
18 | export const slidesState = atom({
19 | key: '@brainhubeu/react-carousel/slidesState',
20 | default: [],
21 | });
22 |
--------------------------------------------------------------------------------
/react-carousel/src/state/selectors/carouselSelectors.js:
--------------------------------------------------------------------------------
1 | import { selector } from 'recoil';
2 | import _flow from 'lodash/flow';
3 | import _bind from 'lodash/bind';
4 |
5 | import clamp from '../../tools/clamp';
6 | import CAROUSEL_STRATEGIES from '../../constants/carouselStrategies';
7 | import {
8 | carouselStrategiesState,
9 | carouselValueState,
10 | slideMovementState,
11 | } from '../atoms/carouselAtoms';
12 | import {
13 | slideOffsetState,
14 | slideWidthState,
15 | slidesState,
16 | } from '../atoms/slideAtoms';
17 |
18 | export const getCurrentValueSelector = selector({
19 | key: '@brainhubeu/react-carousel/getCurrentSlideSelector',
20 | get: ({ get }) => {
21 | const value = get(carouselValueState);
22 |
23 | const slides = get(slidesState);
24 | const getCurrentValueBase = () => clamp(value, slides);
25 |
26 | const strategies = get(carouselStrategiesState)
27 | .map(
28 | (strategy) =>
29 | strategy && strategy[CAROUSEL_STRATEGIES.GET_CURRENT_VALUE],
30 | )
31 | .filter((strategy) => typeof strategy === 'function');
32 |
33 | const enhancedStrategies = strategies.map((strategy) =>
34 | _bind(strategy, null, value),
35 | );
36 |
37 | return enhancedStrategies.length
38 | ? _flow([getCurrentValueBase, ...strategies])()
39 | : getCurrentValueBase();
40 | },
41 | set: ({ set, get }, value) => {
42 | const slides = get(slidesState);
43 | const getCurrentValueBase = () => clamp(value, slides);
44 |
45 | const strategies = get(carouselStrategiesState)
46 | .map((strategy) => strategy && strategy[CAROUSEL_STRATEGIES.CHANGE_SLIDE])
47 | .filter((strategy) => typeof strategy === 'function');
48 |
49 | const enhancedStrategies = strategies.map((strategy) =>
50 | _bind(strategy, null, value),
51 | );
52 |
53 | const newValue = strategies.length
54 | ? _flow([getCurrentValueBase, ...enhancedStrategies])()
55 | : getCurrentValueBase();
56 |
57 | set(carouselValueState, newValue);
58 | },
59 | });
60 |
61 | /**
62 | * Calculates offset in pixels to be applied to track element in order to show current slide correctly
63 | * @return {number} offset in px
64 | */
65 | export const transformOffsetSelector = selector({
66 | key: '@brainhubeu/react-carousel/transformOffsetSelector',
67 | get: ({ get }) => {
68 | const slideWidth = get(slideWidthState);
69 | const slideOffset = get(slideOffsetState);
70 | const dragOffset = get(slideMovementState).dragOffset;
71 | const value = get(carouselValueState);
72 |
73 | const getTransformOffsetBase = () => {
74 | const elementWidthWithOffset = slideWidth + slideOffset;
75 |
76 | return dragOffset - value * elementWidthWithOffset;
77 | };
78 |
79 | const strategies = get(carouselStrategiesState)
80 | .map(
81 | (strategy) =>
82 | strategy && strategy[CAROUSEL_STRATEGIES.GET_TRANSFORM_OFFSET],
83 | )
84 | .filter((strategy) => typeof strategy === 'function');
85 |
86 | const enhancedStrategies = strategies.map((strategy) =>
87 | _bind(strategy, null, value),
88 | );
89 |
90 | return strategies.length
91 | ? _flow([getTransformOffsetBase, ...enhancedStrategies])()
92 | : getTransformOffsetBase();
93 | },
94 | });
95 |
96 | /**
97 | * Checks what slide index is the nearest to the current position (to calculate the result of dragging the slider)
98 | * @return {number} index
99 | */
100 | export const nearestSlideSelector = selector({
101 | key: '@brainhubeu/react-carousel/nearestSlideSelector',
102 | get: ({ get }) => {
103 | const slideWidth = get(slideWidthState);
104 | const dragOffset = get(slideMovementState).dragOffset;
105 | const value = get(carouselValueState);
106 | const slides = get(slidesState);
107 |
108 | const getNearestSlideBase = () => {
109 | const slideIndexOffset = -Math.round(dragOffset / slideWidth);
110 |
111 | return clamp(value + slideIndexOffset, slides);
112 | };
113 |
114 | const strategies = get(carouselStrategiesState)
115 | .map(
116 | (strategy) =>
117 | strategy && strategy[CAROUSEL_STRATEGIES.GET_NEAREST_SLIDE],
118 | )
119 | .filter((strategy) => typeof strategy === 'function');
120 |
121 | const enhancedStrategies = strategies.map((strategy) =>
122 | _bind(strategy, null, value),
123 | );
124 |
125 | return strategies.length
126 | ? _flow([getNearestSlideBase, ...enhancedStrategies])()
127 | : getNearestSlideBase();
128 | },
129 | });
130 |
--------------------------------------------------------------------------------
/react-carousel/src/styles/Arrows.scss:
--------------------------------------------------------------------------------
1 | $clickableAreaSize: 42px;
2 | $clickableAreaColor: #7b59ff;
3 | $clickableAreaColor__hover: lighten(#7b59ff, 3%);
4 | $disabledButtonColor: #cccccc;
5 |
6 | $arrowColor: #fff;
7 | $arrowColor__hover: #fff;
8 | $arrowSize: 10px;
9 | $arrowWeight: 3px;
10 |
11 | .BrainhubCarousel__arrows {
12 | position: relative;
13 | padding: $clickableAreaSize/2;
14 | border: none;
15 | overflow: hidden;
16 | outline: 0;
17 | font-size: 0;
18 | line-height: 0;
19 | background-color: $clickableAreaColor;
20 |
21 | span {
22 | display: block;
23 | position: absolute;
24 | top: 50%;
25 | left: 50%;
26 | border-style: solid;
27 | border-color: $arrowColor;
28 | border-width: $arrowWeight $arrowWeight 0 0;
29 | padding: $arrowSize/2;
30 | transition: 0.3s;
31 | font-size: 0;
32 | }
33 |
34 | &:hover {
35 | background-color: $clickableAreaColor__hover;
36 | span {
37 | display: block;
38 | position: absolute;
39 | top: 50%;
40 | left: 50%;
41 | border-style: solid;
42 | border-color: $arrowColor;
43 | border-width: $arrowWeight $arrowWeight 0 0;
44 | padding: $arrowSize/2;
45 | transition: 0.3s;
46 | font-size: 0;
47 | }
48 |
49 | &:enabled {
50 | background-color: $clickableAreaColor__hover;
51 | span {
52 | border-color: $arrowColor__hover;
53 | margin: 0;
54 | }
55 | }
56 | }
57 |
58 | &:disabled {
59 | background-color: $disabledButtonColor;
60 | }
61 | }
62 |
63 | .BrainhubCarousel__arrowLeft {
64 | span {
65 | transform: translate(-50%, -50%) rotate(-135deg);
66 | margin-left: 0.35 * ($arrowSize - $arrowWeight);
67 | }
68 | }
69 |
70 | .BrainhubCarousel__arrowRight {
71 | span {
72 | transform: translate(-50%, -50%) rotate(45deg);
73 | margin-left: -0.35 * ($arrowSize - $arrowWeight);
74 | }
75 | }
76 |
77 | .BrainhubCarousel--isRTL {
78 | .BrainhubCarousel__arrowLeft {
79 | span {
80 | transform: translate(-50%, -50%) rotate(45deg);
81 | margin-left: -0.35 * ($arrowSize - $arrowWeight);
82 | }
83 | }
84 |
85 | .BrainhubCarousel__custom-arrowLeft {
86 | span {
87 | transform: rotate(180deg);
88 | }
89 | }
90 |
91 | .BrainhubCarousel__arrowRight {
92 | span {
93 | transform: translate(-50%, -50%) rotate(-135deg);
94 | margin-left: 0.35 * ($arrowSize - $arrowWeight);
95 | }
96 | }
97 |
98 | .BrainhubCarousel__custom-arrowRight {
99 | span {
100 | transform: rotate(-180deg);
101 | }
102 | }
103 |
104 | .BrainhubCarousel__arrows {
105 | &:hover {
106 | span {
107 | margin: 0;
108 | }
109 | }
110 | }
111 | }
112 |
113 | .BrainhubCarousel__arrow--disable {
114 | pointer-events: none;
115 | }
116 |
117 |
--------------------------------------------------------------------------------
/react-carousel/src/styles/Carousel.scss:
--------------------------------------------------------------------------------
1 | $loaderColor: #7b59ff;
2 |
3 | .BrainhubCarousel__container {
4 | width: 100%;
5 | overflow: hidden;
6 | }
7 |
8 | .BrainhubCarousel {
9 | overflow: hidden;
10 | display: flex;
11 | align-items: center;
12 |
13 | &.BrainhubCarousel--isRTL {
14 | direction: rtl;
15 |
16 | .BrainhubCarousel__trackContainer {
17 | .BrainhubCarousel__track {
18 | direction: rtl;
19 | }
20 | }
21 | }
22 |
23 | .BrainhubCarousel__trackContainer {
24 | width: 100%;
25 | overflow: hidden;
26 | .BrainhubCarousel__track {
27 | display: flex;
28 | overflow: hidden;
29 | list-style: none;
30 | margin: 0;
31 | padding: 0;
32 |
33 | &.BrainhubCarousel__track--transition {
34 | transition: transform;
35 | }
36 | }
37 | }
38 | }
39 |
40 | /* arrows */
41 | .BrainhubCarousel__arrows {
42 | cursor: pointer;
43 | }
44 |
45 | /* loader */
46 | .BrainhubCarousel__loader {
47 | width: 50px;
48 | height: 50px;
49 | border-radius: 100%;
50 | border: 4px solid $loaderColor;
51 | border-left-color: transparent;
52 | animation: loader 1s infinite linear;
53 | }
54 |
55 | @keyframes loader {
56 | 0% {
57 | transform: rotate(0deg);
58 | }
59 | 100% {
60 | transform: rotate(360deg);
61 | }
62 | }
--------------------------------------------------------------------------------
/react-carousel/src/styles/CarouselDots.scss:
--------------------------------------------------------------------------------
1 | /* variables */
2 | $dots-color: black;
3 |
4 | .BrainhubCarousel__dots {
5 | display: flex;
6 | justify-content: center;
7 | list-style: none;
8 | margin: 0;
9 | padding: 0;
10 | font-size: 0;
11 | line-height: 0;
12 |
13 | &.BrainhubCarousel__dots--isRTL {
14 | direction: rtl;
15 | }
16 |
17 | .BrainhubCarousel__dot {
18 | outline: 0;
19 | padding: 10px;
20 | border: none;
21 | opacity: 0.5;
22 | font-size: 0;
23 | cursor: pointer;
24 | -webkit-appearance: none;
25 |
26 | &.BrainhubCarousel__dot--selected {
27 | opacity: 1 !important;
28 | }
29 |
30 | &:hover {
31 | opacity: 1;
32 | }
33 |
34 | &:before {
35 | content: '';
36 | display: block;
37 | width: 5px;
38 | height: 5px;
39 | border-radius: 50%;
40 | padding: 0;
41 | border: none;
42 | background: $dots-color;
43 | }
44 | }
45 |
46 | .BrainhubCarousel__thumbnail {
47 | outline: 0;
48 | padding: 10px;
49 | border: none;
50 | opacity: 0.5;
51 | font-size: 0;
52 | cursor: pointer;
53 |
54 | &.BrainhubCarousel__thumbnail--selected {
55 | opacity: 1 !important;
56 | }
57 |
58 | &:hover {
59 | opacity: 1;
60 | }
61 | }
62 | }
63 |
64 | .BrainhubCarousel__thumbnail[type=button] {
65 | -webkit-appearance: none;
66 | }
67 |
68 | .BrainhubCarousel--isRTL {
69 | + .BrainhubCarousel__dots {
70 | direction: rtl;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/react-carousel/src/styles/CarouselItem.scss:
--------------------------------------------------------------------------------
1 | .BrainhubCarouselItem {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | position: relative;
6 | &.BrainhubCarouselItem--clickable {
7 | cursor: pointer;
8 | }
9 | &.BrainhubCarouselItem--active {
10 |
11 | }
12 | .debug-number {
13 | position: absolute;
14 | top: 0;
15 | bottom: 0;
16 | left: 0;
17 | right: 0;
18 | display: flex;
19 | justify-content: center;
20 | font-size: 2em;
21 | text-shadow: 0px 0px 9px white;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/react-carousel/src/tools/carouselPluginResolver.js:
--------------------------------------------------------------------------------
1 | import _flatten from 'lodash/flatten';
2 | import _sortBy from 'lodash/sortBy';
3 |
4 | import { plugins as pluginsFunc } from '../constants/plugins';
5 | import pluginsOrder from '../constants/pluginsOrder';
6 |
7 | const carouselPluginResolver = (
8 | plugins,
9 | carouselProps,
10 | trackContainerRef,
11 | carouselRef,
12 | ) => {
13 | const carouselPlugins = carouselProps?.plugins.map((plugin) => {
14 | if (typeof plugin === 'string') {
15 | return (
16 | pluginsFunc[plugin.toUpperCase()] &&
17 | pluginsFunc[plugin.toUpperCase()]({
18 | carouselProps: {
19 | ...carouselProps,
20 | children: carouselProps.children
21 | ? carouselProps.children
22 | : carouselProps.slides,
23 | },
24 | options: plugin.options,
25 | refs: { trackContainerRef, carouselRef },
26 | })
27 | );
28 | }
29 | return plugin.resolve({
30 | carouselProps,
31 | options: plugin.options,
32 | refs: { trackContainerRef, carouselRef },
33 | });
34 | });
35 | const itemClassNames = _flatten(
36 | carouselPlugins.map(
37 | (plugin) =>
38 | plugin.itemClassNames &&
39 | plugin.itemClassNames({
40 | carouselProps,
41 | options: plugin.options,
42 | refs: { trackContainerRef, carouselRef },
43 | }),
44 | ),
45 | ).filter((className) => typeof className === 'string');
46 |
47 | const carouselClassNames = _flatten(
48 | carouselPlugins.map(
49 | (plugin) =>
50 | plugin.carouselClassNames &&
51 | plugin.carouselClassNames({
52 | carouselProps,
53 | options: plugin.options,
54 | refs: { trackContainerRef, carouselRef },
55 | }),
56 | ),
57 | ).filter((className) => typeof className === 'string');
58 |
59 | const carouselCustomProps = Object.assign(
60 | {},
61 | ...carouselPlugins.map(
62 | (plugin) => plugin.carouselCustomProps && plugin.carouselCustomProps(),
63 | ),
64 | );
65 |
66 | const trackCustomProps = Object.assign(
67 | {},
68 | ...carouselPlugins.map(
69 | (plugin) => plugin.trackCustomProps && plugin.trackCustomProps(),
70 | ),
71 | );
72 |
73 | const slideCustomProps = Object.assign(
74 | {},
75 | ...carouselPlugins.map(
76 | (plugin) => plugin.slideCustomProps && plugin.slideCustomProps(),
77 | ),
78 | );
79 |
80 | const beforeCarouselItems =
81 | carouselPlugins.map(
82 | (plugin) => plugin.beforeCarouselItems && plugin.beforeCarouselItems(),
83 | ) || [];
84 |
85 | const afterCarouselItems =
86 | carouselPlugins.map(
87 | (plugin) => plugin.afterCarouselItems && plugin.afterCarouselItems(),
88 | ) || [];
89 |
90 | const strategies = _sortBy(carouselPlugins, (plugin) =>
91 | pluginsOrder.indexOf(plugin.name),
92 | ).map((plugin) => plugin.strategies && plugin.strategies());
93 |
94 | return {
95 | itemClassNames,
96 | carouselClassNames,
97 | beforeCarouselItems,
98 | afterCarouselItems,
99 | strategies,
100 | carouselCustomProps,
101 | trackCustomProps,
102 | slideCustomProps,
103 | carouselPlugins,
104 | };
105 | };
106 |
107 | export default carouselPluginResolver;
108 |
--------------------------------------------------------------------------------
/react-carousel/src/tools/clamp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Clamps number between 0 and last slide index.
3 | * @param {number} value to be clamped
4 | * @param {[node]} slides of react-carousel component
5 | * @param {boolean} rtl decide whether to clamp value for rtl carousel
6 | * @return {number} new value
7 | */
8 | const clamp = (value, slides) => {
9 | const getChildren = () => {
10 | if (slides) {
11 | return slides;
12 | }
13 | return [];
14 | };
15 |
16 | const maxValue = getChildren().length - 1;
17 | if (value > maxValue) {
18 | return maxValue;
19 | }
20 | if (value < 0) {
21 | return 0;
22 | }
23 | return value;
24 | };
25 |
26 | export default clamp;
27 |
--------------------------------------------------------------------------------
/react-carousel/src/tools/getChildren.js:
--------------------------------------------------------------------------------
1 | const getChildren = (children, slides) => {
2 | if (!children) {
3 | if (slides) {
4 | return slides;
5 | }
6 | return [];
7 | }
8 | if (Array.isArray(children)) {
9 | return children;
10 | }
11 | return [children];
12 | };
13 |
14 | export default getChildren;
15 |
--------------------------------------------------------------------------------
/react-carousel/src/tools/simulateEvent.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simulates mouse events when touch events occur
3 | * @param {event} event A touch event
4 | */
5 | const simulateEvent = (event) => {
6 | const touch = event.changedTouches[0];
7 | const { screenX, screenY, clientX, clientY } = touch;
8 | const touchEventMap = {
9 | touchstart: 'mousedown',
10 | touchmove: 'mousemove',
11 | touchend: 'mouseup',
12 | };
13 | const simulatedEvent = new MouseEvent(touchEventMap[event.type], {
14 | bubbles: true,
15 | cancelable: true,
16 | view: window,
17 | detail: 1,
18 | screenX,
19 | screenY,
20 | clientX,
21 | clientY,
22 | });
23 | touch.target.dispatchEvent(simulatedEvent);
24 | };
25 |
26 | export default simulateEvent;
27 |
--------------------------------------------------------------------------------
/react-carousel/test/__mocks__/styleMock.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/react-carousel/test/carousel.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { mount } from 'enzyme';
3 |
4 | import CarouselWrapper from '../src/components/CarouselWrapper';
5 |
6 | import setupCarousel from './tools/setupCarousel';
7 |
8 | const resizeEvent = document.createEvent('Event');
9 | resizeEvent.initEvent('resize', true, true);
10 |
11 | window.resizeTo = (width, height) => {
12 | window.innerWidth = width || global.window.innerWidth;
13 | window.innerHeight = height || global.window.innerHeight;
14 | window.dispatchEvent(resizeEvent);
15 | };
16 |
17 | describe('Carousel', () => {
18 | describe('plain carousel', () => {
19 | test('renders carousel items', () => {
20 | const wrapper = setupCarousel();
21 |
22 | expect(wrapper.find('.BrainhubCarouselItem')).toHaveLength(3);
23 | });
24 |
25 | test('renders carousel items when slides are result of a function', () => {
26 | const renderName = (name) => {name}
;
27 |
28 | const names = ['Dave', 'Kanye', 'Adam'];
29 |
30 | const wrapper = mount(
31 |
32 | Party guests:
33 | {names.map((name) => renderName(name))}
34 | ,
35 | );
36 |
37 | expect(wrapper.find('.BrainhubCarouselItem')).toHaveLength(2);
38 | });
39 |
40 | test('renders carousel items when passed as a prop', () => {
41 | const wrapper = mount( ]} />);
42 |
43 | expect(wrapper.find('.BrainhubCarouselItem')).toHaveLength(1);
44 | });
45 |
46 | test('overwrites carousel item width', () => {
47 | const wrapper = setupCarousel({
48 | itemWidth: 250,
49 | });
50 |
51 | const item = wrapper.find('.BrainhubCarouselItem').first();
52 |
53 | expect(item.props().style).toHaveProperty('width', '250px');
54 | });
55 |
56 | test('picks up correct props to set window size', () => {
57 | const wrapper = setupCarousel({
58 | breakpoints: {
59 | 1200: {
60 | itemWidth: 250,
61 | },
62 | 2400: {
63 | itemWidth: 500,
64 | },
65 | },
66 | });
67 | window.resizeTo(2000, 2000);
68 |
69 | const item = wrapper.find('.BrainhubCarouselItem').first();
70 |
71 | expect(item.props().style).toHaveProperty('width', '250px');
72 | });
73 |
74 | test('picks up correct props to set window size', () => {
75 | const wrapper = setupCarousel({
76 | breakpoints: {
77 | 1200: {
78 | itemWidth: 250,
79 | },
80 | 2400: {
81 | itemWidth: 500,
82 | },
83 | },
84 | });
85 | window.resizeTo(2500, 2500);
86 |
87 | const item = wrapper.find('.BrainhubCarouselItem').first();
88 |
89 | expect(item.props().style).toHaveProperty('width', '500px');
90 | });
91 |
92 | test(`uses default value if it's not declared in the breakpoint`, () => {
93 | window.resizeTo(2000, 2000);
94 |
95 | const declaredWidth = 400;
96 |
97 | const wrapper = setupCarousel({
98 | itemWidth: declaredWidth,
99 | breakpoints: {
100 | 1200: {
101 | value: 1,
102 | },
103 | 2400: {
104 | value: 2,
105 | },
106 | },
107 | });
108 |
109 | expect(
110 | wrapper.find('.BrainhubCarouselItem').first().prop('style').width,
111 | ).toEqual(`${declaredWidth}px`);
112 | });
113 |
114 | test('sets carousel initial slide index', () => {
115 | const wrapper = setupCarousel({
116 | value: 2,
117 | });
118 |
119 | expect(
120 | wrapper
121 | .find('.BrainhubCarouselItem')
122 | .at(2)
123 | .hasClass('BrainhubCarouselItem--active'),
124 | ).toBeTruthy();
125 | });
126 |
127 | test('displays the last slide if the value is greater than the number of slides', () => {
128 | const wrapper = mount(
129 |
130 |
131 |
132 |
133 | ,
134 | );
135 |
136 | expect(
137 | wrapper
138 | .find('.BrainhubCarouselItem--active')
139 | .children()
140 | .hasClass('third'),
141 | ).toBeTruthy();
142 | });
143 |
144 | test('displays the first slide if the value is lower than 0', () => {
145 | const wrapper = mount(
146 |
147 |
148 |
149 |
150 | ,
151 | );
152 |
153 | expect(
154 | wrapper
155 | .find('.BrainhubCarouselItem--active')
156 | .children()
157 | .hasClass('first'),
158 | ).toBeTruthy();
159 | });
160 | });
161 | });
162 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/arrows.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { arrowsPlugin } from '../../src';
4 | import setupCarousel from '../tools/setupCarousel';
5 |
6 | describe('arrows', () => {
7 | test('renders arrows', () => {
8 | const wrapper = setupCarousel({
9 | plugins: ['arrows'],
10 | });
11 |
12 | expect(wrapper.find('.BrainhubCarousel__arrows')).toHaveLength(2);
13 | });
14 |
15 | test('arrow left is disabled when there are no more slides on the left', () => {
16 | const wrapper = setupCarousel({
17 | plugins: ['arrows'],
18 | });
19 |
20 | expect(
21 | wrapper.find('.BrainhubCarousel__arrowRight').props().disabled,
22 | ).toBeFalsy();
23 | expect(
24 | wrapper.find('.BrainhubCarousel__arrowLeft').props().disabled,
25 | ).toBeTruthy();
26 | });
27 |
28 | test('arrow right is disabled when there are no more slides on the right', () => {
29 | const wrapper = setupCarousel({
30 | value: 2,
31 | plugins: ['arrows'],
32 | });
33 |
34 | expect(
35 | wrapper.find('.BrainhubCarousel__arrowRight').props().disabled,
36 | ).toBeTruthy();
37 | expect(
38 | wrapper.find('.BrainhubCarousel__arrowLeft').props().disabled,
39 | ).toBeFalsy();
40 | });
41 |
42 | test('both arrows are enabled with infinite plugin', () => {
43 | const wrapper = setupCarousel({
44 | plugins: ['arrows', 'infinite'],
45 | });
46 |
47 | expect(
48 | wrapper.find('.BrainhubCarousel__arrowRight').props().disabled,
49 | ).toBeFalsy();
50 | expect(
51 | wrapper.find('.BrainhubCarousel__arrowLeft').props().disabled,
52 | ).toBeFalsy();
53 | });
54 |
55 | test('changes slide on active arrow click', () => {
56 | const wrapper = setupCarousel({
57 | plugins: ['arrows'],
58 | });
59 |
60 | expect(
61 | wrapper
62 | .find('.BrainhubCarouselItem')
63 | .first()
64 | .hasClass('BrainhubCarouselItem--active'),
65 | ).toBeTruthy();
66 |
67 | wrapper.find('.BrainhubCarousel__arrowRight').simulate('click');
68 |
69 | expect(
70 | wrapper
71 | .find('.BrainhubCarouselItem')
72 | .at(1)
73 | .hasClass('BrainhubCarouselItem--active'),
74 | ).toBeTruthy();
75 | });
76 |
77 | test('custom arrows work as expected', () => {
78 | const wrapper = setupCarousel({
79 | plugins: [
80 | {
81 | resolve: arrowsPlugin,
82 | options: {
83 | arrowLeft:
,
84 | arrowLeftDisabled:
,
85 | arrowRight:
,
86 | arrowRightDisabled:
,
87 | addArrowClickHandler: true,
88 | },
89 | },
90 | ],
91 | });
92 |
93 | expect(wrapper.find('.left-disabled')).toHaveLength(1);
94 |
95 | wrapper.find('.right').simulate('click');
96 |
97 | expect(wrapper.find('.left-disabled')).toHaveLength(0);
98 | expect(wrapper.find('.left')).toHaveLength(1);
99 |
100 | wrapper.find('.right').simulate('click');
101 |
102 | expect(wrapper.find('.right-disabled')).toHaveLength(1);
103 | expect(wrapper.find('.right')).toHaveLength(0);
104 | });
105 | });
106 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/autoplay.test.js:
--------------------------------------------------------------------------------
1 | import { autoplayPlugin } from '../../src';
2 | import setupCarousel from '../tools/setupCarousel';
3 |
4 | describe('autoplay', () => {
5 | test('clears interval on unmount when autoplay was enabled', () => {
6 | jest.useFakeTimers();
7 |
8 | const wrapper = setupCarousel({
9 | plugins: ['autoplay'],
10 | animationSpeed: 1,
11 | });
12 |
13 | wrapper.unmount();
14 |
15 | expect(clearInterval).toHaveBeenCalled();
16 | });
17 |
18 | test('changes slides automatically', () => {
19 | jest.useFakeTimers();
20 |
21 | Object.defineProperty(document, 'hidden', {
22 | configurable: true,
23 | get: () => false,
24 | });
25 |
26 | const wrapper = setupCarousel({
27 | plugins: [
28 | {
29 | resolve: autoplayPlugin,
30 | options: {
31 | interval: 10,
32 | },
33 | },
34 | ],
35 | animationSpeed: 1,
36 | });
37 |
38 | expect(
39 | wrapper
40 | .find('.BrainhubCarouselItem')
41 | .at(0)
42 | .hasClass('BrainhubCarouselItem--active'),
43 | ).toBeTruthy();
44 |
45 | jest.advanceTimersByTime(11);
46 |
47 | wrapper.update();
48 |
49 | expect(
50 | wrapper
51 | .find('.BrainhubCarouselItem')
52 | .at(1)
53 | .hasClass('BrainhubCarouselItem--active'),
54 | ).toBeTruthy();
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/dots.test.js:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useState } from 'react';
2 | import { mount } from 'enzyme';
3 |
4 | import { Dots } from '../../src';
5 | import CarouselWrapper from '../../src/components/CarouselWrapper';
6 |
7 | const CarouselWithDots = () => {
8 | const [value, setValue] = useState(0);
9 |
10 | const onChange = useCallback(
11 | (value) => {
12 | setValue(value);
13 | },
14 | [setValue],
15 | );
16 |
17 | const slides = Array.from({ length: 5 }, (val, index) =>
);
18 |
19 | return (
20 |
21 |
22 |
23 |
24 | );
25 | };
26 |
27 | const CarouselWithThumbnails = () => {
28 | const [value, setValue] = useState(0);
29 |
30 | const onChange = useCallback(
31 | (value) => {
32 | setValue(value);
33 | },
34 | [setValue],
35 | );
36 |
37 | const slides = Array.from({ length: 5 }, (val, index) =>
);
38 |
39 | return (
40 |
41 |
42 |
48 |
49 | );
50 | };
51 |
52 | describe('dots', () => {
53 | test('renders dots', () => {
54 | const wrapper = mount( );
55 |
56 | expect(wrapper.find('.BrainhubCarousel__dot')).toHaveLength(5);
57 | });
58 |
59 | test('changes slide on dot click', () => {
60 | const wrapper = mount( );
61 |
62 | expect(
63 | wrapper
64 | .find('.BrainhubCarouselItem')
65 | .first()
66 | .hasClass('BrainhubCarouselItem--active'),
67 | ).toBeTruthy();
68 |
69 | wrapper.find('.BrainhubCarousel__dot').at(1).simulate('click');
70 |
71 | expect(
72 | wrapper
73 | .find('.BrainhubCarouselItem')
74 | .at(1)
75 | .hasClass('BrainhubCarouselItem--active'),
76 | ).toBeTruthy();
77 | });
78 |
79 | test('changes slide on thumbnail click', () => {
80 | const wrapper = mount( );
81 |
82 | expect(
83 | wrapper
84 | .find('.BrainhubCarouselItem')
85 | .first()
86 | .hasClass('BrainhubCarouselItem--active'),
87 | ).toBeTruthy();
88 |
89 | wrapper.find('.BrainhubCarousel__thumbnail').at(1).simulate('click');
90 |
91 | expect(
92 | wrapper
93 | .find('.BrainhubCarouselItem')
94 | .at(1)
95 | .hasClass('BrainhubCarouselItem--active'),
96 | ).toBeTruthy();
97 | });
98 | });
99 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/infinite.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import setupCarousel from '../tools/setupCarousel';
4 | import { defaultOptions as infiniteDefaultOptions } from '../../src/plugins/infinite';
5 |
6 | describe('infinite', () => {
7 | it('renders additional clones when in infinite mode', () => {
8 | const sidesToClone = 2; // we create clones for the left and for the right side
9 | const slides = [
,
,
];
10 | const wrapper = setupCarousel({
11 | plugins: ['infinite'],
12 | slides,
13 | });
14 |
15 | const expectedNumberOfSlides =
16 | slides.length +
17 | slides.length *
18 | infiniteDefaultOptions.numberOfInfiniteClones *
19 | sidesToClone;
20 |
21 | expect(wrapper.find('.BrainhubCarouselItem')).toHaveLength(
22 | expectedNumberOfSlides,
23 | );
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/rtl.test.js:
--------------------------------------------------------------------------------
1 | import setupCarousel from '../tools/setupCarousel';
2 |
3 | describe('rtl', () => {
4 | test('adds BrainhubCarousel--isRTL when in RTL mode', () => {
5 | const wrapper = setupCarousel({
6 | plugins: ['rtl'],
7 | });
8 |
9 | expect(wrapper.find('.BrainhubCarousel--isRTL')).toHaveLength(1);
10 | });
11 |
12 | test('left arrow is initially enabled with rtl plugin', () => {
13 | const wrapper = setupCarousel({
14 | plugins: ['rtl', 'arrows'],
15 | });
16 |
17 | expect(
18 | wrapper.find('.BrainhubCarousel__arrowLeft').props().disabled,
19 | ).toBeTruthy();
20 | expect(
21 | wrapper.find('.BrainhubCarousel__arrowRight').props().disabled,
22 | ).toBeFalsy();
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/react-carousel/test/plugins/slidesPerScroll.test.js:
--------------------------------------------------------------------------------
1 | import setupCarousel from '../tools/setupCarousel';
2 | import slidesToScroll from '../../src/plugins/slidesToScroll';
3 |
4 | describe('slidesPerScroll plugin', () => {
5 | test('slides forward as many slides as described in plugin options', () => {
6 | const wrapper = setupCarousel({
7 | plugins: [
8 | 'arrows',
9 | {
10 | resolve: slidesToScroll,
11 | options: {
12 | numberOfSlides: 2,
13 | },
14 | },
15 | ],
16 | });
17 |
18 | expect(
19 | wrapper
20 | .find('.BrainhubCarouselItem')
21 | .at(0)
22 | .hasClass('BrainhubCarouselItem--active'),
23 | ).toBeTruthy();
24 |
25 | wrapper.find('.BrainhubCarousel__arrowRight').simulate('click');
26 |
27 | expect(
28 | wrapper
29 | .find('.BrainhubCarouselItem')
30 | .at(2)
31 | .hasClass('BrainhubCarouselItem--active'),
32 | ).toBeTruthy();
33 | });
34 |
35 | test('slides backward as many slides as described in plugin options', () => {
36 | const wrapper = setupCarousel({
37 | plugins: [
38 | 'arrows',
39 | {
40 | resolve: slidesToScroll,
41 | options: {
42 | numberOfSlides: 2,
43 | },
44 | },
45 | ],
46 | });
47 |
48 | expect(
49 | wrapper
50 | .find('.BrainhubCarouselItem')
51 | .at(0)
52 | .hasClass('BrainhubCarouselItem--active'),
53 | ).toBeTruthy();
54 |
55 | wrapper.find('.BrainhubCarousel__arrowRight').simulate('click');
56 |
57 | expect(
58 | wrapper
59 | .find('.BrainhubCarouselItem')
60 | .at(2)
61 | .hasClass('BrainhubCarouselItem--active'),
62 | ).toBeTruthy();
63 |
64 | wrapper.find('.BrainhubCarousel__arrowLeft').simulate('click');
65 |
66 | expect(
67 | wrapper
68 | .find('.BrainhubCarouselItem')
69 | .at(0)
70 | .hasClass('BrainhubCarouselItem--active'),
71 | ).toBeTruthy();
72 | });
73 |
74 | test('goes to the last slide if numberOfSlides exceeds the total number of slides', () => {
75 | const wrapper = setupCarousel({
76 | plugins: [
77 | 'arrows',
78 | {
79 | resolve: slidesToScroll,
80 | options: {
81 | numberOfSlides: 5,
82 | },
83 | },
84 | ],
85 | });
86 |
87 | expect(
88 | wrapper
89 | .find('.BrainhubCarouselItem')
90 | .at(0)
91 | .hasClass('BrainhubCarouselItem--active'),
92 | ).toBeTruthy();
93 |
94 | wrapper.find('.BrainhubCarousel__arrowRight').simulate('click');
95 |
96 | expect(
97 | wrapper
98 | .find('.BrainhubCarouselItem')
99 | .at(2)
100 | .hasClass('BrainhubCarouselItem--active'),
101 | ).toBeTruthy();
102 | });
103 | });
104 |
--------------------------------------------------------------------------------
/react-carousel/test/tools/setupCarousel.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { mount } from 'enzyme';
3 |
4 | import CarouselWrapper from '../../src/components/CarouselWrapper';
5 |
6 | const setup = (options = {}) =>
7 | mount(
8 |
9 |
16 |
23 |
30 | ,
31 | );
32 |
33 | export default setup;
34 |
--------------------------------------------------------------------------------
/react-carousel/tools/build.js:
--------------------------------------------------------------------------------
1 | // More info on Webpack's Node API here: https://webpack.github.io/docs/node.js-api.html
2 | // Allowing console calls below since this is a build file.
3 | /* eslint-disable no-console */
4 | const webpack = require('webpack');
5 |
6 | const config = require('../webpack.config.prod');
7 |
8 | const {
9 | chalkError,
10 | chalkSuccess,
11 | chalkWarning,
12 | chalkProcessing,
13 | } = require('./chalkConfig');
14 |
15 | process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply.
16 |
17 | console.log(
18 | chalkProcessing('Generating minified bundle. This will take a moment...'),
19 | );
20 |
21 | webpack(config).run((error, stats) => {
22 | if (error) {
23 | // so a fatal error occurred. Stop here.
24 | console.log(chalkError(error));
25 | process.exit(1);
26 | }
27 |
28 | const jsonStats = stats.toJson();
29 |
30 | if (stats.hasErrors()) {
31 | jsonStats.errors.forEach((error) => console.log(chalkError(error)));
32 | process.exit(1);
33 | }
34 |
35 | if (stats.hasWarnings()) {
36 | console.log(chalkWarning('Webpack generated the following warnings: '));
37 | jsonStats.warnings.forEach((warning) => console.log(chalkWarning(warning)));
38 | }
39 |
40 | console.log(`Webpack stats: ${stats}`);
41 |
42 | // if we got this far, the build succeeded.
43 | console.log(
44 | chalkSuccess(
45 | `Your app is compiled in production mode in /lib. It's ready to roll!`,
46 | ),
47 | );
48 | });
49 |
--------------------------------------------------------------------------------
/react-carousel/tools/chalkConfig.js:
--------------------------------------------------------------------------------
1 | // Centralized configuration for chalk, which is used to add color to console.log statements.
2 | const chalk = require('chalk');
3 |
4 | module.exports = {
5 | chalkError: chalk.red,
6 | chalkSuccess: chalk.green,
7 | chalkWarning: chalk.yellow,
8 | chalkProcessing: chalk.blue,
9 | };
10 |
--------------------------------------------------------------------------------
/react-carousel/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const TerserPlugin = require('terser-webpack-plugin');
4 | const webpack = require('webpack');
5 | const autoprefixer = require('autoprefixer');
6 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
7 |
8 | module.exports = {
9 | mode: 'production',
10 | externals: [
11 | {
12 | 'react-dom': {
13 | root: 'ReactDOM',
14 | commonjs2: 'react-dom',
15 | commonjs: 'react-dom',
16 | amd: 'react-dom',
17 | },
18 | },
19 | {
20 | react: {
21 | root: 'React',
22 | commonjs2: 'react',
23 | commonjs: 'react',
24 | amd: 'react',
25 | },
26 | },
27 | ],
28 | resolve: {
29 | extensions: ['.js', '.jsx', '.json'],
30 | modules: ['node_modules', path.join(__dirname, 'src')],
31 | },
32 | devtool: 'source-map',
33 | entry: './src/index.js',
34 | output: {
35 | filename: 'react-carousel.js',
36 | library: 'react-carousel',
37 | libraryTarget: 'umd',
38 | path: path.resolve(__dirname, 'lib'),
39 | umdNamedDefine: true,
40 | globalObject: 'this',
41 | },
42 | plugins: [
43 | new TerserPlugin({
44 | parallel: true,
45 | terserOptions: {
46 | ecma: 6,
47 | },
48 | }),
49 | new ExtractTextPlugin('style.css'),
50 | new webpack.DefinePlugin({
51 | // This fixes https://github.com/brainhubeu/react-carousel/issues/115
52 | 'process.env': {
53 | NODE_ENV: JSON.stringify('production'),
54 | },
55 | }),
56 | ],
57 | module: {
58 | rules: [
59 | {
60 | test: /\.jsx?$/,
61 | exclude: /node_modules/,
62 | use: ['babel-loader'],
63 | },
64 | {
65 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
66 | use: [
67 | {
68 | loader: 'url-loader',
69 | options: {
70 | limit: 10000,
71 | mimetype: 'image/svg+xml',
72 | },
73 | },
74 | ],
75 | },
76 | {
77 | test: /(\.css|\.scss)$/,
78 | use: ExtractTextPlugin.extract({
79 | fallback: 'style-loader',
80 | use: [
81 | {
82 | loader: 'css-loader',
83 | options: {
84 | sourceMap: true,
85 | },
86 | },
87 | {
88 | loader: 'postcss-loader',
89 | options: {
90 | sourceMap: true,
91 | plugins: () => [autoprefixer],
92 | },
93 | },
94 | {
95 | loader: 'sass-loader',
96 | options: {
97 | sourceMap: true,
98 | },
99 | },
100 | ],
101 | }),
102 | },
103 | ],
104 | },
105 | };
106 |
--------------------------------------------------------------------------------
/readme/assets/carousel.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/readme/assets/carousel.gif
--------------------------------------------------------------------------------
/readme/assets/logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/readme/assets/logo.gif
--------------------------------------------------------------------------------
/readme/assets/thumbnails.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brainhubeu/react-carousel/be0aeda9804f16fd7482e42a1b1010a7ec9bb302/readme/assets/thumbnails.gif
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "bumpVersion": "patch",
3 | "commitMessagePrefix": "[renovate] ",
4 | "groupName": "NPM dependencies",
5 | "labels": ["renovate"],
6 | "rangeStrategy": "bump",
7 | "branchPrefix": "fix/renovate/",
8 | "docker": {
9 | "major": {
10 | "enabled": true
11 | }
12 | },
13 | "packageRules": [
14 | {
15 | "groupName": "Docker dependencies",
16 | "managers": ["circleci"]
17 | },
18 | {
19 | "groupName": "gatsby",
20 | "managerBranchPrefix": "gatsby",
21 | "packagePatterns": ["gatsby"],
22 | "rangeStrategy": "pin"
23 | }
24 | ],
25 | "schedule": ["before 3am on the first day of the month"]
26 | }
27 |
--------------------------------------------------------------------------------
/tools/deploy-gh-pages-pr.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | failure() {
5 | local lineno=$1
6 | echo "Failed at $lineno"
7 | }
8 | trap 'failure ${LINENO}' ERR
9 |
10 | for page_number in {1..20}
11 | do
12 | echo "page_number=$page_number"
13 | pr_number=`curl -s "https://beghp.github.io/gh-pages-rc-$page_number/" | grep -o '★☂☀[0-9]\+♞♜♖' | grep -o '[0-9]\+' | head -1 || echo ''`
14 | echo "pr_number=$pr_number"
15 | if [[ "$pr_number" == '' ]]
16 | then
17 | echo "no PR exists for page no $page_number"
18 | if [[ "$first_free_page_number" == '' ]]
19 | then
20 | first_free_page_number=$page_number
21 | fi
22 | elif [[ "https://github.com/brainhubeu/react-carousel/pull/$pr_number" == "$CIRCLE_PULL_REQUEST" ]]
23 | then
24 | echo "this PR is already deployed to the page no $page_number"
25 | already_deployed_page_number=$page_number
26 | break
27 | else
28 | echo "a PR (no $pr_number) exists for page no $page_number"
29 | pr_state=`curl -s "https://api.github.com/repos/brainhubeu/react-carousel/pulls/$pr_number" | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["state"]'`
30 | echo "PR state: $pr_state"
31 | if [[ "$pr_state" == 'open' ]]
32 | then
33 | echo 'the PR is open, continue searching an empty page'
34 | else
35 | echo 'the PR is not open'
36 | if [[ "$first_free_page_number" == '' ]]
37 | then
38 | first_free_page_number=$page_number
39 | fi
40 | fi
41 | fi
42 | done
43 | if [[ "$page_number" == '20' ]]
44 | then
45 | if [[ "$first_free_page_number" == '' || "$first_free_page_number" == '20' ]]
46 | then
47 | echo 'no free page'
48 | exit 1
49 | fi
50 | echo "deploying to $first_free_page_number as it's the first free place"
51 | final_page_number=$first_free_page_number
52 | else
53 | echo "the PR was deployed to the page no $page_number so keeping the same place"
54 | final_page_number=$already_deployed_page_number
55 | fi
56 | echo "final_page_number=$final_page_number"
57 |
58 | page_url="https://beghp.github.io/gh-pages-rc-$final_page_number"
59 | echo "page_url=$page_url"
60 |
61 |
62 | sed -i 's/__RC_ENV__/development/g' docs-www/src/globalReferences.js
63 | sed -i 's/__RC_ENV__/development/g' docs-www/package.json
64 | sed -i "s/__BUILD_INFO__/ (PR #$pr_number, built on `date +'%Y-%m-%d %H:%M:%S'`)/g" docs-www/gatsby-docs-kit.yml
65 | cat docs-www/src/globalReferences.js
66 | cat docs-www/package.json
67 | remote=https://$GIT_TOKEN@github.com/beghp/gh-pages-rc-$final_page_number.git
68 |
69 | yarn install --non-interactive
70 |
71 | PATH_PREFIX=gh-pages-rc-$final_page_number yarn workspace react-carousel-docs build
72 |
73 | mkdir -p gh-pages-branch
74 | cd gh-pages-branch
75 |
76 | git config --global user.email "robert@brainhub.eu" > /dev/null 2>&1
77 | git config --global user.name "DevOps Brainhub" > /dev/null 2>&1
78 | git init
79 | git remote add origin $remote
80 | git remote -v
81 | git fetch origin
82 |
83 | if git rev-parse --verify origin/gh-pages > /dev/null 2>&1
84 | then
85 | echo 'rev-parse true'
86 | git checkout gh-pages
87 | git rm -rf . || echo 'nothing to remove'
88 | cp -r ../docs-www/public/* .
89 | else
90 | echo 'rev-parse false'
91 | git checkout --orphan gh-pages
92 | git rm -rf . || echo 'nothing to remove'
93 | cp -r ../docs-www/public/* .
94 | fi
95 |
96 | git add -A
97 | git commit --allow-empty -m "Deploy to GitHub pages [ci skip]"
98 | git push --force --quiet origin gh-pages
99 |
100 | cd ..
101 | rm -rf gh-pages-branch
102 |
103 | api_pr_url=`echo "$CIRCLE_PULL_REQUEST" | sed 's@https://github.com/brainhubeu/react-carousel/pull/@https://api.github.com/repos/brainhubeu/react-carousel/pulls/@g'`
104 | echo api_pr_url=$api_pr_url
105 | pr_body=`curl -s $api_pr_url | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["body"]' | perl -pe 's/\r?\n/ /' | sed 's@ @ @g'`
106 | echo "pr_body=$pr_body"
107 | deployed_match=`echo $pr_body | grep 'Deployed to https://beghp.github.io' || echo ''`
108 | if [[ "$deployed_match" != '' ]]
109 | then
110 | echo 'page URL already added to the PR description'
111 | else
112 | curl -i -H "Authorization: token $GIT_TOKEN" -X PATCH -d "{\"body\":\"Deployed to $page_url $pr_body\"}" $api_pr_url
113 | fi
114 |
115 | echo "Finished Deployment of gh pages to $page_url"
116 |
--------------------------------------------------------------------------------
/tools/deploy-gh-pages.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | failure() {
5 | local lineno=$1
6 | echo "Failed at $lineno"
7 | }
8 | trap 'failure ${LINENO}' ERR
9 |
10 | remote=https://$GIT_TOKEN@github.com/brainhubeu/react-carousel.git
11 |
12 | sed -i "s/__BUILD_INFO__/ (master, built on `date +'%Y-%m-%d %H:%M:%S'`)/g" docs-www/gatsby-docs-kit.yml
13 |
14 | yarn install --non-interactive
15 |
16 | PATH_PREFIX=react-carousel yarn workspace react-carousel-docs build
17 |
18 | mkdir -p gh-pages-branch
19 | cd gh-pages-branch
20 |
21 | git config --global user.email "robert@brainhub.eu" > /dev/null 2>&1
22 | git config --global user.name "DevOps Brainhub" > /dev/null 2>&1
23 | git init
24 | git remote add origin $remote
25 | git remote -v
26 | git fetch origin
27 |
28 | if git rev-parse --verify origin/gh-pages > /dev/null 2>&1
29 | then
30 | echo 'rev-parse true'
31 | git checkout gh-pages
32 | git rm -rf . || echo 'nothing to remove'
33 | cp -r ../docs-www/public/* .
34 | else
35 | echo 'rev-parse false'
36 | git checkout --orphan gh-pages
37 | git rm -rf . || echo 'nothing to remove'
38 | cp -r ../docs-www/public/* .
39 | fi
40 |
41 | git add -A
42 | git commit --allow-empty -m "Deploy to GitHub pages [ci skip]"
43 | git push --force --quiet origin gh-pages
44 |
45 | cd ..
46 | rm -rf gh-pages-branch
47 |
48 | echo "Finished Deployment of gh pages!"
49 |
--------------------------------------------------------------------------------
/tools/skip-all-e2e-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | sed -i '' 's/describe/describe.skip/g' test/cypress/integration/*
5 |
--------------------------------------------------------------------------------
/tools/unskip-all-e2e-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | sed -i '' 's/describe.skip/describe/g' test/cypress/integration/*
5 |
--------------------------------------------------------------------------------