diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9fcb9676..ffa45946 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ We encourage pull requests concerning: ## Development -Initial install & setup, with **node 10+** & **yarn v1**, run `yarn install`. +Initial install & setup, with **node 16** & **yarn v1**, run `yarn install`. Make changes/updates to the `src/index.ts` file. @@ -27,12 +27,10 @@ Make changes/updates to the `src/index.ts` file. Build, run, and test examples locally: ```sh -# Go into examples folder -react-swipeable$ cd examples # Yarn install -react-swipeable/examples$ yarn +yarn install # Run the start:dev:local command -react-swipeable/examples$ yarn start:dev:local +yarn start:examples:local ``` Then open a browser tab to `http://localhost:8080/`. @@ -50,6 +48,19 @@ All these steps can be verified via a single command. yarn test ``` +## Documentation + +Documentation is managed within the `docs` directory. In order to test and preview changes, you'll require Node 18+ to run locally. + +```sh +# navigate to docs directory +cd docs +# install modules +docs$ yarn install +# start locally and view at http://localhost:3000/ +docs$ yarn start +``` + ### Unit Testing All unit tests are located in: @@ -193,4 +204,6 @@ examples$ python -m http.server 8080 ```sh # From root - build and publish the examples app to github pages $ yarn examples:build:publish + + ``` diff --git a/docs/docs/examples/simple-carousel.mdx b/docs/docs/examples/simple-carousel.mdx index c12ccfb3..56195899 100644 --- a/docs/docs/examples/simple-carousel.mdx +++ b/docs/docs/examples/simple-carousel.mdx @@ -4,7 +4,136 @@ import SimpleCarousel from '@site/src/components/examples/SimpleCarousel' # Simple Carousel -Below is an example implementation of a simple carousel which utilizes the hooks provided by react-swipeable. +Below is an example implementation of a simple carousel which utilizes the hooks provided by `react-swipeable` within a TypeScript context. + + +## Simple Carousel Code Source + +You can see this full example as pure code within the [Carousel.tsx](https://github.com/FormidableLabs/react-swipeable/blob/main/examples/app/SimpleCarousel/Carousel.tsx) file within the React-Swipeable repo directly. + +## Simple Carousel Live Preview +Note: The action of swiping must have a duration of `500ms` or lower in order to trigger the swipe action. + +## Simple Carousel Code Explained + +Import the hook directly from the `react-swipeable` library. In our example, we built and imported a local set of UI components: you can utilize your own UI and styling, or use your favorite UI component library of choice. + +```typescript +import { useSwipeable } from 'react-swipeable'; +import { + Wrapper, + CarouselContainer, + CarouselSlot, + SlideButtonContainer, + SlideButton, + PREV, + NEXT +} from '../components'; +``` + +Below, we set up types and an interface for some of the work we'll be building. Next, we write a function called `getOrder`, which will drive the position of each item in the carousel, and what order of position each will be displayed in context of the carousel. Finally, we have a simple `getInitialState` position that sets the `CarouselState` of the carousel we'll be building. + +```typescript +type Direction = typeof PREV | typeof NEXT; + +interface CarouselState { + pos: number; + sliding: boolean; + dir: Direction; +} + +type CarouselAction = + | { type: Direction, numItems: number } + | { type: 'stopSliding' }; + + +const getOrder = (index: number, pos: number, numItems: number) => { + return index - pos < 0 ? numItems - Math.abs(index - pos) : index - pos; +}; + +const getInitialState = (numItems: number): CarouselState => ({ pos: numItems - 1, sliding: false, dir: NEXT }); +``` + +Next, we build a reducer for controlling the action of the Carousel, using a switch to set `CarouselState` logic. + +```typescript +function reducer(state: CarouselState, action: CarouselAction): CarouselState { + switch (action.type) { + case PREV: + return { + ...state, + dir: PREV, + sliding: true, + pos: state.pos === 0 ? action.numItems - 1 : state.pos - 1 + }; + case NEXT: + return { + ...state, + dir: NEXT, + sliding: true, + pos: state.pos === action.numItems - 1 ? 0 : state.pos + 1 + }; + case 'stopSliding': + return { ...state, sliding: false }; + default: + return state; + } +} +``` + +Then, building upon the reducer logic, the `` is constructed. We hold the number of items within a count of `numItems`. We utilize the reducer within the `React.useReducer` hook. + +By creating `slide`, as a `const`, we can utilize that later in the component, calling it within `useSwipeable`: called upon `slide(NEXT)` and `slide(PREV)`, invoking the `dispatch` and the `timeout` we built within `slide`. Within the use of `useSwippeable`, we set `swipeDuration` to `500ms`. We set `preventScrollOnSwipe` to `true`, and `trackMouse` to `true`. + +At the end, we return the component itself, built with the components we've created, with `handlers` passed into the wrapping `
` around the surrounding container. The `` holds the directional and sliding state, and within that container the items we want to display are mapped as `React.Children`, utilizing `getOrder`. + +When we put it all together, our `` is complete! + +```typescript +const Carousel: FunctionComponent<{children: ReactNode}> = (props) => { + const numItems = React.Children.count(props.children); + const [state, dispatch] = React.useReducer(reducer, getInitialState(numItems)); + + const slide = (dir: Direction) => { + dispatch({ type: dir, numItems }); + setTimeout(() => { + dispatch({ type: 'stopSliding' }); + }, 50); + }; + + const handlers = useSwipeable({ + onSwipedLeft: () => slide(NEXT), + onSwipedRight: () => slide(PREV), + swipeDuration: 500, + preventScrollOnSwipe: true, + trackMouse: true + }); + + return ( +
+ + + {React.Children.map(props.children, (child, index) => ( + + {child} + + ))} + + + + slide(PREV)} float="left"> + Prev + + slide(NEXT)} float="right"> + Next + + +
+ ); +}; +``` diff --git a/docs/src/components/examples/SimpleCarousel/index.tsx b/docs/src/components/examples/SimpleCarousel/index.tsx index 105d12ea..28283fcd 100644 --- a/docs/src/components/examples/SimpleCarousel/index.tsx +++ b/docs/src/components/examples/SimpleCarousel/index.tsx @@ -16,15 +16,6 @@ function SimpleCarousel() {
- Note: swipe must be "faster" than 500ms to trigger. -
- - See code - {" "} - for example usage of{" "} - swipeDuration and{" "} - preventScrollOnSwipe. -
); } diff --git a/examples/app/SimpleCarousel/index.tsx b/examples/app/SimpleCarousel/index.tsx index 4b61ef15..546dfe3c 100644 --- a/examples/app/SimpleCarousel/index.tsx +++ b/examples/app/SimpleCarousel/index.tsx @@ -7,10 +7,6 @@ import Carousel from './Carousel'; function SimpleCarousel() { return (
-
- 🖼 Image Carousel -
- @@ -18,10 +14,6 @@ function SimpleCarousel() { - Note: swipe must be "faster" then 500ms to trigger. -
- See code for example usage of swipeDuration and preventScrollOnSwipe. -
); }