From eed43fe97397ff6b92aee297f4944b066a3f2a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=84=ED=98=84?= <64634992+ksmfou98@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:32:10 +0900 Subject: [PATCH] =?UTF-8?q?swiper=20=EB=AA=A8=EB=93=88=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#180)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 스와이프 모듈 구현 * fix: 배포에러 해결 --------- Co-authored-by: 이재하 --- .pnp.cjs | 70 +++++++-- .yarnrc.yml | 8 +- apps/jurumarble/package.json | 3 +- apps/jurumarble/src/app/layout.tsx | 3 + .../src/app/main/components/Carousel.tsx | 143 ++++++------------ packages/ui/components/index.ts | 1 + .../ui/components/swiper/ContentSwiper.tsx | 88 +++++++++++ packages/ui/components/swiper/index.ts | 1 + packages/ui/package.json | 1 + yarn.lock | 55 ++++++- 10 files changed, 250 insertions(+), 123 deletions(-) create mode 100644 packages/ui/components/swiper/ContentSwiper.tsx create mode 100644 packages/ui/components/swiper/index.ts diff --git a/.pnp.cjs b/.pnp.cjs index a8855367..81c52445 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -4181,6 +4181,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["sharp", "npm:0.32.6"],\ ["styled-components", "virtual:8ec4233c825b2c709f2ff549456a05fb98060d621f5df14748cda36fdb51190eccc2e438466f7464c85557cdad97eb73aa6580e78bca957a1149bfc58c6ddf34#npm:5.3.11"],\ ["styled-reset", "virtual:8ec4233c825b2c709f2ff549456a05fb98060d621f5df14748cda36fdb51190eccc2e438466f7464c85557cdad97eb73aa6580e78bca957a1149bfc58c6ddf34#npm:4.5.1"],\ + ["swiper", "npm:9.4.1"],\ ["typescript", "patch:typescript@npm%3A4.9.3#~builtin::version=4.9.3&hash=d73830"]\ ],\ "linkType": "SOFT"\ @@ -4200,6 +4201,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["react-dom", "virtual:a9e685c95fc9c2c05e15b14465ecc20924383932b7a1aa62172e110ba174ebedc352c8daf5023eb54ef5f0a5595ca6cf8763ef2477e003ebd1850bfb16231d67#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["styled-components", "virtual:8ec4233c825b2c709f2ff549456a05fb98060d621f5df14748cda36fdb51190eccc2e438466f7464c85557cdad97eb73aa6580e78bca957a1149bfc58c6ddf34#npm:5.3.11"],\ + ["swiper", "npm:9.4.1"],\ ["typescript", "patch:typescript@npm%3A4.9.3#~builtin::version=4.9.3&hash=d73830"]\ ],\ "packagePeers": [\ @@ -4225,6 +4227,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["react-dom", "virtual:a9e685c95fc9c2c05e15b14465ecc20924383932b7a1aa62172e110ba174ebedc352c8daf5023eb54ef5f0a5595ca6cf8763ef2477e003ebd1850bfb16231d67#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["styled-components", "virtual:a9e685c95fc9c2c05e15b14465ecc20924383932b7a1aa62172e110ba174ebedc352c8daf5023eb54ef5f0a5595ca6cf8763ef2477e003ebd1850bfb16231d67#npm:5.3.11"],\ + ["swiper", "npm:9.4.1"],\ ["typescript", "patch:typescript@npm%3A4.9.3#~builtin::version=4.9.3&hash=d73830"]\ ],\ "packagePeers": [\ @@ -4248,6 +4251,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["react-dom", "virtual:a9e685c95fc9c2c05e15b14465ecc20924383932b7a1aa62172e110ba174ebedc352c8daf5023eb54ef5f0a5595ca6cf8763ef2477e003ebd1850bfb16231d67#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["styled-components", "virtual:a9e685c95fc9c2c05e15b14465ecc20924383932b7a1aa62172e110ba174ebedc352c8daf5023eb54ef5f0a5595ca6cf8763ef2477e003ebd1850bfb16231d67#npm:5.3.11"],\ + ["swiper", "npm:9.4.1"],\ ["typescript", "patch:typescript@npm%3A4.9.3#~builtin::version=4.9.3&hash=d73830"]\ ],\ "linkType": "SOFT"\ @@ -5447,6 +5451,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["@types/react", [\ + ["npm:17.0.68", {\ + "packageLocation": "./.yarn/cache/@types-react-npm-17.0.68-cbfaf61e95-c6ca4415b5.zip/node_modules/@types/react/",\ + "packageDependencies": [\ + ["@types/react", "npm:17.0.68"],\ + ["@types/prop-types", "npm:15.7.5"],\ + ["@types/scheduler", "npm:0.16.3"],\ + ["csstype", "npm:3.1.2"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:18.2.21", {\ "packageLocation": "./.yarn/cache/@types-react-npm-18.2.21-c50bc2f785-ffed203bfe.zip/node_modules/@types/react/",\ "packageDependencies": [\ @@ -6404,10 +6418,11 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["debug", "virtual:5daecec5378cca9d2b655781dda98457b520644332776e02f43c02749432d960b0fe724013f680814901d9397550da22c63b2a93b9f47877762783265d253473#npm:4.3.4"],\ ["@types/supports-color", null],\ ["ms", "npm:2.1.2"],\ - ["supports-color", "npm:9.4.0"]\ + ["supports-color", null]\ ],\ "packagePeers": [\ - "@types/supports-color"\ + "@types/supports-color",\ + "supports-color"\ ],\ "linkType": "HARD"\ }]\ @@ -6734,10 +6749,11 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["follow-redirects", "virtual:35a845e191d5a8a7376e256c81e9e855732385142c5dc9e26f0b8393c2fb4673b81fed201d5f2c5ab96fb727142683ac03329eab760f2c4870779d4bda6abe8f#npm:1.15.2"],\ ["@types/debug", null],\ - ["debug", "virtual:5daecec5378cca9d2b655781dda98457b520644332776e02f43c02749432d960b0fe724013f680814901d9397550da22c63b2a93b9f47877762783265d253473#npm:4.3.4"]\ + ["debug", null]\ ],\ "packagePeers": [\ - "@types/debug"\ + "@types/debug",\ + "debug"\ ],\ "linkType": "HARD"\ }]\ @@ -7797,6 +7813,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["object-assign", [\ + ["npm:4.1.1", {\ + "packageLocation": "./.yarn/cache/object-assign-npm-4.1.1-1004ad6dec-fcc6e4ea8c.zip/node_modules/object-assign/",\ + "packageDependencies": [\ + ["object-assign", "npm:4.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["once", [\ ["npm:1.4.0", {\ "packageLocation": "./.yarn/cache/once-npm-1.4.0-ccf03ef07a-cd0a885013.zip/node_modules/once/",\ @@ -8124,6 +8149,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["react", [\ + ["npm:17.0.2", {\ + "packageLocation": "./.yarn/cache/react-npm-17.0.2-99ba37d931-b254cc17ce.zip/node_modules/react/",\ + "packageDependencies": [\ + ["react", "npm:17.0.2"],\ + ["loose-envify", "npm:1.4.0"],\ + ["object-assign", "npm:4.1.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:18.2.0", {\ "packageLocation": "./.yarn/cache/react-npm-18.2.0-1eae08fee2-88e38092da.zip/node_modules/react/",\ "packageDependencies": [\ @@ -8649,6 +8683,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["ssr-window", [\ + ["npm:4.0.2", {\ + "packageLocation": "./.yarn/cache/ssr-window-npm-4.0.2-01f9c0151e-df18260092.zip/node_modules/ssr-window/",\ + "packageDependencies": [\ + ["ssr-window", "npm:4.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["ssri", [\ ["npm:10.0.5", {\ "packageLocation": "./.yarn/cache/ssri-npm-10.0.5-1a7557d04d-0a31b65f21.zip/node_modules/ssri/",\ @@ -8959,13 +9002,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["has-flag", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ - }],\ - ["npm:9.4.0", {\ - "packageLocation": "./.yarn/cache/supports-color-npm-9.4.0-a415f39758-cb8ff8daea.zip/node_modules/supports-color/",\ - "packageDependencies": [\ - ["supports-color", "npm:9.4.0"]\ - ],\ - "linkType": "HARD"\ }]\ ]],\ ["supports-preserve-symlinks-flag", [\ @@ -9015,6 +9051,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["swiper", [\ + ["npm:9.4.1", {\ + "packageLocation": "./.yarn/cache/swiper-npm-9.4.1-38d46d35a3-1180b3b766.zip/node_modules/swiper/",\ + "packageDependencies": [\ + ["swiper", "npm:9.4.1"],\ + ["@types/react", "npm:17.0.68"],\ + ["react", "npm:17.0.2"],\ + ["ssr-window", "npm:4.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["tapable", [\ ["npm:2.2.1", {\ "packageLocation": "./.yarn/cache/tapable-npm-2.2.1-8cf5ff3039-3b7a1b4d86.zip/node_modules/tapable/",\ diff --git a/.yarnrc.yml b/.yarnrc.yml index 393dc26b..c09535e6 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -3,11 +3,9 @@ plugins: spec: "@yarnpkg/plugin-typescript" packageExtensions: - follow-redirects@*: + swiper@*: dependencies: - debug: "*" - debug@*: - dependencies: - supports-color: "*" + "@types/react": "^17" + react: "^17" yarnPath: .yarn/releases/yarn-3.3.0.cjs diff --git a/apps/jurumarble/package.json b/apps/jurumarble/package.json index 3aee09e4..03c890d0 100644 --- a/apps/jurumarble/package.json +++ b/apps/jurumarble/package.json @@ -27,7 +27,8 @@ "react-toastify": "^9.1.3", "sharp": "^0.32.6", "styled-components": "^5.3.6", - "styled-reset": "^4.5.1" + "styled-reset": "^4.5.1", + "swiper": "9.4.1" }, "devDependencies": { "@svgr/cli": "^8.0.1", diff --git a/apps/jurumarble/src/app/layout.tsx b/apps/jurumarble/src/app/layout.tsx index 65c6a297..eb7009e5 100644 --- a/apps/jurumarble/src/app/layout.tsx +++ b/apps/jurumarble/src/app/layout.tsx @@ -7,6 +7,9 @@ import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import { injectStyle } from "react-toastify/dist/inject-style"; import AuthProcess from "components/AuthProcess"; +import "swiper/css"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; export const metadata: Metadata = { title: "주루마블", diff --git a/apps/jurumarble/src/app/main/components/Carousel.tsx b/apps/jurumarble/src/app/main/components/Carousel.tsx index c9350f90..ccec3494 100644 --- a/apps/jurumarble/src/app/main/components/Carousel.tsx +++ b/apps/jurumarble/src/app/main/components/Carousel.tsx @@ -3,12 +3,11 @@ import Path from "lib/Path"; import Image from "next/image"; import { useRouter } from "next/navigation"; import styled, { css } from "styled-components"; -import { useCallback, useEffect, useRef, useState } from "react"; import { SvgIcPrevious, SvgNext } from "src/assets/icons/components"; - -const SLIDE_MOVE_COUNT = 1; -const ORIGINAL_IMAGE_LENGTH = 10; -const MOVE_DISTANCE = 300; +import { ContentSwiper } from "@monorepo/ui"; +import { Autoplay } from "swiper"; +import SwiperCore from "swiper"; +import { useRef } from "react"; interface Props { hotDrinkList: GetHotDrinkResponse[]; @@ -16,83 +15,50 @@ interface Props { function Carousel({ hotDrinkList }: Props) { const router = useRouter(); - const slideRef = useRef(null); - const [currentSlide, setCurrentSlide] = useState(1); - const [isAnimation, setIsAnimation] = useState(true); - const [isFlowing, setIsFlowing] = useState(true); - - const onNextSlide = useCallback(() => { - setCurrentSlide((prev) => prev + SLIDE_MOVE_COUNT); - }, [currentSlide]); - - const onPrevSlide = useCallback(() => { - setCurrentSlide((prev) => prev - SLIDE_MOVE_COUNT); - }, [currentSlide]); - - useEffect(() => { - if (!slideRef.current) return; - - if (currentSlide === ORIGINAL_IMAGE_LENGTH + 1) { - setTimeout(() => { - setIsAnimation(false); - slideRef.current!.style.transform = `translateX(-${ - MOVE_DISTANCE * ORIGINAL_IMAGE_LENGTH - }px)`; - setCurrentSlide(1); - }, 500); - - setTimeout(() => { - setIsAnimation(true); - }, 600); - } else if (currentSlide === 0) { - setTimeout(() => { - setIsAnimation(false); - slideRef.current!.style.transform = `translateX(+${MOVE_DISTANCE}px)`; - setCurrentSlide(ORIGINAL_IMAGE_LENGTH); - }, 500); - - setTimeout(() => { - setIsAnimation(true); - }, 600); - } - slideRef.current.style.transform = `translateX(-${MOVE_DISTANCE * (currentSlide - 1)}px)`; - }, [currentSlide]); - - useEffect(() => { - let intervalId: NodeJS.Timeout; - if (isFlowing) { - intervalId = setInterval(() => { - setCurrentSlide((prev) => prev + SLIDE_MOVE_COUNT); - }, 3500); - } - return () => clearTimeout(intervalId); - }, [isFlowing, currentSlide]); + const ref = useRef(null); + + const onNextSlide = () => { + ref.current?.slideNext(); + }; + + const onPrevSlide = () => { + ref.current?.slidePrev(); + }; return ( <> - - {hotDrinkList.map((hotDrink: GetHotDrinkResponse, index: number) => { - const { drinkId, image, name, manufactureAddress } = hotDrink; - return ( - router.push(`${Path.DRINK_INFO_PAGE}/${drinkId}`)} - > - - - {index + 1} - 전통주 - - - {name} - {manufactureAddress} - - - - ); - })} - + ( + router.push(`${Path.DRINK_INFO_PAGE}/${drinkId}`)}> + + + {index + 1} + 전통주 + + + {name} + {manufactureAddress} + + + + )} + /> @@ -114,29 +80,10 @@ const Container = styled.div` overflow: hidden; `; -const Slides = styled.ol<{ isAnimation: boolean }>` - display: flex; - /* overflow-x: auto; - scroll-snap-type: x mandatory; */ - gap: 8px; - transition: transform 0.5s ease-in-out; - ${({ isAnimation }) => isAnimation && `transform: translateX(-${MOVE_DISTANCE}px);`} - - /** - @Todo 모바일에서는 보이게 하기 - **/ - -ms-overflow-style: none /* IE and Edge 스크롤바 없애는 css*/; - scrollbar-width: none; /* Firefox 스크롤바 없애는 css */ - &::-webkit-scrollbar { - display: none; /* Chrome , Safari , Opera 스크롤바 없애는 css*/ - } -`; - const Slide = styled.li` width: 292px; - height: 120px; + height: 130px; padding-top: 20px; - /* scroll-snap-align: start; */ cursor: pointer; `; diff --git a/packages/ui/components/index.ts b/packages/ui/components/index.ts index e586b589..f6ee5998 100644 --- a/packages/ui/components/index.ts +++ b/packages/ui/components/index.ts @@ -7,3 +7,4 @@ export { default as Input } from "./input/Input"; export { default as FloatComponentTemplate } from "./modal/FloatComponentTemplate"; export { default as DivideLine } from "./divide/DivideLine"; export * from "./selectBox"; +export * from "./swiper"; diff --git a/packages/ui/components/swiper/ContentSwiper.tsx b/packages/ui/components/swiper/ContentSwiper.tsx new file mode 100644 index 00000000..5b7a0e9d --- /dev/null +++ b/packages/ui/components/swiper/ContentSwiper.tsx @@ -0,0 +1,88 @@ +"use client"; +import { RefObject, useImperativeHandle, useState } from "react"; +import { SwiperProps, SwiperSlide, SwiperSlideProps, Swiper } from "swiper/react"; +import SwiperCore from "swiper"; +import styled, { css } from "styled-components"; + +export interface ContentSwiperProps { + swiperProps?: SwiperProps; + slideProps?: ContentSwiperSlideProps & Pick; + data: T[]; + renderItem: (item: T, index: number, activeIndex: number) => JSX.Element; + initialIndex?: number; + handler?: RefObject; + keyProp?: keyof T; +} + +export const ContentSwiper = ({ + initialIndex = 0, + data, + renderItem, + swiperProps, + slideProps = {}, + handler, + keyProp, +}: ContentSwiperProps) => { + const [swiper, setSwiper] = useState(); + const [activeIndex, setActiveIndex] = useState(() => initialIndex); + + useImperativeHandle(handler, () => swiper, [swiper]); + + return ( + { + setActiveIndex(swiper.activeIndex); + swiperProps?.onSlideChange?.(swiper); + }} + {...swiperProps} + > + {data.map((item, index) => ( + + {renderItem?.(item, index, activeIndex) as any} + + ))} + + + + ); +}; + +interface ContentSwiperSlideProps { + width?: string; + swipeCount?: number; + scrollMargin?: number; +} + +const StyledSwiper = styled(Swiper)<{ + $slideProps: ContentSwiperSlideProps; + children: any; +}>` + ${({ $slideProps: { scrollMargin, swipeCount = 1, width = "100%" } }) => css` + .swiper-slide { + width: ${width}; + + &:nth-of-type(${swipeCount}n) { + scroll-snap-stop: always; + scroll-snap-align: start; + } + + ${scrollMargin && + css` + scroll-margin: ${scrollMargin}px; + &:first-child { + padding-left: ${scrollMargin}px; + } + + &:last-child { + padding-right: ${scrollMargin}px; + } + `} + + > a { + display: block; + } + } + `} +`; diff --git a/packages/ui/components/swiper/index.ts b/packages/ui/components/swiper/index.ts new file mode 100644 index 00000000..d0a51d1b --- /dev/null +++ b/packages/ui/components/swiper/index.ts @@ -0,0 +1 @@ +export * from "./ContentSwiper"; diff --git a/packages/ui/package.json b/packages/ui/package.json index 3d030811..13d86f12 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -15,6 +15,7 @@ "react-dom": "^18.2.0", "react-is": "^18.2.0", "styled-components": "^5.3.6", + "swiper": "9.4.1", "typescript": "4.9.3" }, "peerDependencies": { diff --git a/yarn.lock b/yarn.lock index 62f5fa18..a7f4b3a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1642,6 +1642,7 @@ __metadata: sharp: ^0.32.6 styled-components: ^5.3.6 styled-reset: ^4.5.1 + swiper: 9.4.1 typescript: 4.9.3 languageName: unknown linkType: soft @@ -1658,6 +1659,7 @@ __metadata: react-dom: ^18.2.0 react-is: ^18.2.0 styled-components: ^5.3.6 + swiper: 9.4.1 typescript: 4.9.3 peerDependencies: react: ^18.2.0 @@ -2384,6 +2386,17 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:^17": + version: 17.0.68 + resolution: "@types/react@npm:17.0.68" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: c6ca4415b53b1abe91162b29af541a1797a56a6f462ef796e8ebda3eaa4d0609205f4f17b3fce8d9a12235d4ffd8a67c47b5e018ed85c2f3bee0fba8f54638c1 + languageName: node + linkType: hard + "@types/scheduler@npm:*": version: 0.16.3 resolution: "@types/scheduler@npm:0.16.3" @@ -3091,7 +3104,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:*, debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.3": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.3": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -4293,6 +4306,13 @@ __metadata: languageName: node linkType: hard +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -4634,6 +4654,16 @@ __metadata: languageName: node linkType: hard +"react@npm:^17": + version: 17.0.2 + resolution: "react@npm:17.0.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + languageName: node + linkType: hard + "readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -4959,6 +4989,13 @@ __metadata: languageName: node linkType: hard +"ssr-window@npm:^4.0.2": + version: 4.0.2 + resolution: "ssr-window@npm:4.0.2" + checksum: df182600927f4f3225224cf8c02338ea637c9750519505bbfb9a9236741a2a7ec088386fb948bca7b447b8303d9109e7dc7672e3de041c79ac2a0e03665af7d2 + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" @@ -5120,13 +5157,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:*": - version: 9.4.0 - resolution: "supports-color@npm:9.4.0" - checksum: cb8ff8daeaf1db642156f69a9aa545b6c01dd9c4def4f90a49f46cbf24be0c245d392fcf37acd119cd1819b99dad2cc9b7e3260813f64bcfd7f5b18b5a1eefb8 - languageName: node - linkType: hard - "supports-color@npm:^5.3.0, supports-color@npm:^5.5.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -5192,6 +5222,15 @@ __metadata: languageName: node linkType: hard +"swiper@npm:9.4.1": + version: 9.4.1 + resolution: "swiper@npm:9.4.1" + dependencies: + ssr-window: ^4.0.2 + checksum: 1180b3b766f25cbe636fafbb56adbddf8a240077c504a335a62d1773f4452df1bd9ca09bccfe86478c3b9401879c4e8f7ed3824e74299f8b48953e8fc7f08bc3 + languageName: node + linkType: hard + "tapable@npm:^2.2.0": version: 2.2.1 resolution: "tapable@npm:2.2.1"