diff --git a/src/App/App.jsx b/src/App/App.jsx index 08ec3dec..1c28ee1a 100644 --- a/src/App/App.jsx +++ b/src/App/App.jsx @@ -10,14 +10,10 @@ import { Example8, Example9, Example10, + Example11, } from './examples'; import s from './style.scss'; - -// function demoClick(ev) { -// console.log('ev', Object.assign({}, ev)); -// } - class DevelopmentApp extends React.Component { constructor() { super(); @@ -43,18 +39,24 @@ class DevelopmentApp extends React.Component {

Pure React Carousel

- Pure React Carousel is a suite of unopinionated React components that a - developer can use to create robust carousels with almost no limits on DOM structure - or styling. + Pure React Carousel is a suite of unopinionated React components that a developer + can use to create robust carousels with almost no limits on DOM structure or + styling.

If you're tired of fighting some other developer's CSS and DOM structure, this carousel is for you.

@@ -82,25 +86,37 @@ class DevelopmentApp extends React.Component {

The components in Pure React Carousel provide the bare-minimum of styling and javascript - required to function correctly as a carousel. Just like using table HTML tags - will give you a bare-bones table that you will need to style, Pure React Carousel - requires that you provide additional styles and optional javascript in order to meet - your project's specific functionality and branding requirements. + required to function correctly as a carousel. Just like using table HTML tags will give + you a bare-bones table that you will need to style, Pure React Carousel requires that + you provide additional styles and optional javascript in order to meet your + project's specific functionality and branding requirements.

- The benefit of Pure React Carousel is that our components are focused on one task: - being an WCAG accessible carousel. Besides that, our goal is to get out of your way. + The benefit of Pure React Carousel is that our components are focused on one task: being + an WCAG accessible carousel. Besides that, our goal is to get out of your way.

Real World Example

- Here are two examples of what can be acheived with Pure React Carousel. This is how - we use the suite of components on the Express.com website. + Here are two examples of what can be acheived with Pure React Carousel. This is how we + use the suite of components on the Express.com website. +

+

+ example of pure react carousel on the product detail page for a dress on Express.com +

+

+ example of pure react carousel on the product detail page for a shirt on Express.com

-

example of pure react carousel on the product detail page for a dress on Express.com

-

example of pure react carousel on the product detail page for a shirt on Express.com

@@ -108,10 +124,10 @@ class DevelopmentApp extends React.Component {

Default Carousel Examples

Why are these examples so... ugly?

- These examples are completely un-styled. Pure React Carousel does not come with - styles that must be defeated in order to match your organization's branding. So, - to distract you from the seeming lack of finess, most of our examples - involve pictures of cats! + These examples are completely un-styled. Pure React Carousel does not come with styles + that must be defeated in order to match your organization's branding. So, to + distract you from the seeming lack of finess, most of our examples involve pictures of + cats!

- { (value === '0' || value === '1') && ( + {(value === '0' || value === '1') && (

)} - { (value === '0' || value === '2') && ( + {(value === '0' || value === '2') && (

)} - { (value === '0' || value === '3') && ( + {(value === '0' || value === '3') && (

)} - { (value === '0' || value === '4') && ( + {(value === '0' || value === '4') && (

)} - { (value === '0' || value === '5') && ( + {(value === '0' || value === '5') && (

)} - { (value === '0' || value === '6') && ( + {(value === '0' || value === '6') && (

)} - { (value === '0' || value === '7') && ( + {(value === '0' || value === '7') && (

)} - { (value === '0' || value === '8') && ( + {(value === '0' || value === '8') && (

)} - { (value === '0' || value === '9') && ( + {(value === '0' || value === '9') && (

)} - { (value === '0' || value === '10') && ( + {(value === '0' || value === '10') && (

)} + {(value === '0' || value === '11') && ( +
+
+ +
+ )}
diff --git a/src/App/examples/Example11/Example11.jsx b/src/App/examples/Example11/Example11.jsx new file mode 100644 index 00000000..6f4c1ab6 --- /dev/null +++ b/src/App/examples/Example11/Example11.jsx @@ -0,0 +1,135 @@ +import React from 'react'; +import { + ButtonBack, + ButtonFirst, + ButtonLast, + ButtonNext, + CarouselProvider, + DotGroup, + Image, + Slide, + Slider, +} from '../../..'; + +import s from '../../style.scss'; + +function eventLogger(ev) { + // eslint-disable-next-line no-console + console.log(ev.type, ev.target); +} + +export default () => ( + +

Carousel with custom event handlers.

+

+ Simple carousel with custom event handlers attachet to the + {' '} + <Slider /> + {' '} + component's + {' '} + trayProps + {' '} +property. Open your browser devloper tools and look at + the console log, then manipulate the carousel. +

+ + + + + + + + + + + + + + + + + + + + + First + Back + Next + Last + +
+); diff --git a/src/App/examples/Example11/index.js b/src/App/examples/Example11/index.js new file mode 100644 index 00000000..4100adea --- /dev/null +++ b/src/App/examples/Example11/index.js @@ -0,0 +1,3 @@ +import Example11 from './Example11'; + +export default Example11; diff --git a/src/App/examples/index.js b/src/App/examples/index.js index 29184520..a60b3797 100644 --- a/src/App/examples/index.js +++ b/src/App/examples/index.js @@ -8,3 +8,4 @@ export { default as Example7 } from './Example7'; export { default as Example8 } from './Example8'; export { default as Example9 } from './Example9'; export { default as Example10 } from './Example10'; +export { default as Example11 } from './Example11'; diff --git a/src/Slider/Slider.jsx b/src/Slider/Slider.jsx index b4481c40..13e1267e 100644 --- a/src/Slider/Slider.jsx +++ b/src/Slider/Slider.jsx @@ -40,7 +40,17 @@ const Slider = class Slider extends React.Component { tabIndex: PropTypes.number, totalSlides: PropTypes.number.isRequired, touchEnabled: PropTypes.bool.isRequired, - trayProps: PropTypes.shape({}), + trayProps: PropTypes.shape({ + className: PropTypes.string, + onClickCapture: PropTypes.func, + onMouseDown: PropTypes.func, + onTouchCancel: PropTypes.func, + onTouchEnd: PropTypes.func, + onTouchMove: PropTypes.func, + onTouchStart: PropTypes.func, + ref: PropTypes.shape({}), + style: PropTypes.string, + }), trayTag: PropTypes.string, visibleSlides: PropTypes.number, } @@ -157,7 +167,12 @@ const Slider = class Slider extends React.Component { // 6) mouseup // 7) click - onDragStart({ + getSliderRef(el) { + this.sliderTrayElement = el; + } + + + fakeOnDragStart({ screenX, screenY, touchDrag = false, @@ -183,7 +198,7 @@ const Slider = class Slider extends React.Component { }); } - onDragMove(screenX, screenY) { + fakeOnDragMove(screenX, screenY) { this.moveTimer = window.requestAnimationFrame.call(window, () => { this.setState(state => ({ deltaX: screenX - state.startX, @@ -192,7 +207,7 @@ const Slider = class Slider extends React.Component { }); } - onDragEnd() { + fakeOnDragEnd() { window.cancelAnimationFrame.call(window, this.moveTimer); this.computeCurrentSlide(); @@ -213,10 +228,6 @@ const Slider = class Slider extends React.Component { this.isDocumentScrolling = this.props.lockOnWindowScroll ? false : null; } - getSliderRef(el) { - this.sliderTrayElement = el; - } - callCallback(propName, ev) { const { trayProps } = this.props; if (trayProps && typeof trayProps[propName] === 'function') { @@ -231,7 +242,7 @@ const Slider = class Slider extends React.Component { return; } ev.preventDefault(); - this.onDragStart({ + this.fakeOnDragStart({ screenX: ev.screenX, screenY: ev.screenY, mouseDrag: true, @@ -243,13 +254,13 @@ const Slider = class Slider extends React.Component { if (!this.state.isBeingMouseDragged) return; this.setState({ cancelNextClick: true }); ev.preventDefault(); - this.onDragMove(ev.screenX, ev.screenY); + this.fakeOnDragMove(ev.screenX, ev.screenY); } handleOnMouseUp(ev) { if (!this.state.isBeingMouseDragged) return; ev.preventDefault(); - this.onDragEnd(); + this.fakeOnDragEnd(); } handleOnClickCapture(ev) { @@ -257,7 +268,6 @@ const Slider = class Slider extends React.Component { this.callCallback('onClickCapture', ev); return; } - ev.stopPropagation(); ev.preventDefault(); this.setState({ cancelNextClick: false }); this.callCallback('onClickCapture', ev); @@ -271,11 +281,10 @@ const Slider = class Slider extends React.Component { if (this.props.orientation === 'vertical') { ev.preventDefault(); - ev.stopPropagation(); } const touch = ev.targetTouches[0]; - this.onDragStart({ + this.fakeOnDragStart({ screenX: touch.screenX, screenY: touch.screenY, touchDrag: true, @@ -304,7 +313,7 @@ const Slider = class Slider extends React.Component { window.cancelAnimationFrame.call(window, this.moveTimer); const touch = ev.targetTouches[0]; - this.onDragMove(touch.screenX, touch.screenY); + this.fakeOnDragMove(touch.screenX, touch.screenY); this.callCallback('onTouchMove', ev); } @@ -332,7 +341,6 @@ const Slider = class Slider extends React.Component { // left arrow if (keyCode === 37) { ev.preventDefault(); - ev.stopPropagation(); this.focus(); newStoreState.currentSlide = Math.max(0, currentSlide - 1); newStoreState.isPlaying = false; @@ -341,7 +349,6 @@ const Slider = class Slider extends React.Component { // right arrow if (keyCode === 39) { ev.preventDefault(); - ev.stopPropagation(); this.focus(); newStoreState.currentSlide = Math.min( totalSlides - visibleSlides, @@ -457,7 +464,7 @@ const Slider = class Slider extends React.Component { endTouchMove() { if (!this.props.touchEnabled) return; - this.onDragEnd(); + this.fakeOnDragEnd(); } renderMasterSpinner() { @@ -575,8 +582,6 @@ const Slider = class Slider extends React.Component { const newTabIndex = tabIndex !== null ? tabIndex : 0; - // console.log(Object.assign({}, trayStyle), new Date()); - // remove `dragStep` and `step` from Slider div, since it isn't a valid html attribute const { dragStep, step, ...rest } = props; diff --git a/src/Slider/__tests__/Slider.test.jsx b/src/Slider/__tests__/Slider.test.jsx index e762aa03..0fcec388 100644 --- a/src/Slider/__tests__/Slider.test.jsx +++ b/src/Slider/__tests__/Slider.test.jsx @@ -238,7 +238,7 @@ describe('', () => { const ev = { preventDefault: jest.fn(), }; - instance.onDragMove = jest.fn(); + instance.fakeOnDragMove = jest.fn(); instance.setState = jest.fn(); instance.handleOnMouseMove(ev); expect(ev.preventDefault).toHaveBeenCalledTimes(1); @@ -249,13 +249,13 @@ describe('', () => { const ev = { preventDefault: jest.fn(), }; - instance.onDragMove = jest.fn(); + instance.fakeOnDragMove = jest.fn(); instance.setState = jest.fn(); instance.handleOnMouseMove(ev); expect(instance.setState).toHaveBeenCalledTimes(1); expect(instance.setState).toHaveBeenCalledWith({ cancelNextClick: true }); }); - it('should call onDragMove and pass it the event screen x and y values', () => { + it('should call fakeOnDragMove and pass it the event screen x and y values', () => { const instance = new Slider({}); instance.state.isBeingMouseDragged = true; const ev = { @@ -263,11 +263,11 @@ describe('', () => { screenX: 1, screenY: 2, }; - instance.onDragMove = jest.fn(); + instance.fakeOnDragMove = jest.fn(); instance.setState = jest.fn(); instance.handleOnMouseMove(ev); - expect(instance.onDragMove).toHaveBeenCalledTimes(1); - expect(instance.onDragMove).toHaveBeenCalledWith(1, 2); + expect(instance.fakeOnDragMove).toHaveBeenCalledTimes(1); + expect(instance.fakeOnDragMove).toHaveBeenCalledWith(1, 2); }); }); describe('onMouseUp()', () => { @@ -282,11 +282,11 @@ describe('', () => { const ev = { preventDefault: jest.fn(), }; - instance.onDragEnd = jest.fn(); + instance.fakeOnDragEnd = jest.fn(); instance.handleOnMouseUp(ev); expect(ev.preventDefault).toHaveBeenCalledTimes(1); }); - it('should call onDragEnd and pass it the event screen x and y values', () => { + it('should call fakeOnDragEnd and pass it the event screen x and y values', () => { const instance = new Slider({}); instance.state.isBeingMouseDragged = true; const ev = { @@ -294,9 +294,9 @@ describe('', () => { screenX: 1, screenY: 2, }; - instance.onDragEnd = jest.fn(); + instance.fakeOnDragEnd = jest.fn(); instance.handleOnMouseUp(ev); - expect(instance.onDragEnd).toHaveBeenCalledTimes(1); + expect(instance.fakeOnDragEnd).toHaveBeenCalledTimes(1); }); }); describe('handleOnClickCapture()', () => { @@ -304,7 +304,7 @@ describe('', () => { const instance = new Slider({}); expect(instance.handleOnClickCapture()).toBe(undefined); }); - it('should call preventDefault, stopPropagation and set cancelNextClick to false', () => { + it('should call preventDefault and set cancelNextClick to false', () => { const instance = new Slider({}); instance.state.cancelNextClick = true; instance.setState = jest.fn(); @@ -315,7 +315,7 @@ describe('', () => { instance.handleOnClickCapture(ev); expect(instance.setState).toHaveBeenCalledWith({ cancelNextClick: false }); expect(ev.preventDefault).toHaveBeenCalledTimes(1); - expect(ev.stopPropagation).toHaveBeenCalledTimes(1); + // expect(ev.stopPropagation).toHaveBeenCalledTimes(1); }); }); describe('renderMasterSpinner()', () => { @@ -435,7 +435,7 @@ describe('', () => { expect(instance.originalOverflow).toBe('scroll'); expect(global.document.documentElement.style.overflow).toBe('hidden'); expect(touch100.preventDefault).toHaveBeenCalledTimes(1); - expect(touch100.stopPropagation).toHaveBeenCalledTimes(1); + // expect(touch100.stopPropagation).toHaveBeenCalledTimes(1); global.document.documentElement.style.overflow = ''; });