diff --git a/packages/carousel/package.json b/packages/carousel/package.json
index ec430a7ed..8fae14e7e 100644
--- a/packages/carousel/package.json
+++ b/packages/carousel/package.json
@@ -29,6 +29,8 @@
"react"
],
"peerDependencies": {
+ "@crave/farmblocks-icon": "^1.0.0",
+ "@crave/farmblocks-button": "^10.0.5",
"prop-types": "^15.7.2",
"react": "^16.13.0",
"styled-components": "^5.2.2"
@@ -36,6 +38,7 @@
"dependencies": {
"@crave/farmblocks-image": "^3.2.6",
"@crave/farmblocks-text": "^3.6.5",
- "@crave/farmblocks-theme": "^1.10.1"
+ "@crave/farmblocks-theme": "^1.10.1",
+ "lodash.debounce": "^4.0.8"
}
}
diff --git a/packages/carousel/src/Carousel.js b/packages/carousel/src/Carousel.js
index 5f05d324e..38247080b 100644
--- a/packages/carousel/src/Carousel.js
+++ b/packages/carousel/src/Carousel.js
@@ -1,139 +1,190 @@
-import * as React from "react";
+import React, { useState, useEffect, useMemo } from "react";
import PropTypes from "prop-types";
-import Image from "@crave/farmblocks-image";
-import Text from "@crave/farmblocks-text";
-
-import Container from "./styledComponents/Carousel";
-
-const defaultConfig = {
- width: 656,
- height: 328,
- margin: 20,
- fontSize: 88,
- displayTime: 4,
- transitionTime: 2,
- border: "4px solid rgba(255, 255, 255, 0.56)",
- borderRadius: "16px",
-};
+import debounce from "lodash.debounce";
+import { SmChevronRight, SmChevronLeft } from "@crave/farmblocks-icon";
+import {
+ Container,
+ Wrapper,
+ Content,
+ ButtonContainer,
+ ArrowButton,
+} from "./styledComponents/Carousel";
+
+import Dots from "./components/Dots";
+import useTouch from "./hooks/useTouch";
+
+function Carousel(
+ {
+ qtyOfSlidesPerSet,
+ infiniteLoop,
+ children,
+ leftButtonProps,
+ rightButtonProps,
+ },
+ ...props
+) {
+ const CAROUSEL_DELAY = 300;
+
+ const displayNumber =
+ qtyOfSlidesPerSet < children.length ? qtyOfSlidesPerSet : children.length;
+
+ const [dotIndex, setDotIndex] = useState(0);
+ const [currentIndex, setCurrentIndex] = useState(
+ infiniteLoop && displayNumber < children.length ? displayNumber : 0,
+ );
+
+ useEffect(() => {
+ if (infiniteLoop) setCurrentIndex(dotIndex + displayNumber);
+ else if (currentIndex > children.length - qtyOfSlidesPerSet)
+ setCurrentIndex(children.length - qtyOfSlidesPerSet);
+ }, [displayNumber]);
+
+ const totalOfCards = children.length;
+ const isRepeating = useMemo(
+ () => infiniteLoop && children.length > displayNumber,
+ [children, infiniteLoop, displayNumber],
+ );
+
+ const [transitionEnabled, setTransitionEnabled] = useState(true);
+
+ useEffect(() => {
+ if (isRepeating) {
+ if (currentIndex === displayNumber || currentIndex === totalOfCards) {
+ setTransitionEnabled(true);
+ }
+ }
+ }, [currentIndex, isRepeating, displayNumber, totalOfCards]);
-class Carousel extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- activeItem: 0,
- };
+ function handleDotClick(index) {
+ setDotIndex(index);
+ setCurrentIndex(index + displayNumber);
}
- componentDidMount = () => {
- this.setInterval();
- };
+ const nextSlide = debounce(() => {
+ if (dotIndex < totalOfCards - 1) setDotIndex((prevState) => prevState + 1);
+ else if (isRepeating && dotIndex === totalOfCards - 1) {
+ setDotIndex(0);
+ }
+ const result = totalOfCards - displayNumber;
- componentDidUpdate(prevProps) {
- if (prevProps.imageSet !== this.props.imageSet) {
- this.setState({ activeItem: 0 });
- this.setInterval();
+ if (isRepeating || currentIndex < result) {
+ setCurrentIndex((prevState) => prevState + 1);
}
- }
+ }, CAROUSEL_DELAY);
- componentWillUnmount = () => {
- this.clearInterval();
- };
+ const prevSlide = debounce(() => {
+ if (dotIndex === 0) setDotIndex(totalOfCards - 1);
+ else setDotIndex((prevState) => prevState - 1);
- nextItem = () => {
- const activeItem = this.state.activeItem + 1; // eslint-disable-line
- if (activeItem === this.props.imageSet.length) {
- this.clearInterval();
- this.props.onEnd();
- return;
+ if (isRepeating || currentIndex > 0) {
+ setCurrentIndex((prevState) => prevState - 1);
}
- this.props.onChange(activeItem);
- this.setState({ activeItem });
- };
-
- setInterval = () => {
- if (this.transitionId) {
- return;
+ }, CAROUSEL_DELAY);
+
+ const { handleTouchStart, handleTouchMove } = useTouch({
+ nextSlide,
+ prevSlide,
+ });
+
+ function handleTransitionEnd() {
+ if (isRepeating) {
+ if (currentIndex === 0) {
+ setTransitionEnabled(false);
+ setCurrentIndex(totalOfCards);
+ } else if (currentIndex === totalOfCards + displayNumber) {
+ setTransitionEnabled(false);
+ setCurrentIndex(displayNumber);
+ }
}
+ }
- const { displayTime } = { ...defaultConfig, ...this.props.itemConfig };
-
- this.transitionId = window.setInterval(this.nextItem, displayTime * 1000);
- };
-
- clearInterval = () => {
- if (this.transitionId) {
- window.clearInterval(this.transitionId);
- delete this.transitionId;
+ const renderExtraPrev = useMemo(() => {
+ const output = [];
+ for (let index = 0; index < displayNumber; index += 1) {
+ output.push(children[totalOfCards - 1 - index]);
}
- };
-
- render() {
- const { imageSet, itemConfig } = this.props;
- const configProps = { ...defaultConfig, ...itemConfig };
-
- return (
-
-
- {imageSet.map((item, index) => {
- const isActive = index === this.state.activeItem;
- return (
- -
-
-
- {item.name}
-
-
- );
- })}
-
-
- );
- }
+ output.reverse();
+ return output;
+ }, [children, totalOfCards, displayNumber]);
+
+ const renderExtraNext = useMemo(() => {
+ const output = [];
+ for (let index = 0; index < displayNumber; index += 1) {
+ output.push(children[index]);
+ }
+ return output;
+ }, [children, displayNumber]);
+
+ const showLeftArrow = isRepeating || currentIndex > 0;
+ const showRightArrow =
+ isRepeating || currentIndex < totalOfCards - displayNumber;
+ const renderExtras = totalOfCards > displayNumber && isRepeating;
+
+ return (
+
+
+
+ {showLeftArrow && (
+ }
+ {...leftButtonProps}
+ onClick={(event) => {
+ prevSlide();
+ leftButtonProps?.onClick?.(event);
+ }}
+ />
+ )}
+
+
+ handleTouchStart(event)}
+ onTouchMove={(event) => handleTouchMove(event)}
+ >
+ {renderExtras && renderExtraPrev}
+ {children}
+ {renderExtras && renderExtraNext}
+
+
+
+ {showRightArrow && (
+ }
+ {...rightButtonProps}
+ onClick={(event) => {
+ nextSlide();
+ rightButtonProps?.onClick?.(event);
+ }}
+ />
+ )}
+
+
+ {isRepeating && (
+
+ )}
+
+ );
}
Carousel.propTypes = {
- imageSet: PropTypes.arrayOf(
- PropTypes.shape({ image: PropTypes.string, name: PropTypes.string }),
- ),
- onChange: PropTypes.func,
- onEnd: PropTypes.func,
- scale: PropTypes.bool,
- itemConfig: PropTypes.shape({
- width: PropTypes.number,
- height: PropTypes.number,
- margin: PropTypes.number,
- fontSize: PropTypes.number,
- displayTime: PropTypes.number,
- transitionTime: PropTypes.number,
- border: PropTypes.string,
- }),
- className: PropTypes.string,
+ children: PropTypes.node.isRequired,
+ qtyOfSlidesPerSet: PropTypes.number,
+ infiniteLoop: PropTypes.bool,
+ leftButtonProps: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
+ rightButtonProps: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
};
-
Carousel.defaultProps = {
- itemConfig: defaultConfig,
- scale: true,
- onChange: () => null,
- onEnd: () => null,
+ infiniteLoop: false,
+ qtyOfSlidesPerSet: 1,
};
export default Carousel;
diff --git a/packages/carousel/src/Carousel.story.js b/packages/carousel/src/Carousel.story.js
index 77b9d5d4c..b16a5a727 100644
--- a/packages/carousel/src/Carousel.story.js
+++ b/packages/carousel/src/Carousel.story.js
@@ -1,101 +1,159 @@
import React from "react";
import { storiesOf } from "@storybook/react";
-import { action } from "@storybook/addon-actions";
-import Carousel from ".";
+import { MdArrowLeft, MdArrowRight } from "@crave/farmblocks-icon";
+
+import { Carousel, Slide, useResizeWindow } from ".";
const imageSet = [
- {
- image: "https://picsum.photos/640/?image=1080",
- name: "Organic Pepper",
- },
- {
- image: "https://picsum.photos/640/?image=824",
- name: "Tomato",
- },
- {
- image: "https://picsum.photos/640/?image=889",
- name: "Grapefruit",
- },
- {
- image: "https://picsum.photos/640/?image=674",
- name: "Tomato",
- },
- {
- image: "https://picsum.photos/640/?image=292",
- name: "Tomato",
- },
- {
- image: "https://picsum.photos/640/?image=517",
- name: "Tomato",
- },
- {
- image: "https://picsum.photos/640/?image=627",
- name: "Tomato",
- },
- {
- image: "https://picsum.photos/640/?image=75",
- name: "Tomato",
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+];
+
+const leftButtonStyle = {
+ icon: ,
+ style: {
+ borderRadius: "0px",
},
- {
- image: "https://picsum.photos/640/?image=766",
- name: "Romaine Lettuce",
+};
+const rightButtonStyle = {
+ icon: ,
+ style: {
+ borderRadius: "0px",
},
-];
+};
storiesOf("Carousel", module)
- .add("1 photo", () => )
+ .add("1 photo", () => (
+
+
+ {imageSet[0]}
+
+
+ ))
- .add("1 photo with onEnd", () => (
-
+ .add("2 photos", () => (
+
+
+ {imageSet[0]}
+ {imageSet[1]}
+
+
))
- .add("2 photos", () => )
+ .add("all photos", () => {
+ const AllPhotos = () => {
+ const { displayNumber } = useResizeWindow({
+ breakpoints: [
+ {
+ width: 768,
+ slidesToShow: 1,
+ },
+ {
+ width: 1200,
+ slidesToShow: 3,
+ },
+ {
+ width: 1000,
+ slidesToShow: 2,
+ },
+ ],
+ qtyOfSlidesPerSet: 4,
+ });
+ return (
+
+
+ {imageSet.map((value) => (
+ {value}
+ ))}
+
+
+ );
+ };
- .add("all photos", () => )
- .add("no scale", () => )
+ return ;
+ })
+ .add("infinite loop", () => {
+ const InfinitLoop = () => {
+ const { displayNumber } = useResizeWindow({
+ breakpoints: [
+ {
+ width: 768,
+ slidesToShow: 1,
+ },
+ {
+ width: 1200,
+ slidesToShow: 2,
+ },
+ ],
+ infiniteLoop: true,
+ qtyOfSlidesPerSet: 3,
+ numberOfCards: imageSet.length,
+ dotIndex: 0,
+ });
+ return (
+
+
+ {imageSet.map((value) => (
+ {value}
+ ))}
+
+
+ );
+ };
- .add("all photos with onChange and onEnd", () => (
-
- ))
- .add("partial custom config", () => (
-
- ))
- .add("custom config", () => (
- ;
+ })
+ .add("Custom carousel", () => (
+
- ))
- .add("extended style", () => (
-
+ >
+
+ {imageSet.map((value) => (
+ {value}
+ ))}
+
+
));
diff --git a/packages/carousel/src/Carousel.test.js b/packages/carousel/src/Carousel.test.js
index 964876d56..7e0dbca2b 100644
--- a/packages/carousel/src/Carousel.test.js
+++ b/packages/carousel/src/Carousel.test.js
@@ -1,122 +1,89 @@
import React from "react";
-import renderer from "react-test-renderer";
-import { configure, mount } from "enzyme";
-import Adapter from "enzyme-adapter-react-16";
-import Carousel from ".";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
-describe("Carousel", () => {
- configure({ adapter: new Adapter() });
- jest.useFakeTimers();
-
- let clearIntervalSpy;
- let setIntervalSpy;
-
- beforeEach(() => {
- clearIntervalSpy = jest.spyOn(window, "clearInterval");
- setIntervalSpy = jest.spyOn(window, "setInterval");
- });
-
- afterEach(() => {
- clearTimeout.mockClear();
- clearIntervalSpy.mockClear();
- setIntervalSpy.mockClear();
- });
-
- test("active photo should change after displayTime", () => {
- const imageSet = [
- { image: "http://example.com/1.png", name: "1" },
- { image: "http://example.com/2.png", name: "2" },
- { image: "http://example.com/3.png", name: "3" },
- ];
- const component = renderer.create();
- const state = component.getInstance().state;
- expect(state.activeItem).toBe(0);
-
- jest.runOnlyPendingTimers();
-
- const finalState = component.getInstance().state;
- expect(finalState.activeItem).toBe(1);
- });
-
- test("onEnd event handler should be called after the last photo", () => {
- const imageSet = [
- { image: "http://example.com/1.png", name: "1" },
- { image: "http://example.com/2.png", name: "2" },
- { image: "http://example.com/3.png", name: "3" },
- ];
- const onEndMock = jest.fn();
- renderer.create();
- jest.runAllTimers();
-
- expect(onEndMock).toBeCalled();
- });
-
- test("setInterval should be called on mount and not called if there's a transitionId", () => {
- const imageSet = [{ image: "http://example.com/1.png", name: "1" }];
- const component = renderer.create();
+import { Carousel, Slide } from ".";
- const cb = component.getInstance().nextItem;
-
- expect(setIntervalSpy).toHaveBeenCalledWith(cb, 4000);
- expect(setIntervalSpy).toHaveBeenCalledTimes(1);
-
- // set interval should not be called again
- component.getInstance().setInterval();
- expect(setIntervalSpy).toHaveBeenCalledTimes(1);
+describe("Carousel", () => {
+ const imageSet = [
+ ,
+ ,
+ ,
+ ];
+
+ const makeSut = ({ ...props }) => {
+ render(
+
+ {imageSet.map((value) => (
+ {value}
+ ))}
+ ,
+ );
+ };
+
+ it("should render component without arrows and dots", () => {
+ const initialValues = {
+ qtyOfSlidesPerSet: imageSet.length,
+ };
+ makeSut(initialValues);
+
+ expect(screen.queryByTestId("left-arrow")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("right-arrow")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("dots-container")).not.toBeInTheDocument();
});
+ it("should render component with arrows", () => {
+ const initialValues = {
+ qtyOfSlidesPerSet: imageSet.length - 1,
+ };
+ makeSut(initialValues);
- test("clearInterval should be called on unmount", () => {
- const imageSet = [
- { image: "http://example.com/1.png", name: "1" },
- { image: "http://example.com/2.png", name: "2" },
- { image: "http://example.com/3.png", name: "3" },
- ];
- const component = renderer.create();
-
- const transitionId = component.getInstance().transitionId;
-
- expect(transitionId).toBeDefined();
- component.unmount();
- expect(clearIntervalSpy).toHaveBeenCalledWith(transitionId);
- });
+ // check if proper elements are renderer
+ const rightArrow = screen.queryByTestId("right-arrow");
- test("clearInterval should not be called if there is no transitionId on unmount", () => {
- const imageSet = [{ image: "http://example.com/1.png", name: "1" }];
- const component = renderer.create();
+ expect(screen.queryByTestId("left-arrow")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("dots-container")).not.toBeInTheDocument();
+ expect(rightArrow).toBeInTheDocument();
- delete component.getInstance().transitionId;
+ // click o right arrow
+ userEvent.click(rightArrow);
- component.unmount();
- expect(clearIntervalSpy).not.toHaveBeenCalled();
+ // check if proper elements are renderer
+ expect(rightArrow).not.toBeInTheDocument();
+ expect(screen.queryByTestId("left-arrow")).toBeInTheDocument();
});
- describe("Receiving new props", () => {
- const imageSet = [{ image: "http://example.com/1.png", name: "1" }];
- let component, setStateSpy, setIntervSpy;
-
- beforeEach(() => {
- component = mount();
- setStateSpy = jest.spyOn(component.instance(), "setState");
- setIntervSpy = jest.spyOn(component.instance(), "setInterval");
- });
-
- afterEach(() => {
- setStateSpy.mockClear();
- setIntervSpy.mockClear();
- });
-
- test("activeItem should be set to 0 when imageSet changes", () => {
- component.setProps({ imageSet: [] });
-
- expect(setStateSpy).toHaveBeenCalledWith({ activeItem: 0 });
- expect(setIntervSpy).toHaveBeenCalledTimes(1);
- });
-
- test("state should not change when imageSet doesn't change", () => {
- component.setProps({ imageSet });
-
- expect(setStateSpy).not.toHaveBeenCalled();
- expect(setIntervSpy).not.toHaveBeenCalled();
- });
+ it("should render component with infinite scroll", () => {
+ const initialValues = {
+ qtyOfSlidesPerSet: 2,
+ infiniteLoop: true,
+ };
+ makeSut(initialValues);
+
+ // check if proper elements are renderer
+ const rightArrow = screen.queryByTestId("right-arrow");
+ const leftArrow = screen.queryByTestId("left-arrow");
+ const dotsContainer = screen.queryByTestId("dots-container");
+
+ expect(dotsContainer.children[0].classList.contains("active")).toBe(true);
+ expect(rightArrow).toBeInTheDocument();
+ expect(leftArrow).toBeInTheDocument();
+
+ // click on last Dot
+ userEvent.click(dotsContainer.children[2]);
+
+ // check if active dot has changed and arrows are still in screen
+ expect(rightArrow).toBeInTheDocument();
+ expect(leftArrow).toBeInTheDocument();
+ expect(dotsContainer.children[0].classList.contains("active")).toBe(false);
+ expect(dotsContainer.children[2].classList.contains("active")).toBe(true);
+
+ // click on next
+ userEvent.click(rightArrow);
+
+ // check if active dot has go back to first position
+ expect(rightArrow).toBeInTheDocument();
+ expect(leftArrow).toBeInTheDocument();
+ expect(dotsContainer.children[2].classList.contains("active")).toBe(false);
+ expect(dotsContainer.children[0].classList.contains("active")).toBe(true);
});
});
diff --git a/packages/carousel/src/__snapshots__/Carousel.story.storyshot b/packages/carousel/src/__snapshots__/Carousel.story.storyshot
index c99a21eee..4d7200a07 100644
--- a/packages/carousel/src/__snapshots__/Carousel.story.storyshot
+++ b/packages/carousel/src/__snapshots__/Carousel.story.storyshot
@@ -1,1905 +1,1972 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots Carousel 1 photo 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+.c5 {
+ padding: 8px;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c5 * {
+ width: 100%;
+ border-radius: 20px;
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.08);
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c4 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c0 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c1 {
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c3 {
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-transition: all 250ms linear;
+ transition: all 250ms linear;
+ -ms-overflow-style: none;
+ -webkit-scrollbar-width: none;
+ -moz-scrollbar-width: none;
+ -ms-scrollbar-width: none;
+ scrollbar-width: none;
+ -webkit-transform: translateX( -NaN% );
+ -ms-transform: translateX( -NaN% );
+ transform: translateX( -NaN% );
+}
+
+.c3 > * {
+ width: NaN%;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c3::-webkit-scrollbar {
+ display: none;
}
.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: end;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-right: 16px;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-left: 16px;
}
-
- -
+
-
- Organic Pepper
+
+
+
+
+
+
+
-
-
+
+
+
`;
-exports[`Storyshots Carousel 1 photo with onEnd 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+exports[`Storyshots Carousel 2 photos 1`] = `
+.c5 {
+ padding: 8px;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c5 * {
+ width: 100%;
+ border-radius: 20px;
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.08);
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c4 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c0 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c1 {
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c3 {
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-transition: all 250ms linear;
+ transition: all 250ms linear;
+ -ms-overflow-style: none;
+ -webkit-scrollbar-width: none;
+ -moz-scrollbar-width: none;
+ -ms-scrollbar-width: none;
+ scrollbar-width: none;
+ -webkit-transform: translateX( -0% );
+ -ms-transform: translateX( -0% );
+ transform: translateX( -0% );
+}
+
+.c3 > * {
+ width: 50%;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c3::-webkit-scrollbar {
+ display: none;
}
.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: end;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-right: 16px;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-left: 16px;
}
-
- -
+
-
- Organic Pepper
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
`;
-exports[`Storyshots Carousel 2 photos 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+exports[`Storyshots Carousel Custom carousel 1`] = `
+.c5 {
+ display: inline-block;
+ vertical-align: text-bottom;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c5 .farmblocks-icon {
+ display: block;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c3 {
+ font-size: 16px;
+ font-family: lato,sans-serif;
+ font-weight: 600;
+ -webkit-font-smoothing: antialiased !important;
+ -moz-osx-font-smoothing: grayscale;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ padding: 4px 4px;
+ border-radius: 4px;
+ line-height: 1.5;
+ height: 40px;
+ min-width: 40px;
+ width: 40px;
+ white-space: nowrap;
+ cursor: pointer;
+ -webkit-transition: background 0.3s,color 0.3s,border-color 0.3s;
+ transition: background 0.3s,color 0.3s,border-color 0.3s;
+ background-color: #FFFFFF;
+ color: #59636f;
+ border: solid 1px rgba(0,0,0,0.16);
+ box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.16);
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c3 span {
+ overflow: hidden;
+ text-overflow: ellipsis;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c3:disabled {
+ background-color: rgba(0,0,0,0.32);
+ color: rgba(0,0,0,0.32);
+ border-width: 1px;
+ border-color: rgba(0,0,0,0.16);
+ box-shadow: none;
+ cursor: default;
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c3:disabled .icon {
+ color: rgba(0,0,0,0.32);
}
-.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+.c3 .icon {
+ -webkit-transition: color 0.3s ease;
+ transition: color 0.3s ease;
+ color: rgba(0,0,0,0.32);
+ line-height: 1;
}
-
-
- -
-
-
- Organic Pepper
-
-
- -
-
-
- Tomato
-
-
-
-
-`;
-
-exports[`Storyshots Carousel all photos 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+.c3:not(:disabled):hover,
+.c3:not(:disabled).hovered,
+.c3:not(:disabled):active,
+.c3:not(:disabled).active {
+ color: #3498db;
+ border-width: 2px;
+ border-color: #3498db;
+ box-shadow: 0px 4px 4px 0px rgba(0,0,0,0.16);
+ padding: 3px 3px;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c3:not(:disabled):hover .icon,
+.c3:not(:disabled).hovered .icon,
+.c3:not(:disabled):active .icon,
+.c3:not(:disabled).active .icon,
+.c3:not(:disabled):focus .icon,
+.c3:not(:disabled).focused .icon {
+ color: #3498db;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+.c3:not(:disabled).active,
+.c3:not(:disabled):active {
+ box-shadow: none;
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c3:focus,
+.c3.focused {
+ outline: none;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c3.focus-visible,
+.c3.focused:not(:disabled) {
+ box-shadow: 0 0 0 3px rgba(52,152,219,0.56);
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c8 {
+ padding: 8px;
}
-.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+.c8 * {
+ width: 100%;
+ border-radius: 500px;
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.08);
}
-
-
- -
-
-
- Organic Pepper
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Grapefruit
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Romaine Lettuce
-
-
-
-
-`;
+.c7 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+}
-exports[`Storyshots Carousel all photos with onChange and onEnd 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+.c0 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
}
.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+}
+
+.c6 {
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-transition: all 250ms linear;
+ transition: all 250ms linear;
+ -ms-overflow-style: none;
+ -webkit-scrollbar-width: none;
+ -moz-scrollbar-width: none;
+ -ms-scrollbar-width: none;
+ scrollbar-width: none;
+ -webkit-transform: translateX( -100% );
+ -ms-transform: translateX( -100% );
+ transform: translateX( -100% );
+}
+
+.c6 > * {
+ width: 50%;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c6::-webkit-scrollbar {
+ display: none;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c2 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: end;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+ margin-right: 16px;
+}
+
+.c9 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-left: 16px;
+}
+
+.c4 {
+ border-radius: 32px;
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c10 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c11 {
+ height: 8px;
+ width: 8px;
+ margin-right: 6px;
+ cursor: pointer;
+ border-radius: 50%;
+ background: rgba(0,0,0,0.08);
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c11.active {
+ background: rgba(0,0,0,0.48);
}
-.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+@media (hover:none) and (pointer:coarse) {
+ .c4 {
+ display: none;
+ }
}
-
- -
+
-
-
-
-
-
- Tomato
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Romaine Lettuce
-
-
-
+
+
+
+
+
`;
-exports[`Storyshots Carousel custom config 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+exports[`Storyshots Carousel all photos 1`] = `
+.c9 {
+ display: inline-block;
+ vertical-align: text-bottom;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c9 .farmblocks-icon {
+ display: block;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -121.9px;
- height: 247.8px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c7 {
+ font-size: 16px;
+ font-family: lato,sans-serif;
+ font-weight: 600;
+ -webkit-font-smoothing: antialiased !important;
+ -moz-osx-font-smoothing: grayscale;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 0.5s;
- -webkit-transition: transform 0.5s;
- transition: transform 0.5s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ padding: 4px 4px;
+ border-radius: 4px;
+ line-height: 1.5;
+ height: 40px;
+ min-width: 40px;
+ width: 40px;
+ white-space: nowrap;
+ cursor: pointer;
+ -webkit-transition: background 0.3s,color 0.3s,border-color 0.3s;
+ transition: background 0.3s,color 0.3s,border-color 0.3s;
+ background-color: #FFFFFF;
+ color: #59636f;
+ border: solid 1px rgba(0,0,0,0.16);
+ box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.16);
}
-.c0 ul li {
- margin: 2px;
- min-width: 200px;
- width: 200px;
- height: 200px;
- -webkit-transition: all 0.5s;
- transition: all 0.5s;
- will-change: transform;
+.c7 span {
+ overflow: hidden;
+ text-overflow: ellipsis;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c7:disabled {
+ background-color: rgba(0,0,0,0.32);
+ color: rgba(0,0,0,0.32);
+ border-width: 1px;
+ border-color: rgba(0,0,0,0.16);
+ box-shadow: none;
+ cursor: default;
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 23.900000000000006px;
+.c7:disabled .icon {
+ color: rgba(0,0,0,0.32);
}
-.c2 border {
- radius: 100%;
- width: 4px;
- color: green;
+.c7 .icon {
+ -webkit-transition: color 0.3s ease;
+ transition: color 0.3s ease;
+ color: rgba(0,0,0,0.32);
+ line-height: 1;
}
-
-
- -
-
-
- Organic Pepper
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Grapefruit
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Romaine Lettuce
-
-
-
-
-`;
+.c7:not(:disabled):hover,
+.c7:not(:disabled).hovered,
+.c7:not(:disabled):active,
+.c7:not(:disabled).active {
+ color: #3498db;
+ border-width: 2px;
+ border-color: #3498db;
+ box-shadow: 0px 4px 4px 0px rgba(0,0,0,0.16);
+ padding: 3px 3px;
+}
-exports[`Storyshots Carousel extended style 1`] = `
-.c4 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+.c7:not(:disabled):hover .icon,
+.c7:not(:disabled).hovered .icon,
+.c7:not(:disabled):active .icon,
+.c7:not(:disabled).active .icon,
+.c7:not(:disabled):focus .icon,
+.c7:not(:disabled).focused .icon {
+ color: #3498db;
}
-.c2 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c7:not(:disabled).active,
+.c7:not(:disabled):active {
+ box-shadow: none;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c7:focus,
+.c7.focused {
+ outline: none;
+}
+
+.c7.focus-visible,
+.c7.focused:not(:disabled) {
+ box-shadow: 0 0 0 3px rgba(52,152,219,0.56);
+}
+
+.c5 {
+ padding: 8px;
+}
+
+.c5 * {
+ width: 100%;
+ border-radius: 20px;
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.08);
+}
+
+.c4 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
-}
-
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c0 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c1 {
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
}
.c3 {
- border: 4px solid rgba(255,255,255,0.56);
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-transition: all 250ms linear;
+ transition: all 250ms linear;
+ -ms-overflow-style: none;
+ -webkit-scrollbar-width: none;
+ -moz-scrollbar-width: none;
+ -ms-scrollbar-width: none;
+ scrollbar-width: none;
+ -webkit-transform: translateX( -0% );
+ -ms-transform: translateX( -0% );
+ transform: translateX( -0% );
+}
+
+.c3 > * {
+ width: 25%;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c3::-webkit-scrollbar {
+ display: none;
}
-.c1 {
- background: lavender;
+.c2 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: end;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-right: 16px;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-left: 16px;
}
-.c1 .image {
- background-size: 50%;
- background-repeat: repeat;
+.c8 {
+ border-radius: 32px;
}
-.c1 .itemLabel {
- color: red;
+@media (hover:none) and (pointer:coarse) {
+ .c8 {
+ display: none;
+ }
}
-
- -
-
-
- Organic Pepper
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Grapefruit
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
+
-
- Tomato
-
-
-
-
-
- Tomato
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- Romaine Lettuce
+
-
-
+
+
`;
-exports[`Storyshots Carousel no scale 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+exports[`Storyshots Carousel infinite loop 1`] = `
+.c5 {
+ display: inline-block;
+ vertical-align: text-bottom;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c5 .farmblocks-icon {
+ display: block;
}
-.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -328px;
- height: 368px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+.c3 {
+ font-size: 16px;
+ font-family: lato,sans-serif;
+ font-weight: 600;
+ -webkit-font-smoothing: antialiased !important;
+ -moz-osx-font-smoothing: grayscale;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2s;
- -webkit-transition: transform 2s;
- transition: transform 2s;
- will-change: transform;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ padding: 4px 4px;
+ border-radius: 4px;
+ line-height: 1.5;
+ height: 40px;
+ min-width: 40px;
+ width: 40px;
+ white-space: nowrap;
+ cursor: pointer;
+ -webkit-transition: background 0.3s,color 0.3s,border-color 0.3s;
+ transition: background 0.3s,color 0.3s,border-color 0.3s;
+ background-color: #FFFFFF;
+ color: #59636f;
+ border: solid 1px rgba(0,0,0,0.16);
+ box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.16);
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2s;
- transition: all 2s;
- will-change: transform;
+.c3 span {
+ overflow: hidden;
+ text-overflow: ellipsis;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c3:disabled {
+ background-color: rgba(0,0,0,0.32);
+ color: rgba(0,0,0,0.32);
+ border-width: 1px;
+ border-color: rgba(0,0,0,0.16);
+ box-shadow: none;
+ cursor: default;
}
-.c0 ul li.active {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 20px;
+.c3:disabled .icon {
+ color: rgba(0,0,0,0.32);
}
-.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+.c3 .icon {
+ -webkit-transition: color 0.3s ease;
+ transition: color 0.3s ease;
+ color: rgba(0,0,0,0.32);
+ line-height: 1;
}
-
-
- -
-
-
- Organic Pepper
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Grapefruit
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Tomato
-
-
- -
-
-
- Romaine Lettuce
-
-
-
-
-`;
+.c3:not(:disabled):hover,
+.c3:not(:disabled).hovered,
+.c3:not(:disabled):active,
+.c3:not(:disabled).active {
+ color: #3498db;
+ border-width: 2px;
+ border-color: #3498db;
+ box-shadow: 0px 4px 4px 0px rgba(0,0,0,0.16);
+ padding: 3px 3px;
+}
-exports[`Storyshots Carousel partial custom config 1`] = `
-.c3 {
- font-family: Lato,sans-serif;
- font-size: 88px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- color: #2f313a;
- text-align: center;
- font-weight: 600;
+.c3:not(:disabled):hover .icon,
+.c3:not(:disabled).hovered .icon,
+.c3:not(:disabled):active .icon,
+.c3:not(:disabled).active .icon,
+.c3:not(:disabled):focus .icon,
+.c3:not(:disabled).focused .icon {
+ color: #3498db;
}
-.c1 {
- box-sizing: border-box;
- border-radius: 16px;
- object-fit: cover;
+.c3:not(:disabled).active,
+.c3:not(:disabled):active {
+ box-shadow: none;
+}
+
+.c3:focus,
+.c3.focused {
+ outline: none;
+}
+
+.c3.focus-visible,
+.c3.focused:not(:disabled) {
+ box-shadow: 0 0 0 3px rgba(52,152,219,0.56);
+}
+
+.c8 {
+ padding: 8px;
+}
+
+.c8 * {
+ width: 100%;
+ border-radius: 20px;
+ box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.08);
+}
+
+.c7 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
.c0 {
- position: relative;
-}
-
-.c0 ul {
- position: relative;
- left: 50%;
- margin-left: -399.83200000000005px;
- height: 439.83200000000005px;
- list-style: none;
- padding: 0;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
- display: -ms-inline-flexbox;
- display: inline-flex;
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+}
+
+.c1 {
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+}
+
+.c6 {
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-transition: all 250ms linear;
+ transition: all 250ms linear;
+ -ms-overflow-style: none;
+ -webkit-scrollbar-width: none;
+ -moz-scrollbar-width: none;
+ -ms-scrollbar-width: none;
+ scrollbar-width: none;
+ -webkit-transform: translateX( -100% );
+ -ms-transform: translateX( -100% );
+ transform: translateX( -100% );
+}
+
+.c6 > * {
+ width: 33.333333333333336%;
+ -webkit-flex-shrink: 0;
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c6::-webkit-scrollbar {
+ display: none;
+}
+
+.c2 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: end;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ margin-right: 16px;
+}
+
+.c9 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
- -webkit-transform: translateX( 0px );
- -ms-transform: translateX( 0px );
- transform: translateX( 0px );
- -webkit-transition: -webkit-transform 2.5s;
- -webkit-transition: transform 2.5s;
- transition: transform 2.5s;
- will-change: transform;
+ margin-left: 16px;
}
-.c0 ul li {
- margin: 20px;
- min-width: 656px;
- width: 656px;
- height: 328px;
- -webkit-transition: all 2.5s;
- transition: all 2.5s;
- will-change: transform;
+.c4 {
+ border-radius: 32px;
+}
+
+.c10 {
+ width: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
}
-.c0 ul li .image {
- box-shadow: 0 4px 40px 0 rgba(0,0,0,0.32);
+.c11 {
+ height: 8px;
+ width: 8px;
+ margin-right: 6px;
+ cursor: pointer;
+ border-radius: 50%;
+ background: rgba(0,0,0,0.08);
}
-.c0 ul li.active {
- -webkit-transform: scale(1.219);
- -ms-transform: scale(1.219);
- transform: scale(1.219);
- -webkit-transform-origin: bottom;
- -ms-transform-origin: bottom;
- transform-origin: bottom;
- margin: 0 91.83200000000005px;
+.c11.active {
+ background: rgba(0,0,0,0.48);
}
-.c2 {
- border: 4px solid rgba(255,255,255,0.56);
+@media (hover:none) and (pointer:coarse) {
+ .c4 {
+ display: none;
+ }
}
-
- -
+
-
-
-
-
-
- Tomato
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Tomato
-
-
-
-
-
-
- Romaine Lettuce
-
-
-
+
+
+
+
+
`;
diff --git a/packages/carousel/src/components/Dots.js b/packages/carousel/src/components/Dots.js
new file mode 100644
index 000000000..e4414d6d0
--- /dev/null
+++ b/packages/carousel/src/components/Dots.js
@@ -0,0 +1,25 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { Dot, DotsContainer } from "../styledComponents/Dots";
+
+function Dots({ slides, handleClick, selectedDot }) {
+ return (
+
+ {slides.map((item, index) => (
+ handleClick(index)}
+ className={selectedDot === index ? "active" : ""}
+ />
+ ))}
+
+ );
+}
+
+Dots.propTypes = {
+ slides: PropTypes.node.isRequired,
+ handleClick: PropTypes.func,
+ selectedDot: PropTypes.number,
+};
+
+export default Dots;
diff --git a/packages/carousel/src/components/Slide.js b/packages/carousel/src/components/Slide.js
new file mode 100644
index 000000000..dd44f497f
--- /dev/null
+++ b/packages/carousel/src/components/Slide.js
@@ -0,0 +1,23 @@
+import React from "react";
+import PropTypes from "prop-types";
+
+import { Container, Wrapper } from "../styledComponents/Slide";
+
+const Slide = ({ children, borderRadius, ...props }) => (
+
+
+ {children}
+
+
+);
+
+Slide.propTypes = {
+ children: PropTypes.node.isRequired,
+ borderRadius: PropTypes.number,
+};
+
+Slide.defaultProps = {
+ borderRadius: 20,
+};
+
+export default Slide;
diff --git a/packages/carousel/src/hooks/useResizeWindow.js b/packages/carousel/src/hooks/useResizeWindow.js
new file mode 100644
index 000000000..21e778bb0
--- /dev/null
+++ b/packages/carousel/src/hooks/useResizeWindow.js
@@ -0,0 +1,71 @@
+import { useState, useEffect, useRef, useCallback } from "react";
+import PropTypes from "prop-types";
+
+import debounce from "lodash.debounce";
+
+const getWidth = () => window.innerWidth;
+
+const useResizeWindow = ({ qtyOfSlidesPerSet, breakpoints }) => {
+ const RESIZE_DELAY = 300;
+ const [screendWidth, setScreenWidth] = useState(window.innerWidth);
+ const [screenThresholds, setScreenThresholds] = useState(breakpoints);
+ const [displayNumber, setDisplayNumber] = useState(qtyOfSlidesPerSet);
+
+ const handleWindowSizeChange = () => {
+ setScreenWidth(window.innerWidth);
+ };
+
+ function handleResize() {
+ const screenSize = getWidth();
+ for (let i = 0; i < screenThresholds.length; i += 1) {
+ if (screenSize <= screenThresholds[i].width) {
+ setDisplayNumber(screenThresholds[i].slidesToShow);
+ return;
+ }
+ }
+ setDisplayNumber(qtyOfSlidesPerSet);
+ }
+
+ function sortBreakpoints() {
+ setScreenThresholds(
+ breakpoints.sort((a, b) => (a.width > b.width ? 1 : -1)),
+ );
+ }
+
+ useEffect(() => {
+ sortBreakpoints();
+ }, []);
+
+ const debouncedFunctionRef = useRef();
+ debouncedFunctionRef.current = () => handleResize();
+
+ const debouncedChange = useCallback(
+ debounce(() => debouncedFunctionRef.current(), RESIZE_DELAY),
+ [],
+ );
+
+ useEffect(() => {
+ debouncedChange();
+ }, [screendWidth]);
+
+ useEffect(() => {
+ window.addEventListener("resize", handleWindowSizeChange);
+ return () => {
+ window.removeEventListener("resize", handleWindowSizeChange);
+ };
+ }, []);
+
+ return { displayNumber };
+};
+
+useResizeWindow.propTypes = {
+ qtyOfSlidesPerSet: PropTypes.number,
+ breakpoints: PropTypes.arrayOf(
+ PropTypes.shape({
+ width: PropTypes.number,
+ slidesToShow: PropTypes.number,
+ }),
+ ),
+};
+
+export default useResizeWindow;
diff --git a/packages/carousel/src/hooks/useResizeWindow.test.js b/packages/carousel/src/hooks/useResizeWindow.test.js
new file mode 100644
index 000000000..b07365a95
--- /dev/null
+++ b/packages/carousel/src/hooks/useResizeWindow.test.js
@@ -0,0 +1,165 @@
+import React from "react";
+import { render } from "@testing-library/react";
+import PropTypes from "prop-types";
+import useResizeWindow from "./useResizeWindow";
+
+const CompWithResizeHook = ({
+ displayNumber,
+ setDisplayNumber,
+ setCurrentIndex,
+ dotIndex,
+ numberOfCards,
+ defaultQtyOfSlides,
+ breakpoints,
+ infiniteLoop,
+}) => {
+ useResizeWindow({
+ displayNumber,
+ setDisplayNumber,
+ setCurrentIndex,
+ dotIndex,
+ numberOfCards,
+ defaultQtyOfSlides,
+ breakpoints,
+ infiniteLoop,
+ });
+
+ return (
+
+
+
+ );
+};
+
+CompWithResizeHook.propTypes = {
+ displayNumber: PropTypes.number,
+ setDisplayNumber: PropTypes.func,
+ setCurrentIndex: PropTypes.func,
+ dotIndex: PropTypes.number,
+ numberOfCards: PropTypes.number,
+ defaultQtyOfSlides: PropTypes.number,
+ breakpoints: PropTypes.arrayOf(PropTypes.number),
+ infiniteLoop: PropTypes.bool,
+};
+
+describe("(Carousel/hooks) useResizeWindow", () => {
+ const setDisplayNumberMock = jest.fn();
+ const setCurrentIndexMock = jest.fn();
+ const spy = jest.fn();
+ const testSmallWidth = 700;
+ const testMediumWidth = 900;
+ const testLargeWidth = 1600;
+
+ beforeEach(() => {
+ window.addEventListener("resize", spy);
+ });
+
+ afterAll(() => {
+ jest.restoreAllMocks();
+ window.removeEventListener("resize", spy);
+ });
+
+ const makeSut = ({ ...props }) => render();
+
+ it("should not fire resize event by default", () => {
+ const initialValues = {
+ displayNumber: 3,
+ setDisplayNumber: setDisplayNumberMock,
+ setCurrentIndex: setCurrentIndexMock,
+ dotIndex: 0,
+ numberOfCards: 5,
+ defaultQtyOfSlides: 3,
+ breakpoints: [1, 2],
+ infiniteLoop: true,
+ };
+ makeSut(initialValues);
+
+ expect(spy).not.toHaveBeenCalled();
+ expect(window.innerWidth).not.toBeLessThanOrEqual(testSmallWidth);
+ expect(window.innerWidth).toBeGreaterThan(testMediumWidth);
+ expect(window.innerWidth).toBeLessThanOrEqual(testLargeWidth);
+ });
+
+ xdescribe("when resize event is fired", () => {
+ const initialDotIndex = 0;
+
+ beforeAll(() => {
+ window.dispatchEvent(new Event("resize"));
+ });
+
+ it("should update the values relevant for a width lower than 768px", () => {
+ const initialValues = {
+ displayNumber: 3,
+ setDisplayNumber: setDisplayNumberMock,
+ setCurrentIndex: setCurrentIndexMock,
+ dotIndex: initialDotIndex,
+ numberOfCards: 5,
+ defaultQtyOfSlides: 3,
+ breakpoints: [1, 2],
+ infiniteLoop: true,
+ };
+ // Set screenwidth to be 700
+ window.innerWidth = testSmallWidth;
+
+ makeSut(initialValues);
+
+ expect(spy).toHaveBeenCalled();
+ expect(window.innerWidth).toBe(testSmallWidth);
+ // Need to set de diplsay to 1
+ expect(setDisplayNumberMock).toBeCalledWith(1);
+ // Current index will be dotIndex + 1 < numberOfCards ? dotIndex + 1 : 0
+ expect(setCurrentIndexMock).toBeCalledWith(initialDotIndex + 1);
+ });
+
+ it("should update the values relevant for a width lower than 1200px", () => {
+ const initialValues = {
+ displayNumber: 3,
+ setDisplayNumber: setDisplayNumberMock,
+ setCurrentIndex: setCurrentIndexMock,
+ dotIndex: initialDotIndex,
+ numberOfCards: 5,
+ defaultQtyOfSlides: 3,
+ breakpoints: [1, 2],
+ infiniteLoop: true,
+ };
+ // Set screenwidth to be 900
+ window.innerWidth = testMediumWidth;
+
+ makeSut(initialValues);
+
+ expect(spy).toHaveBeenCalled();
+ expect(window.innerWidth).toBe(testMediumWidth);
+ // Need to set de diplsay to 2
+ expect(setDisplayNumberMock).toBeCalledWith(2);
+ // Current index will be numberOfCards > 2 ? dotIndex + 2 : 0
+ expect(setCurrentIndexMock).toBeCalledWith(initialDotIndex + 2);
+ });
+
+ it("should update the values relevant for a width greater or equal than 1200px", () => {
+ const slidesToShowMock = 3;
+ const initialValues = {
+ displayNumber: 3,
+ setDisplayNumber: setDisplayNumberMock,
+ setCurrentIndex: setCurrentIndexMock,
+ dotIndex: initialDotIndex,
+ numberOfCards: 5,
+ defaultQtyOfSlides: slidesToShowMock,
+ breakpoints: [1, 2],
+ infiniteLoop: true,
+ };
+ // Set screenwidth to be 1600
+ window.innerWidth = testLargeWidth;
+
+ makeSut(initialValues);
+
+ expect(spy).toHaveBeenCalled();
+ expect(window.innerWidth).toBe(testLargeWidth);
+ // Need to set de diplsay to slidesToShowMock
+ expect(setDisplayNumberMock).toBeCalledWith(slidesToShowMock);
+ // Current index will be dotIndex + slidesToShowMock
+ expect(setCurrentIndexMock).toBeCalledWith(
+ initialDotIndex + slidesToShowMock,
+ );
+ });
+ });
+});
diff --git a/packages/carousel/src/hooks/useTouch.js b/packages/carousel/src/hooks/useTouch.js
new file mode 100644
index 000000000..6464081d9
--- /dev/null
+++ b/packages/carousel/src/hooks/useTouch.js
@@ -0,0 +1,38 @@
+import { useState } from "react";
+import PropTypes from "prop-types";
+
+const useTouch = ({ nextSlide, prevSlide }) => {
+ const TOUCH_THRESHOLD = 5;
+ const [touchPosition, setTouchPosition] = useState(null);
+ const handleTouchStart = (event) => {
+ const touchDown = event.touches[0].clientX;
+ setTouchPosition(touchDown);
+ };
+
+ const handleTouchMove = (event) => {
+ const touchDown = touchPosition;
+
+ if (touchDown === null) {
+ return;
+ }
+ const currentTouch = event.touches[0].clientX;
+ const touchDragDiff = touchDown - currentTouch;
+
+ if (touchDragDiff > TOUCH_THRESHOLD) {
+ nextSlide();
+ }
+
+ if (touchDragDiff < -TOUCH_THRESHOLD) {
+ prevSlide();
+ }
+ setTouchPosition(null);
+ };
+ return { handleTouchStart, handleTouchMove };
+};
+
+useTouch.propTypes = {
+ nextSlide: PropTypes.func,
+ prevSlide: PropTypes.func,
+};
+
+export default useTouch;
diff --git a/packages/carousel/src/index.js b/packages/carousel/src/index.js
index db04c20ed..ad6e449b6 100644
--- a/packages/carousel/src/index.js
+++ b/packages/carousel/src/index.js
@@ -1 +1,5 @@
-export { default } from "./Carousel";
+import Slide from "./components/Slide";
+import Carousel from "./Carousel";
+import useResizeWindow from "./hooks/useResizeWindow";
+
+export { Carousel, Slide, useResizeWindow };
diff --git a/packages/carousel/src/styledComponents/Carousel.js b/packages/carousel/src/styledComponents/Carousel.js
index 50a5879f0..beead5232 100644
--- a/packages/carousel/src/styledComponents/Carousel.js
+++ b/packages/carousel/src/styledComponents/Carousel.js
@@ -1,63 +1,57 @@
import styled from "styled-components";
-import { colors } from "@crave/farmblocks-theme";
+import Button from "@crave/farmblocks-button";
-const scale = (props) => (props.shouldScale ? 1.219 : 1);
-const activeItemWidth = (props) => props.itemConfig.width * scale(props);
-const activeItemHeight = (props) => props.itemConfig.height * scale(props);
-const spaceBetweenItems = (props) => props.itemConfig.margin * 2;
-const stepDistance = (props) =>
- props.itemConfig.width + spaceBetweenItems(props);
-const activeItemMargin = (props) => {
- const { itemConfig } = props;
- const scaledWidth = itemConfig.width * scale(props);
-
- // We get the difference from scaled width and normal width.
- // This difference is the total margin we have to compensate due to transform: scale.
- // Then we divide it by 2 because we need to add this on left and right margin
- const scaledMargin = (scaledWidth - itemConfig.width) / 2;
-
- // Just add the default margin to it
- return scaledMargin + itemConfig.margin;
-};
-
-const Container = styled.div`
- position: relative;
- ul {
- position: relative;
- left: 50%;
- margin-left: ${(props) => -(activeItemWidth(props) / 2)}px;
- height: ${(props) => activeItemHeight(props) + spaceBetweenItems(props)}px;
- list-style: none;
- padding: 0;
- display: inline-flex;
- align-items: center;
+export const Container = styled.div`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+`;
- transform: translateX(
- ${(props) => -(props.activeItem * stepDistance(props))}px
- );
- transition: transform ${(props) => props.itemConfig.transitionTime}s;
- will-change: transform;
+export const Wrapper = styled.div`
+ display: grid;
+ grid-template-columns: 1fr 10fr 1fr;
+ align-items: center;
+ justify-content: center;
+ flex-direction: row;
+`;
- li {
- margin: ${(props) => props.itemConfig.margin}px;
- min-width: ${(props) => props.itemConfig.width}px;
- width: ${(props) => props.itemConfig.width}px;
- height: ${(props) => props.itemConfig.height}px;
+export const Content = styled.div`
+ width: 100%;
+ height: 100%;
+ display: flex;
+ transition: ${(props) =>
+ props.transitionEnabled ? "all 250ms linear" : "none"};
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+ transform: translateX(
+ -${(props) => props.currentIndex * (100 / props.displayNumber)}%
+ );
+
+ & > * {
+ width: ${(props) => 100 / props.displayNumber}%;
+ flex-shrink: 0;
+ flex-grow: 1;
+ }
+ &::-webkit-scrollbar {
+ display: none;
+ }
+`;
- transition: all ${(props) => props.itemConfig.transitionTime}s;
- will-change: transform;
+export const ButtonContainer = styled.div`
+ display: flex;
+ justify-content: ${(props) =>
+ props.direction === "left" ? "flex-end" : "flex-start"};
+ align-items: center;
+ ${(props) =>
+ props.direction === "left" ? "margin-right: 16px" : "margin-left: 16px"};
+`;
- .image {
- box-shadow: 0 4px 40px 0 ${colors.GREY_32};
- }
+export const ArrowButton = styled(Button)`
+ border-radius: 32px;
- &.active {
- transform: scale(${scale});
- transform-origin: bottom;
- margin: 0 ${activeItemMargin}px;
- }
+ @media (hover: none) and (pointer: coarse) {
+ & {
+ display: none;
}
}
`;
-
-export default Container;
diff --git a/packages/carousel/src/styledComponents/Dots.js b/packages/carousel/src/styledComponents/Dots.js
new file mode 100644
index 000000000..5f596bd9b
--- /dev/null
+++ b/packages/carousel/src/styledComponents/Dots.js
@@ -0,0 +1,21 @@
+import styled from "styled-components";
+
+export const DotsContainer = styled.div`
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
+export const Dot = styled.span`
+ height: 8px;
+ width: 8px;
+ margin-right: 6px;
+ cursor: pointer;
+ border-radius: 50%;
+ background: rgba(0, 0, 0, 0.08);
+
+ &.active {
+ background: rgba(0, 0, 0, 0.48);
+ }
+`;
diff --git a/packages/carousel/src/styledComponents/Slide.js b/packages/carousel/src/styledComponents/Slide.js
new file mode 100644
index 000000000..0da0c4bd9
--- /dev/null
+++ b/packages/carousel/src/styledComponents/Slide.js
@@ -0,0 +1,16 @@
+import styled from "styled-components";
+
+export const Container = styled.div`
+ padding: 8px;
+ * {
+ width: 100%;
+ border-radius: ${({ borderRadius }) => borderRadius}px;
+ box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.08);
+ }
+`;
+
+export const Wrapper = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;