242 lines
9.7 KiB
XML
242 lines
9.7 KiB
XML
/** THEME */
|
|
import Carousel from "$/base/Carousel/Carousel";
|
|
import Section, { ButtonSectionProps } from "$/uwil/Section";
|
|
import {
|
|
BgColorName,
|
|
ImageShapeName,
|
|
imageShapes,
|
|
} from "@/front/lib/constants";
|
|
import { cn } from "@/lib/utils";
|
|
import { CarouselProps, TextProps } from "@/types/front";
|
|
|
|
type CarouselSectionProps = CarouselProps & {
|
|
title?: TextProps;
|
|
subtitle?: TextProps;
|
|
description?: TextProps;
|
|
variant?: BgColorName;
|
|
button?: ButtonSectionProps;
|
|
sectionClassName?: string;
|
|
shape?: ImageShapeName;
|
|
};
|
|
|
|
/**
|
|
* CarouselSection
|
|
*
|
|
* A composed section component that displays:
|
|
* - optional textual content (title, subtitle, description)
|
|
* - an optional CTA button
|
|
* - a carousel of items
|
|
*
|
|
* This component acts as a wrapper around the `Section` layout component
|
|
* and injects a `Carousel` inside it.
|
|
*
|
|
* Behavior:
|
|
* - Only provided props are passed to `Section` (no empty fields).
|
|
* - The `button.icon` is conditionally added if defined.
|
|
* - The carousel is always rendered with the given `items` and `carousel` config.
|
|
*
|
|
* @param {CarouselSectionProps} props
|
|
*
|
|
* @property {TextProps} title - Optional title displayed at the top of the section
|
|
* @property {TextProps} subtitle - Optional subtitle displayed above or below the title
|
|
* @property {TextProps} description - Optional description text
|
|
* @property {BgColorName} variant - Visual theme (background color variant)
|
|
* @property {ButtonSectionProps} button - Optional CTA button
|
|
* @property {Array} props.items - List of items passed to the Carousel
|
|
* @property {ImageShapeName} shape - Optional Shape of each slider Image
|
|
* @property {Object} carousel - Swiper configuration (breakpoints, pagination, etc.)
|
|
*
|
|
* @example
|
|
* <CarouselSection
|
|
* variant="primary"
|
|
* title={{ text: "Featured products" }}
|
|
* description={{ text: "Discover our selection" }}
|
|
* button={{ href: "/shop", label: "See all" }}
|
|
* items={[...]}
|
|
* carousel={{ slidesPerView: 1 }}
|
|
* />
|
|
*/
|
|
export default function CarouselSection(props: CarouselSectionProps) {
|
|
const {
|
|
title,
|
|
subtitle,
|
|
description,
|
|
variant,
|
|
button,
|
|
items,
|
|
carousel,
|
|
sectionClassName,
|
|
shape = imageShapes.ROUNDED,
|
|
} = props;
|
|
const buttonProps = button
|
|
? {
|
|
button: {
|
|
href: button.href,
|
|
label: button.label,
|
|
...(button.icon
|
|
? {
|
|
icon: {
|
|
icon: button.icon.icon,
|
|
},
|
|
}
|
|
: {}),
|
|
},
|
|
}
|
|
: {};
|
|
return (
|
|
<Section
|
|
className={cn(sectionClassName)}
|
|
containerClassName="px-0"
|
|
variant={variant}
|
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
{...(title && {
|
|
title: {
|
|
text: title.text,
|
|
font: title.font,
|
|
weight: title.weight,
|
|
},
|
|
})}
|
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
{...(description && {
|
|
description: {
|
|
text: description.text,
|
|
font: description.font,
|
|
weight: description.weight,
|
|
},
|
|
})}
|
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
{...(subtitle && {
|
|
subtitle: {
|
|
text: subtitle.text,
|
|
font: subtitle.font,
|
|
weight: subtitle.weight,
|
|
},
|
|
})}
|
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
{...buttonProps}
|
|
>
|
|
<Carousel
|
|
shape={shape}
|
|
prevBtn={
|
|
<svg
|
|
width="55"
|
|
height="67"
|
|
viewBox="0 0 55 67"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<g filter="url(#filter0_d_7429_6669)">
|
|
<path
|
|
className="stroke-primary-foreground"
|
|
d="M27.5 1.5C33.1912 1.5 38.674 6.01701 42.8438 12.7158C46.971 19.3463 49.5 27.6486 49.5 34.291C49.4998 47.448 39.5909 57.5 27.5 57.5C15.4091 57.5 5.50021 47.448 5.5 34.291C5.5 27.6486 8.029 19.3463 12.1562 12.7158C16.326 6.01701 21.8088 1.5 27.5 1.5Z"
|
|
strokeWidth="3"
|
|
/>
|
|
<path
|
|
className="fill-primary-foreground"
|
|
d="M25.5072 21.7103L16.9811 30.6752C16.8259 30.8457 16.7042 31.0468 16.623 31.2669C16.4525 31.7034 16.4525 32.193 16.623 32.6295C16.7042 32.8496 16.8259 33.0507 16.9811 33.2212L25.5072 42.1861C25.6662 42.3533 25.8549 42.4859 26.0627 42.5763C26.2704 42.6668 26.4931 42.7134 26.7179 42.7134C27.172 42.7134 27.6075 42.5237 27.9286 42.1861C28.2497 41.8485 28.4301 41.3905 28.4301 40.9131C28.4301 40.4356 28.2497 39.9777 27.9286 39.6401L22.3014 33.7412L35.244 33.7412C35.6962 33.7412 36.13 33.5523 36.4498 33.216C36.7695 32.8798 36.9492 32.4237 36.9492 31.9482C36.9492 31.4727 36.7695 31.0166 36.4498 30.6804C36.13 30.3441 35.6962 30.1552 35.244 30.1552L22.3014 30.1552L27.9286 24.2564C28.0884 24.0897 28.2153 23.8914 28.3019 23.6729C28.3884 23.4544 28.433 23.22 28.433 22.9833C28.433 22.7467 28.3884 22.5123 28.3019 22.2938C28.2153 22.0753 28.0884 21.877 27.9286 21.7103C27.7701 21.5423 27.5815 21.4089 27.3737 21.3179C27.1659 21.2268 26.943 21.18 26.7179 21.18C26.4928 21.18 26.2699 21.2268 26.0621 21.3179C25.8543 21.4089 25.6657 21.5423 25.5072 21.7103Z"
|
|
/>
|
|
</g>
|
|
<defs>
|
|
<filter
|
|
id="filter0_d_7429_6669"
|
|
x="0"
|
|
y="0"
|
|
width="55"
|
|
height="67"
|
|
filterUnits="userSpaceOnUse"
|
|
colorInterpolationFilters="sRGB"
|
|
>
|
|
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
|
<feColorMatrix
|
|
in="SourceAlpha"
|
|
type="matrix"
|
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
|
result="hardAlpha"
|
|
/>
|
|
<feOffset dy="4" />
|
|
<feGaussianBlur stdDeviation="2" />
|
|
<feComposite in2="hardAlpha" operator="out" />
|
|
<feColorMatrix
|
|
type="matrix"
|
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
|
/>
|
|
<feBlend
|
|
mode="normal"
|
|
in2="BackgroundImageFix"
|
|
result="effect1_dropShadow_7429_6669"
|
|
/>
|
|
<feBlend
|
|
mode="normal"
|
|
in="SourceGraphic"
|
|
in2="effect1_dropShadow_7429_6669"
|
|
result="shape"
|
|
/>
|
|
</filter>
|
|
</defs>
|
|
</svg>
|
|
}
|
|
nextBtn={
|
|
<svg
|
|
width="56"
|
|
height="67"
|
|
viewBox="0 0 56 67"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<g filter="url(#filter0_d_7429_6696)">
|
|
<path
|
|
className="stroke-primary-foreground"
|
|
d="M28 1.5C33.8446 1.5 39.4518 6.03781 43.7051 12.7285C47.9196 19.3584 50.5 27.6561 50.5 34.291C50.4998 47.4178 40.3963 57.5 28 57.5C15.6037 57.5 5.50021 47.4178 5.5 34.291C5.5 27.6561 8.08039 19.3584 12.2949 12.7285C16.5482 6.03781 22.1554 1.5 28 1.5Z"
|
|
strokeWidth="3"
|
|
/>
|
|
<path
|
|
className="fill-primary-foreground"
|
|
d="M28.4461 42.1832L37.1536 33.2184C37.3121 33.0478 37.4364 32.8468 37.5193 32.6267C37.6934 32.1902 37.6934 31.7005 37.5193 31.264C37.4364 31.0439 37.3121 30.8429 37.1536 30.6723L28.4461 21.7075C28.2837 21.5403 28.0909 21.4077 27.8788 21.3172C27.6666 21.2267 27.4392 21.1802 27.2096 21.1802C26.7458 21.1802 26.3011 21.3699 25.9731 21.7075C25.6452 22.0451 25.461 22.503 25.461 22.9805C25.461 23.458 25.6452 23.9159 25.9731 24.2535L31.7201 30.1524L18.5021 30.1524C18.0402 30.1524 17.5973 30.3413 17.2707 30.6775C16.9441 31.0138 16.7606 31.4698 16.7606 31.9453C16.7606 32.4209 16.9441 32.8769 17.2707 33.2132C17.5973 33.5494 18.0402 33.7383 18.5021 33.7383L31.7201 33.7383L25.9731 39.6372C25.8099 39.8039 25.6804 40.0022 25.5919 40.2207C25.5035 40.4392 25.458 40.6735 25.458 40.9102C25.458 41.1469 25.5035 41.3813 25.5919 41.5997C25.6804 41.8182 25.8099 42.0165 25.9731 42.1832C26.135 42.3513 26.3276 42.4847 26.5399 42.5757C26.7521 42.6667 26.9797 42.7136 27.2096 42.7136C27.4395 42.7136 27.6671 42.6667 27.8793 42.5757C28.0916 42.4847 28.2842 42.3513 28.4461 42.1832Z"
|
|
/>
|
|
</g>
|
|
<defs>
|
|
<filter
|
|
id="filter0_d_7429_6696"
|
|
x="0"
|
|
y="0"
|
|
width="56"
|
|
height="67"
|
|
filterUnits="userSpaceOnUse"
|
|
colorInterpolationFilters="sRGB"
|
|
>
|
|
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
|
<feColorMatrix
|
|
in="SourceAlpha"
|
|
type="matrix"
|
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
|
result="hardAlpha"
|
|
/>
|
|
<feOffset dy="4" />
|
|
<feGaussianBlur stdDeviation="2" />
|
|
<feComposite in2="hardAlpha" operator="out" />
|
|
<feColorMatrix
|
|
type="matrix"
|
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
|
/>
|
|
<feBlend
|
|
mode="normal"
|
|
in2="BackgroundImageFix"
|
|
result="effect1_dropShadow_7429_6696"
|
|
/>
|
|
<feBlend
|
|
mode="normal"
|
|
in="SourceGraphic"
|
|
in2="effect1_dropShadow_7429_6696"
|
|
result="shape"
|
|
/>
|
|
</filter>
|
|
</defs>
|
|
</svg>
|
|
}
|
|
items={items}
|
|
carousel={carousel}
|
|
variant={variant}
|
|
/>
|
|
</Section>
|
|
);
|
|
}
|