From dc161603afe0dbf0b70b83da7b6ed2ddad1222ef Mon Sep 17 00:00:00 2001 From: jeremy Date: Thu, 5 Sep 2024 13:39:31 -0500 Subject: [PATCH] inital commit for real --- ResponsiveCarousel/ResponsiveCarousel.jsx | 187 ++++++++++++++++++ .../ResponsiveCarousel.readme.md | 92 +++++++++ package-lock.json | 54 +++++ package.json | 18 ++ 4 files changed, 351 insertions(+) create mode 100644 ResponsiveCarousel/ResponsiveCarousel.jsx create mode 100644 ResponsiveCarousel/ResponsiveCarousel.readme.md create mode 100644 package-lock.json create mode 100644 package.json diff --git a/ResponsiveCarousel/ResponsiveCarousel.jsx b/ResponsiveCarousel/ResponsiveCarousel.jsx new file mode 100644 index 0000000..396e5da --- /dev/null +++ b/ResponsiveCarousel/ResponsiveCarousel.jsx @@ -0,0 +1,187 @@ +import React, { useEffect, useRef, useState } from "react"; +import { FaChevronLeft, FaChevronRight } from "react-icons/fa"; + +/** + * A responsive carousel component that displays a list of children in a sliding manner. + * It supports various features such as auto-play, pause on hover, navigation buttons, and responsive design. + * + * @param {ReactNode[]} children - The list of children to be displayed in the carousel. + * @param {number} limit - The maximum number of children to be displayed in a single slide. + * @param {number} [mdLimit] - The maximum number of children to be displayed in a single slide on medium-sized screens. + * @param {number} [smLimit] - The maximum number of children to be displayed in a single slide on small-sized screens. + * @param {number} [lgLimit] - The maximum number of children to be displayed in a single slide on large-sized screens. + * @param {string} [title] - The title of the carousel. + * @param {string} [bgImg] - The background image of the carousel. + * @param {number} [autoAdvanceInterval] - The interval at which the carousel auto-advances. + * @param {boolean} [pauseOnHover] - Whether the carousel should pause on hover. + * @param {boolean} [autoPlay] - Whether the carousel should auto-play. + * @param {string} [arrowPosition] - The position of the navigation arrows. + * @param {boolean} [showArrows] - Whether to show the navigation arrows. + * @param {string} [border] - The border style of the carousel. + * @param {boolean} [showNavigation] - Whether to show the navigation buttons. + * @param {string} [gap] - The gap between the children. + * @param {string} [bg] - The background color of the carousel. + * @param {string} [px] - The padding x of the carousel. + * @param {string} [py] - The padding y of the carousel. + * @return {JSX.Element} The carousel component. + */ + +const useInterval = (callback, delay) => { + const savedCallback = useRef(); + + useEffect(() => { + savedCallback.current = callback; + }, [callback]); + + useEffect(() => { + const tick = () => { + savedCallback.current(); + }; + + if (delay !== null) { + const id = setInterval(tick, delay); + return () => clearInterval(id); + } + }, [delay]); +}; + +const ResponsiveCarousel = ({ + children, + limit, + mdLimit, + smLimit, + lgLimit, + title, + bgImg, + autoAdvanceInterval, + pauseOnHover, + autoPlay, + arrowPosition, + showArrows, + border, + showNavigation, + gap, + bg, + px, + py, +}) => { + const [currentSlide, setCurrentSlide] = useState(0); + const slideCount = Math.ceil(children.length / limit); + const [isPlaying, setIsPlaying] = useState(autoPlay); + const [updatedLimit, setUpdatedLimit] = useState(limit); + + useEffect(() => { + const updateLimit = () => { + if (window.innerWidth >= 1280) { + setUpdatedLimit(lgLimit || limit); + } else if (window.innerWidth >= 768) { + setUpdatedLimit(mdLimit || limit); + } else { + setUpdatedLimit(smLimit || limit); + } + }; + updateLimit(); + window.addEventListener("resize", updateLimit); + return () => window.removeEventListener("resize", updateLimit); + }, [limit, mdLimit, smLimit, lgLimit]); + + const chunkedChildren = Array.from({ length: slideCount }, (_, i) => + children.slice(i * updatedLimit, (i + 1) * updatedLimit) + ); + + // console.log("border: ", border != "none" ? border + "px" : border); + const prevSlide = () => { + setCurrentSlide((prevSlide) => + prevSlide === 0 ? slideCount - 1 : prevSlide - 1 + ); + }; + + const nextSlide = () => { + setCurrentSlide((prevSlide) => + prevSlide === slideCount - 1 ? 0 : prevSlide + 1 + ); + }; + + useEffect(() => { + if (autoPlay) { + const id = setInterval(() => { + if (isPlaying) { + nextSlide(); + } + }, autoAdvanceInterval); + + return () => clearInterval(id); + } + }, [autoPlay, autoAdvanceInterval, isPlaying]); + + const handleMouseEnter = () => { + if (pauseOnHover) { + setIsPlaying(false); + } + }; + const RenderButtons = () => { + return ( +
+ + +
+ ); + }; + + const handleMouseLeave = () => { + if (pauseOnHover) { + setIsPlaying(autoPlay); + } + }; + + return ( + <> + {title && ( +
+
+ {title} +
+ + {showArrows && } +
+ )} +
+
+ {chunkedChildren.map((chunk, index) => ( +
+ {chunk} +
+ ))} +
+
+ + ); +}; +export default ResponsiveCarousel; diff --git a/ResponsiveCarousel/ResponsiveCarousel.readme.md b/ResponsiveCarousel/ResponsiveCarousel.readme.md new file mode 100644 index 0000000..476829e --- /dev/null +++ b/ResponsiveCarousel/ResponsiveCarousel.readme.md @@ -0,0 +1,92 @@ +# ResponsiveCarousel.jsx +========================= + +## Overview +------------ + +ResponsiveCarousel is a flexible and customizable carousel component built with React. It is designed to work seamlessly across various devices and screen sizes, providing a responsive and engaging user experience. + +## Features +------------ + +* **Responsive Design**: The carousel adapts to different screen sizes and devices, ensuring a consistent and optimal viewing experience. +* **Customizable**: Easily customize the carousel's appearance, behavior, and layout to fit your specific needs. +* **Touch and Swipe Support**: Supports touch and swipe gestures for navigating through the carousel on mobile devices. +* **Keyboard Navigation**: Allows users to navigate through the carousel using their keyboard. +* **Auto-Play and Pause**: Automatically plays the carousel and pauses on hover or when the user interacts with it. + +## Props +------------ + +The following props are available for customizing the ResponsiveCarousel component: + +### Required Props + +* **children**: The content to be displayed within the carousel. This can be a single element or an array of elements. + +### Optional Props + +* **limit**: The maximum number of items to display within the carousel at a given time. Defaults to 3. +* **mdLimit**: The maximum number of items to display within the carousel on medium-sized screens. Defaults to 4. +* **smLimit**: The maximum number of items to display within the carousel on small-sized screens. Defaults to 2. +* **lgLimit**: The maximum number of items to display within the carousel on large-sized screens. Defaults to 5. +* **title**: The title of the carousel. Defaults to an empty string. +* **bgImg**: The background image of the carousel. Defaults to an empty string. +* **autoAdvanceInterval**: The interval at which the carousel automatically advances. Defaults to 3000 milliseconds. +* **pauseOnHover**: Whether the carousel should pause when the user hovers over it. Defaults to true. +* **autoPlay**: Whether the carousel should automatically play. Defaults to true. +* **arrowPosition**: The position of the navigation arrows. Defaults to "center". +* **showArrows**: Whether to display the navigation arrows. Defaults to true. +* **border**: The border style of the carousel. Defaults to "solid 1px #ccc". +* **showNavigation**: Whether to display the navigation buttons. Defaults to true. +* **gap**: The gap between items within the carousel. Defaults to "10px". +* **bg**: The background color of the carousel. Defaults to "#fff". +* **px**: The padding x of the carousel. Defaults to "20px". +* **py**: The padding y of the carousel. Defaults to "10px". + +## Usage +----- + +To use the ResponsiveCarousel component, simply import it into your React application and pass in the required props. + +```jsx +import React from 'react'; +import ResponsiveCarousel from './ResponsiveCarousel'; + +const MyComponent = () => { + const carouselChildren = [ +
Child 1
, +
Child 2
, +
Child 3
, +
Child 4
, +
Child 5
, +
Child 6
, + ]; + + return ( +
+ +
+ ); +}; + +export default MyComponent; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e336dc9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,54 @@ +{ + "name": "re-comp-lib", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "re-comp-lib", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "react-icons": "^5.3.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "peerDependencies": { + "react": "*" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3421470 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "re-comp-lib", + "version": "1.0.0", + "description": "A lib of react components", + "main": "null", + "scripts": { + "test": "vitest" + }, + "keywords": [ + "components", + "lib" + ], + "author": "Jeremy Hayes", + "license": "MIT", + "dependencies": { + "react-icons": "^5.3.0" + } +}