@growth-angels/ds-core 1.12.10 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  type ReactType = typeof import('react');
2
3
  type ExtendedReactType = ReactType & {
3
4
  createRoot: (container: Element | DocumentFragment) => {
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export const useReactAdapter = () => {
2
3
  // Check if WordPress element is available (WordPress context)
3
4
  if (typeof window !== 'undefined' && window.wp?.element) {
@@ -5,5 +6,5 @@ export const useReactAdapter = () => {
5
6
  }
6
7
  // Fallback for non-WordPress environments (Storybook, tests, SSR)
7
8
  // This will bundle React only in non-WordPress builds
8
- return import('react');
9
+ return React;
9
10
  };
@@ -1,2 +1,5 @@
1
1
  import { CarouselProps } from "./Carousel.types";
2
+ import "swiper/css";
3
+ import "swiper/css/navigation";
4
+ import "swiper/css/pagination";
2
5
  export declare const Carousel: (props: CarouselProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,146 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "../../atoms/atoms";
3
- import { useBreakpointObserver } from "../../hooks/useBreakPointObserver";
4
3
  import { useReactAdapter } from "../../hooks/useReactAdaptater";
4
+ import { Swiper, SwiperSlide } from "swiper/react";
5
+ import { Navigation, Pagination, A11y } from "swiper/modules";
6
+ import "swiper/css";
7
+ import "swiper/css/navigation";
8
+ import "swiper/css/pagination";
5
9
  export const Carousel = (props) => {
6
- const { children, slidesPerView = { sm: 1, md: 2, lg: 3, xl: 4 }, spaceBetween = 20, navigation, pagination, context, hasPagination, hasNavigation, loop = false, } = props;
7
- const { useEffect, useState, useRef, Children } = useReactAdapter();
8
- const trackRef = useRef(null);
9
- const isNavigatingRef = useRef(false);
10
+ const { children, slidesPerView = { xs: 1, sm: 1, md: 2, lg: 3, xl: 4 }, spaceBetween = 20, navigation, pagination, context, hasPagination, hasNavigation, loop = false, } = props;
11
+ const { useRef, Children } = useReactAdapter();
12
+ const swiperRef = useRef(null);
10
13
  const slides = Children.toArray(children);
11
- const calculatePages = (totalSlides = 0, slidesPerView = 0, step = 1) => {
12
- return Math.max(1, Math.ceil((totalSlides - slidesPerView) / step) + 1);
13
- };
14
- const [activeSlideIndex, setActiveSlideIndex] = useState(0);
15
- const [activeDOMIndex, setActiveDOMIndex] = useState(0);
16
- const [isAtEnd, setIsAtEnd] = useState(false);
17
- const [isAtStart, setIsAtStart] = useState(true);
18
- const [totalPages, setTotalPages] = useState(0);
19
14
  const displayNavigation = hasNavigation;
20
15
  const displayPagination = hasPagination;
21
- useEffect(() => {
22
- if (loop) {
23
- setIsAtStart(false);
24
- setIsAtEnd(false);
25
- }
26
- else {
27
- setIsAtStart(activeSlideIndex === 0);
28
- setIsAtEnd(activeSlideIndex === totalPages - 1);
29
- }
30
- }, [activeSlideIndex, totalPages, loop]);
31
- const breakpoint = useBreakpointObserver({ sm: 768, md: 992, lg: 1200, xl: 1400 });
32
- useEffect(() => {
33
- setTotalPages(calculatePages(slides.length, slidesPerView[breakpoint], 1));
34
- }, [breakpoint, slidesPerView]);
35
- useEffect(() => {
36
- const track = trackRef.current;
37
- if (!track)
38
- return;
39
- const handleScroll = () => {
40
- if (loop) {
41
- const slideWidth = track.scrollWidth / (slides.length * 3);
42
- const scrollLeft = track.scrollLeft;
43
- // Repositionnement infini (uniquement si pas en navigation)
44
- if (!isNavigatingRef.current) {
45
- if (scrollLeft <= slideWidth * slides.length) {
46
- track.scrollLeft = scrollLeft + slideWidth * slides.length;
47
- }
48
- else if (scrollLeft >= slideWidth * slides.length * 2) {
49
- track.scrollLeft = scrollLeft - slideWidth * slides.length;
50
- }
51
- }
52
- const scrollPosition = track.scrollLeft + slideWidth / 2;
53
- const domIndex = Math.floor(scrollPosition / slideWidth);
54
- const index = domIndex % slides.length;
55
- setActiveDOMIndex(domIndex);
56
- setActiveSlideIndex(index);
57
- }
58
- else {
59
- const slideWidth = track.scrollWidth / slides.length;
60
- const scrollPosition = track.scrollLeft + slideWidth / 2;
61
- const index = Math.floor(scrollPosition / slideWidth);
62
- setActiveSlideIndex(Math.min(index, slides.length - 1));
63
- setActiveDOMIndex(index);
64
- }
65
- };
66
- track.addEventListener("scroll", handleScroll);
67
- // Position initiale au milieu en mode loop
68
- if (loop) {
69
- setTimeout(() => {
70
- const slideWidth = track.scrollWidth / (slides.length * 3);
71
- track.scrollLeft = slideWidth * slides.length;
72
- }, 0);
73
- }
74
- return () => track.removeEventListener("scroll", handleScroll);
75
- }, [slides.length, loop]);
76
- const style = Object.fromEntries(Object.entries(slidesPerView).map(([key, value]) => [`--ga-ds-slides-per-view-${key}`, `${value}`]));
77
- const goPrev = () => {
78
- if (!trackRef.current)
79
- return;
80
- const allSlides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide");
81
- if (activeSlideIndex === 0 && !loop)
82
- return;
83
- isNavigatingRef.current = true;
84
- if (loop) {
85
- // En mode loop, on utilise l'index DOM actuel
86
- allSlides[activeDOMIndex - 1]?.scrollIntoView({
87
- behavior: "smooth",
88
- block: "nearest",
89
- inline: "start",
90
- });
91
- }
92
- else {
93
- const nextIndex = activeSlideIndex - 1;
94
- allSlides[nextIndex]?.scrollIntoView({
95
- behavior: "smooth",
96
- block: "nearest",
97
- inline: "start",
98
- });
99
- }
100
- setTimeout(() => {
101
- isNavigatingRef.current = false;
102
- }, 600);
103
- };
104
- const goNext = () => {
105
- if (!trackRef.current)
106
- return;
107
- const allSlides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide");
108
- isNavigatingRef.current = true;
109
- if (loop) {
110
- // En mode loop, on utilise l'index DOM actuel
111
- allSlides[activeDOMIndex + 1]?.scrollIntoView({
112
- behavior: "smooth",
113
- block: "nearest",
114
- inline: "start",
115
- });
116
- }
117
- else {
118
- const totalSlides = allSlides.length;
119
- if (activeSlideIndex >= totalSlides - 1)
120
- return;
121
- if (isAtEnd)
122
- return;
123
- const nextIndex = activeSlideIndex + 1;
124
- allSlides[nextIndex]?.scrollIntoView({
125
- behavior: "smooth",
126
- block: "nearest",
127
- inline: "start",
128
- });
129
- }
130
- setTimeout(() => {
131
- isNavigatingRef.current = false;
132
- }, 600);
133
- };
134
- const goTo = (nextIndex) => {
135
- if (!trackRef.current)
136
- return;
137
- const slides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide");
138
- slides[nextIndex]?.scrollIntoView({
139
- behavior: "smooth",
140
- block: "nearest",
141
- inline: "start",
142
- });
143
- };
144
16
  const classes = ["ga-ds-carousel"];
145
17
  if (props.extraClassNames) {
146
18
  if (typeof props.extraClassNames === "string") {
@@ -150,19 +22,31 @@ export const Carousel = (props) => {
150
22
  classes.push(...props.extraClassNames);
151
23
  }
152
24
  }
153
- return (_jsxs("div", { className: classes.join(" "), style: style, children: [navigation?.positionY === "top" && displayNavigation && (_jsx(CarouselNavigation, { goPrev: goPrev, goNext: goNext, isAtStart: isAtStart, isAtEnd: isAtEnd })), _jsx("div", { className: "ga-ds-carousel__track", ref: trackRef, style: {
154
- "--ga-ds-space-between": `${spaceBetween / 10}rem`,
155
- }, children: context === "wp-editor"
25
+ const breakpoints = {
26
+ 0: { slidesPerView: slidesPerView.xs || slidesPerView.sm || 1 },
27
+ 576: { slidesPerView: slidesPerView.sm || 1 },
28
+ 992: { slidesPerView: slidesPerView.md || 2 },
29
+ 1200: { slidesPerView: slidesPerView.lg || 3 },
30
+ 1440: { slidesPerView: slidesPerView.xl || 4 },
31
+ };
32
+ return (_jsxs("div", { className: classes.join(" "), children: [navigation?.positionY === "top" && displayNavigation && _jsx(CarouselNavigation, {}), _jsx(Swiper, { modules: [Navigation, Pagination, A11y], spaceBetween: spaceBetween, breakpoints: breakpoints, loop: loop, navigation: displayNavigation
33
+ ? {
34
+ prevEl: ".ga-ds-carousel__button--prev",
35
+ nextEl: ".ga-ds-carousel__button--next",
36
+ }
37
+ : false, pagination: displayPagination && pagination
38
+ ? {
39
+ clickable: pagination.clickable,
40
+ el: ".ga-ds-carousel__dots",
41
+ bulletClass: "ga-ds-carousel__dot",
42
+ bulletActiveClass: "ga-ds-carousel__dot--active",
43
+ }
44
+ : false, onSwiper: (swiper) => {
45
+ swiperRef.current = swiper;
46
+ }, className: "ga-ds-carousel__track", children: context === "wp-editor"
156
47
  ? children
157
- : slides.map((child, index) => {
158
- return (_jsx("div", { className: `ga-ds-carousel__slide ${index === activeDOMIndex ? "ga-ds-carousel__slide--active" : ""}`, children: child }, index));
159
- }) }), _jsxs("div", { className: "ga-ds-carousel__navigation", children: [pagination && displayPagination && (_jsx(CarouselPagination, { totalPages: totalPages, activeSlideIndex: activeSlideIndex, goTo: goTo, clickable: pagination.clickable })), displayNavigation && navigation?.positionY === "bottom" && (_jsx(CarouselNavigation, { goPrev: goPrev, goNext: goNext, isAtStart: isAtStart, isAtEnd: isAtEnd }))] })] }));
160
- };
161
- const CarouselNavigation = ({ goPrev, goNext, isAtStart, isAtEnd, }) => {
162
- return (_jsxs("div", { className: `ga-ds-carousel__arrows`, children: [_jsx(Button, { extraClassNames: ["ga-ds-carousel__button", "ga-ds-carousel__button--prev"], icon: "chevron-left", onClick: goPrev, disabled: isAtStart }), _jsx(Button, { extraClassNames: ["ga-ds-carousel__button", "ga-ds-carousel__button--next"], icon: "chevron-right", onClick: goNext, disabled: isAtEnd })] }));
48
+ : slides.map((child, index) => (_jsx(SwiperSlide, { className: "ga-ds-carousel__slide", children: child }, index))) }), _jsxs("div", { className: "ga-ds-carousel__navigation", children: [displayPagination && _jsx("div", { className: "ga-ds-carousel__dots" }), displayNavigation && navigation?.positionY === "bottom" && _jsx(CarouselNavigation, {})] })] }));
163
49
  };
164
- const CarouselPagination = ({ totalPages, activeSlideIndex, goTo, clickable, }) => {
165
- return (_jsx("div", { className: "ga-ds-carousel__dots", children: Array.from({ length: totalPages }, (_, index) => index).map((_, index) => (_jsx("span", { className: `ga-ds-carousel__dot ${index === activeSlideIndex ? "ga-ds-carousel__dot--active" : ""}`, onClick: () => clickable && goTo(index), style: {
166
- cursor: clickable ? "pointer" : "default",
167
- } }, index))) }));
50
+ const CarouselNavigation = () => {
51
+ return (_jsxs("div", { className: `ga-ds-carousel__arrows`, children: [_jsx(Button, { extraClassNames: ["ga-ds-carousel__button", "ga-ds-carousel__button--prev"], icon: "chevron-left" }), _jsx(Button, { extraClassNames: ["ga-ds-carousel__button", "ga-ds-carousel__button--next"], icon: "chevron-right" })] }));
168
52
  };
@@ -2,6 +2,7 @@ import { WordpressDefault } from "../../global.types";
2
2
  export type CarouselAttributes = {
3
3
  context?: 'wp-editor';
4
4
  slidesPerView?: {
5
+ xs?: number;
5
6
  sm: number;
6
7
  md: number;
7
8
  lg: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-angels/ds-core",
3
- "version": "1.12.10",
3
+ "version": "1.13.0",
4
4
  "description": "Design system by Growth Angels",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -37,7 +37,8 @@
37
37
  "build-storybook": "storybook build"
38
38
  },
39
39
  "dependencies": {
40
- "@growth-angels/foundation": "^1.4.1"
40
+ "@growth-angels/foundation": "^1.4.1",
41
+ "swiper": "^11.1.15"
41
42
  },
42
43
  "peerDependencies": {
43
44
  "react": ">=18"
@@ -1,3 +1,4 @@
1
+ import React from 'react'
1
2
  // @ts-ignore - React types from window.wp.element
2
3
  type ReactType = typeof import('react')
3
4
 
@@ -27,6 +28,6 @@ export const useReactAdapter = (): ExtendedReactType => {
27
28
 
28
29
  // Fallback for non-WordPress environments (Storybook, tests, SSR)
29
30
  // This will bundle React only in non-WordPress builds
30
- return import('react') as unknown as ExtendedReactType
31
+ return React as ExtendedReactType
31
32
  }
32
33
 
@@ -1,12 +1,17 @@
1
1
  import { Button } from "../../atoms/atoms"
2
- import { useBreakpointObserver } from "../../hooks/useBreakPointObserver"
3
2
  import { useReactAdapter } from "../../hooks/useReactAdaptater"
4
3
  import { CarouselProps } from "./Carousel.types"
4
+ import { Swiper, SwiperSlide } from "swiper/react"
5
+ import { Navigation, Pagination, A11y } from "swiper/modules"
6
+ import type { Swiper as SwiperType } from "swiper"
7
+ import "swiper/css"
8
+ import "swiper/css/navigation"
9
+ import "swiper/css/pagination"
5
10
 
6
11
  export const Carousel = (props: CarouselProps) => {
7
12
  const {
8
13
  children,
9
- slidesPerView = { sm: 1, md: 2, lg: 3, xl: 4 },
14
+ slidesPerView = { xs: 1, sm: 1, md: 2, lg: 3, xl: 4 },
10
15
  spaceBetween = 20,
11
16
  navigation,
12
17
  pagination,
@@ -15,158 +20,13 @@ export const Carousel = (props: CarouselProps) => {
15
20
  hasNavigation,
16
21
  loop = false,
17
22
  } = props
18
- const { useEffect, useState, useRef, Children } = useReactAdapter()
19
- const trackRef = useRef<HTMLDivElement>(null)
20
- const isNavigatingRef = useRef(false)
23
+ const { useRef, Children } = useReactAdapter()
24
+ const swiperRef = useRef<SwiperType | null>(null)
21
25
  const slides = Children.toArray(children)
22
26
 
23
- const calculatePages = (totalSlides = 0, slidesPerView = 0, step = 1) => {
24
- return Math.max(1, Math.ceil((totalSlides - slidesPerView) / step) + 1)
25
- }
26
-
27
- const [activeSlideIndex, setActiveSlideIndex] = useState(0)
28
- const [activeDOMIndex, setActiveDOMIndex] = useState(0)
29
- const [isAtEnd, setIsAtEnd] = useState(false)
30
- const [isAtStart, setIsAtStart] = useState(true)
31
- const [totalPages, setTotalPages] = useState(0)
32
-
33
27
  const displayNavigation = hasNavigation
34
28
  const displayPagination = hasPagination
35
29
 
36
- useEffect(() => {
37
- if (loop) {
38
- setIsAtStart(false)
39
- setIsAtEnd(false)
40
- } else {
41
- setIsAtStart(activeSlideIndex === 0)
42
- setIsAtEnd(activeSlideIndex === totalPages - 1)
43
- }
44
- }, [activeSlideIndex, totalPages, loop])
45
-
46
- const breakpoint = useBreakpointObserver({ sm: 768, md: 992, lg: 1200, xl: 1400 })
47
-
48
- useEffect(() => {
49
- setTotalPages(calculatePages(slides.length, slidesPerView[breakpoint], 1))
50
- }, [breakpoint, slidesPerView])
51
-
52
- useEffect(() => {
53
- const track = trackRef.current
54
- if (!track) return
55
-
56
- const handleScroll = () => {
57
- if (loop) {
58
- const slideWidth = track.scrollWidth / (slides.length * 3)
59
- const scrollLeft = track.scrollLeft
60
-
61
- // Repositionnement infini (uniquement si pas en navigation)
62
- if (!isNavigatingRef.current) {
63
- if (scrollLeft <= slideWidth * slides.length) {
64
- track.scrollLeft = scrollLeft + slideWidth * slides.length
65
- } else if (scrollLeft >= slideWidth * slides.length * 2) {
66
- track.scrollLeft = scrollLeft - slideWidth * slides.length
67
- }
68
- }
69
-
70
- const scrollPosition = track.scrollLeft + slideWidth / 2
71
- const domIndex = Math.floor(scrollPosition / slideWidth)
72
- const index = domIndex % slides.length
73
- setActiveDOMIndex(domIndex)
74
- setActiveSlideIndex(index)
75
- } else {
76
- const slideWidth = track.scrollWidth / slides.length
77
- const scrollPosition = track.scrollLeft + slideWidth / 2
78
- const index = Math.floor(scrollPosition / slideWidth)
79
- setActiveSlideIndex(Math.min(index, slides.length - 1))
80
- setActiveDOMIndex(index)
81
- }
82
- }
83
-
84
- track.addEventListener("scroll", handleScroll)
85
-
86
- // Position initiale au milieu en mode loop
87
- if (loop) {
88
- setTimeout(() => {
89
- const slideWidth = track.scrollWidth / (slides.length * 3)
90
- track.scrollLeft = slideWidth * slides.length
91
- }, 0)
92
- }
93
-
94
- return () => track.removeEventListener("scroll", handleScroll)
95
- }, [slides.length, loop])
96
-
97
- const style = Object.fromEntries(
98
- Object.entries(slidesPerView).map(([key, value]) => [`--ga-ds-slides-per-view-${key}`, `${value}`])
99
- )
100
-
101
- const goPrev = () => {
102
- if (!trackRef.current) return
103
- const allSlides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide")
104
- if (activeSlideIndex === 0 && !loop) return
105
-
106
- isNavigatingRef.current = true
107
-
108
- if (loop) {
109
- // En mode loop, on utilise l'index DOM actuel
110
- allSlides[activeDOMIndex - 1]?.scrollIntoView({
111
- behavior: "smooth",
112
- block: "nearest",
113
- inline: "start",
114
- })
115
- } else {
116
- const nextIndex = activeSlideIndex - 1
117
- allSlides[nextIndex]?.scrollIntoView({
118
- behavior: "smooth",
119
- block: "nearest",
120
- inline: "start",
121
- })
122
- }
123
-
124
- setTimeout(() => {
125
- isNavigatingRef.current = false
126
- }, 600)
127
- }
128
-
129
- const goNext = () => {
130
- if (!trackRef.current) return
131
- const allSlides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide")
132
-
133
- isNavigatingRef.current = true
134
-
135
- if (loop) {
136
- // En mode loop, on utilise l'index DOM actuel
137
- allSlides[activeDOMIndex + 1]?.scrollIntoView({
138
- behavior: "smooth",
139
- block: "nearest",
140
- inline: "start",
141
- })
142
- } else {
143
- const totalSlides = allSlides.length
144
- if (activeSlideIndex >= totalSlides - 1) return
145
- if (isAtEnd) return
146
-
147
- const nextIndex = activeSlideIndex + 1
148
- allSlides[nextIndex]?.scrollIntoView({
149
- behavior: "smooth",
150
- block: "nearest",
151
- inline: "start",
152
- })
153
- }
154
-
155
- setTimeout(() => {
156
- isNavigatingRef.current = false
157
- }, 600)
158
- }
159
-
160
- const goTo = (nextIndex: number) => {
161
- if (!trackRef.current) return
162
- const slides = trackRef.current.querySelectorAll(".ga-ds-carousel__slide")
163
- slides[nextIndex]?.scrollIntoView({
164
- behavior: "smooth",
165
- block: "nearest",
166
- inline: "start",
167
- })
168
- }
169
-
170
30
  const classes = ["ga-ds-carousel"]
171
31
 
172
32
  if (props.extraClassNames) {
@@ -177,103 +37,68 @@ export const Carousel = (props: CarouselProps) => {
177
37
  }
178
38
  }
179
39
 
40
+ const breakpoints = {
41
+ 0: { slidesPerView: slidesPerView.xs || slidesPerView.sm || 1 },
42
+ 576: { slidesPerView: slidesPerView.sm || 1 },
43
+ 992: { slidesPerView: slidesPerView.md || 2 },
44
+ 1200: { slidesPerView: slidesPerView.lg || 3 },
45
+ 1440: { slidesPerView: slidesPerView.xl || 4 },
46
+ }
47
+
180
48
  return (
181
- <div className={classes.join(" ")} style={style}>
182
- {navigation?.positionY === "top" && displayNavigation && (
183
- <CarouselNavigation goPrev={goPrev} goNext={goNext} isAtStart={isAtStart} isAtEnd={isAtEnd} />
184
- )}
185
- <div
186
- className="ga-ds-carousel__track"
187
- ref={trackRef}
188
- style={
189
- {
190
- "--ga-ds-space-between": `${spaceBetween / 10}rem`,
191
- } as React.CSSProperties
49
+ <div className={classes.join(" ")}>
50
+ {navigation?.positionY === "top" && displayNavigation && <CarouselNavigation />}
51
+
52
+ <Swiper
53
+ modules={[Navigation, Pagination, A11y]}
54
+ spaceBetween={spaceBetween}
55
+ breakpoints={breakpoints}
56
+ loop={loop}
57
+ navigation={
58
+ displayNavigation
59
+ ? {
60
+ prevEl: ".ga-ds-carousel__button--prev",
61
+ nextEl: ".ga-ds-carousel__button--next",
62
+ }
63
+ : false
64
+ }
65
+ pagination={
66
+ displayPagination && pagination
67
+ ? {
68
+ clickable: pagination.clickable,
69
+ el: ".ga-ds-carousel__dots",
70
+ bulletClass: "ga-ds-carousel__dot",
71
+ bulletActiveClass: "ga-ds-carousel__dot--active",
72
+ }
73
+ : false
192
74
  }
75
+ onSwiper={(swiper: SwiperType) => {
76
+ swiperRef.current = swiper
77
+ }}
78
+ className="ga-ds-carousel__track"
193
79
  >
194
80
  {context === "wp-editor"
195
81
  ? children
196
- : slides.map((child, index) => {
197
- return (
198
- <div
199
- key={index}
200
- className={`ga-ds-carousel__slide ${index === activeDOMIndex ? "ga-ds-carousel__slide--active" : ""}`}
201
- >
202
- {child}
203
- </div>
204
- )
205
- })}
206
- </div>
82
+ : slides.map((child, index) => (
83
+ <SwiperSlide key={index} className="ga-ds-carousel__slide">
84
+ {child}
85
+ </SwiperSlide>
86
+ ))}
87
+ </Swiper>
207
88
 
208
89
  <div className="ga-ds-carousel__navigation">
209
- {pagination && displayPagination && (
210
- <CarouselPagination
211
- totalPages={totalPages}
212
- activeSlideIndex={activeSlideIndex}
213
- goTo={goTo}
214
- clickable={pagination.clickable}
215
- />
216
- )}
217
- {displayNavigation && navigation?.positionY === "bottom" && (
218
- <CarouselNavigation goPrev={goPrev} goNext={goNext} isAtStart={isAtStart} isAtEnd={isAtEnd} />
219
- )}
90
+ {displayPagination && <div className="ga-ds-carousel__dots"></div>}
91
+ {displayNavigation && navigation?.positionY === "bottom" && <CarouselNavigation />}
220
92
  </div>
221
93
  </div>
222
94
  )
223
95
  }
224
96
 
225
- const CarouselNavigation = ({
226
- goPrev,
227
- goNext,
228
- isAtStart,
229
- isAtEnd,
230
- }: {
231
- goPrev: () => void
232
- goNext: () => void
233
- isAtStart: boolean
234
- isAtEnd: boolean
235
- }) => {
97
+ const CarouselNavigation = () => {
236
98
  return (
237
99
  <div className={`ga-ds-carousel__arrows`}>
238
- <Button
239
- extraClassNames={["ga-ds-carousel__button", "ga-ds-carousel__button--prev"]}
240
- icon="chevron-left"
241
- onClick={goPrev}
242
- disabled={isAtStart}
243
- />
244
- <Button
245
- extraClassNames={["ga-ds-carousel__button", "ga-ds-carousel__button--next"]}
246
- icon="chevron-right"
247
- onClick={goNext}
248
- disabled={isAtEnd}
249
- />
250
- </div>
251
- )
252
- }
253
-
254
- const CarouselPagination = ({
255
- totalPages,
256
- activeSlideIndex,
257
- goTo,
258
- clickable,
259
- }: {
260
- totalPages: number
261
- activeSlideIndex: number
262
- goTo: (nextIndex: number) => void
263
- clickable: boolean
264
- }) => {
265
- return (
266
- <div className="ga-ds-carousel__dots">
267
- {Array.from({ length: totalPages }, (_, index) => index).map((_, index) => (
268
- <span
269
- key={index}
270
- className={`ga-ds-carousel__dot ${index === activeSlideIndex ? "ga-ds-carousel__dot--active" : ""}`}
271
- onClick={() => clickable && goTo(index)}
272
- style={{
273
- cursor: clickable ? "pointer" : "default",
274
- }}
275
- ></span>
276
- ))}
100
+ <Button extraClassNames={["ga-ds-carousel__button", "ga-ds-carousel__button--prev"]} icon="chevron-left" />
101
+ <Button extraClassNames={["ga-ds-carousel__button", "ga-ds-carousel__button--next"]} icon="chevron-right" />
277
102
  </div>
278
103
  )
279
104
  }
@@ -3,6 +3,7 @@ import { WordpressDefault } from "../../global.types"
3
3
  export type CarouselAttributes = {
4
4
  context?: 'wp-editor'
5
5
  slidesPerView?: {
6
+ xs?: number
6
7
  sm: number
7
8
  md: number
8
9
  lg: number