Created
September 7, 2023 11:27
-
-
Save 7iomka/cfa476e6e164df31fcc56d8caf42f5a7 to your computer and use it in GitHub Desktop.
effector-view-example-usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { CarouselStylesNames, Embla } from '@mantine/carousel'; | |
import { Carousel } from '@mantine/carousel'; | |
import { useMantineTheme } from '@mantine/core'; | |
import { useCallback, useEffect, useRef, useState } from 'react'; | |
import AutoHeight from 'embla-carousel-auto-height'; | |
import type { CategoryEntity } from '@/shared/api'; | |
import { createView } from '@/shared/lib/view'; | |
import { ImageCard } from '@/shared/ui'; | |
import type { CustomCarouselStylesParams } from '@/shared/lib/mantine'; | |
import { useCarouselStyles } from '@/shared/lib/mantine'; | |
import styles from './category-cards-carousel.module.scss'; | |
interface CategoryCardsCarouselProps { | |
className?: string; | |
items: CategoryEntity[]; | |
} | |
const CategoryCardsCarousel = createView<CategoryCardsCarouselProps>() | |
.displayName('CategoryCardsCarousel') | |
.map(() => { | |
const autoHeightPluginRef = useRef(AutoHeight()); | |
const [embla, setEmbla] = useState<Embla | null>(null); | |
const carouselConfig: CustomCarouselStylesParams = { | |
containScroll: 'trimSnaps', | |
slidesToScroll: 'auto', | |
includeGapInSize: true, | |
slideGap: 16, | |
loop: true, | |
slideSize: '50%', | |
align: 'start', | |
breakpoints: [{ minWidth: 'lg', slideSize: '25%', slideGap: 30 }], | |
plugins: [autoHeightPluginRef.current], | |
}; | |
const { classes, cx } = useCarouselStyles(carouselConfig); | |
const toggleActiveWhenScrollable = useCallback(() => { | |
if (!embla) return; | |
const isScrollable = embla.internalEngine().slideLooper.canLoop(); | |
embla.reInit({ active: isScrollable }); | |
}, [embla]); | |
const { breakpoints } = useMantineTheme(); | |
const { controls: controlsStyles, ...restClasses } = classes; | |
const carouselClasses: Partial<Record<CarouselStylesNames, string>> = { | |
controls: cx(controlsStyles, styles.controls), | |
...restClasses, | |
}; | |
return { | |
embla, | |
setEmbla, | |
toggleActiveWhenScrollable, | |
carouselConfig, | |
carouselClasses, | |
breakpoints, | |
cx, | |
autoHeightPluginRef, | |
}; | |
}) | |
.effect(({ embla, toggleActiveWhenScrollable }) => { | |
useEffect(() => { | |
if (!embla) return; | |
toggleActiveWhenScrollable(); | |
embla.on('resize', toggleActiveWhenScrollable); | |
}, [embla, toggleActiveWhenScrollable]); | |
}) | |
.memo() | |
.view( | |
({ | |
className, | |
items, | |
setEmbla, | |
carouselConfig, | |
carouselClasses, | |
cx, | |
breakpoints, | |
autoHeightPluginRef, | |
}) => ( | |
<Carousel | |
getEmblaApi={setEmbla} | |
{...carouselConfig} | |
classNames={carouselClasses} | |
className={className} | |
styles={{ | |
container: { | |
alignItems: 'flex-start', | |
transition: 'height 0.2s', | |
}, | |
}} | |
plugins={[autoHeightPluginRef.current]} | |
> | |
{items.map(({ id, name, url, ...rest }, index) => ( | |
<Carousel.Slide key={index}> | |
<ImageCard | |
title={name} | |
href={url} | |
{...rest} | |
sizes={`(min-width: ${breakpoints.lg}) 25vw, 50vw`} | |
/> | |
</Carousel.Slide> | |
))} | |
</Carousel> | |
), | |
).Memo; | |
export type { CategoryCardsCarouselProps }; | |
export { CategoryCardsCarousel }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { CarouselStylesNames, Embla } from '@mantine/carousel'; | |
import { Carousel } from '@mantine/carousel'; | |
import { useMantineTheme } from '@mantine/core'; | |
import { memo, useCallback, useEffect, useRef, useState } from 'react'; | |
import AutoHeight from 'embla-carousel-auto-height'; | |
import type { CategoryEntity } from '@/shared/api'; | |
import { ImageCard } from '@/shared/ui'; | |
import type { CustomCarouselStylesParams } from '@/shared/lib/mantine'; | |
import { useCarouselStyles } from '@/shared/lib/mantine'; | |
import styles from './category-cards-carousel.module.scss'; | |
interface CategoryCardsCarouselProps { | |
className?: string; | |
items: CategoryEntity[]; | |
} | |
const CategoryCardsCarousel = memo(({ className, items }: CategoryCardsCarouselProps) => { | |
const autoHeightPluginRef = useRef(AutoHeight()); | |
const [embla, setEmbla] = useState<Embla | null>(null); | |
const carouselConfig: CustomCarouselStylesParams = { | |
containScroll: 'trimSnaps', | |
slidesToScroll: 'auto', | |
includeGapInSize: true, | |
slideGap: 16, | |
loop: true, | |
slideSize: '50%', | |
align: 'start', | |
breakpoints: [{ minWidth: 'lg', slideSize: '25%', slideGap: 30 }], | |
plugins: [autoHeightPluginRef.current], | |
}; | |
const { classes, cx } = useCarouselStyles(carouselConfig); | |
const toggleActiveWhenScrollable = useCallback(() => { | |
if (!embla) return; | |
const isScrollable = embla.internalEngine().slideLooper.canLoop(); | |
embla.reInit({ active: isScrollable }); | |
}, [embla]); | |
const { breakpoints } = useMantineTheme(); | |
const { controls: controlsStyles, ...restClasses } = classes; | |
const carouselClasses: Partial<Record<CarouselStylesNames, string>> = { | |
controls: cx(controlsStyles, styles.controls), | |
...restClasses, | |
}; | |
useEffect(() => { | |
if (!embla) return; | |
toggleActiveWhenScrollable(); | |
embla.on('resize', toggleActiveWhenScrollable); | |
}, [embla, toggleActiveWhenScrollable]); | |
return ( | |
<Carousel | |
getEmblaApi={setEmbla} | |
{...carouselConfig} | |
classNames={carouselClasses} | |
className={className} | |
styles={{ | |
container: { | |
alignItems: 'flex-start', | |
transition: 'height 0.2s', | |
}, | |
}} | |
plugins={[autoHeightPluginRef.current]} | |
> | |
{items.map(({ id, name, url, ...rest }, index) => ( | |
<Carousel.Slide key={index}> | |
<ImageCard | |
title={name} | |
href={url} | |
{...rest} | |
sizes={`(min-width: ${breakpoints.lg}) 25vw, 50vw`} | |
/> | |
</Carousel.Slide> | |
))} | |
</Carousel> | |
); | |
}); | |
export type { CategoryCardsCarouselProps }; | |
export { CategoryCardsCarousel }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment