swiper: use astro native component

Use astro native component for swiper capabilities.

Signed-off-by: Pascal Brand <pascal.brand38@gmail.com>
This commit is contained in:
Pascal Brand
2026-03-25 11:13:07 +01:00
parent ce8d2b77cd
commit f3006e0a1f
15 changed files with 74 additions and 91 deletions

47
v3/package-lock.json generated
View File

@@ -21,6 +21,7 @@
"astro": "^4.15.5",
"astro-embed": "^0.7.2",
"astro-icon": "^1.1.1",
"astro-swiper": "^2.4.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"embla-carousel-react": "^8.3.0",
@@ -30,7 +31,6 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sweetalert2": "^11.14.2",
"swiper": "^11.1.14",
"tailwindcss-animate": "^1.0.7",
"unpic": "^3.18.0",
"vanilla-cookieconsent": "^3.0.1"
@@ -219,8 +219,7 @@
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.10.3.tgz",
"integrity": "sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/@astrojs/internal-helpers": {
"version": "0.4.1",
@@ -477,7 +476,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz",
"integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.25.7",
@@ -2792,7 +2790,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz",
"integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -2803,7 +2800,6 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/react": "*"
}
@@ -2883,7 +2879,6 @@
"integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
"dev": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.8.1",
@@ -3169,7 +3164,6 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3353,7 +3347,6 @@
"resolved": "https://registry.npmjs.org/astro/-/astro-4.16.1.tgz",
"integrity": "sha512-ZeZd+L147HHgHmvoSkve7KM3EutV+hY0mOCa4PwARHEFAAh+omo4MUNoTWsFkfq7ozTgR0PCXQwslrZduoWHNg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@astrojs/compiler": "^2.10.3",
"@astrojs/internal-helpers": "0.4.1",
@@ -4064,6 +4057,19 @@
"@iconify/utils": "^2.1.30"
}
},
"node_modules/astro-swiper": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/astro-swiper/-/astro-swiper-2.4.0.tgz",
"integrity": "sha512-oTYMSwqIfyjt3xBrIk4fhxPCtj9DfMTPLnHcZ0VXVhnFFaqyK/2DYpnUV4n1EiGkby/QDa4tZ/bOsHSsH1xogg==",
"license": "MIT",
"dependencies": {
"swiper": "^12.1.3"
},
"engines": {
"node": ">=20",
"pnpm": ">=10.30.3"
}
},
"node_modules/astrojs-compiler-sync": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astrojs-compiler-sync/-/astrojs-compiler-sync-1.0.0.tgz",
@@ -4261,7 +4267,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001663",
"electron-to-chromium": "^1.5.28",
@@ -5182,8 +5187,7 @@
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.3.0.tgz",
"integrity": "sha512-Ve8dhI4w28qBqR8J+aMtv7rLK89r1ZA5HocwFz6uMB/i5EiC7bGI7y+AM80yAVUJw3qqaZYK7clmZMUR8kM3UA==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/embla-carousel-react": {
"version": "8.3.0",
@@ -5332,7 +5336,6 @@
"integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.11.0",
@@ -7077,7 +7080,6 @@
"integrity": "sha512-V0RMVZzK1+rCHpymRv4URK2lNhIRyO8g7U7zOFwVAhJuat74HtkjIQpQRKNCwFEYkRGpafOpmXXLoaoBcyVtBg==",
"devOptional": true,
"license": "MPL-2.0",
"peer": true,
"dependencies": {
"detect-libc": "^1.0.3"
},
@@ -9481,7 +9483,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
@@ -9650,7 +9651,6 @@
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -9667,7 +9667,6 @@
"integrity": "sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@astrojs/compiler": "^2.9.1",
"prettier": "^3.0.0",
@@ -9769,7 +9768,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -9782,7 +9780,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -10149,7 +10146,6 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
"integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.6"
},
@@ -10787,9 +10783,9 @@
}
},
"node_modules/swiper": {
"version": "11.1.14",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.14.tgz",
"integrity": "sha512-VbQLQXC04io6AoAjIUWuZwW4MSYozkcP9KjLdrsG/00Q/yiwvhz9RQyt0nHXV10hi9NVnDNy1/wv7Dzq1lkOCQ==",
"version": "12.1.3",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.3.tgz",
"integrity": "sha512-XcWlVmkHFICI4fuoJKgbp8PscDcS4i7pBH8nwJRBi3dpQvhCySwsWRYm4bOf/BzKVWkHOYaFw7qz9uBSrY3oug==",
"funding": [
{
"type": "patreon",
@@ -10838,7 +10834,6 @@
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz",
"integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -10988,7 +10983,6 @@
"integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
"devOptional": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -11167,7 +11161,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -11526,7 +11519,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
"integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
@@ -12331,7 +12323,6 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@@ -35,6 +35,7 @@
"astro": "^4.15.5",
"astro-embed": "^0.7.2",
"astro-icon": "^1.1.1",
"astro-swiper": "^2.4.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"embla-carousel-react": "^8.3.0",
@@ -44,7 +45,6 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sweetalert2": "^11.14.2",
"swiper": "^11.1.14",
"tailwindcss-animate": "^1.0.7",
"unpic": "^3.18.0",
"vanilla-cookieconsent": "^3.0.1"

View File

@@ -0,0 +1,43 @@
---
import { Swiper, SwiperWrapper, SwiperSlide, SwiperPagination, SwiperLazyPreloader} from 'astro-swiper';
interface Props {
list: {
src: string;
alt?: string;
class: string;
}[];
}
const { list } = Astro.props;
---
<Swiper
style={{
'--swiper-pagination-bullet-inactive-color': '#fff',
'--swiper-pagination-bullet-inactive-opacity': 0.5,
'--swiper-pagination-bullet-size': '12px',
}}
options={{
spaceBetween: 0,
slidesPerView: 1,
pagination:{
clickable: true,
el: ".swiper-pagination",
},
mousewheel:{ forceToAxis: true, sensitivity: 0.1, releaseOnEdges: true },
autoplay:{
delay: 2500,
disableOnInteraction: true,
},
scrollbar: true
}}
>
<SwiperWrapper>
{list.map((item) => (
<SwiperSlide>
<img src={item.src} class={item.class} loading="lazy" alt={item.alt} />
<SwiperLazyPreloader class="swiper-lazy-preloader-white"></SwiperLazyPreloader>
</SwiperSlide>
))}
</SwiperWrapper>
<SwiperPagination/>
</Swiper>

View File

@@ -1,40 +0,0 @@
/* https://swiperjs.com/demos */
import 'swiper/css';
import 'swiper/css/pagination';
import { Autoplay, Pagination, Scrollbar, Mousewheel } from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';
const Carousel = ({ list }) => {
return (
<Swiper
spaceBetween={0}
slidesPerView={1}
pagination={{ clickable: true }}
style={{
'--swiper-pagination-bullet-inactive-color': '#fff',
'--swiper-pagination-bullet-inactive-opacity': 0.5,
'--swiper-pagination-bullet-size': '12px',
}}
mousewheel={{ forceToAxis: true, sensitivity: 0.1, releaseOnEdges: true }}
autoplay={{
delay: 2500,
disableOnInteraction: true,
}}
// https://github.com/nolimits4web/swiper/blob/40a705e5bcadf2ee2ee90591ff9ed95c1aaf9026/src/swiper-element.mjs#L286
// workaround for {true} which cause console error
lazy='true'
scrollbar
modules={[Pagination, Autoplay, Scrollbar, Mousewheel]}
>
{list.map((item, i) => (
<SwiperSlide key={'p' + i}>
<img src={item.src} className={item.className} loading="lazy" alt={item.alt} />
<div className="swiper-lazy-preloader swiper-lazy-preloader-white"></div>
</SwiperSlide>
))}
</Swiper>
);
};
export default Carousel;

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -49,7 +49,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -46,7 +46,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -44,7 +44,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -44,7 +44,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -45,7 +45,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },

View File

@@ -7,7 +7,7 @@ import Content from '~/components/widgets/Content.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import Stats from '~/components/widgets/Stats.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Carousel from '~/components/widgets/Carousel.jsx';
import Carousel from '~/components/widgets/Carousel.astro';
import Note from '~/components/widgets/Note.astro';
const metadata = {
@@ -44,7 +44,6 @@ const metadata = {
<Fragment slot="content">
<br /><br />
<Carousel
client:load
list={[
{ src: '/remote.jpg', className: 'rounded-[15px] border border-gray-700' },
{ src: '/main.png', className: 'rounded-[15px] border border-gray-700' },