diff --git a/README.md b/README.md index 11248ee..fd053ba 100644 --- a/README.md +++ b/README.md @@ -33,5 +33,5 @@ ReactDOM.render( ``` # License -Distributed under the MIT License. See `LICENSE` for more information. +Distributed under the MIT License. See `LICENSE` for more information. diff --git a/__tests__/helpers.spec.tsx b/__tests__/helpers.spec.tsx index eae377d..a111fdf 100644 --- a/__tests__/helpers.spec.tsx +++ b/__tests__/helpers.spec.tsx @@ -2,6 +2,7 @@ import React, { MouseEvent, TouchEvent } from 'react'; import * as helpers from '../src/helpers'; import { carouselItemNodes } from './__fixtures__/nodes'; import { SlideDirection } from '../src/types/carousel'; +import { getOuterWidth } from '../src/helpers'; describe('helpers', () => { it('should return to head of circular items list', async () => { @@ -67,4 +68,13 @@ describe('helpers', () => { expect(result).toEqual(pageX); }); + + it('should return width of element', async () => { + const width = 30; + const element = document.createElement('div'); + Object.defineProperty(element, 'offsetWidth', { value: width }); + const result = getOuterWidth(element); + + expect(result).toEqual(width); + }); }); diff --git a/jest.config.js b/jest.config.js index 69e6c47..3524023 100644 --- a/jest.config.js +++ b/jest.config.js @@ -10,6 +10,7 @@ module.exports = { statements: 100, }, }, + coveragePathIgnorePatterns: ['/src/components/scrolling-carousel'], testPathIgnorePatterns: ['/__tests__/__fixtures__/'], transform: { '^.+\\.tsx?$': 'ts-jest', diff --git a/src/components/carousel/index.tsx b/src/components/carousel/index.tsx index 1c8b40a..b0610a5 100644 --- a/src/components/carousel/index.tsx +++ b/src/components/carousel/index.tsx @@ -51,7 +51,9 @@ export const Carousel: FunctionComponent = (userProps: CarouselPr isSliding: true, }); setCurrent(next); - setShowArrow(getShowArrow(props.children.length, props.show, props.infinite, next)); + setShowArrow( + getShowArrow(props.children.length, props.show, props.infinite, next), + ); setTimeout(() => { if (props.infinite) { setItems(cleanItems(rotated, slide, direction)); diff --git a/src/components/scrolling-carousel/index.tsx b/src/components/scrolling-carousel/index.tsx new file mode 100644 index 0000000..3eb819f --- /dev/null +++ b/src/components/scrolling-carousel/index.tsx @@ -0,0 +1,155 @@ +import React, { + FunctionComponent, + MouseEvent, + useState, + useRef, + useCallback, +} from 'react'; +import { Item, SlideDirection } from '../../types/carousel'; +import styles from '../../styles/slider/styles.module.css'; +import { getOuterWidth } from '../../helpers'; + +export const ScrollingCarousel: FunctionComponent = ({ + children, + className, +}: SliderProps) => { + const slider = useRef(null); + const [isDown, setIsDown] = useState(false); + const [position, setPosition] = useState({ + startX: 0, + scrollLeft: 0, + }); + + const showArrows = (): Arrows => { + const sliderElement = slider.current; + return { + left: !!sliderElement && sliderElement.scrollLeft > 0, + right: + !!sliderElement && + sliderElement.scrollWidth > + sliderElement.scrollLeft + sliderElement.offsetWidth, + }; + }; + const [showArrow, setShowArrow] = useState(showArrows()); + + const onScroll = (_: Event) => { + setShowArrow(showArrows()); + }; + + const ref = useCallback( + (node) => { + if (node !== null) { + Object.defineProperty(slider, 'current', { value: node }); + setShowArrow(showArrows()); + node.addEventListener('scroll', onScroll); + } + }, + [slider], + ); + + const mouseDown = (e: MouseEvent) => { + setIsDown(true); + setPosition({ + startX: e.pageX - slider.current!.offsetLeft, + scrollLeft: slider.current!.scrollLeft, + }); + }; + + const mouseUp = (_: MouseEvent) => { + setIsDown(false); + setShowArrow(showArrows()); + }; + + const mouseMove = (e: MouseEvent) => { + if (!isDown) return; + e.preventDefault(); + + const eventPosition = e.pageX - slider.current!.offsetLeft; + const slide = eventPosition - position.startX; + + slider.current!.scrollLeft = position.scrollLeft - slide; + }; + + const calculateSlideAmount = (direction: SlideDirection): number => { + const _slider = slider.current!; + const currentView = + direction === SlideDirection.Left + ? _slider.scrollLeft + _slider.offsetWidth + : _slider.scrollLeft; + + const childNodes = Array.from(_slider.children) as HTMLElement[]; + let nodeWidthSum = 0; + for (const node of childNodes) { + const nodeWidth = getOuterWidth(node); + nodeWidthSum += nodeWidth; + + if (nodeWidthSum >= currentView) { + const showingPart = + direction === SlideDirection.Left + ? nodeWidthSum - currentView + : nodeWidth; + + return (_slider.offsetWidth - showingPart) * direction; + } + } + + return _slider.offsetWidth; + }; + + const slide = (direction: SlideDirection) => { + const slideAmount = calculateSlideAmount(direction); + const start = slider.current!.scrollLeft; + smoothHorizontalScroll(500, slideAmount, start); + }; + + const smoothHorizontalScroll = (time: number, amount: number, start: number) => { + let curTime = 0; + for (let scrollCounter = 0; curTime <= time; scrollCounter++) { + window.setTimeout( + smoothHorizontalScrollBehavior, + curTime, + (scrollCounter * amount) / 100 + start, + ); + curTime += time / 100; + } + }; + + const smoothHorizontalScrollBehavior = (amount: number) => { + slider.current!.scrollLeft = amount; + }; + + return ( +
+ {showArrow.left && ( +
+
+ )} + {showArrow.right && ( +
+
+ )} +
+ {children} +
+
+ ); +}; + +export interface SliderProps { + children: Item[]; + className?: string; +} + +export type Arrows = { + left: boolean; + right: boolean; +}; diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 0a2fc28..9e109e7 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -133,3 +133,13 @@ export function getPageX(e: TouchEvent | MouseEvent): number { } return 0; } + +export function getOuterWidth(el: HTMLElement) { + const style = getComputedStyle(el); + + return ( + el.offsetWidth + + (parseInt(style.marginLeft, 10) || 0) + + (parseInt(style.marginRight, 10) || 0) + ); +} diff --git a/src/index.ts b/src/index.ts index b3d1201..75f0c05 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ import { Carousel } from './components/carousel'; +import { ScrollingCarousel } from './components/scrolling-carousel'; -export { Carousel }; +export { Carousel, ScrollingCarousel }; diff --git a/src/styles/slider/styles.module.css b/src/styles/slider/styles.module.css new file mode 100644 index 0000000..ffd21e5 --- /dev/null +++ b/src/styles/slider/styles.module.css @@ -0,0 +1,20 @@ +.sliderBase { + width: 100%; + position: relative; +} + +.slider { + display: flex; + overflow-x: auto; + scrollbar-width: none; /* Firefox 64 */ + -ms-overflow-style: none; /* Internet Explorer 11 */ +} + +.slider::-webkit-scrollbar { + /** WebKit */ + display: none; +} + +.slider > * { + flex: 0 0 auto; +} diff --git a/src/styles/slider/styles.module.css.d.ts b/src/styles/slider/styles.module.css.d.ts new file mode 100644 index 0000000..beb1d0c --- /dev/null +++ b/src/styles/slider/styles.module.css.d.ts @@ -0,0 +1,8 @@ +export const sliderBase: string; +export const slider: string; +interface Namespace { + sliderBase: string; + slider: string; +} +declare const stylesModule: Namespace; +export default stylesModule; diff --git a/website/docs/scrollingCarousel.md b/website/docs/scrollingCarousel.md new file mode 100644 index 0000000..f1369a2 --- /dev/null +++ b/website/docs/scrollingCarousel.md @@ -0,0 +1,49 @@ +--- +id: scrolling-carousel +title: Scrolling carousel +--- + +Scrollable carousel like google's web component `g-scrolling-carousel` + +import {ScrollingCarousel} from '@trendyol-js/react-carousel'; +const slideData = [{"text":"skyline","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAADAQEBAAAAAAAAAAAAAAAEBQcDAgH/xAAvEAACAQIEAwUIAwAAAAAAAAABAgMEEQAFEiETMVFBYXGBkRQjMoKxssLwBiJC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwQC/8QAIREAAQQBAwUAAAAAAAAAAAAAAQACAxEEEjHwBSFBYYH/2gAMAwEAAhEDEQA/AFYz3KA0UbVjI8jBNSxEqvifHp64fSURSxNSQOw8K3nzxNeLC2oVWX00hIKkoNPnZSADftAxSsnzWlzaiHBbdAFbWu6+O+KHYWrYArAmr0s56CopYjOt5Y99TD4k77dMc+0RG2mzX5Ww5pEWJSEqKhiu22kW9RgWfK6KpqONA1TTSsukknWhNulhbpsbd2JZuly1qaEzMsbFSmanqYT76ETqP9xHS4HhyPpgzJp3o5hPHUMkc4ZCrf1J+K3zCw27LnffDhoL722xjPlUVQtm1qNWqysQL9bcjhhkPBF+CiMYoo6k/mBWniiMBZ4xpNpgS3PckW/RgOXO5plVlnqujcSoCHbbkFP1GMhlNTGvuK1UW/L2WI/jjw5ZVstjmcy90KLF9gGKDlM71fPqMRlf/9k="},{"text":"r35","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAEBQYHAv/EACwQAAEDAwEFCAMBAAAAAAAAAAECAwQABRESBiExQXETIiNRYZGhsRRSwQf/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAwDAQACEQMRAD8A2VaCsUG/AyCpakpSOJJwKVzNvbLGcCEOaxzUTgDpxzUhdtqjc5ZEO4PvKUT2TaYoV2Y8gAoZ64JqyJar5DlrYJbdu0BC/wBVyUA/dBybaiU2XIrzT6cZy0sK+qxiVZp866POsrdkvBRW4oN6dIHHmcdKfWa2SC2gvSWoTqDlK0vHI6ADI96uGpWfcIxltIQmdhWB4jaUg53b+4Dkdafx7ibcw0xFeVokK0vAtJBCfQjfR7+wDBV4E+U0nOcFWr7rhH+fpAwq5PHcRkoSdx9Du+KCZRdl/kx57bim21btGvuhJz3ccgBjkcnJzniSm5F86ITMh5fmngf581UW3YW1wUpS6pcjScjtDu9qesx4sROlhpCQPIUH/9k="},{"text":"custom","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAEAAwEAAAAAAAAAAAAAAAAGAwQHBf/EADAQAAIBAwIEBQALAQAAAAAAAAECAwQFEQAhBhITMRQiQVFhFSMyM0JEcZGhwdEH/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQIA/8QAGxEAAgMAAwAAAAAAAAAAAAAAAAECEUEDEhP/2gAMAwEAAhEDEQA/ANQt6RNU1xVdhMoGO33aH+9RXF+ndqWUo5iWlnyApKklosZAB27742Gh9tqfpS0LPLItPJ0o35ESIiM8qqcc+cAAex+CdR1dTXMI6mC6VPXkikmTp0S5yWww5S/qFGBn0/DqHyPC1BaduE2yO2LT0ppopPpJX6YAjblNT5crsfsn+NXaykJ4ioZgBhaKpXOd93g/zQl2miqqrxslS0KQRMB4bBk88bEK2dmG+2TsD231yOIuJpKbwdRSTVFPP4aKR2EhPkLHC7nYZjGRv7HT6VguKwpcNSUFZbZ6y/VCUlppWSEsFDyluXChVAyNiNwD6+2ldpb/AJzdZ6e1Ut0uck0mRCplniztnl5gqj07E7n50YquGLZV03hqaaWjgZldo4wCGdQwDEnfOGPrjtqnQ8FrbbhTVtDdwJaeVZU6lPzeZSCOzDTYdGMrlYOFrPAtc5utOVqIUhU3Au0khcAEoSRyjuc52B21mt1eOS+wz0a1G8jo/M6yGRRy/WHChRk74xjykke6Op4cFZM8lwuhfM8k6JBF0wrvyE4yzbAopAGMfptqektlrtamSlVpKo/mJn5mA+PY/P7b76E6VXZlBn//2Q=="},{"text":"liberty walk","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAADBAYFAv/EAC0QAAEDAgQEAwkAAAAAAAAAAAECAwQFEQASIWEGMUFREyJxFDJSYpGhwdHh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAQMEAgD/xAAeEQACAQMFAAAAAAAAAAAAAAABAgAREyEDEjJBQv/aAAwDAQACEQMRAD8AsFsbYCuPtjYWztgK2tsa3QFJjqjbYmalw6uRJelPqCE2JUpOtx6bdsWrxabF3XEIHzKAwoZUFRIEyMT28VJ/OOajDMC1U4hKpxNDp8hEd91tLy+aQq+X1On72wm/WWZ1Of8AZaszDlJzJSHmiqx6EEWHbodxfEsvhSqJflyC5HdcdW6prxHFEgLI5nKToAPXlvgNN4PqzGjwp0keGEgLdeTbe4Av/TicWzyNZS13yI/Hg0hyOl6o1JIqK02eU2C4OeoClam/fp0tjmVTqDQKcHXZzknx0qUGn0hXlJ943vl25ddOeAq4RqJOZMano6+SU9f7g4TXwxXpMtblREZacqbFLxUUlObLpkHxK+uGnVToxC6D1ys//9k="},{"text":"wallpaper","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAaAAACAwEBAAAAAAAAAAAAAAAFBgMEBwIB/8QALBAAAgEDAwEGBgMAAAAAAAAAAQIDBBESAAUhMQYTIkFRcRRhkaHR8VJigf/EABYBAQEBAAAAAAAAAAAAAAAAAAIDBP/EABsRAQACAwEBAAAAAAAAAAAAAAEAAhIhQREi/9oADAMBAAIRAxEAPwDKYaeecXiiJW9siQAPPqffU7U0cSK0hkYsoZVxC34v1P0007rR10dUKXbqZJKwO6yzPGlxi1reIWt53At6aml7O7lFSyy7v8EC1sDmnN79ceOfl89aC1nsgtTkXkXb4ZFRjSqzAEu+cmIsb8A29uv+a8jr441kQU8NXGwZbgCHEnE5BV6EY8X/AJEe9+PYkWb4VKYlpLE965Kpb0A8R5/eu5uzxgpUSCCesldj4STghBtwo638uToPhbFdyoWtTMPmWV36uemDR1itFyoU1AUgeliR9tQbr2nqqs09NInfUcao5ja+OQHJNvMm/PtqzP2So5PFSVGH9XGQ/OgdbtG5wHuhTysitcGK7qT68A206p7uSCrGKg3umi7U0j1FOYacSCN42cNZHFgb+nIPtovX9swY0gSekVg8vfCFXOCC+FiSRcG/TWYypOkmMzEOoC4EG9h0FjohSbXXbg3jCwxHkkrj9vPoPpoO2LECf//Z"},{"text":"nismo","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAADAQEBAAAAAAAAAAAAAAADBQYHBAL/xAAqEAABBAAFAwIHAQAAAAAAAAABAgMEEQAFEiExBhNRQZEUIjJhgaGxB//EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAGER/9oADAMBAAIRAxEAPwAqYivGCJhqPpiiZyuQ6abjOna70ED3wF6FmQKmmcuX3K47qCoDzQVgEvwR8Y8mGfGFEuJ1u28SqBOCLNJbU3f6Jwy6dV1RNbpeWh1tCtJckI7WqjRpVjf70cA06R/0lnPM0cgTm2WCGi42806pSTRFg6kitjf4OCSeoe3KfVIzRiWlCCtKIqB20AXeo9w2fGw9efTDYqp0Na1sxUhS0FCqO1EUecHjzc0Ql5CkyHA+jQsuPWQnfYE3XOC5V70z1rPX1KWHgEtTUn5QskoOkqBvnbjcnnauMWzudqiUubNhM2B9bzd/0nGHIZmLcadaKmpAG60m62rbHS3lMl1ZcfecKibO+m/bER//2Q=="},{"text":"godzilla","img":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBgQFBwL/xAAsEAACAQIFAQcEAwAAAAAAAAABAgMEEQAFEiExYQYTIlGBkaEUMkJxI0FD/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwIB/8QAGxEAAgIDAQAAAAAAAAAAAAAAAAECERIyQQP/2gAMAwEAAhEDEQA/AIWVUWa0njRUZOfG+xxapOgD99EI9H5wynSPQ47y7tLTTQd3UUClebhr+uM+zzNJMzrtKPppi40IrbLfi/XDN0DGLkObdpcrWoiphKZDIyLrKC3i69Bb3HWx1qqWvoqerpphoqNZjjOzFVYi9vb9XtjNAIFO+oSBiFHkdsHy+YUFbC5P8ZCozHmMFvEVA5Nr+pxmRT80MOQuI2jYWJB4OL5I6dqerf6ZHNQSZABu5t/fXCLl1RJ9IwgnhWU/aTKLj0OA1NTmUjBnmMZQaQBokv15J3xll4EpKCKhhTvLGokH+ymMRm3ALWBPHGIQhqhWRxV8EwQfcAASAeLHAJ6upmCPMkSvGPxhCaz5kAAHn4xYp2rrYY0iENNaInT3cdgDvuPj2xLvgsIwe7o//9k="},{"text":"blue","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR7vhDBHGcYfgGumwP_JdDsWdbmRBJrO822ayjYBWnUeOpg4mvv5HBrUCHh&s"},{"text":"r32","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTcedysoUHEN5Pu8C5gy1_H_-fwbYUbZTqHhLblNaFvYGMlDVdQ6r0d3T5n&s"},{"text":"gold","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRVUpJPnUV2JjON_U8j_GsNfpzB1TE_1YSPTFB4ElJX3-e7BPB_Dz0WJLvZ&s"},{"text":"white","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQawL7bAfO-DV0rY3XlWnkm2cJcAAB9JQsZw4P9k8R0RElWDOhPyJ06WEMO&s"},{"text":"nissan","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-3a4aW0nL4gsFvceXOcqfFT5qlrOwHU0DySevbEo8-45XzIJJxu4x5ZeB&s"},{"text":"modified","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXsPphsOHUfc10c5bCr6VkCDK2d0YYYc7PkjiA527xIMsJZw7x5qqt3GZZ&s"},{"text":"red","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSoJnGchkU3zwrTdq4WbFSjd5E-ehy9gtEaaxiuOE9-LHZnh8PYhANsp3D_&s"},{"text":"rocket bunny","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYefgcSyvUOC_qcNY9yZV7AX8yPaDlnZ3BU5eH794jT3AQH6AiTVXPDl5S&s"},{"text":"r33","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRA2ZYkl0giWGtaNXKwr2z8HbJszowxKEQTDATCJMLvJ7kpGsRl9dr8CBnD&s"},{"text":"chrome","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFtKFD8Oalc6HqSrkWVMtPTitLO0mXpV9ofKYxgusg8zjfZdlaA4wX3KVv&s"},{"text":"car","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdTsdEjLHkQIYipiaZcLUP9LG2GsplKl7MQSuawbDbOgtQ_5ygK46i_3xc&s"},{"text":"cool","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfhHP8XoQ0X3eL4J_Xy0BJ0pnvrkINkKR78N6yhfXa7eWXn3UBh1ZzMep8&s"},{"text":"widebody","img":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlGGm-Hh5so6PtScyr7lXrB9V13dFr7mtMJC5YlO9aaDPHfPQNRvzsFPK_&s"}]; + +
+ +{ + slideData.map((d, i) => +
+ + {d.text} +
+ ) +} +
+
+ +```jsx + + + + + +, +``` diff --git a/website/docs/scrollingCarouselApi.md b/website/docs/scrollingCarouselApi.md new file mode 100644 index 0000000..e75eb9b --- /dev/null +++ b/website/docs/scrollingCarouselApi.md @@ -0,0 +1,17 @@ +--- +id: scrolling-carousel-api +title: Scrolling Carousel +--- + +Scrollable carousel like google's web component `g-scrolling-carousel` + +```jsx + +``` + +### Props + +| Name | type | required | default | descripiton | +| --------- | :----: | -------: | ------: | -------------------------------------------: | +| children | Node[] | true | [] | Child items that will be wrapped by carousel | +| className | string | false | "" | same as react's className property | diff --git a/website/sidebars.js b/website/sidebars.js index 8863903..a7bde2a 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -1,7 +1,7 @@ module.exports = { someSidebar: { Docusaurus: ['installation', 'usage'], - API: ['carousel'], - Examples: ['infinity', 'swipible'], + API: ['carousel', 'scrolling-carousel-api'], + Examples: ['infinity', 'swipible', 'scrolling-carousel'], }, }; diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 229fa1b..cccca66 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -48,3 +48,64 @@ .exampleCarousel1 div:first-child { text-align: center; } + +.scrolling-carousel-example1-container { + width: 660px; +} + +.scrolling-carousel-example1 > [data-arrow='left'] { + background: linear-gradient(90deg, #fff 10%, rgba(255, 255, 255, 0)); + top: 0px; + left: 0; + opacity: 1; + height: 42px; + width: 88px; + position: absolute; + cursor: pointer; + bottom: 0; + margin-bottom: auto; + margin-top: auto; +} +.scrolling-carousel-example1 > [data-arrow='left'] > button { + background: url('https://cdn.dsmcdn.com/web/production/slick-arrow.svg') no-repeat + center; + transform: rotateZ(180deg) scale(0.5); + height: 40px; + left: -13px; + border: none; + outline: none; + cursor: pointer; +} + +.scrolling-carousel-example1 > [data-arrow='right'] { + background: linear-gradient(270deg, #fff 10%, rgba(255, 255, 255, 0)); + right: 0; + opacity: 1; + height: 42px; + width: 88px; + position: absolute; + cursor: pointer; + top: 0; + bottom: 0; + margin-bottom: auto; + margin-top: auto; +} +.scrolling-carousel-example1 > [data-arrow='right'] > button { + background: url('https://cdn.dsmcdn.com/web/production/slick-arrow.svg') no-repeat; + height: 40px; + transform: scale(0.5); + border: none; + outline: none; + position: absolute; + right: -16px; + cursor: pointer; +} + +[data-theme='dark'] .scrolling-carousel-example1 > [data-arrow='right'] { + background: linear-gradient(270deg, #121212 10%, rgba(255, 255, 255, 0)); +} + +[data-theme='dark'] .scrolling-carousel-example1 > [data-arrow='left'] { + background: linear-gradient(90deg, #121212 10%, rgba(255, 255, 255, 0)); + top: 0px; +} diff --git a/website/src/pages/index.js b/website/src/pages/index.js index 1d49ffb..f8b20b2 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -4,10 +4,112 @@ import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl from '@docusaurus/useBaseUrl'; -import { Carousel } from '@trendyol-js/react-carousel'; +import { Carousel, ScrollingCarousel } from '@trendyol-js/react-carousel'; import styles from './styles.module.css'; import { Redirect } from '@docusaurus/router'; +const slideData = [ + { + text: 'skyline', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAADAQEBAAAAAAAAAAAAAAAEBQcDAgH/xAAvEAACAQIEAwUIAwAAAAAAAAABAgMEEQAFEiETMVFBYXGBkRQjMoKxssLwBiJC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwQC/8QAIREAAQQBAwUAAAAAAAAAAAAAAQACAxEEEjHwBSFBYYH/2gAMAwEAAhEDEQA/AFYz3KA0UbVjI8jBNSxEqvifHp64fSURSxNSQOw8K3nzxNeLC2oVWX00hIKkoNPnZSADftAxSsnzWlzaiHBbdAFbWu6+O+KHYWrYArAmr0s56CopYjOt5Y99TD4k77dMc+0RG2mzX5Ww5pEWJSEqKhiu22kW9RgWfK6KpqONA1TTSsukknWhNulhbpsbd2JZuly1qaEzMsbFSmanqYT76ETqP9xHS4HhyPpgzJp3o5hPHUMkc4ZCrf1J+K3zCw27LnffDhoL722xjPlUVQtm1qNWqysQL9bcjhhkPBF+CiMYoo6k/mBWniiMBZ4xpNpgS3PckW/RgOXO5plVlnqujcSoCHbbkFP1GMhlNTGvuK1UW/L2WI/jjw5ZVstjmcy90KLF9gGKDlM71fPqMRlf/9k=', + }, + { + text: 'r35', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAEBQYHAv/EACwQAAEDAwEFCAMBAAAAAAAAAAECAwQABRESBiExQXETIiNRYZGhsRRSwQf/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAwDAQACEQMRAD8A2VaCsUG/AyCpakpSOJJwKVzNvbLGcCEOaxzUTgDpxzUhdtqjc5ZEO4PvKUT2TaYoV2Y8gAoZ64JqyJar5DlrYJbdu0BC/wBVyUA/dBybaiU2XIrzT6cZy0sK+qxiVZp866POsrdkvBRW4oN6dIHHmcdKfWa2SC2gvSWoTqDlK0vHI6ADI96uGpWfcIxltIQmdhWB4jaUg53b+4Dkdafx7ibcw0xFeVokK0vAtJBCfQjfR7+wDBV4E+U0nOcFWr7rhH+fpAwq5PHcRkoSdx9Du+KCZRdl/kx57bim21btGvuhJz3ccgBjkcnJzniSm5F86ITMh5fmngf581UW3YW1wUpS6pcjScjtDu9qesx4sROlhpCQPIUH/9k=', + }, + { + text: 'custom', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAEAAwEAAAAAAAAAAAAAAAAGAwQHBf/EADAQAAIBAwIEBQALAQAAAAAAAAECAwQFEQAhBhITMRQiQVFhFSMyM0JEcZGhwdEH/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQIA/8QAGxEAAgMAAwAAAAAAAAAAAAAAAAECEUEDEhP/2gAMAwEAAhEDEQA/ANQt6RNU1xVdhMoGO33aH+9RXF+ndqWUo5iWlnyApKklosZAB27742Gh9tqfpS0LPLItPJ0o35ESIiM8qqcc+cAAex+CdR1dTXMI6mC6VPXkikmTp0S5yWww5S/qFGBn0/DqHyPC1BaduE2yO2LT0ppopPpJX6YAjblNT5crsfsn+NXaykJ4ioZgBhaKpXOd93g/zQl2miqqrxslS0KQRMB4bBk88bEK2dmG+2TsD231yOIuJpKbwdRSTVFPP4aKR2EhPkLHC7nYZjGRv7HT6VguKwpcNSUFZbZ6y/VCUlppWSEsFDyluXChVAyNiNwD6+2ldpb/AJzdZ6e1Ut0uck0mRCplniztnl5gqj07E7n50YquGLZV03hqaaWjgZldo4wCGdQwDEnfOGPrjtqnQ8FrbbhTVtDdwJaeVZU6lPzeZSCOzDTYdGMrlYOFrPAtc5utOVqIUhU3Au0khcAEoSRyjuc52B21mt1eOS+wz0a1G8jo/M6yGRRy/WHChRk74xjykke6Op4cFZM8lwuhfM8k6JBF0wrvyE4yzbAopAGMfptqektlrtamSlVpKo/mJn5mA+PY/P7b76E6VXZlBn//2Q==', + }, + { + text: 'liberty walk', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAADBAYFAv/EAC0QAAEDAgQEAwkAAAAAAAAAAAECAwQFEQASIWEGMUFREyJxFDJSYpGhwdHh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAQMEAgD/xAAeEQACAQMFAAAAAAAAAAAAAAABAgAREyEDEjJBQv/aAAwDAQACEQMRAD8AsFsbYCuPtjYWztgK2tsa3QFJjqjbYmalw6uRJelPqCE2JUpOtx6bdsWrxabF3XEIHzKAwoZUFRIEyMT28VJ/OOajDMC1U4hKpxNDp8hEd91tLy+aQq+X1On72wm/WWZ1Of8AZaszDlJzJSHmiqx6EEWHbodxfEsvhSqJflyC5HdcdW6prxHFEgLI5nKToAPXlvgNN4PqzGjwp0keGEgLdeTbe4Av/TicWzyNZS13yI/Hg0hyOl6o1JIqK02eU2C4OeoClam/fp0tjmVTqDQKcHXZzknx0qUGn0hXlJ943vl25ddOeAq4RqJOZMano6+SU9f7g4TXwxXpMtblREZacqbFLxUUlObLpkHxK+uGnVToxC6D1ys//9k=', + }, + { + text: 'wallpaper', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAaAAACAwEBAAAAAAAAAAAAAAAFBgMEBwIB/8QALBAAAgEDAwEGBgMAAAAAAAAAAQIDBBESAAUhMQYTIkFRcRRhkaHR8VJigf/EABYBAQEBAAAAAAAAAAAAAAAAAAIDBP/EABsRAQACAwEBAAAAAAAAAAAAAAEAAhIhQREi/9oADAMBAAIRAxEAPwDKYaeecXiiJW9siQAPPqffU7U0cSK0hkYsoZVxC34v1P0007rR10dUKXbqZJKwO6yzPGlxi1reIWt53At6aml7O7lFSyy7v8EC1sDmnN79ceOfl89aC1nsgtTkXkXb4ZFRjSqzAEu+cmIsb8A29uv+a8jr441kQU8NXGwZbgCHEnE5BV6EY8X/AJEe9+PYkWb4VKYlpLE965Kpb0A8R5/eu5uzxgpUSCCesldj4STghBtwo638uToPhbFdyoWtTMPmWV36uemDR1itFyoU1AUgeliR9tQbr2nqqs09NInfUcao5ja+OQHJNvMm/PtqzP2So5PFSVGH9XGQ/OgdbtG5wHuhTysitcGK7qT68A206p7uSCrGKg3umi7U0j1FOYacSCN42cNZHFgb+nIPtovX9swY0gSekVg8vfCFXOCC+FiSRcG/TWYypOkmMzEOoC4EG9h0FjohSbXXbg3jCwxHkkrj9vPoPpoO2LECf//Z', + }, + { + text: 'nismo', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAADAQEBAAAAAAAAAAAAAAADBQYHBAL/xAAqEAABBAAFAwIHAQAAAAAAAAABAgMEEQAFEiExBhNRQZEUIjJhgaGxB//EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAGER/9oADAMBAAIRAxEAPwAqYivGCJhqPpiiZyuQ6abjOna70ED3wF6FmQKmmcuX3K47qCoDzQVgEvwR8Y8mGfGFEuJ1u28SqBOCLNJbU3f6Jwy6dV1RNbpeWh1tCtJckI7WqjRpVjf70cA06R/0lnPM0cgTm2WCGi42806pSTRFg6kitjf4OCSeoe3KfVIzRiWlCCtKIqB20AXeo9w2fGw9efTDYqp0Na1sxUhS0FCqO1EUecHjzc0Ql5CkyHA+jQsuPWQnfYE3XOC5V70z1rPX1KWHgEtTUn5QskoOkqBvnbjcnnauMWzudqiUubNhM2B9bzd/0nGHIZmLcadaKmpAG60m62rbHS3lMl1ZcfecKibO+m/bER//2Q==', + }, + { + text: 'godzilla', + img: + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3N//AABEIACAAIAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBgQFBwL/xAAsEAACAQIFAQcEAwAAAAAAAAABAgMEEQAFEiExYQYTIlGBkaEUMkJxI0FD/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwIB/8QAGxEAAgIDAQAAAAAAAAAAAAAAAAECERIyQQP/2gAMAwEAAhEDEQA/AIWVUWa0njRUZOfG+xxapOgD99EI9H5wynSPQ47y7tLTTQd3UUClebhr+uM+zzNJMzrtKPppi40IrbLfi/XDN0DGLkObdpcrWoiphKZDIyLrKC3i69Bb3HWx1qqWvoqerpphoqNZjjOzFVYi9vb9XtjNAIFO+oSBiFHkdsHy+YUFbC5P8ZCozHmMFvEVA5Nr+pxmRT80MOQuI2jYWJB4OL5I6dqerf6ZHNQSZABu5t/fXCLl1RJ9IwgnhWU/aTKLj0OA1NTmUjBnmMZQaQBokv15J3xll4EpKCKhhTvLGokH+ymMRm3ALWBPHGIQhqhWRxV8EwQfcAASAeLHAJ6upmCPMkSvGPxhCaz5kAAHn4xYp2rrYY0iENNaInT3cdgDvuPj2xLvgsIwe7o//9k=', + }, + { + text: 'blue', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR7vhDBHGcYfgGumwP_JdDsWdbmRBJrO822ayjYBWnUeOpg4mvv5HBrUCHh&s', + }, + { + text: 'r32', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTcedysoUHEN5Pu8C5gy1_H_-fwbYUbZTqHhLblNaFvYGMlDVdQ6r0d3T5n&s', + }, + { + text: 'gold', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRVUpJPnUV2JjON_U8j_GsNfpzB1TE_1YSPTFB4ElJX3-e7BPB_Dz0WJLvZ&s', + }, + { + text: 'white', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQawL7bAfO-DV0rY3XlWnkm2cJcAAB9JQsZw4P9k8R0RElWDOhPyJ06WEMO&s', + }, + { + text: 'nissan', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-3a4aW0nL4gsFvceXOcqfFT5qlrOwHU0DySevbEo8-45XzIJJxu4x5ZeB&s', + }, + { + text: 'modified', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXsPphsOHUfc10c5bCr6VkCDK2d0YYYc7PkjiA527xIMsJZw7x5qqt3GZZ&s', + }, + { + text: 'red', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSoJnGchkU3zwrTdq4WbFSjd5E-ehy9gtEaaxiuOE9-LHZnh8PYhANsp3D_&s', + }, + { + text: 'rocket bunny', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYefgcSyvUOC_qcNY9yZV7AX8yPaDlnZ3BU5eH794jT3AQH6AiTVXPDl5S&s', + }, + { + text: 'r33', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRA2ZYkl0giWGtaNXKwr2z8HbJszowxKEQTDATCJMLvJ7kpGsRl9dr8CBnD&s', + }, + { + text: 'chrome', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFtKFD8Oalc6HqSrkWVMtPTitLO0mXpV9ofKYxgusg8zjfZdlaA4wX3KVv&s', + }, + { + text: 'car', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdTsdEjLHkQIYipiaZcLUP9LG2GsplKl7MQSuawbDbOgtQ_5ygK46i_3xc&s', + }, + { + text: 'cool', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfhHP8XoQ0X3eL4J_Xy0BJ0pnvrkINkKR78N6yhfXa7eWXn3UBh1ZzMep8&s', + }, + { + text: 'widebody', + img: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlGGm-Hh5so6PtScyr7lXrB9V13dFr7mtMJC5YlO9aaDPHfPQNRvzsFPK_&s', + }, +]; const features = [ { title: <>Easy to Use, @@ -92,6 +194,42 @@ function Home() {
+
+
+
+ + {slideData.map((d) => ( +
+ + {d.text} +
+ ))} +
+
+
+