diff --git a/.gitignore b/.gitignore index 461172fc..d83ff111 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +*storybook.log diff --git a/.storybook/main.ts b/.storybook/main.ts index fe121a2c..1bd3b515 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,4 +1,3 @@ -/** @type { import('@storybook/react-webpack5').StorybookConfig } */ import type { StorybookConfig } from "@storybook/nextjs" const config: StorybookConfig = { @@ -13,6 +12,6 @@ const config: StorybookConfig = { name: "@storybook/nextjs", options: {}, }, - staticDirs: ["..\\public"], + staticDirs: ["../public"], } export default config diff --git a/.storybook/preview.ts b/.storybook/preview.ts index b0fb2bdb..a5e2d6c0 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,4 +1,5 @@ import type { Preview } from "@storybook/react" +import "../src/app/globals.css" const preview: Preview = { initialGlobals: { diff --git a/package.json b/package.json index 6715780c..eb1b32a9 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,12 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "lint:fix": "next lint --fix", + "format": "prettier --write .", + "type-check": "tsc --noEmit", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "@headlessui/react": "^2.2.1", @@ -20,13 +25,16 @@ "algoliasearch": "^5.20.3", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "embla-carousel-autoplay": "^8.6.0", "embla-carousel-react": "^8.5.2", + "embla-carousel-wheel-gestures": "^8.1.0", "i18next": "^25.2.1", "i18next-browser-languagedetector": "^8.1.0", "js-cookie": "^3.0.5", "lodash": "^4.17.21", "next": "15.1.4", "next-intl": "^3.26.3", + "prettier": "^3.6.2", "react": "^19.0.0", "react-country-flag": "^3.1.0", "react-dom": "^19.0.0", diff --git a/src/components/atoms/Indicator/Indicator.tsx b/src/components/atoms/Indicator/Indicator.tsx deleted file mode 100644 index 6404cd4c..00000000 --- a/src/components/atoms/Indicator/Indicator.tsx +++ /dev/null @@ -1,76 +0,0 @@ -'use client'; -import { cn } from '@/lib/utils'; -import { useEffect, useRef, useState } from 'react'; - -interface IndicatorProps { - size?: 'small' | 'medium' | 'large'; - step: number; - maxStep: number; - className?: string; - variant?: 'light' | 'dark'; -} - -export function Indicator({ - variant = 'light', - size = 'medium', - step, - maxStep, - className, -}: IndicatorProps) { - const [wrapperWidth, setWrapperWidth] = useState(0); - - const wrapperRef = useRef(null); - - const baseClasses = { - light: 'rounded-md bg-tertiary/10 relative', - dark: 'rounded-md bg-primary/10 relative', - }; - const sizeClasses = { - small: 'w-full h-1', - medium: 'w-full h-1', - large: 'w-full h-1', - }; - - useEffect(() => { - window.addEventListener('resize', () => { - setWrapperWidth( - wrapperRef.current - ? wrapperRef.current.offsetWidth - : 0 - ); - }); - - return () => - window.removeEventListener('resize', () => null); - }, []); - - useEffect(() => { - setWrapperWidth( - wrapperRef.current - ? wrapperRef.current.offsetWidth - : 0 - ); - }, [wrapperRef]); - - return ( -
-
-
- ); -} diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts index 9923c938..0e23f968 100644 --- a/src/components/atoms/index.ts +++ b/src/components/atoms/index.ts @@ -1,41 +1,18 @@ -import { Button } from "./Button/Button" -import { IconButton } from "./IconButton/IconButton" -import { Avatar } from "./Avatar/Avatar" -import { Badge } from "./Badge/Badge" -import { Breadcrumbs } from "./Breadcrumbs/Breadcrumbs" -import { Checkbox } from "./Checkbox/Checkbox" -import { Chip } from "./Chip/Chip" -import { Divider } from "./Divider/Divider" -import { Indicator } from "./Indicator/Indicator" -import { Input } from "./Input/Input" -import { Textarea } from "./Textarea/Textarea" -import { PaginationButton } from "./PaginationButton/PaginationButton" -import { Card } from "./Card/Card" -import { StarRating } from "./StarRating/StarRating" -import { InteractiveStarRating } from "./InteractiveStarRating/InteractiveStarRating" -import { Label } from "./Label/Label" -import { TabsTrigger } from "./TabsTrigger/TabsTrigger" -import { NavigationItem } from "./NavigationItem/NavigationItem" -import { LogoutButton } from "./LogoutButton/LogoutButton" - -export { - Button, - IconButton, - Avatar, - Badge, - Breadcrumbs, - Checkbox, - Chip, - Divider, - Indicator, - Input, - Textarea, - PaginationButton, - Card, - StarRating, - InteractiveStarRating, - Label, - TabsTrigger, - NavigationItem, - LogoutButton, -} +export { Button } from "./Button/Button" +export { IconButton } from "./IconButton/IconButton" +export { Avatar } from "./Avatar/Avatar" +export { Badge } from "./Badge/Badge" +export { Breadcrumbs } from "./Breadcrumbs/Breadcrumbs" +export { Checkbox } from "./Checkbox/Checkbox" +export { Chip } from "./Chip/Chip" +export { Divider } from "./Divider/Divider" +export { Input } from "./Input/Input" +export { Textarea } from "./Textarea/Textarea" +export { PaginationButton } from "./PaginationButton/PaginationButton" +export { Card } from "./Card/Card" +export { StarRating } from "./StarRating/StarRating" +export { InteractiveStarRating } from "./InteractiveStarRating/InteractiveStarRating" +export { Label } from "./Label/Label" +export { TabsTrigger } from "./TabsTrigger/TabsTrigger" +export { NavigationItem } from "./NavigationItem/NavigationItem" +export { LogoutButton } from "./LogoutButton/LogoutButton" diff --git a/src/components/cells/Carousel/Carousel.stories.tsx b/src/components/cells/Carousel/Carousel.stories.tsx new file mode 100644 index 00000000..540e334f --- /dev/null +++ b/src/components/cells/Carousel/Carousel.stories.tsx @@ -0,0 +1,510 @@ +import type { Meta, StoryObj } from "@storybook/react" +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselPrevious, + CarouselNext, + CarouselDots, + CarouselProgress, + CarouselThumbnails, + useCarousel, +} from "./Carousel" +import Autoplay from "embla-carousel-autoplay" + +// ============================================================================ +// Helper Components for Stories +// ============================================================================ + +function DemoSlide({ + index, + color, + title, +}: { + index: number + color: string + title?: string +}) { + return ( +
+
+
{index}
+ {title &&
{title}
} +
+
+ ) +} + +function ProductSlide({ index }: { index: number }) { + return ( +
+
+ 🏥 +
+

Medical Product {index}

+

+ High quality medical product description +

+
+ $299.99 + +
+
+ ) +} + +function CustomNumberIndicator() { + const { selectedIndex, slideCount, scrollTo } = useCarousel() + + return ( +
+ {Array.from({ length: slideCount }).map((_, i) => ( + + ))} +
+ ) +} + +// ============================================================================ +// Shared Data +// ============================================================================ + +const colors = [ + "bg-gradient-to-br from-blue-500 to-blue-700", + "bg-gradient-to-br from-purple-500 to-purple-700", + "bg-gradient-to-br from-pink-500 to-pink-700", + "bg-gradient-to-br from-green-500 to-green-700", + "bg-gradient-to-br from-orange-500 to-orange-700", +] + +const slides = colors.map((color, i) => ( + +)) + +const heroSlides = [ + { + id: 1, + color: "bg-gradient-to-r from-blue-600 to-cyan-500", + title: "Medical Equipment", + }, + { + id: 2, + color: "bg-gradient-to-r from-purple-600 to-pink-500", + title: "Professional Machinery", + }, + { + id: 3, + color: "bg-gradient-to-r from-green-600 to-teal-500", + title: "Pharmaceutical Products", + }, +] + +const productSlides = Array.from({ length: 8 }).map((_, i) => ( + +)) + +const thumbnails = colors.map((_, i) => ({ + id: `thumb-${i}`, + url: `https://placehold.co/200x200/${ + ["3B82F6", "A855F7", "EC4899", "10B981", "F97316"][i] + }/FFFFFF?text=${i + 1}`, +})) + +// ============================================================================ +// Meta Configuration +// ============================================================================ + +const meta: Meta = { + title: "Components/Cells/Carousel", + component: Carousel, + parameters: { + layout: "padded", + }, + tags: ["autodocs"], +} + +export default meta +type Story = StoryObj + +// ============================================================================ +// Stories +// ============================================================================ + +export const WithDots: Story = { + name: "1. Carousel with Dots", + render: () => ( + + + {slides.map((slide, index) => ( + {slide} + ))} + + + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Simple carousel with dot indicators. Ideal for hero sections or featured content.", + }, + }, + }, +} + +export const WithProgress: Story = { + name: "2. Carousel with Progress Bar", + render: () => ( + + + {slides.slice(0, 4).map((slide, index) => ( + {slide} + ))} + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Carousel with progress bar. Perfect for showing progress through a sequence.", + }, + }, + }, +} + +export const WithThumbnails: Story = { + name: "3. Carousel with Thumbnails", + render: () => ( + + + {slides.map((slide, index) => ( + {slide} + ))} + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Carousel with navigable thumbnails. Ideal for product galleries.", + }, + }, + }, +} + +export const WithAutoplay: Story = { + name: "4. Carousel with Autoplay", + render: () => ( + + + {heroSlides.map((slide) => ( + + + + ))} + + + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Carousel with automatic playback. Perfect for banners and promotional slides.", + }, + }, + }, +} + +export const WithOutsideArrows: Story = { + name: "5. Carousel with Outside Arrows", + render: () => ( +
+ + + {productSlides.map((slide, index) => ( + {slide} + ))} + + + +
+ +
+
+
+ ), + parameters: { + docs: { + description: { + story: + "Carousel with arrows positioned outside the content. Useful when you don't want arrows to overlap.", + }, + }, + }, +} + +export const BasicComposable: Story = { + name: "6. Basic Composable Pattern", + render: () => ( + + + {slides.map((slide, i) => ( + {slide} + ))} + + + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Use individual components to create custom layouts. Full control over positioning.", + }, + }, + }, +} + +export const CustomLayout: Story = { + name: "7. Custom Layout", + render: () => ( + + + {slides.slice(0, 4).map((slide, i) => ( + {slide} + ))} + +
+ +
+ +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Indicators and controls in a custom layout. Arrows and progress in a row.", + }, + }, + }, +} + +export const CustomIndicator: Story = { + name: "8. Custom Indicator with useCarousel", + render: () => ( + + + {slides.map((slide, i) => ( + {slide} + ))} + + + + + + ), + parameters: { + docs: { + description: { + story: "Create fully custom indicators using the useCarousel hook.", + }, + }, + }, +} + +export const Vertical: Story = { + name: "9. Vertical Carousel", + render: () => ( + + + {slides.slice(0, 3).map((slide, i) => ( + + {slide} + + ))} + + + + + ), + parameters: { + docs: { + description: { + story: + "Vertical orientation for special layouts. Arrows adjust automatically.", + }, + }, + }, +} + +export const MultipleVisible: Story = { + name: "10. Multiple Slides Visible", + render: () => ( + + + {productSlides.map((slide, i) => ( + + {slide} + + ))} + + + +
+ +
+
+ ), + parameters: { + docs: { + description: { + story: + "Show multiple slides at once by adjusting the basis of CarouselItem.", + }, + }, + }, +} + +export const CustomProgressColors: Story = { + name: "11. Custom Progress Colors", + render: () => ( +
+ {/* Default colors */} +
+

Default (Brand Blue)

+ + + {slides.slice(0, 3).map((slide, i) => ( + {slide} + ))} + +
+ +
+
+
+ + {/* Green variant */} +
+

Green (Success)

+ + + {slides.slice(0, 3).map((slide, i) => ( + {slide} + ))} + +
+ +
+
+
+ + {/* Purple variant */} +
+

Purple (Custom)

+ + + {slides.slice(0, 3).map((slide, i) => ( + {slide} + ))} + +
+ +
+
+
+
+ ), + parameters: { + docs: { + description: { + story: + "Customize the track (background) and fill (progress) colors of the indicator.", + }, + }, + }, +} diff --git a/src/components/cells/Carousel/Carousel.tsx b/src/components/cells/Carousel/Carousel.tsx index e8daa49b..2deda7f0 100644 --- a/src/components/cells/Carousel/Carousel.tsx +++ b/src/components/cells/Carousel/Carousel.tsx @@ -1,83 +1,421 @@ "use client" -import useEmblaCarousel from "embla-carousel-react" - -import { Indicator } from "@/components/atoms" +import * as React from "react" +import useEmblaCarousel, { + type UseEmblaCarouselType, +} from "embla-carousel-react" +import WheelGesturesPlugin from "embla-carousel-wheel-gestures" import { ArrowLeftIcon, ArrowRightIcon } from "@/icons" -import { useCallback, useEffect, useState } from "react" -import { EmblaCarouselType } from "embla-carousel" -import tailwindConfig from "../../../../tailwind.config" - -export const CustomCarousel = ({ - variant = "light", - items, - align = "start", -}: { - variant?: "light" | "dark" - items: React.ReactNode[] - align?: "center" | "start" | "end" -}) => { - const [emblaRef, emblaApi] = useEmblaCarousel({ - loop: true, - align, - }) - - const [selectedIndex, setSelectedIndex] = useState(0) - - const maxStep = items.length - - const onSelect = useCallback((emblaApi: EmblaCarouselType) => { - setSelectedIndex(emblaApi.selectedScrollSnap()) +import { cn } from "@/lib/utils" +import Image from "next/image" + +// ============================================================================ +// Types +// ============================================================================ + +type CarouselApi = UseEmblaCarouselType[1] +type UseCarouselParameters = Parameters +type CarouselOptions = UseCarouselParameters[0] +type CarouselPlugin = UseCarouselParameters[1] + +type CarouselProps = { + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" + setApi?: (api: CarouselApi) => void + disableWheelGestures?: boolean +} + +type CarouselContextProps = { + carouselRef: ReturnType[0] + api: ReturnType[1] + scrollPrev: () => void + scrollNext: () => void + canScrollPrev: boolean + canScrollNext: boolean + selectedIndex: number + slideCount: number + scrollTo: (index: number) => void + scrollProgress: number +} & CarouselProps + +// ============================================================================ +// Context +// ============================================================================ + +const CarouselContext = React.createContext(null) + +export function useCarousel() { + const context = React.useContext(CarouselContext) + + if (!context) { + throw new Error("useCarousel must be used within a ") + } + + return context +} + +// ============================================================================ +// Base Carousel Component +// ============================================================================ + +export function Carousel({ + orientation = "horizontal", + opts, + setApi, + plugins, + disableWheelGestures = false, + className, + children, + ...props +}: React.ComponentProps<"div"> & CarouselProps) { + // Merge WheelGesturesPlugin with user-provided plugins unless disabled + const allPlugins = React.useMemo(() => { + return [ + ...(plugins ?? []), + ...(disableWheelGestures + ? [] + : [WheelGesturesPlugin({ forceWheelAxis: "x" })]), + ] + }, [plugins, disableWheelGestures]) + + const [carouselRef, api] = useEmblaCarousel( + { + skipSnaps: true, + axis: orientation === "horizontal" ? "x" : "y", + ...opts, + }, + allPlugins + ) + const [canScrollPrev, setCanScrollPrev] = React.useState(false) + const [canScrollNext, setCanScrollNext] = React.useState(false) + const [selectedIndex, setSelectedIndex] = React.useState(0) + const [slideCount, setSlideCount] = React.useState(0) + const [scrollProgress, setScrollProgress] = React.useState(0) + + const onSelect = React.useCallback((api: CarouselApi) => { + if (!api) return + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + + const currentSnap = api.selectedScrollSnap() + const snapCount = api.scrollSnapList().length + + setSelectedIndex(currentSnap) + setSlideCount(api.slideNodes().length) + + // Calculate progress based on snap position (handles multiple visible slides) + const progress = snapCount > 1 ? currentSnap / (snapCount - 1) : 0 + setScrollProgress(progress) }, []) - useEffect(() => { - if (!emblaApi) return + const scrollPrev = React.useCallback(() => { + api?.scrollPrev() + }, [api]) - onSelect(emblaApi) - emblaApi.on("reInit", onSelect).on("select", onSelect) - }, [emblaApi, onSelect]) + const scrollNext = React.useCallback(() => { + api?.scrollNext() + }, [api]) - const changeSlideHandler = useCallback( + const scrollTo = React.useCallback( (index: number) => { - if (!emblaApi) return - emblaApi.scrollTo(index) + api?.scrollTo(index) }, - [emblaApi] + [api] ) - const arrowColor = { - light: tailwindConfig.theme.extend.colors.primary, - dark: tailwindConfig.theme.extend.colors.tertiary, - } + const handleKeyDown = React.useCallback( + (event: React.KeyboardEvent) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, + [scrollPrev, scrollNext] + ) + + React.useEffect(() => { + if (!api || !setApi) return + setApi(api) + }, [api, setApi]) + + React.useEffect(() => { + if (!api) return + + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api.off("select", onSelect) + } + }, [api, onSelect]) return ( -
+
-
- {items.map((slide) => slide)} -
- -
-
- -
-
- - -
-
+ {children}
+
+ ) +} + +// ============================================================================ +// CarouselContent & CarouselItem +// ============================================================================ + +export function CarouselContent({ + className, + ...props +}: React.ComponentProps<"div">) { + const { carouselRef, orientation } = useCarousel() + + return ( +
+
) } + +export function CarouselItem({ + className, + ...props +}: React.ComponentProps<"div">) { + const { orientation } = useCarousel() + + return ( +
+ ) +} + +// ============================================================================ +// Arrow Navigation Components +// ============================================================================ + +export function CarouselPrevious({ + className, + children, + ...props +}: React.ComponentProps<"button">) { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + + ) +} + +export function CarouselNext({ + className, + children, + ...props +}: React.ComponentProps<"button">) { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + + ) +} + +// ============================================================================ +// Indicator Components +// ============================================================================ + +export function CarouselDots({ + className, + ...props +}: React.ComponentProps<"div">) { + const { selectedIndex, slideCount, scrollTo } = useCarousel() + + return ( +
+ {Array.from({ length: slideCount }).map((_, index) => ( +
+ ) +} + +export function CarouselProgress({ + className, + trackClassName, + fillClassName, + ...props +}: React.ComponentProps<"div"> & { + trackClassName?: string + fillClassName?: string +}) { + const { scrollProgress } = useCarousel() + + // Use Embla's scrollProgress (0-1) - automatically handles multiple visible slides + const progress = Math.max(0, Math.min(100, scrollProgress * 100)) + + return ( +
+
+
+ ) +} + +type ThumbnailData = { + id: string + url: string +} + +export function CarouselThumbnails({ + thumbnails, + className, + ...props +}: React.ComponentProps<"div"> & { + thumbnails: ThumbnailData[] +}) { + const { selectedIndex, scrollTo, orientation } = useCarousel() + + return ( +
+ {thumbnails.map((thumbnail, index) => ( + + ))} +
+ ) +} + +// ============================================================================ +// Exports +// ============================================================================ + +export type { CarouselApi, CarouselOptions, CarouselPlugin, ThumbnailData } diff --git a/src/components/cells/ProductCarousel/ProductCarousel.tsx b/src/components/cells/ProductCarousel/ProductCarousel.tsx index d2cc8d28..72c3b427 100644 --- a/src/components/cells/ProductCarousel/ProductCarousel.tsx +++ b/src/components/cells/ProductCarousel/ProductCarousel.tsx @@ -1,10 +1,10 @@ "use client" -import useEmblaCarousel from "embla-carousel-react" import { HttpTypes } from "@medusajs/types" import Image from "next/image" import { ProductCarouselIndicator } from "@/components/molecules" import { useScreenSize } from "@/hooks/useScreenSize" +import { Carousel, CarouselContent, CarouselItem } from "@/components/cells" export const ProductCarousel = ({ slides = [], @@ -13,26 +13,24 @@ export const ProductCarousel = ({ }) => { const screenSize = useScreenSize() - const [emblaRef, emblaApi] = useEmblaCarousel({ - axis: - screenSize === "xs" || screenSize === "sm" || screenSize === "md" - ? "x" - : "y", - loop: true, - align: "start", - }) - return ( -
-
+ -
+ {(slides || []).map((slide, idx) => ( -
-
+ ))} -
- {slides?.length ? ( - - ) : null} -
+ + {slides?.length ? : null} +
) } diff --git a/src/components/cells/index.ts b/src/components/cells/index.ts index 6086b67d..f6daff34 100644 --- a/src/components/cells/index.ts +++ b/src/components/cells/index.ts @@ -1,67 +1,46 @@ -import { Navbar } from "./Navbar/Navbar" -import { CustomCarousel as Carousel } from "./Carousel/Carousel" -import { Pagination } from "./Pagination/Pagination" -import { ProductFilter } from "./ProductFilter/ProductFilter" -import { BrandFilter } from "./BrandFilter/BrandFilter" -import { PriceFilter } from "./PriceFilter/PriceFilter" -import { SizeFilter } from "./SizeFilter/SizeFilter" -import { ConditionFilter } from "./ConditionFilter/ConditionFilter" -import { ColorFilter } from "./ColorFilter/ColorFilter" -import { SellerRatingFilter } from "./SellerRatingFilter/SellerRatingFilter" -import { ActiveFilterElement } from "./ActiveFilterElement/ActiveFilterElement" -import { MobileNavbar } from "./MobileNavbar/MobileNavbar" -import { ProductDetailsHeader } from "./ProductDetailsHeader/ProductDetailsHeader" -import { ProductPageDetails } from "./ProductPageDetails/ProductPageDetails" -import { ProductDetailsMeasurements } from "./ProductDetailsMeasurements/ProductDetailsMeasurements" -import { ProductDetailsShipping } from "./ProductDetailsShipping/ProductDetailsShipping" -import { ProductDetailsSeller } from "./ProductDetailsSeller/ProductDetailsSeller" -import { ProductDetailsSellerReviews } from "./ProductDetailsSellerReviews/ProductDetailsSellerReviews" -import { ProductDetailsFooter } from "./ProductDetailsFooter/ProductDetailsFooter" -import { ProductCarousel } from "./ProductCarousel/ProductCarousel" -import { SellerReviewTab } from "./SellerReviewTab/SellerReviewTab" -import { CartItemsHeader } from "./CartItemsHeader/CartItemsHeader" -import { CartItemsFooter } from "./CartItemsFooter/CartItemsFooter" -import { CartItemsProducts } from "./CartItemsProducts/CartItemsProducts" -import { HeadingCategories } from "./HeadingCategories/HeadingCategories" -import { CartDropdown } from "./CartDropdown/CartDropdown" -import { LabeledInput } from "./LabeledInput/LabeledInput" -import { OrderAddresses } from "./OrderAddresses/OrderAddresses" -import { OrderProductListItem } from "./OrderProductListItem/OrderProductListItem" -import { OrderTimeline } from "./OrderTimeline/OrderTimeline" -import { WishlistItem } from "./WishlistItem/WishlistItem" -import { ProductAdditionalAttributes } from "./ProductAdditionalAttributes/ProductAdditionalAttributes" - +export { Navbar } from "./Navbar/Navbar" export { - Navbar, Carousel, - Pagination, - ProductFilter, - BrandFilter, - PriceFilter, - SizeFilter, - ConditionFilter, - ColorFilter, - SellerRatingFilter, - ActiveFilterElement, - MobileNavbar, - ProductDetailsHeader, - ProductPageDetails, - ProductDetailsMeasurements, - ProductDetailsShipping, - ProductDetailsSeller, - ProductDetailsSellerReviews, - ProductDetailsFooter, - ProductCarousel, - SellerReviewTab, - CartItemsHeader, - CartItemsFooter, - CartItemsProducts, - HeadingCategories, - CartDropdown, - LabeledInput, - OrderAddresses, - OrderProductListItem, - OrderTimeline, - WishlistItem, - ProductAdditionalAttributes, -} + CarouselContent, + CarouselItem, + CarouselPrevious, + CarouselNext, + CarouselDots, + CarouselProgress, + CarouselThumbnails, + useCarousel, + type CarouselApi, + type CarouselOptions, + type CarouselPlugin, + type ThumbnailData, +} from "./Carousel/Carousel" +export { Pagination } from "./Pagination/Pagination" +export { ProductFilter } from "./ProductFilter/ProductFilter" +export { BrandFilter } from "./BrandFilter/BrandFilter" +export { PriceFilter } from "./PriceFilter/PriceFilter" +export { SizeFilter } from "./SizeFilter/SizeFilter" +export { ConditionFilter } from "./ConditionFilter/ConditionFilter" +export { ColorFilter } from "./ColorFilter/ColorFilter" +export { SellerRatingFilter } from "./SellerRatingFilter/SellerRatingFilter" +export { ActiveFilterElement } from "./ActiveFilterElement/ActiveFilterElement" +export { MobileNavbar } from "./MobileNavbar/MobileNavbar" +export { ProductDetailsHeader } from "./ProductDetailsHeader/ProductDetailsHeader" +export { ProductPageDetails } from "./ProductPageDetails/ProductPageDetails" +export { ProductDetailsMeasurements } from "./ProductDetailsMeasurements/ProductDetailsMeasurements" +export { ProductDetailsShipping } from "./ProductDetailsShipping/ProductDetailsShipping" +export { ProductDetailsSeller } from "./ProductDetailsSeller/ProductDetailsSeller" +export { ProductDetailsSellerReviews } from "./ProductDetailsSellerReviews/ProductDetailsSellerReviews" +export { ProductDetailsFooter } from "./ProductDetailsFooter/ProductDetailsFooter" +export { ProductCarousel } from "./ProductCarousel/ProductCarousel" +export { SellerReviewTab } from "./SellerReviewTab/SellerReviewTab" +export { CartItemsHeader } from "./CartItemsHeader/CartItemsHeader" +export { CartItemsFooter } from "./CartItemsFooter/CartItemsFooter" +export { CartItemsProducts } from "./CartItemsProducts/CartItemsProducts" +export { HeadingCategories } from "./HeadingCategories/HeadingCategories" +export { CartDropdown } from "./CartDropdown/CartDropdown" +export { LabeledInput } from "./LabeledInput/LabeledInput" +export { OrderAddresses } from "./OrderAddresses/OrderAddresses" +export { OrderProductListItem } from "./OrderProductListItem/OrderProductListItem" +export { OrderTimeline } from "./OrderTimeline/OrderTimeline" +export { WishlistItem } from "./WishlistItem/WishlistItem" +export { ProductAdditionalAttributes } from "./ProductAdditionalAttributes/ProductAdditionalAttributes" diff --git a/src/components/molecules/ProductCarouselIndicator/ProductCarouselIndicator.tsx b/src/components/molecules/ProductCarouselIndicator/ProductCarouselIndicator.tsx index 9cc054aa..1e5c18cb 100644 --- a/src/components/molecules/ProductCarouselIndicator/ProductCarouselIndicator.tsx +++ b/src/components/molecules/ProductCarouselIndicator/ProductCarouselIndicator.tsx @@ -1,88 +1,92 @@ "use client" import Image from "next/image" import { HttpTypes } from "@medusajs/types" -import { EmblaCarouselType } from "embla-carousel" -import { useCallback, useEffect, useState } from "react" +import { useCallback } from "react" import { cn } from "@/lib/utils" -import { Indicator } from "@/components/atoms" -import useEmblaCarousel from "embla-carousel-react" +import { + Carousel, + CarouselContent, + CarouselItem, + useCarousel, +} from "@/components/cells" -export const ProductCarouselIndicator = ({ - slides = [], - embla: parentEmbla, +function ThumbnailsCarousel({ + slides, }: { slides: HttpTypes.StoreProduct["images"] - embla?: EmblaCarouselType -}) => { - const [selectedIndex, setSelectedIndex] = useState(0) - - const [emblaRef, emblaApi] = useEmblaCarousel({ - axis: "y", - loop: true, - align: "start", - }) +}) { + const { selectedIndex, scrollTo, api: parentApi } = useCarousel() const changeSlideHandler = useCallback( (index: number) => { - if (!parentEmbla) return - parentEmbla.scrollTo(index) - - if (!emblaApi) return - emblaApi.scrollTo(index) + if (!parentApi) return + scrollTo(index) }, - [parentEmbla, emblaApi] + [parentApi, scrollTo] ) - const onSelect = useCallback((emblaApi: EmblaCarouselType) => { - setSelectedIndex(emblaApi.selectedScrollSnap()) - }, []) - - useEffect(() => { - if (!parentEmbla) return + return ( +
+ + + {(slides || []).map((slide, index) => ( + changeSlideHandler(index)} + > + + + ))} + + +
+ ) +} - onSelect(parentEmbla) - parentEmbla.on("reInit", onSelect).on("select", onSelect) - }, [parentEmbla, onSelect]) +export const ProductCarouselIndicator = ({ + slides = [], +}: { + slides: HttpTypes.StoreProduct["images"] +}) => { + const { selectedIndex } = useCarousel() + const totalSlides = slides?.length || 0 + const progress = + totalSlides > 0 ? ((selectedIndex + 1) / totalSlides) * 100 : 0 return ( -
-
- + {/* Mobile Progress Bar */} +
+
-
-
-
- {(slides || []).map((slide, index) => ( -
changeSlideHandler(index)} - > - -
- ))} -
-
-
+ {/* Desktop Thumbnails */} +
) } diff --git a/src/components/organisms/CartItems/EmptyCart.tsx b/src/components/organisms/CartItems/EmptyCart.tsx index 26bb6273..f897efca 100644 --- a/src/components/organisms/CartItems/EmptyCart.tsx +++ b/src/components/organisms/CartItems/EmptyCart.tsx @@ -1,5 +1,5 @@ import { Button } from "@/components/atoms" -import { Carousel } from "@/components/cells" +import { Carousel, CarouselContent, CarouselItem } from "@/components/cells" import LocalizedClientLink from "@/components/molecules/LocalizedLink/LocalizedLink" import { listCategories } from "@/lib/data/categories" import { CategoryCard } from "../CategoryCard/CategoryCard" @@ -20,11 +20,15 @@ export const EmptyCart = async () => {
- ( - - ))} - /> + + + {categories?.map((category) => ( + + + + ))} + +
) } diff --git a/src/components/organisms/HomeProductsCarousel/AlgoliaProductsCarousel.tsx b/src/components/organisms/HomeProductsCarousel/AlgoliaProductsCarousel.tsx index 6ebf8d22..2fdb4791 100644 --- a/src/components/organisms/HomeProductsCarousel/AlgoliaProductsCarousel.tsx +++ b/src/components/organisms/HomeProductsCarousel/AlgoliaProductsCarousel.tsx @@ -1,15 +1,22 @@ "use client" -import { HttpTypes } from "@medusajs/types" -import { Carousel } from "@/components/cells" +import type { HttpTypes } from "@medusajs/types" +import { Carousel, CarouselContent, CarouselItem } from "@/components/cells" import { client } from "@/lib/client" import { Configure, useHits } from "react-instantsearch" import { InstantSearchNext } from "react-instantsearch-nextjs" import { ProductCard } from "../ProductCard/ProductCard" import { listProducts } from "@/lib/data/products" -import { useEffect, useState } from "react" +import { useEffect, useMemo, useState } from "react" import { getProductPrice } from "@/lib/helpers/get-product-price" +// Shape of your Algolia hit. Extend with what ProductCard needs. +type ProductHit = { + objectID: string // product id + handle?: string // include this in your index if possible + // ...other fields used by +} + export const AlgoliaProductsCarousel = ({ locale, seller_handle, @@ -19,11 +26,17 @@ export const AlgoliaProductsCarousel = ({ seller_handle?: string currency_code: string }) => { - const filters = `${ - seller_handle - ? `NOT seller:null AND seller.handle:${seller_handle} AND ` - : "NOT seller:null AND " - }NOT seller.store_status:SUSPENDED AND supported_countries:${locale} AND variants.prices.currency_code:${currency_code}` + // Build Algolia filters once per relevant prop change + const filters = useMemo(() => { + const parts = [ + "NOT seller:null", + "NOT seller.store_status:SUSPENDED", + `supported_countries:${locale}`, + `variants.prices.currency_code:${currency_code}`, + ] + if (seller_handle) parts.splice(1, 0, `seller.handle:${seller_handle}`) + return parts.join(" AND ") + }, [locale, seller_handle, currency_code]) return ( @@ -34,27 +47,69 @@ export const AlgoliaProductsCarousel = ({ } const ProductsListing = ({ locale }: { locale: string }) => { - const [prod, setProd] = useState(null) - const { items } = useHits() + const { items } = useHits() + const [apiById, setApiById] = useState>( + new Map() + ) + + // Stable list of unique ids and handles so the effect only runs when hits actually change + const ids = useMemo( + () => Array.from(new Set(items.map((i) => i.objectID))), + [items] + ) + const handles = useMemo( + () => + Array.from( + new Set(items.map((i) => i.handle).filter(Boolean)) + ) as string[], + [items] + ) useEffect(() => { + let cancelled = false + + // No hits, clear and exit + if (ids.length === 0) { + setApiById(new Map()) + return () => { + cancelled = true + } + } + + // Fetch only the products we’re about to render. listProducts({ countryCode: locale, queryParams: { - limit: 99999, + limit: handles.length || ids.length, + handle: handles.length ? handles : undefined, + // Id filtering? fields: "*variants.calculated_price,*seller.reviews,-thumbnail,-images,-type,-tags,-variants.options,-options,-collection,-collection_id", }, - }).then(({ response }) => { - setProd(response.products) }) - }, []) + .then(({ response }) => { + if (cancelled) return + const map = new Map() + for (const p of response.products ?? []) { + const { cheapestPrice } = getProductPrice({ product: p }) + if (cheapestPrice) map.set(p.id, p) + } + setApiById(map) + }) + .catch(() => { + if (!cancelled) setApiById(new Map()) + }) + + return () => { + cancelled = true + } + }, [locale, ids, handles]) return ( <> -
-
- {!items.length ? ( +
+
+ {items.length === 0 ? (

no results

@@ -62,23 +117,21 @@ const ProductsListing = ({ locale }: { locale: string }) => {

) : ( -
- ( - + + {items.map((hit) => ( + { - const { cheapestPrice } = getProductPrice({ - product: p, - }) - return p.id === hit.objectID && Boolean(cheapestPrice) && p - })} - /> + className="basis-full md:basis-1/2 lg:basis-1/4" + > + + ))} - /> -
+ + )}
diff --git a/src/components/organisms/HomeProductsCarousel/HomeProductsCarousel.tsx b/src/components/organisms/HomeProductsCarousel/HomeProductsCarousel.tsx index da47fc9e..c279aced 100644 --- a/src/components/organisms/HomeProductsCarousel/HomeProductsCarousel.tsx +++ b/src/components/organisms/HomeProductsCarousel/HomeProductsCarousel.tsx @@ -1,8 +1,8 @@ -import { Carousel } from "@/components/cells" +import { Carousel, CarouselContent, CarouselItem } from "@/components/cells" import { ProductCard } from "../ProductCard/ProductCard" import { listProducts } from "@/lib/data/products" -import { Product } from "@/types/product" -import { HttpTypes } from "@medusajs/types" +import type { Product } from "@/types/product" +import type { HttpTypes } from "@medusajs/types" import { getProductPrice } from "@/lib/helpers/get-product-price" export const HomeProductsCarousel = async ({ @@ -15,48 +15,58 @@ export const HomeProductsCarousel = async ({ home: boolean }) => { const { - response: { products }, + response: { products = [] }, } = await listProducts({ countryCode: locale, queryParams: { limit: home ? 4 : undefined, order: "created_at", - handle: home - ? undefined - : sellerProducts.map((product) => product.handle), + handle: + !home && sellerProducts.length + ? sellerProducts.map((p) => p.handle) + : undefined, }, forceCache: !home, }) if (!products.length && !sellerProducts.length) return null + const allProducts = sellerProducts.length ? sellerProducts : products + + // For the non-home case, precompute a lookup of API products that have a price + const apiById: Map | undefined = + !home && products.length + ? new Map( + products + .filter((p) => { + const { cheapestPrice } = getProductPrice({ product: p }) + return !!cheapestPrice + }) + .map((p) => [p.id, p] as const) + ) + : undefined + return (
- ( - { - const { cheapestPrice } = getProductPrice({ - product: p, - }) - return ( - cheapestPrice && - p.id === product.id && - Boolean(cheapestPrice) - ) - }) - } - /> - ) - )} - /> + + + {allProducts.map((product) => { + const api_product = home + ? // If `product` is not actually a HttpTypes.StoreProduct, adapt it. + (product as unknown as HttpTypes.StoreProduct) + : apiById?.get(product.id) + + return ( + + + + ) + })} + +
) } diff --git a/src/components/sections/HomeCategories/HomeCategories.tsx b/src/components/sections/HomeCategories/HomeCategories.tsx index 7ee82947..00788280 100644 --- a/src/components/sections/HomeCategories/HomeCategories.tsx +++ b/src/components/sections/HomeCategories/HomeCategories.tsx @@ -1,4 +1,4 @@ -import { Carousel } from "@/components/cells" +import { Carousel, CarouselContent, CarouselItem } from "@/components/cells" import { CategoryCard } from "@/components/organisms" export const categories: { id: number; name: string; handle: string }[] = [ @@ -35,11 +35,18 @@ export const HomeCategories = async ({ heading }: { heading: string }) => {

{heading}

- ( - - ))} - /> + + + {categories?.map((category) => ( + + + + ))} + + ) } diff --git a/src/components/sections/HomePopularBrandsSection/HomePopularBrandsSection.tsx b/src/components/sections/HomePopularBrandsSection/HomePopularBrandsSection.tsx index 47c754e6..2cc1f97f 100644 --- a/src/components/sections/HomePopularBrandsSection/HomePopularBrandsSection.tsx +++ b/src/components/sections/HomePopularBrandsSection/HomePopularBrandsSection.tsx @@ -1,6 +1,6 @@ import { Brand } from '@/types/brands'; import { BrandCard } from '@/components/organisms'; -import { Carousel } from '@/components/cells'; +import { Carousel, CarouselContent, CarouselItem } from '@/components/cells'; const brands: Brand[] = [ { @@ -37,12 +37,18 @@ export function HomePopularBrandsSection() { POPULAR BRANDS
- ( - - ))} - /> + + + {brands.map((brand) => ( + + + + ))} + + ); } diff --git a/yarn.lock b/yarn.lock index 3ae53fd9..6b1608d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -155,7 +155,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz" integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg== -"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.18.9", "@babel/core@^7.24.4", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0": +"@babel/core@^7.18.9", "@babel/core@^7.24.4": version "7.26.7" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz" integrity sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA== @@ -1042,16 +1042,16 @@ resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz" integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== -"@esbuild/android-arm@0.24.2": - version "0.24.2" - resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz" - integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== - "@esbuild/android-arm64@0.24.2": version "0.24.2" resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz" integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== +"@esbuild/android-arm@0.24.2": + version "0.24.2" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz" + integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== + "@esbuild/android-x64@0.24.2": version "0.24.2" resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz" @@ -1077,16 +1077,16 @@ resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz" integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== -"@esbuild/linux-arm@0.24.2": - version "0.24.2" - resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz" - integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== - "@esbuild/linux-arm64@0.24.2": version "0.24.2" resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz" integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== +"@esbuild/linux-arm@0.24.2": + version "0.24.2" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz" + integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== + "@esbuild/linux-ia32@0.24.2": version "0.24.2" resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz" @@ -1269,7 +1269,7 @@ decimal.js "10" tslib "2" -"@formatjs/fast-memoize@^2.2.0", "@formatjs/fast-memoize@2.2.6": +"@formatjs/fast-memoize@2.2.6", "@formatjs/fast-memoize@^2.2.0": version "2.2.6" resolved "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz" integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw== @@ -1293,7 +1293,7 @@ "@formatjs/ecma402-abstract" "2.3.2" tslib "2" -"@formatjs/intl-localematcher@^0.5.4", "@formatjs/intl-localematcher@0.5.10": +"@formatjs/intl-localematcher@0.5.10", "@formatjs/intl-localematcher@^0.5.4": version "0.5.10" resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz" integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q== @@ -1368,16 +1368,16 @@ resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz" integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ== -"@img/sharp-libvips-linux-arm@1.0.5": - version "1.0.5" - resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz" - integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== - "@img/sharp-libvips-linux-arm64@1.0.4": version "1.0.4" resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz" integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA== +"@img/sharp-libvips-linux-arm@1.0.5": + version "1.0.5" + resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz" + integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== + "@img/sharp-libvips-linux-s390x@1.0.4": version "1.0.4" resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz" @@ -1398,13 +1398,6 @@ resolved "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz" integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw== -"@img/sharp-linux-arm@0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz" - integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== - optionalDependencies: - "@img/sharp-libvips-linux-arm" "1.0.5" - "@img/sharp-linux-arm64@0.33.5": version "0.33.5" resolved "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz" @@ -1412,6 +1405,13 @@ optionalDependencies: "@img/sharp-libvips-linux-arm64" "1.0.4" +"@img/sharp-linux-arm@0.33.5": + version "0.33.5" + resolved "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz" + integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.0.5" + "@img/sharp-linux-s390x@0.33.5": version "0.33.5" resolved "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz" @@ -1486,11 +1486,6 @@ dependencies: "@swc/helpers" "^0.5.0" -"@ioredis/commands@^1.1.1": - version "1.2.0" - resolved "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz" - integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== - "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" @@ -1650,7 +1645,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -3542,7 +3537,7 @@ dependencies: memoizerific "^1.11.3" -"@storybook/blocks@^8.4.7", "@storybook/blocks@8.5.3": +"@storybook/blocks@8.5.3", "@storybook/blocks@^8.4.7": version "8.5.3" resolved "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.5.3.tgz" integrity sha512-a/PpHFmeBtVB9Q/6cNAnqfeCqMowsrI8nGka0Nl7BB3x1eJnS3I1Qo3Skht0LBEsmXOgXk4dwWxpeQL3qHMRkw== @@ -3617,7 +3612,7 @@ dependencies: unplugin "^1.3.1" -"@storybook/csf@^0.1.11", "@storybook/csf@0.1.12": +"@storybook/csf@0.1.12", "@storybook/csf@^0.1.11": version "0.1.12" resolved "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.12.tgz" integrity sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw== @@ -3732,7 +3727,7 @@ resolved "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.5.3.tgz" integrity sha512-kNIGk6mpXW3Wy+uS9pH9b9w/54EPJnH+QXA6MX4EQgmxhMQlGlS/l/YZp+3jsVQW4YgTmqe740qB+ccJAKZxBQ== -"@storybook/react@^8.4.7", "@storybook/react@8.5.3": +"@storybook/react@8.5.3", "@storybook/react@^8.4.7": version "8.5.3" resolved "https://registry.npmjs.org/@storybook/react/-/react-8.5.3.tgz" integrity sha512-QIdBSjsnwV/J919i4Fi7DlwxDKHU815t0c4B/w2KTMtKKBkk+Bge+vgVi0/lNqD3eF4w3yjVWGbkzUQZ63yiPg== @@ -3744,7 +3739,7 @@ "@storybook/react-dom-shim" "8.5.3" "@storybook/theming" "8.5.3" -"@storybook/test@^8.4.7", "@storybook/test@8.5.3": +"@storybook/test@8.5.3", "@storybook/test@^8.4.7": version "8.5.3" resolved "https://registry.npmjs.org/@storybook/test/-/test-8.5.3.tgz" integrity sha512-2smoDbtU6Qh4yk0uD18qGfW6ll7lZBzKlF58Ha1CgWR4o+jpeeTQcfDLH9gG6sNrpojF7AVzMh/aN9BDHD+Chg== @@ -3770,7 +3765,7 @@ dependencies: prop-types "^15.7.2" -"@stripe/stripe-js@^7.1.0", "@stripe/stripe-js@>=1.44.1 <8.0.0": +"@stripe/stripe-js@^7.1.0": version "7.2.0" resolved "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.2.0.tgz" integrity sha512-BXlt6BsFE599yOATuz78FiW9z4SyipCH3j1SDyKWe/3OUBdhcOr/BWnBi1xrtcC2kfqrTJjgvfH2PTfMPRmbTw== @@ -3780,7 +3775,7 @@ resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@^0.5.0", "@swc/helpers@0.5.15": +"@swc/helpers@0.5.15", "@swc/helpers@^0.5.0": version "0.5.15" resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz" integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== @@ -3818,7 +3813,7 @@ resolved "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz" integrity sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg== -"@testing-library/dom@>=7.21.4", "@testing-library/dom@10.4.0": +"@testing-library/dom@10.4.0": version "10.4.0" resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz" integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== @@ -3981,12 +3976,12 @@ resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz" integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA== -"@types/react-dom@*", "@types/react-dom@^19": +"@types/react-dom@^19": version "19.0.3" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz" integrity sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA== -"@types/react@*", "@types/react@^19", "@types/react@^19.0.0", "@types/react@>=16": +"@types/react@^19": version "19.0.8" resolved "https://registry.npmjs.org/@types/react/-/react-19.0.8.tgz" integrity sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw== @@ -4023,7 +4018,7 @@ natural-compare "^1.4.0" ts-api-utils "^2.0.1" -"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0": +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": version "8.23.0" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz" integrity sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q== @@ -4071,7 +4066,7 @@ semver "^7.6.0" ts-api-utils "^2.0.1" -"@typescript-eslint/utils@^8.8.1", "@typescript-eslint/utils@8.23.0": +"@typescript-eslint/utils@8.23.0", "@typescript-eslint/utils@^8.8.1": version "8.23.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz" integrity sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA== @@ -4120,15 +4115,6 @@ dependencies: tinyspy "^3.0.0" -"@vitest/utils@^2.1.1": - version "2.1.9" - resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz" - integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ== - dependencies: - "@vitest/pretty-format" "2.1.9" - loupe "^3.1.2" - tinyrainbow "^1.2.0" - "@vitest/utils@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz" @@ -4139,7 +4125,16 @@ loupe "^3.1.1" tinyrainbow "^1.2.0" -"@webassemblyjs/ast@^1.14.1", "@webassemblyjs/ast@1.14.1": +"@vitest/utils@^2.1.1": + version "2.1.9" + resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz" + integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ== + dependencies: + "@vitest/pretty-format" "2.1.9" + loupe "^3.1.2" + tinyrainbow "^1.2.0" + +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz" integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== @@ -4240,7 +4235,7 @@ "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/wasm-parser" "1.14.1" -"@webassemblyjs/wasm-parser@^1.14.1", "@webassemblyjs/wasm-parser@1.14.1": +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz" integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== @@ -4287,7 +4282,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0, acorn@^8.8.2: +acorn@^8.14.0, acorn@^8.8.2: version "8.14.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -4319,7 +4314,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: +ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -4329,17 +4324,7 @@ ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0: - version "8.17.1" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -ajv@^8.8.2, ajv@^8.9.0: +ajv@^8.0.0, ajv@^8.9.0: version "8.17.1" resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -4356,7 +4341,7 @@ algoliasearch-helper@3.24.1: dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^5.20.3, "algoliasearch@>= 3.1 < 6": +algoliasearch@^5.20.3: version "5.20.3" resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.3.tgz" integrity sha512-iNC6BGvipaalFfDfDnXUje8GUlW5asj0cTMsZJwO/0rhsyLx1L7GZFAY8wW+eQ6AM4Yge2p5GSE5hrBlfSD90Q== @@ -4442,7 +4427,7 @@ aria-hidden@^1.2.4: dependencies: tslib "^2.0.0" -aria-query@^5.0.0, aria-query@5.3.0: +aria-query@5.3.0, aria-query@^5.0.0: version "5.3.0" resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== @@ -4591,14 +4576,6 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -awilix@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/awilix/-/awilix-8.0.1.tgz" - integrity sha512-zDSp4R204scvQIDb2GMoWigzXemn0+3AKKIAt543T9v2h7lmoypvkmcx1W/Jet/nm27R1N1AsqrsYVviAR9KrA== - dependencies: - camel-case "^4.1.2" - fast-glob "^3.2.12" - axe-core@^4.10.0: version "4.10.2" resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz" @@ -4673,17 +4650,7 @@ binary-extensions@^2.0.0: resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bn.js@^4.0.0: - version "4.12.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz" - integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== - -bn.js@^4.1.0: - version "4.12.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz" - integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== - -bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.1" resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz" integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== @@ -4793,7 +4760,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.24.0, browserslist@^4.24.3, "browserslist@>= 4.21.0": +browserslist@^4.24.0, browserslist@^4.24.3: version "4.24.4" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -4969,6 +4936,11 @@ client-only@0.0.1: resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +clsx@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== + clsx@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" @@ -4979,16 +4951,6 @@ clsx@^2.0.0, clsx@^2.1.1: resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== -clsx@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz" - integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== - -cluster-key-slot@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz" - integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -5326,11 +5288,6 @@ define-properties@^1.1.3, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -denque@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz" - integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== - dequal@^2.0.2, dequal@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" @@ -5479,6 +5436,11 @@ elliptic@^6.5.3, elliptic@^6.5.5: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +embla-carousel-autoplay@^8.6.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz#bc86c97de00d52ec34b05058736ef50af6e0d0e4" + integrity sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA== + embla-carousel-react@^8.5.2: version "8.5.2" resolved "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.5.2.tgz" @@ -5492,6 +5454,13 @@ embla-carousel-reactive-utils@8.5.2: resolved "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.5.2.tgz" integrity sha512-QC8/hYSK/pEmqEdU1IO5O+XNc/Ptmmq7uCB44vKplgLKhB/l0+yvYx0+Cv0sF6Ena8Srld5vUErZkT+yTahtDg== +embla-carousel-wheel-gestures@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/embla-carousel-wheel-gestures/-/embla-carousel-wheel-gestures-8.1.0.tgz#dfdb865f634058723c46539bdde45248673a43a5" + integrity sha512-J68jkYrxbWDmXOm2n2YHl+uMEXzkGSKjWmjaEgL9xVvPb3HqVmg6rJSKfI3sqIDVvm7mkeTy87wtG/5263XqHQ== + dependencies: + wheel-gestures "^2.2.5" + embla-carousel@8.5.2: version "8.5.2" resolved "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.2.tgz" @@ -5687,7 +5656,7 @@ esbuild-register@^3.5.0: dependencies: debug "^4.3.4" -"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", "esbuild@>=0.12 <1": +"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0": version "0.24.2" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz" integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== @@ -5774,7 +5743,7 @@ eslint-module-utils@^2.12.0: dependencies: debug "^3.2.7" -eslint-plugin-import@*, eslint-plugin-import@^2.31.0: +eslint-plugin-import@^2.31.0: version "2.31.0" resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== @@ -5858,14 +5827,6 @@ eslint-plugin-storybook@^0.11.2: "@typescript-eslint/utils" "^8.8.1" ts-dedent "^2.2.0" -eslint-scope@^8.2.0: - version "8.2.0" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz" - integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" @@ -5874,6 +5835,14 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" @@ -5884,7 +5853,7 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.23.0 || ^8.0.0 || ^9.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9, eslint@>=8: +eslint@^9: version "9.19.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz" integrity sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA== @@ -5997,27 +5966,27 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.12, fast-glob@^3.3.2: - version "3.3.3" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" - integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.8" + micromatch "^4.0.4" -fast-glob@3.3.1: - version "3.3.1" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.4" + micromatch "^4.0.8" fast-json-parse@^1.0.3: version "1.0.3" @@ -6267,7 +6236,7 @@ get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -6281,13 +6250,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" @@ -6494,7 +6456,7 @@ i18next-browser-languagedetector@^8.1.0: dependencies: "@babel/runtime" "^7.23.2" -i18next@^25.2.1, "i18next@>= 23.2.3": +i18next@^25.2.1: version "25.2.1" resolved "https://registry.npmjs.org/i18next/-/i18next-25.2.1.tgz" integrity sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw== @@ -6549,7 +6511,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4, inherits@2: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -6598,21 +6560,6 @@ intl-messageformat@^10.1.0, intl-messageformat@^10.5.14: "@formatjs/icu-messageformat-parser" "2.11.0" tslib "2" -ioredis@^5.4.1: - version "5.6.1" - resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz" - integrity sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA== - dependencies: - "@ioredis/commands" "^1.1.1" - cluster-key-slot "^1.1.0" - debug "^4.3.4" - denque "^2.1.0" - lodash.defaults "^4.2.0" - lodash.isarguments "^3.1.0" - redis-errors "^1.2.0" - redis-parser "^3.0.0" - standard-as-callback "^2.1.0" - is-arguments@^1.0.4: version "1.2.0" resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz" @@ -6892,7 +6839,7 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jiti@*, jiti@^1.20.0, jiti@^1.21.6: +jiti@^1.20.0, jiti@^1.21.6: version "1.21.7" resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== @@ -7027,16 +6974,7 @@ loader-runner@^4.2.0: resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^2.0.4: +loader-utils@^2.0.0, loader-utils@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== @@ -7076,16 +7014,6 @@ lodash.debounce@^4.0.8: resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" - integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== - -lodash.isarguments@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz" - integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" @@ -7295,7 +7223,7 @@ neo-async@^2.6.2: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -next-intl@^3, next-intl@^3.26.3: +next-intl@^3.26.3: version "3.26.3" resolved "https://registry.npmjs.org/next-intl/-/next-intl-3.26.3.tgz" integrity sha512-6Y97ODrDsEE1J8cXKMHwg1laLdtkN66QMIqG8BzH4zennJRUNTtM8UMtBDyhfmF6uiZ+xsbWLXmHUgmUymUsfQ== @@ -7304,7 +7232,7 @@ next-intl@^3, next-intl@^3.26.3: negotiator "^1.0.0" use-intl "^3.26.3" -"next@^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0", "next@^13.5.0 || ^14.0.0 || ^15.0.0", "next@>= 13.4 < 16", next@15.1.4: +next@15.1.4: version "15.1.4" resolved "https://registry.npmjs.org/next/-/next-15.1.4.tgz" integrity sha512-mTaq9dwaSuwwOrcu3ebjDYObekkxRnXpuVL21zotM8qE2W0HBOdVIdg2Li9QjMEZrj73LN96LcWcz62V19FjAg== @@ -7802,15 +7730,7 @@ postcss-nested@^6.2.0: dependencies: postcss-selector-parser "^6.1.1" -postcss-selector-parser@^6.1.1: - version "6.1.2" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz" - integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-selector-parser@^6.1.2: +postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: version "6.1.2" resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz" integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== @@ -7831,15 +7751,6 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^ resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -"postcss@^7.0.0 || ^8.0.1", postcss@^8, postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.47, postcss@>=8.0.9: - version "8.5.1" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz" - integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== - dependencies: - nanoid "^3.3.8" - picocolors "^1.1.1" - source-map-js "^1.2.1" - postcss@8.4.31: version "8.4.31" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" @@ -7849,6 +7760,15 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8, postcss@^8.2.14, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.47: + version "8.5.1" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz" + integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + preact@^10.10.0: version "10.26.1" resolved "https://registry.npmjs.org/preact/-/preact-10.26.1.tgz" @@ -7859,6 +7779,11 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" + integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== + pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" @@ -8121,13 +8046,6 @@ react-docgen@^7.0.0: resolve "^1.22.1" strip-indent "^4.0.0" -"react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom@^18 || ^19 || ^19.0.0-rc", "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@^19.0.0, "react-dom@>= 16.8.0 < 20", react-dom@>=16.8, react-dom@>=16.8.0, "react-dom@>=16.8.0 <20.0.0": - version "19.0.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz" - integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== - dependencies: - scheduler "^0.25.0" - "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0": version "18.3.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" @@ -8136,7 +8054,14 @@ react-docgen@^7.0.0: loose-envify "^1.1.0" scheduler "^0.23.2" -react-hook-form@^7.0.0, react-hook-form@^7.54.2: +react-dom@^19.0.0: + version "19.0.0" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz" + integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== + dependencies: + scheduler "^0.25.0" + +react-hook-form@^7.54.2: version "7.54.2" resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz" integrity sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg== @@ -8164,7 +8089,7 @@ react-instantsearch-nextjs@^0.4.4: resolved "https://registry.npmjs.org/react-instantsearch-nextjs/-/react-instantsearch-nextjs-0.4.4.tgz" integrity sha512-q133svbkuGFNyAwpFNIVamDMvyCE+iag9XMDwmHv+LVOK9BV00Nv9JM9ayU80d1R4DzIBns3yIfpD8ThbtfzRQ== -react-instantsearch@^7.15.3, "react-instantsearch@>= 7.1.0 < 8": +react-instantsearch@^7.15.3: version "7.15.3" resolved "https://registry.npmjs.org/react-instantsearch/-/react-instantsearch-7.15.3.tgz" integrity sha512-KDKvLgizxGRrHIy2RfFYvgw/VmyYHXLNk0TJkRpyoUClUhn1zoXwESFjSLz1n4AY/utkZkuhpfmJo9S7NfEqoQ== @@ -8184,7 +8109,7 @@ react-is@^17.0.1: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-refresh@^0.14.0, "react-refresh@>=0.10.0 <1.0.0": +react-refresh@^0.14.0: version "0.14.2" resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -8248,18 +8173,18 @@ react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: get-nonce "^1.0.0" tslib "^2.0.0" -"react@^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react@^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19 || ^19.0.0-rc", "react@^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^19.0.0, "react@>= 16.8.0", "react@>= 16.8.0 < 20", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16, react@>=16.0.0, react@>=16.8, react@>=16.8.0, "react@>=16.8.0 <20.0.0", react@>=17: - version "19.0.0" - resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz" - integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== - -"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.3.1: +"react@^16.8.0 || ^17.0.0 || ^18.0.0": 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== dependencies: loose-envify "^1.1.0" +react@^19.0.0: + version "19.0.0" + resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz" + integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz" @@ -8280,16 +8205,7 @@ readable-stream@^2.3.8: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.5.0: - version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^3.6.0: +readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -8335,18 +8251,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redis-errors@^1.0.0, redis-errors@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz" - integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== - -redis-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz" - integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== - dependencies: - redis-errors "^1.0.0" - reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: version "1.0.10" resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz" @@ -8524,12 +8428,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@~5.1.1: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -8570,16 +8469,7 @@ scheduler@^0.25.0: resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz" integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== -schema-utils@^3.1.1: - version "3.3.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^3.2.0: +schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -8603,12 +8493,7 @@ search-insights@^2.17.2: resolved "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz" integrity sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ== -semver@^6.0.0: - version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^6.3.1: +semver@^6.0.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -8780,7 +8665,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0: +source-map@0.6.1, source-map@^0.6.0, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8790,21 +8675,6 @@ source-map@^0.7.3: resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== -source-map@~0.6.0: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - stable-hash@^0.0.4: version "0.0.4" resolved "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz" @@ -8815,11 +8685,6 @@ stackframe@^1.3.4: resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz" integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== -standard-as-callback@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz" - integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== - storybook-i18n@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/storybook-i18n/-/storybook-i18n-3.1.1.tgz" @@ -8832,7 +8697,7 @@ storybook-next-intl@^1.2.4: dependencies: storybook-i18n "3.1.1" -"storybook@^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0", storybook@^8.4.7, storybook@^8.5.3: +storybook@^8.4.7: version "8.5.3" resolved "https://registry.npmjs.org/storybook/-/storybook-8.5.3.tgz" integrity sha512-2WtNBZ45u1AhviRU+U+ld588tH8gDa702dNSq5C8UBaE9PlOsazGsyp90dw1s9YRvi+ejrjKAupQAU0GwwUiVg== @@ -8862,20 +8727,6 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -string_decoder@^1.1.1, string_decoder@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -8971,6 +8822,20 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" +string_decoder@^1.1.1, string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -9021,7 +8886,7 @@ style-loader@^3.3.1: resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz" integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== -styled-jsx@^5.1.6, styled-jsx@5.1.6: +styled-jsx@5.1.6, styled-jsx@^5.1.6: version "5.1.6" resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz" integrity sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA== @@ -9098,7 +8963,7 @@ tailwindcss@^3.4.1: resolve "^1.22.8" sucrase "^3.35.0" -talkjs@^0.37.0, talkjs@>=0: +talkjs@^0.37.0: version "0.37.0" resolved "https://registry.npmjs.org/talkjs/-/talkjs-0.37.0.tgz" integrity sha512-oIfCcJ4hY/YXercUPDutKW6ynyNZ8/TQSSarrOrbmuPjuySjCtut1HW/WTHez0MnhbjvgBI/cgJVXf4l3oofSg== @@ -9226,7 +9091,7 @@ tsconfig-paths@^4.0.0, tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0, tslib@2: +tslib@2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -9248,7 +9113,7 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^2.14.0, type-fest@^2.19.0, "type-fest@>=0.17.0 <5.0.0": +type-fest@^2.14.0, type-fest@^2.19.0: version "2.19.0" resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== @@ -9298,7 +9163,7 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typescript@^5, "typescript@>= 4.2.x", "typescript@>= 4.3.x", "typescript@>= 4.5.5 < 6", "typescript@>= 4.x", typescript@>=3.3.1, typescript@>=4.8.4, "typescript@>=4.8.4 <5.8.0", typescript@>=4.9.5, typescript@>3.6.0: +typescript@^5: version "5.7.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz" integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== @@ -9465,7 +9330,7 @@ webpack-dev-middleware@^6.1.2: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-hot-middleware@^2.25.1, webpack-hot-middleware@2.x: +webpack-hot-middleware@^2.25.1: version "2.26.1" resolved "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz" integrity sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A== @@ -9484,7 +9349,7 @@ webpack-virtual-modules@^0.6.0, webpack-virtual-modules@^0.6.2: resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz" integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== -webpack@^5.0.0, webpack@^5.1.0, webpack@^5.11.0, webpack@^5.20.0, "webpack@>= 4", "webpack@>=4.43.0 <6.0.0", webpack@>=5, webpack@5: +webpack@5: version "5.97.1" resolved "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz" integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg== @@ -9513,6 +9378,11 @@ webpack@^5.0.0, webpack@^5.1.0, webpack@^5.11.0, webpack@^5.20.0, "webpack@>= 4" watchpack "^2.4.1" webpack-sources "^3.2.3" +wheel-gestures@^2.2.5: + version "2.2.48" + resolved "https://registry.yarnpkg.com/wheel-gestures/-/wheel-gestures-2.2.48.tgz#7b84b2522e66962efb50b5fe7e4a55503061255e" + integrity sha512-f+Gy33Oa5Z14XY9679Zze+7VFhbsQfBFXodnU2x589l4kxGM9L5Y8zETTmcMR5pWOPQyRv4Z0lNax6xCO0NSlA== + which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz"