@yamada-ui/carousel 2.0.7-next-20241005220055 → 2.0.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/carousel-control.js +2 -2
- package/dist/carousel-control.js.map +1 -1
- package/dist/carousel-control.mjs +2 -2
- package/dist/carousel-indicators.js +5 -5
- package/dist/carousel-indicators.js.map +1 -1
- package/dist/carousel-indicators.mjs +2 -2
- package/dist/carousel-slide.js +6 -7
- package/dist/carousel-slide.js.map +1 -1
- package/dist/carousel-slide.mjs +2 -2
- package/dist/carousel.d.mts +47 -47
- package/dist/carousel.d.ts +47 -47
- package/dist/carousel.js +71 -70
- package/dist/carousel.js.map +1 -1
- package/dist/carousel.mjs +5 -5
- package/dist/{chunk-OQNU22B2.mjs → chunk-CXXL47SC.mjs} +8 -9
- package/dist/chunk-CXXL47SC.mjs.map +1 -0
- package/dist/{chunk-T3LMURPY.mjs → chunk-PEXGWNKB.mjs} +4 -4
- package/dist/chunk-PEXGWNKB.mjs.map +1 -0
- package/dist/{chunk-LRO4RIBJ.mjs → chunk-SYCPZC2C.mjs} +41 -31
- package/dist/chunk-SYCPZC2C.mjs.map +1 -0
- package/dist/{chunk-W6XPFRNI.mjs → chunk-UTOIPGGP.mjs} +7 -7
- package/dist/chunk-UTOIPGGP.mjs.map +1 -0
- package/dist/{chunk-LV5JHVV6.mjs → chunk-WSTWB7CV.mjs} +29 -37
- package/dist/chunk-WSTWB7CV.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +71 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/use-carousel.d.mts +71 -99
- package/dist/use-carousel.d.ts +71 -99
- package/dist/use-carousel.js +39 -29
- package/dist/use-carousel.js.map +1 -1
- package/dist/use-carousel.mjs +1 -1
- package/package.json +7 -8
- package/dist/chunk-LRO4RIBJ.mjs.map +0 -1
- package/dist/chunk-LV5JHVV6.mjs.map +0 -1
- package/dist/chunk-OQNU22B2.mjs.map +0 -1
- package/dist/chunk-T3LMURPY.mjs.map +0 -1
- package/dist/chunk-W6XPFRNI.mjs.map +0 -1
package/dist/carousel-control.js
CHANGED
@@ -87,7 +87,6 @@ var CarouselControlPrev = (0, import_core2.forwardRef)(
|
|
87
87
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
88
88
|
CarouselControl,
|
89
89
|
{
|
90
|
-
operation: "prev",
|
91
90
|
className: (0, import_utils2.cx)("ui-carousel__control--prev", className),
|
92
91
|
"aria-label": "Go to previous slide",
|
93
92
|
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
@@ -99,6 +98,7 @@ var CarouselControlPrev = (0, import_core2.forwardRef)(
|
|
99
98
|
}
|
100
99
|
}
|
101
100
|
),
|
101
|
+
operation: "prev",
|
102
102
|
...getControlProps(rest, ref)
|
103
103
|
}
|
104
104
|
);
|
@@ -113,7 +113,6 @@ var CarouselControlNext = (0, import_core2.forwardRef)(
|
|
113
113
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
114
114
|
CarouselControl,
|
115
115
|
{
|
116
|
-
operation: "next",
|
117
116
|
className: (0, import_utils2.cx)("ui-carousel__control--next", className),
|
118
117
|
"aria-label": "Go to next slide",
|
119
118
|
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
@@ -125,6 +124,7 @@ var CarouselControlNext = (0, import_core2.forwardRef)(
|
|
125
124
|
}
|
126
125
|
}
|
127
126
|
),
|
127
|
+
operation: "next",
|
128
128
|
...getControlProps(rest, ref)
|
129
129
|
}
|
130
130
|
);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/carousel-control.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { IconButtonProps } from \"@yamada-ui/button\"\nimport { IconButton } from \"@yamada-ui/button\"\nimport type { CSSUIObject } from \"@yamada-ui/core\"\nimport { forwardRef } from \"@yamada-ui/core\"\nimport { ChevronIcon } from \"@yamada-ui/icon\"\nimport { cx } from \"@yamada-ui/utils\"\nimport { useCarouselContext, useCarouselControl } from \"./use-carousel\"\n\nexport interface CarouselControlProps extends IconButtonProps {}\n\nexport const CarouselControlPrev = forwardRef<CarouselControlProps, \"button\">(\n ({ className, ...rest }, ref) => {\n const { orientation } = useCarouselContext()\n\n const { getControlProps } = useCarouselControl({ operation: \"prev\" })\n\n return (\n <CarouselControl\n operation=\"prev\"\n className={cx(\"ui-carousel__control--prev\", className)}\n aria-label=\"Go to previous slide\"\n icon={\n <ChevronIcon\n __css={{\n fontSize: \"1.5em\",\n transform:\n orientation === \"vertical\" ? \"rotate(180deg)\" : \"rotate(90deg)\",\n }}\n />\n }\n {...getControlProps(rest, ref)}\n />\n )\n },\n)\n\nCarouselControlPrev.displayName = \"CarouselControlPrev\"\nCarouselControlPrev.__ui__ = \"CarouselControlPrev\"\n\nexport const CarouselControlNext = forwardRef<CarouselControlProps, \"button\">(\n ({ className, ...rest }, ref) => {\n const { orientation } = useCarouselContext()\n\n const { getControlProps } = useCarouselControl({ operation: \"next\" })\n\n return (\n <CarouselControl\n operation=\"next\"\n className={cx(\"ui-carousel__control--next\", className)}\n aria-label=\"Go to next slide\"\n icon={\n <ChevronIcon\n __css={{\n fontSize: \"1.5em\",\n transform:\n orientation === \"vertical\" ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n }}\n />\n }\n {...getControlProps(rest, ref)}\n />\n )\n },\n)\n\nCarouselControlNext.displayName = \"CarouselControlNext\"\nCarouselControlNext.__ui__ = \"CarouselControlNext\"\n\nconst CarouselControl = forwardRef<\n CarouselControlProps & { operation: \"prev\" | \"next\" },\n \"button\"\n>(({ className, operation, ...rest }, ref) => {\n const { styles } = useCarouselContext()\n\n const css: CSSUIObject = {\n position: \"absolute\",\n zIndex: \"fallback(kurillin, 9)\",\n ...styles.control,\n ...styles[operation],\n }\n\n return (\n <IconButton\n ref={ref}\n className={cx(\"ui-carousel__control\", className)}\n colorScheme={[\"whiteAlpha\", \"blackAlpha\"]}\n isRounded\n __css={css}\n {...rest}\n />\n )\n})\n\nCarouselControl.displayName = \"CarouselControl\"\nCarouselControl.__ui__ = \"CarouselControl\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n HTMLUIProps,\n CSSUIProps,\n PropGetter,\n RequiredPropGetter,\n HTMLProps,\n} from \"@yamada-ui/core\"\nimport { layoutStyleProperties } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n indexes: number[]\n selectedIndex: number\n orientation: \"vertical\" | \"horizontal\"\n includeGapInSize: boolean\n slidesToScroll: number\n slideSize: string | number\n gap: CSSUIProps[\"gap\"]\n styles: { [key: string]: CSSUIObject }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"onChange\" | \"draggable\" | \"gap\"> {\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: string | number\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n}\n\nexport const useCarousel = ({\n index,\n defaultIndex = 0,\n onChange,\n align = \"center\",\n orientation = \"horizontal\",\n autoplay = false,\n stopMouseEnterAutoplay = true,\n loop = true,\n duration = 25,\n delay = 4000,\n slidesToScroll = 1,\n draggable = true,\n dragFree = false,\n inViewThreshold = 0,\n skipSnaps = false,\n containScroll = false,\n slideSize = \"100%\",\n includeGapInSize = true,\n onScrollProgress,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n controlRef,\n children,\n ...rest\n}: UseCarouselProps) => {\n const [{ gap = \"fallback(4, 1rem)\", ...containerProps }, slidesProps] =\n splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n value: index,\n defaultValue: defaultIndex,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n axis: isVertical ? \"y\" : \"x\",\n startIndex: defaultIndex,\n loop,\n align,\n slidesToScroll,\n duration,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n indexes,\n selectedIndex,\n orientation,\n slideSize,\n gap,\n slidesToScroll,\n includeGapInSize,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / (slidesToScroll ?? 1))\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"prev\" | \"next\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { selectedIndex, carousel, indexes } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n HTMLProps<\"button\"> & { index: number },\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":"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","names":["import_core","import_utils"]}
|
1
|
+
{"version":3,"sources":["../src/carousel-control.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type { CSSUIObject } from \"@yamada-ui/core\"\nimport { IconButton } from \"@yamada-ui/button\"\nimport { forwardRef } from \"@yamada-ui/core\"\nimport { ChevronIcon } from \"@yamada-ui/icon\"\nimport { cx } from \"@yamada-ui/utils\"\nimport { useCarouselContext, useCarouselControl } from \"./use-carousel\"\n\nexport interface CarouselControlProps extends IconButtonProps {}\n\nexport const CarouselControlPrev = forwardRef<CarouselControlProps, \"button\">(\n ({ className, ...rest }, ref) => {\n const { orientation } = useCarouselContext()\n const { getControlProps } = useCarouselControl({ operation: \"prev\" })\n\n return (\n <CarouselControl\n className={cx(\"ui-carousel__control--prev\", className)}\n aria-label=\"Go to previous slide\"\n icon={\n <ChevronIcon\n __css={{\n fontSize: \"1.5em\",\n transform:\n orientation === \"vertical\" ? \"rotate(180deg)\" : \"rotate(90deg)\",\n }}\n />\n }\n operation=\"prev\"\n {...getControlProps(rest, ref)}\n />\n )\n },\n)\n\nCarouselControlPrev.displayName = \"CarouselControlPrev\"\nCarouselControlPrev.__ui__ = \"CarouselControlPrev\"\n\nexport const CarouselControlNext = forwardRef<CarouselControlProps, \"button\">(\n ({ className, ...rest }, ref) => {\n const { orientation } = useCarouselContext()\n const { getControlProps } = useCarouselControl({ operation: \"next\" })\n\n return (\n <CarouselControl\n className={cx(\"ui-carousel__control--next\", className)}\n aria-label=\"Go to next slide\"\n icon={\n <ChevronIcon\n __css={{\n fontSize: \"1.5em\",\n transform:\n orientation === \"vertical\" ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n }}\n />\n }\n operation=\"next\"\n {...getControlProps(rest, ref)}\n />\n )\n },\n)\n\nCarouselControlNext.displayName = \"CarouselControlNext\"\nCarouselControlNext.__ui__ = \"CarouselControlNext\"\n\nconst CarouselControl = forwardRef<\n { operation: \"next\" | \"prev\" } & CarouselControlProps,\n \"button\"\n>(({ className, operation, ...rest }, ref) => {\n const { styles } = useCarouselContext()\n\n const css: CSSUIObject = {\n position: \"absolute\",\n zIndex: \"fallback(kurillin, 9)\",\n ...styles.control,\n ...styles[operation],\n }\n\n return (\n <IconButton\n ref={ref}\n className={cx(\"ui-carousel__control\", className)}\n colorScheme={[\"whiteAlpha\", \"blackAlpha\"]}\n isRounded\n __css={css}\n {...rest}\n />\n )\n})\n\nCarouselControl.displayName = \"CarouselControl\"\nCarouselControl.__ui__ = \"CarouselControl\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n CSSUIProps,\n HTMLProps,\n HTMLUIProps,\n PropGetter,\n RequiredPropGetter,\n} from \"@yamada-ui/core\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { layoutStyleProperties, mergeVars } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n includeGapInSize: boolean\n indexes: number[]\n orientation: \"horizontal\" | \"vertical\"\n selectedIndex: number\n slidesToScroll: number\n styles: { [key: string]: CSSUIObject | undefined }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"draggable\" | \"gap\" | \"onChange\"> {\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"horizontal\" | \"vertical\"\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: CSSUIProps[\"width\"]\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n}\n\nexport const useCarousel = ({\n align = \"center\",\n autoplay = false,\n children,\n containScroll = false,\n controlRef,\n defaultIndex = 0,\n delay = 4000,\n dragFree = false,\n draggable = true,\n duration = 25,\n includeGapInSize = true,\n index,\n inViewThreshold = 0,\n loop = true,\n orientation = \"horizontal\",\n skipSnaps = false,\n slideSize = \"100%\",\n slidesToScroll = 1,\n stopMouseEnterAutoplay = true,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n onChange,\n onScrollProgress,\n ...rest\n}: UseCarouselProps) => {\n const [\n { gap = \"fallback(4, 1rem)\", ...containerProps },\n { vars, ...slidesProps },\n ] = splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n defaultValue: defaultIndex,\n value: index,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n align,\n axis: isVertical ? \"y\" : \"x\",\n containScroll,\n dragFree,\n duration,\n inViewThreshold,\n loop,\n skipSnaps,\n slidesToScroll,\n startIndex: defaultIndex,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n if (index === undefined) return\n\n carousel.scrollTo(index)\n }, [index])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n vars: mergeVars(vars, [\n { name: \"gap\", token: \"spaces\", value: gap },\n { name: \"slideSize\", token: \"sizes\", value: slideSize },\n ]),\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps, gap, slideSize, vars],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n includeGapInSize,\n indexes,\n orientation,\n selectedIndex,\n slidesToScroll,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / slidesToScroll)\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"next\" | \"prev\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { carousel, indexes, selectedIndex } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n { index: number } & HTMLProps<\"button\">,\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":"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","names":["import_core","import_utils"]}
|
@@ -49,7 +49,7 @@ var [CarouselProvider, useCarouselContext] = (0, import_utils.createContext)({
|
|
49
49
|
errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in "<Carousel />"`
|
50
50
|
});
|
51
51
|
var useCarouselIndicators = () => {
|
52
|
-
const {
|
52
|
+
const { carousel, indexes, selectedIndex } = useCarouselContext();
|
53
53
|
const onClick = (0, import_react.useCallback)(
|
54
54
|
(ev, index) => {
|
55
55
|
if (!carousel) return;
|
@@ -79,13 +79,13 @@ var useCarouselIndicators = () => {
|
|
79
79
|
var import_jsx_runtime = require("react/jsx-runtime");
|
80
80
|
var CarouselIndicators = (0, import_core2.forwardRef)(
|
81
81
|
({ className, component, ...rest }, ref) => {
|
82
|
-
const {
|
82
|
+
const { orientation, selectedIndex, styles } = useCarouselContext();
|
83
83
|
const { indexes, getIndicatorProps } = useCarouselIndicators();
|
84
84
|
const css = {
|
85
|
-
position: "absolute",
|
86
|
-
zIndex: "fallback(kurillin, 9)",
|
87
85
|
display: "flex",
|
88
86
|
justifyContent: "center",
|
87
|
+
position: "absolute",
|
88
|
+
zIndex: "fallback(kurillin, 9)",
|
89
89
|
...styles.indicators,
|
90
90
|
...orientation === "vertical" ? { flexDirection: "column" } : { flexDirection: "row" }
|
91
91
|
};
|
@@ -127,8 +127,8 @@ var CarouselIndicator = ({
|
|
127
127
|
import_core2.ui.button,
|
128
128
|
{
|
129
129
|
type: "button",
|
130
|
-
tabIndex: -1,
|
131
130
|
className: (0, import_utils2.cx)("ui-carousel__indicators__indicator", className),
|
131
|
+
tabIndex: -1,
|
132
132
|
__css: css,
|
133
133
|
...rest
|
134
134
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/carousel-indicators.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { HTMLUIProps, CSSUIObject, FC } from \"@yamada-ui/core\"\nimport { ui, forwardRef } from \"@yamada-ui/core\"\nimport { cx } from \"@yamada-ui/utils\"\nimport type { ReactElement } from \"react\"\nimport { cloneElement } from \"react\"\nimport { useCarouselContext, useCarouselIndicators } from \"./use-carousel\"\n\ninterface CarouselIndicatorsOptions {\n /**\n * The custom carousel indicator to use.\n */\n component?: FC<{ index: number; isSelected: boolean }>\n}\n\nexport interface CarouselIndicatorsProps\n extends HTMLUIProps,\n CarouselIndicatorsOptions {}\n\nexport const CarouselIndicators = forwardRef<CarouselIndicatorsProps, \"div\">(\n ({ className, component, ...rest }, ref) => {\n const { selectedIndex, orientation, styles } = useCarouselContext()\n\n const { indexes, getIndicatorProps } = useCarouselIndicators()\n\n const css: CSSUIObject = {\n position: \"absolute\",\n zIndex: \"fallback(kurillin, 9)\",\n display: \"flex\",\n justifyContent: \"center\",\n ...styles.indicators,\n ...(orientation === \"vertical\"\n ? { flexDirection: \"column\" }\n : { flexDirection: \"row\" }),\n }\n\n return (\n <ui.div\n ref={ref}\n className={cx(\"ui-carousel__indicators\", className)}\n __css={css}\n {...rest}\n >\n {indexes.map((index) => {\n const isSelected = index === selectedIndex\n\n if (typeof component === \"function\") {\n const child = component({\n index,\n isSelected,\n }) as ReactElement | null\n\n if (!child) return null\n\n const props = getIndicatorProps({ ...child.props, index })\n\n return cloneElement(child as ReactElement, props)\n } else {\n const { key, ...props } = getIndicatorProps({ index })\n\n return <CarouselIndicator key={key} {...props} />\n }\n })}\n </ui.div>\n )\n },\n)\n\nCarouselIndicators.displayName = \"CarouselIndicators\"\nCarouselIndicators.__ui__ = \"CarouselIndicators\"\n\ninterface CarouselIndicatorProps extends HTMLUIProps<\"button\"> {}\n\nconst CarouselIndicator: FC<CarouselIndicatorProps> = ({\n className,\n ...rest\n}) => {\n const { styles } = useCarouselContext()\n\n const css: CSSUIObject = { ...styles.indicator }\n\n return (\n <ui.button\n type=\"button\"\n tabIndex={-1}\n className={cx(\"ui-carousel__indicators__indicator\", className)}\n __css={css}\n {...rest}\n />\n )\n}\n\nCarouselIndicator.displayName = \"CarouselIndicator\"\nCarouselIndicator.__ui__ = \"CarouselIndicator\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n HTMLUIProps,\n CSSUIProps,\n PropGetter,\n RequiredPropGetter,\n HTMLProps,\n} from \"@yamada-ui/core\"\nimport { layoutStyleProperties } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n indexes: number[]\n selectedIndex: number\n orientation: \"vertical\" | \"horizontal\"\n includeGapInSize: boolean\n slidesToScroll: number\n slideSize: string | number\n gap: CSSUIProps[\"gap\"]\n styles: { [key: string]: CSSUIObject }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"onChange\" | \"draggable\" | \"gap\"> {\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: string | number\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n}\n\nexport const useCarousel = ({\n index,\n defaultIndex = 0,\n onChange,\n align = \"center\",\n orientation = \"horizontal\",\n autoplay = false,\n stopMouseEnterAutoplay = true,\n loop = true,\n duration = 25,\n delay = 4000,\n slidesToScroll = 1,\n draggable = true,\n dragFree = false,\n inViewThreshold = 0,\n skipSnaps = false,\n containScroll = false,\n slideSize = \"100%\",\n includeGapInSize = true,\n onScrollProgress,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n controlRef,\n children,\n ...rest\n}: UseCarouselProps) => {\n const [{ gap = \"fallback(4, 1rem)\", ...containerProps }, slidesProps] =\n splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n value: index,\n defaultValue: defaultIndex,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n axis: isVertical ? \"y\" : \"x\",\n startIndex: defaultIndex,\n loop,\n align,\n slidesToScroll,\n duration,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n indexes,\n selectedIndex,\n orientation,\n slideSize,\n gap,\n slidesToScroll,\n includeGapInSize,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / (slidesToScroll ?? 1))\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"prev\" | \"next\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { selectedIndex, carousel, indexes } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n HTMLProps<\"button\"> & { index: number },\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":"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","names":["import_core","import_utils","import_react"]}
|
1
|
+
{"version":3,"sources":["../src/carousel-indicators.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { CSSUIObject, FC, HTMLUIProps } from \"@yamada-ui/core\"\nimport type { ReactElement } from \"react\"\nimport { forwardRef, ui } from \"@yamada-ui/core\"\nimport { cx } from \"@yamada-ui/utils\"\nimport { cloneElement } from \"react\"\nimport { useCarouselContext, useCarouselIndicators } from \"./use-carousel\"\n\ninterface CarouselIndicatorsOptions {\n /**\n * The custom carousel indicator to use.\n */\n component?: FC<{ index: number; isSelected: boolean }>\n}\n\nexport interface CarouselIndicatorsProps\n extends HTMLUIProps,\n CarouselIndicatorsOptions {}\n\nexport const CarouselIndicators = forwardRef<CarouselIndicatorsProps, \"div\">(\n ({ className, component, ...rest }, ref) => {\n const { orientation, selectedIndex, styles } = useCarouselContext()\n const { indexes, getIndicatorProps } = useCarouselIndicators()\n\n const css: CSSUIObject = {\n display: \"flex\",\n justifyContent: \"center\",\n position: \"absolute\",\n zIndex: \"fallback(kurillin, 9)\",\n ...styles.indicators,\n ...(orientation === \"vertical\"\n ? { flexDirection: \"column\" }\n : { flexDirection: \"row\" }),\n }\n\n return (\n <ui.div\n ref={ref}\n className={cx(\"ui-carousel__indicators\", className)}\n __css={css}\n {...rest}\n >\n {indexes.map((index) => {\n const isSelected = index === selectedIndex\n\n if (typeof component === \"function\") {\n const child = component({\n index,\n isSelected,\n }) as null | ReactElement\n\n if (!child) return null\n\n const props = getIndicatorProps({ ...child.props, index })\n\n return cloneElement(child as ReactElement, props)\n } else {\n const { key, ...props } = getIndicatorProps({ index })\n\n return <CarouselIndicator key={key} {...props} />\n }\n })}\n </ui.div>\n )\n },\n)\n\nCarouselIndicators.displayName = \"CarouselIndicators\"\nCarouselIndicators.__ui__ = \"CarouselIndicators\"\n\ninterface CarouselIndicatorProps extends HTMLUIProps<\"button\"> {}\n\nconst CarouselIndicator: FC<CarouselIndicatorProps> = ({\n className,\n ...rest\n}) => {\n const { styles } = useCarouselContext()\n\n const css: CSSUIObject = { ...styles.indicator }\n\n return (\n <ui.button\n type=\"button\"\n className={cx(\"ui-carousel__indicators__indicator\", className)}\n tabIndex={-1}\n __css={css}\n {...rest}\n />\n )\n}\n\nCarouselIndicator.displayName = \"CarouselIndicator\"\nCarouselIndicator.__ui__ = \"CarouselIndicator\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n CSSUIProps,\n HTMLProps,\n HTMLUIProps,\n PropGetter,\n RequiredPropGetter,\n} from \"@yamada-ui/core\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { layoutStyleProperties, mergeVars } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n includeGapInSize: boolean\n indexes: number[]\n orientation: \"horizontal\" | \"vertical\"\n selectedIndex: number\n slidesToScroll: number\n styles: { [key: string]: CSSUIObject | undefined }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"draggable\" | \"gap\" | \"onChange\"> {\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"horizontal\" | \"vertical\"\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: CSSUIProps[\"width\"]\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n}\n\nexport const useCarousel = ({\n align = \"center\",\n autoplay = false,\n children,\n containScroll = false,\n controlRef,\n defaultIndex = 0,\n delay = 4000,\n dragFree = false,\n draggable = true,\n duration = 25,\n includeGapInSize = true,\n index,\n inViewThreshold = 0,\n loop = true,\n orientation = \"horizontal\",\n skipSnaps = false,\n slideSize = \"100%\",\n slidesToScroll = 1,\n stopMouseEnterAutoplay = true,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n onChange,\n onScrollProgress,\n ...rest\n}: UseCarouselProps) => {\n const [\n { gap = \"fallback(4, 1rem)\", ...containerProps },\n { vars, ...slidesProps },\n ] = splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n defaultValue: defaultIndex,\n value: index,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n align,\n axis: isVertical ? \"y\" : \"x\",\n containScroll,\n dragFree,\n duration,\n inViewThreshold,\n loop,\n skipSnaps,\n slidesToScroll,\n startIndex: defaultIndex,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n if (index === undefined) return\n\n carousel.scrollTo(index)\n }, [index])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n vars: mergeVars(vars, [\n { name: \"gap\", token: \"spaces\", value: gap },\n { name: \"slideSize\", token: \"sizes\", value: slideSize },\n ]),\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps, gap, slideSize, vars],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n includeGapInSize,\n indexes,\n orientation,\n selectedIndex,\n slidesToScroll,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / slidesToScroll)\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"next\" | \"prev\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { carousel, indexes, selectedIndex } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n { index: number } & HTMLProps<\"button\">,\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":"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","names":["import_core","import_utils","import_react"]}
|
package/dist/carousel-slide.js
CHANGED
@@ -49,7 +49,7 @@ var [CarouselProvider, useCarouselContext] = (0, import_utils.createContext)({
|
|
49
49
|
});
|
50
50
|
var useCarouselSlide = ({ index }) => {
|
51
51
|
const { selectedIndex, slidesToScroll } = useCarouselContext();
|
52
|
-
index = Math.floor((index != null ? index : 0) /
|
52
|
+
index = Math.floor((index != null ? index : 0) / slidesToScroll);
|
53
53
|
const isSelected = index === selectedIndex;
|
54
54
|
const getSlideProps = (0, import_react.useCallback)(
|
55
55
|
(props = {}) => ({
|
@@ -66,13 +66,13 @@ var useCarouselSlide = ({ index }) => {
|
|
66
66
|
var import_jsx_runtime = require("react/jsx-runtime");
|
67
67
|
var CarouselSlide = (0, import_core2.forwardRef)(
|
68
68
|
({ className, size, ...rest }, ref) => {
|
69
|
-
const {
|
69
|
+
const { includeGapInSize, orientation } = useCarouselContext();
|
70
70
|
const { getSlideProps } = useCarouselSlide(rest);
|
71
|
-
size != null ? size : size = slideSize;
|
71
|
+
size != null ? size : size = "$slideSize";
|
72
72
|
const css = {
|
73
|
-
position: "relative",
|
74
73
|
flex: `0 0 ${size}`,
|
75
|
-
|
74
|
+
position: "relative",
|
75
|
+
...includeGapInSize ? { [orientation === "vertical" ? "pb" : "pr"]: "$gap" } : { [orientation === "vertical" ? "mb" : "mr"]: "$gap" }
|
76
76
|
};
|
77
77
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
78
78
|
import_core2.ui.div,
|
@@ -94,8 +94,7 @@ var CarouselSlideInner = (0, import_core2.forwardRef)(
|
|
94
94
|
{
|
95
95
|
ref,
|
96
96
|
className: "ui-carousel__slide__inner",
|
97
|
-
|
98
|
-
h: "100%",
|
97
|
+
boxSize: "100%",
|
99
98
|
...rest
|
100
99
|
}
|
101
100
|
);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/carousel-slide.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { HTMLUIProps, CSSUIObject } from \"@yamada-ui/core\"\nimport { ui, forwardRef } from \"@yamada-ui/core\"\nimport { cx } from \"@yamada-ui/utils\"\nimport type { UseCarouselSlideProps } from \"./use-carousel\"\nimport { useCarouselContext, useCarouselSlide } from \"./use-carousel\"\n\ninterface CarouselSlideOptions {\n /**\n * The CSS `width` property.\n */\n size?: CSSUIObject[\"width\"]\n}\n\nexport interface CarouselSlideProps\n extends HTMLUIProps,\n UseCarouselSlideProps,\n CarouselSlideOptions {}\n\nexport const CarouselSlide = forwardRef<CarouselSlideProps, \"div\">(\n ({ className, size, ...rest }, ref) => {\n const { slideSize, includeGapInSize, orientation, gap } =\n useCarouselContext()\n\n const { getSlideProps } = useCarouselSlide(rest)\n\n size ??= slideSize\n\n const css: CSSUIObject = {\n position: \"relative\",\n flex: `0 0 ${size}`,\n ...(includeGapInSize\n ? { [orientation === \"vertical\" ? \"pb\" : \"pr\"]: gap }\n : { [orientation === \"vertical\" ? \"mb\" : \"mr\"]: gap }),\n }\n\n return (\n <ui.div\n className={cx(\"ui-carousel__slide\", className)}\n __css={css}\n {...getSlideProps({})}\n >\n <CarouselSlideInner ref={ref} {...rest} />\n </ui.div>\n )\n },\n)\n\nCarouselSlide.displayName = \"CarouselSlide\"\nCarouselSlide.__ui__ = \"CarouselSlide\"\n\ninterface CarouselSlideInnerProps extends HTMLUIProps {}\n\nconst CarouselSlideInner = forwardRef<CarouselSlideInnerProps, \"div\">(\n ({ ...rest }, ref) => {\n return (\n <ui.div\n ref={ref}\n className=\"ui-carousel__slide__inner\"\n w=\"100%\"\n h=\"100%\"\n {...rest}\n />\n )\n },\n)\n\nCarouselSlideInner.displayName = \"CarouselSlideInner\"\nCarouselSlideInner.__ui__ = \"CarouselSlideInner\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n HTMLUIProps,\n CSSUIProps,\n PropGetter,\n RequiredPropGetter,\n HTMLProps,\n} from \"@yamada-ui/core\"\nimport { layoutStyleProperties } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n indexes: number[]\n selectedIndex: number\n orientation: \"vertical\" | \"horizontal\"\n includeGapInSize: boolean\n slidesToScroll: number\n slideSize: string | number\n gap: CSSUIProps[\"gap\"]\n styles: { [key: string]: CSSUIObject }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"onChange\" | \"draggable\" | \"gap\"> {\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: string | number\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n}\n\nexport const useCarousel = ({\n index,\n defaultIndex = 0,\n onChange,\n align = \"center\",\n orientation = \"horizontal\",\n autoplay = false,\n stopMouseEnterAutoplay = true,\n loop = true,\n duration = 25,\n delay = 4000,\n slidesToScroll = 1,\n draggable = true,\n dragFree = false,\n inViewThreshold = 0,\n skipSnaps = false,\n containScroll = false,\n slideSize = \"100%\",\n includeGapInSize = true,\n onScrollProgress,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n controlRef,\n children,\n ...rest\n}: UseCarouselProps) => {\n const [{ gap = \"fallback(4, 1rem)\", ...containerProps }, slidesProps] =\n splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n value: index,\n defaultValue: defaultIndex,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n axis: isVertical ? \"y\" : \"x\",\n startIndex: defaultIndex,\n loop,\n align,\n slidesToScroll,\n duration,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n indexes,\n selectedIndex,\n orientation,\n slideSize,\n gap,\n slidesToScroll,\n includeGapInSize,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / (slidesToScroll ?? 1))\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"prev\" | \"next\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { selectedIndex, carousel, indexes } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n HTMLProps<\"button\"> & { index: number },\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,IAAAA,eAA+B;AAC/B,IAAAC,gBAAmB;;;ACOnB,kBAAsC;AACtC,oCAAqC;AACrC,mBAOO;AAEP,kCAA6B;AAE7B,mBAAmE;AAsB5D,IAAM,CAAC,kBAAkB,kBAAkB,QAChD,4BAA+B;AAAA,EAC7B,MAAM;AAAA,EACN,cAAc;AAChB,CAAC;AAiWI,IAAM,mBAAmB,CAAC,EAAE,MAAM,MAA6B;AACpE,QAAM,EAAE,eAAe,eAAe,IAAI,mBAAmB;AAE7D,UAAQ,KAAK,OAAO,wBAAS,MAAM,0CAAkB,EAAE;AAEvD,QAAM,aAAa,UAAU;AAE7B,QAAM,oBAA4B;AAAA,IAChC,CAAC,QAAQ,CAAC,OAAO;AAAA,MACf,GAAG;AAAA,MACH,cAAc;AAAA,MACd,qBAAiB,uBAAS,UAAU;AAAA,IACtC;AAAA,IACA,CAAC,YAAY,KAAK;AAAA,EACpB;AAEA,SAAO,EAAE,cAAc;AACzB;;;ADzXQ;AAvBD,IAAM,oBAAgB;AAAA,EAC3B,CAAC,EAAE,WAAW,MAAM,GAAG,KAAK,GAAG,QAAQ;AACrC,UAAM,EAAE,WAAW,kBAAkB,aAAa,IAAI,IACpD,mBAAmB;AAErB,UAAM,EAAE,cAAc,IAAI,iBAAiB,IAAI;AAE/C,iCAAS;AAET,UAAM,MAAmB;AAAA,MACvB,UAAU;AAAA,MACV,MAAM,OAAO,IAAI;AAAA,MACjB,GAAI,mBACA,EAAE,CAAC,gBAAgB,aAAa,OAAO,IAAI,GAAG,IAAI,IAClD,EAAE,CAAC,gBAAgB,aAAa,OAAO,IAAI,GAAG,IAAI;AAAA,IACxD;AAEA,WACE;AAAA,MAAC,gBAAG;AAAA,MAAH;AAAA,QACC,eAAW,kBAAG,sBAAsB,SAAS;AAAA,QAC7C,OAAO;AAAA,QACN,GAAG,cAAc,CAAC,CAAC;AAAA,QAEpB,sDAAC,sBAAmB,KAAW,GAAG,MAAM;AAAA;AAAA,IAC1C;AAAA,EAEJ;AACF;AAEA,cAAc,cAAc;AAC5B,cAAc,SAAS;AAIvB,IAAM,yBAAqB;AAAA,EACzB,CAAC,EAAE,GAAG,KAAK,GAAG,QAAQ;AACpB,WACE;AAAA,MAAC,gBAAG;AAAA,MAAH;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACV,GAAE;AAAA,QACF,GAAE;AAAA,QACD,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,mBAAmB,cAAc;AACjC,mBAAmB,SAAS;","names":["import_core","import_utils"]}
|
1
|
+
{"version":3,"sources":["../src/carousel-slide.tsx","../src/use-carousel.ts"],"sourcesContent":["import type { CSSUIObject, HTMLUIProps } from \"@yamada-ui/core\"\nimport type { UseCarouselSlideProps } from \"./use-carousel\"\nimport { forwardRef, ui } from \"@yamada-ui/core\"\nimport { cx } from \"@yamada-ui/utils\"\nimport { useCarouselContext, useCarouselSlide } from \"./use-carousel\"\n\ninterface CarouselSlideOptions {\n /**\n * The CSS `width` property.\n */\n size?: CSSUIObject[\"width\"]\n}\n\nexport interface CarouselSlideProps\n extends HTMLUIProps,\n UseCarouselSlideProps,\n CarouselSlideOptions {}\n\nexport const CarouselSlide = forwardRef<CarouselSlideProps, \"div\">(\n ({ className, size, ...rest }, ref) => {\n const { includeGapInSize, orientation } = useCarouselContext()\n const { getSlideProps } = useCarouselSlide(rest)\n\n size ??= \"$slideSize\"\n\n const css: CSSUIObject = {\n flex: `0 0 ${size}`,\n position: \"relative\",\n ...(includeGapInSize\n ? { [orientation === \"vertical\" ? \"pb\" : \"pr\"]: \"$gap\" }\n : { [orientation === \"vertical\" ? \"mb\" : \"mr\"]: \"$gap\" }),\n }\n\n return (\n <ui.div\n className={cx(\"ui-carousel__slide\", className)}\n __css={css}\n {...getSlideProps({})}\n >\n <CarouselSlideInner ref={ref} {...rest} />\n </ui.div>\n )\n },\n)\n\nCarouselSlide.displayName = \"CarouselSlide\"\nCarouselSlide.__ui__ = \"CarouselSlide\"\n\ninterface CarouselSlideInnerProps extends HTMLUIProps {}\n\nconst CarouselSlideInner = forwardRef<CarouselSlideInnerProps, \"div\">(\n ({ ...rest }, ref) => {\n return (\n <ui.div\n ref={ref}\n className=\"ui-carousel__slide__inner\"\n boxSize=\"100%\"\n {...rest}\n />\n )\n },\n)\n\nCarouselSlideInner.displayName = \"CarouselSlideInner\"\nCarouselSlideInner.__ui__ = \"CarouselSlideInner\"\n","import type { IconButtonProps } from \"@yamada-ui/button\"\nimport type {\n CSSUIObject,\n CSSUIProps,\n HTMLProps,\n HTMLUIProps,\n PropGetter,\n RequiredPropGetter,\n} from \"@yamada-ui/core\"\nimport type { EmblaCarouselType, EmblaOptionsType } from \"embla-carousel\"\nimport type { MouseEvent, RefObject } from \"react\"\nimport { layoutStyleProperties, mergeVars } from \"@yamada-ui/core\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport {\n assignRef,\n createContext,\n dataAttr,\n handlerAll,\n splitObject,\n useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport useEmblaCarousel from \"embla-carousel-react\"\nimport { Children, useCallback, useEffect, useRef, useState } from \"react\"\n\nexport type AlignmentOptionType = EmblaOptionsType[\"align\"]\nexport type ScrollContainOptionType = EmblaOptionsType[\"containScroll\"]\nexport type SlidesInViewOptionsType = EmblaOptionsType[\"inViewThreshold\"]\nexport type DragHandlerOptionType = EmblaOptionsType[\"watchDrag\"]\nexport type ResizeHandlerOptionType = EmblaOptionsType[\"watchResize\"]\nexport type SlidesHandlerOptionType = EmblaOptionsType[\"watchSlides\"]\nexport type CarouselControl = EmblaCarouselType\n\ninterface CarouselContext {\n carousel: CarouselControl | undefined\n includeGapInSize: boolean\n indexes: number[]\n orientation: \"horizontal\" | \"vertical\"\n selectedIndex: number\n slidesToScroll: number\n styles: { [key: string]: CSSUIObject | undefined }\n}\n\nexport const [CarouselProvider, useCarouselContext] =\n createContext<CarouselContext>({\n name: \"CarouselContext\",\n errorMessage: `useCarouselContext returned is 'undefined'. Seems you forgot to wrap the components in \"<Carousel />\"`,\n })\n\nexport interface UseCarouselProps\n extends Omit<HTMLUIProps, \"draggable\" | \"gap\" | \"onChange\"> {\n /**\n * The alignment of the carousel.\n *\n * @default 'center'\n */\n align?: AlignmentOptionType\n /**\n * If `true`, the carousel will be autoplay.\n *\n * @default false\n */\n autoplay?: boolean\n /**\n * Clear leading and trailing empty space that causes excessive scrolling.\n * Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.\n *\n * @default false\n */\n containScroll?: ScrollContainOptionType\n /**\n * Ref of the resizable item callback.\n */\n controlRef?: RefObject<CarouselControl | undefined>\n /**\n * The initial index of the carousel slide.\n *\n * @default 0\n */\n defaultIndex?: number\n /**\n * The number for the autoplay interval of the carousel.\n *\n * @default 4000\n */\n delay?: number\n /**\n * If `true`, momentum scrolling will be enabled.\n *\n * @default false\n */\n dragFree?: boolean\n /**\n * If `true`, carousel can be scrolled with mouse and touch interactions.\n *\n * @default true\n */\n draggable?: boolean\n /**\n * Set scroll duration when triggered by any of the API methods.\n * Higher numbers enables slower scrolling.\n * Drag interactions are not affected because duration is then determined by the drag force.\n *\n * @default 25\n */\n duration?: number\n /**\n * The CSS `gap` property.\n *\n * @default '4'\n */\n gap?: CSSUIProps[\"gap\"]\n /**\n * If `true`, gap will be treated as part of the carousel slide size.\n *\n * @default true\n */\n includeGapInSize?: boolean\n /**\n * The index of the carousel slide.\n */\n index?: number\n /**\n * Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.\n *\n * @default 0\n */\n inViewThreshold?: SlidesInViewOptionsType\n /**\n * If `true`, infinite looping.\n * Automatically falls back to false if slide content isn't enough to loop.\n *\n * @default true\n */\n loop?: boolean\n /**\n * The orientation of the carousel.\n *\n * @default 'horizontal'\n */\n orientation?: \"horizontal\" | \"vertical\"\n /**\n * If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.\n * Note that this option will be ignored if the dragFree option is set to true.\n *\n * @default false\n */\n skipSnaps?: boolean\n /**\n * The carousel slide width.\n *\n * @default '100%'\n */\n slideSize?: CSSUIProps[\"width\"]\n /**\n * The number of slides that should be scrolled with next or previous buttons.\n *\n * @default 1\n */\n slidesToScroll?: number\n /**\n * If `true`, autoplay will pause when the mouse entries over.\n *\n * @default true\n */\n stopMouseEnterAutoplay?: boolean\n /**\n * Enables for scrolling the carousel with mouse and touch interactions.\n * Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.\n *\n * @default true\n */\n watchDrag?: DragHandlerOptionType\n /**\n * Embla automatically watches the container and slides for size changes and runs `reInit` when any size has changed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.\n *\n * @default true\n */\n watchResize?: ResizeHandlerOptionType\n /**\n * Embla automatically watches the container for added and/or removed slides and runs `reInit` if needed.\n * Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.\n *\n * @default true\n */\n watchSlides?: SlidesHandlerOptionType\n /**\n * The callback invoked when carousel slide selected.\n */\n onChange?: (index: number) => void\n /**\n * A callback that return the current scroll amount when the carousel is scrolled.\n */\n onScrollProgress?: (progress: number) => void\n}\n\nexport const useCarousel = ({\n align = \"center\",\n autoplay = false,\n children,\n containScroll = false,\n controlRef,\n defaultIndex = 0,\n delay = 4000,\n dragFree = false,\n draggable = true,\n duration = 25,\n includeGapInSize = true,\n index,\n inViewThreshold = 0,\n loop = true,\n orientation = \"horizontal\",\n skipSnaps = false,\n slideSize = \"100%\",\n slidesToScroll = 1,\n stopMouseEnterAutoplay = true,\n watchDrag = draggable,\n watchResize = true,\n watchSlides = true,\n onChange,\n onScrollProgress,\n ...rest\n}: UseCarouselProps) => {\n const [\n { gap = \"fallback(4, 1rem)\", ...containerProps },\n { vars, ...slidesProps },\n ] = splitObject(rest, layoutStyleProperties)\n\n const [selectedIndex, setSelectedIndex] = useControllableState({\n defaultValue: defaultIndex,\n value: index,\n onChange,\n })\n\n const isVertical = orientation === \"vertical\"\n\n const [carouselRef, carousel] = useEmblaCarousel(\n {\n align,\n axis: isVertical ? \"y\" : \"x\",\n containScroll,\n dragFree,\n duration,\n inViewThreshold,\n loop,\n skipSnaps,\n slidesToScroll,\n startIndex: defaultIndex,\n watchDrag,\n watchResize,\n watchSlides,\n },\n [],\n )\n\n assignRef(controlRef, carousel)\n\n const [indexes, setIndexes] = useState<number[]>([])\n const [isMouseEnter, setIsMouseEnter] = useState<boolean>(false)\n\n const timeoutId = useRef<any>(undefined)\n\n const onScroll = useCallback(() => {\n if (!carousel) return\n\n const progress = Math.round(\n Math.max(0, Math.min(1, carousel.scrollProgress())) * 100,\n )\n\n onScrollProgress?.(progress)\n }, [carousel, onScrollProgress])\n\n const onSelect = useCallback(() => {\n if (!carousel) return\n\n const index = carousel.selectedScrollSnap()\n\n setSelectedIndex(index)\n }, [carousel, setSelectedIndex])\n\n useEffect(() => {\n const isStop = isMouseEnter && stopMouseEnterAutoplay\n const isLast = !carousel?.canScrollNext()\n\n if (carousel && autoplay && !isStop && !isLast) {\n timeoutId.current = setInterval(() => {\n carousel.scrollNext()\n }, delay)\n } else {\n if (timeoutId.current) clearInterval(timeoutId.current)\n\n timeoutId.current = undefined\n }\n\n return () => {\n if (timeoutId.current) clearInterval(timeoutId.current)\n }\n }, [\n autoplay,\n delay,\n stopMouseEnterAutoplay,\n carousel,\n isMouseEnter,\n loop,\n selectedIndex,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n carousel.reInit()\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [\n Children.toArray(children).length,\n align,\n orientation,\n loop,\n duration,\n gap,\n slidesToScroll,\n draggable,\n dragFree,\n inViewThreshold,\n skipSnaps,\n containScroll,\n slideSize,\n includeGapInSize,\n ])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n const snapList = carousel.scrollSnapList()\n const indexes = snapList.map((_, i) => i)\n\n setIndexes(indexes)\n }, [carousel])\n\n useUpdateEffect(() => {\n if (carousel) {\n carousel.on(\"select\", onSelect)\n carousel.on(\"scroll\", onScroll)\n\n onScroll()\n\n return () => {\n carousel.off(\"select\", onSelect)\n carousel.off(\"scroll\", onScroll)\n }\n }\n }, [carousel, onScroll])\n\n useUpdateEffect(() => {\n if (!carousel) return\n\n if (index === undefined) return\n\n carousel.scrollTo(index)\n }, [index])\n\n const getContainerProps: PropGetter = useCallback(\n (props = {}, ref = null) => ({\n ...containerProps,\n ...props,\n ref,\n vars: mergeVars(vars, [\n { name: \"gap\", token: \"spaces\", value: gap },\n { name: \"slideSize\", token: \"sizes\", value: slideSize },\n ]),\n onMouseEnter: handlerAll(props.onMouseEnter, () => {\n setIsMouseEnter(true)\n }),\n onMouseLeave: handlerAll(props.onMouseLeave, () => {\n setIsMouseEnter(false)\n }),\n }),\n [containerProps, gap, slideSize, vars],\n )\n\n const getSlidesProps: PropGetter = useCallback(\n (props = {}) => ({\n ...slidesProps,\n ...props,\n ref: carouselRef,\n }),\n [slidesProps, carouselRef],\n )\n\n return {\n carousel,\n children,\n includeGapInSize,\n indexes,\n orientation,\n selectedIndex,\n slidesToScroll,\n getContainerProps,\n getSlidesProps,\n }\n}\n\nexport type UseCarouselReturn = ReturnType<typeof useCarousel>\n\nexport interface UseCarouselSlideProps {\n index?: number\n}\n\nexport const useCarouselSlide = ({ index }: UseCarouselSlideProps) => {\n const { selectedIndex, slidesToScroll } = useCarouselContext()\n\n index = Math.floor((index ?? 0) / slidesToScroll)\n\n const isSelected = index === selectedIndex\n\n const getSlideProps: PropGetter = useCallback(\n (props = {}) => ({\n ...props,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n }),\n [isSelected, index],\n )\n\n return { getSlideProps }\n}\n\nexport type UseCarouselSlideReturn = ReturnType<typeof useCarouselSlide>\n\nexport interface UseCarouselControlProps extends IconButtonProps {\n operation: \"next\" | \"prev\"\n}\n\nexport const useCarouselControl = ({\n operation,\n ...rest\n}: UseCarouselControlProps) => {\n const { carousel } = useCarouselContext()\n\n const isPrev = operation === \"prev\"\n\n const disabled =\n rest.disabled ??\n rest.isDisabled ??\n (isPrev ? !carousel?.canScrollPrev() : !carousel?.canScrollNext())\n\n const onClick = useCallback(() => {\n if (!carousel) return\n\n if (isPrev) {\n carousel.scrollPrev()\n } else {\n carousel.scrollNext()\n }\n }, [carousel, isPrev])\n\n const getControlProps: PropGetter<\"button\"> = useCallback(\n (props = {}, ref = null) => ({\n ...props,\n ref,\n disabled,\n onClick: handlerAll(props.onClick, onClick),\n }),\n [disabled, onClick],\n )\n\n return { getControlProps }\n}\n\nexport type UseCarouselControlReturn = ReturnType<typeof useCarouselControl>\n\nexport const useCarouselIndicators = () => {\n const { carousel, indexes, selectedIndex } = useCarouselContext()\n\n const onClick = useCallback(\n (ev: MouseEvent, index: number) => {\n if (!carousel) return\n\n ev.stopPropagation()\n\n carousel.scrollTo(index)\n },\n [carousel],\n )\n\n const getIndicatorProps: RequiredPropGetter<\n { index: number } & HTMLProps<\"button\">,\n HTMLProps<\"button\">\n > = useCallback(\n ({ index, ...props }) => {\n const isSelected = index === selectedIndex\n\n return {\n \"aria-label\": `Go to ${index + 1} slide`,\n ...props,\n key: index,\n \"data-index\": index,\n \"data-selected\": dataAttr(isSelected),\n onClick: handlerAll(props.onClick, (ev) => onClick(ev, index)),\n }\n },\n [onClick, selectedIndex],\n )\n\n return { indexes, getIndicatorProps }\n}\n\nexport type UseCarouselIndicatorsReturn = ReturnType<\n typeof useCarouselIndicators\n>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAAA,eAA+B;AAC/B,IAAAC,gBAAmB;;;ACQnB,kBAAiD;AACjD,oCAAqC;AACrC,mBAOO;AACP,kCAA6B;AAC7B,mBAAmE;AAoB5D,IAAM,CAAC,kBAAkB,kBAAkB,QAChD,4BAA+B;AAAA,EAC7B,MAAM;AAAA,EACN,cAAc;AAChB,CAAC;AA6WI,IAAM,mBAAmB,CAAC,EAAE,MAAM,MAA6B;AACpE,QAAM,EAAE,eAAe,eAAe,IAAI,mBAAmB;AAE7D,UAAQ,KAAK,OAAO,wBAAS,KAAK,cAAc;AAEhD,QAAM,aAAa,UAAU;AAE7B,QAAM,oBAA4B;AAAA,IAChC,CAAC,QAAQ,CAAC,OAAO;AAAA,MACf,GAAG;AAAA,MACH,cAAc;AAAA,MACd,qBAAiB,uBAAS,UAAU;AAAA,IACtC;AAAA,IACA,CAAC,YAAY,KAAK;AAAA,EACpB;AAEA,SAAO,EAAE,cAAc;AACzB;;;ADrYQ;AArBD,IAAM,oBAAgB;AAAA,EAC3B,CAAC,EAAE,WAAW,MAAM,GAAG,KAAK,GAAG,QAAQ;AACrC,UAAM,EAAE,kBAAkB,YAAY,IAAI,mBAAmB;AAC7D,UAAM,EAAE,cAAc,IAAI,iBAAiB,IAAI;AAE/C,iCAAS;AAET,UAAM,MAAmB;AAAA,MACvB,MAAM,OAAO,IAAI;AAAA,MACjB,UAAU;AAAA,MACV,GAAI,mBACA,EAAE,CAAC,gBAAgB,aAAa,OAAO,IAAI,GAAG,OAAO,IACrD,EAAE,CAAC,gBAAgB,aAAa,OAAO,IAAI,GAAG,OAAO;AAAA,IAC3D;AAEA,WACE;AAAA,MAAC,gBAAG;AAAA,MAAH;AAAA,QACC,eAAW,kBAAG,sBAAsB,SAAS;AAAA,QAC7C,OAAO;AAAA,QACN,GAAG,cAAc,CAAC,CAAC;AAAA,QAEpB,sDAAC,sBAAmB,KAAW,GAAG,MAAM;AAAA;AAAA,IAC1C;AAAA,EAEJ;AACF;AAEA,cAAc,cAAc;AAC5B,cAAc,SAAS;AAIvB,IAAM,yBAAqB;AAAA,EACzB,CAAC,EAAE,GAAG,KAAK,GAAG,QAAQ;AACpB,WACE;AAAA,MAAC,gBAAG;AAAA,MAAH;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACV,SAAQ;AAAA,QACP,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,mBAAmB,cAAc;AACjC,mBAAmB,SAAS;","names":["import_core","import_utils"]}
|
package/dist/carousel-slide.mjs
CHANGED
package/dist/carousel.d.mts
CHANGED
@@ -8,18 +8,18 @@ import 'react';
|
|
8
8
|
import 'embla-carousel';
|
9
9
|
|
10
10
|
interface CarouselOptions {
|
11
|
-
/**
|
12
|
-
* The orientation of the carousel.
|
13
|
-
*
|
14
|
-
* @default 'horizontal'
|
15
|
-
*/
|
16
|
-
orientation?: Token<"vertical" | "horizontal">;
|
17
11
|
/**
|
18
12
|
* The alignment of the carousel.
|
19
13
|
*
|
20
14
|
* @default 'center'
|
21
15
|
*/
|
22
16
|
align?: Token<AlignmentOptionType>;
|
17
|
+
/**
|
18
|
+
* If `true`, the carousel will be autoplay.
|
19
|
+
*
|
20
|
+
* @default false
|
21
|
+
*/
|
22
|
+
autoplay?: Token<boolean>;
|
23
23
|
/**
|
24
24
|
* Clear leading and trailing empty space that causes excessive scrolling.
|
25
25
|
* Use trimSnaps to only use snap points that trigger scrolling or keepSnaps to keep them.
|
@@ -28,11 +28,11 @@ interface CarouselOptions {
|
|
28
28
|
*/
|
29
29
|
containScroll?: Token<ScrollContainOptionType>;
|
30
30
|
/**
|
31
|
-
* The number
|
31
|
+
* The number for the autoplay interval of the carousel.
|
32
32
|
*
|
33
|
-
* @default
|
33
|
+
* @default 4000
|
34
34
|
*/
|
35
|
-
|
35
|
+
delay?: Token<number>;
|
36
36
|
/**
|
37
37
|
* If `true`, momentum scrolling will be enabled.
|
38
38
|
*
|
@@ -45,6 +45,20 @@ interface CarouselOptions {
|
|
45
45
|
* @default true
|
46
46
|
*/
|
47
47
|
draggable?: Token<boolean>;
|
48
|
+
/**
|
49
|
+
* Set scroll duration when triggered by any of the API methods.
|
50
|
+
* Higher numbers enables slower scrolling.
|
51
|
+
* Drag interactions are not affected because duration is then determined by the drag force.
|
52
|
+
*
|
53
|
+
* @default 25
|
54
|
+
*/
|
55
|
+
duration?: Token<number>;
|
56
|
+
/**
|
57
|
+
* If `true`, gap will be treated as part of the carousel slide size.
|
58
|
+
*
|
59
|
+
* @default true
|
60
|
+
*/
|
61
|
+
includeGapInSize?: Token<boolean>;
|
48
62
|
/**
|
49
63
|
* Choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view.
|
50
64
|
*
|
@@ -58,6 +72,12 @@ interface CarouselOptions {
|
|
58
72
|
* @default true
|
59
73
|
*/
|
60
74
|
loop?: Token<boolean>;
|
75
|
+
/**
|
76
|
+
* The orientation of the carousel.
|
77
|
+
*
|
78
|
+
* @default 'horizontal'
|
79
|
+
*/
|
80
|
+
orientation?: Token<"horizontal" | "vertical">;
|
61
81
|
/**
|
62
82
|
* If `true`, allow the carousel to skip scroll snaps if it's dragged vigorously.
|
63
83
|
* Note that this option will be ignored if the dragFree option is set to true.
|
@@ -66,25 +86,15 @@ interface CarouselOptions {
|
|
66
86
|
*/
|
67
87
|
skipSnaps?: Token<boolean>;
|
68
88
|
/**
|
69
|
-
*
|
70
|
-
* Higher numbers enables slower scrolling.
|
71
|
-
* Drag interactions are not affected because duration is then determined by the drag force.
|
72
|
-
*
|
73
|
-
* @default 25
|
74
|
-
*/
|
75
|
-
duration?: Token<number>;
|
76
|
-
/**
|
77
|
-
* The number for the autoplay interval of the carousel.
|
78
|
-
*
|
79
|
-
* @default 4000
|
89
|
+
* The CSS `width` property.
|
80
90
|
*/
|
81
|
-
|
91
|
+
slideSize?: CSSUIProps["width"];
|
82
92
|
/**
|
83
|
-
*
|
93
|
+
* The number of slides that should be scrolled with next or previous buttons.
|
84
94
|
*
|
85
|
-
* @default
|
95
|
+
* @default 1
|
86
96
|
*/
|
87
|
-
|
97
|
+
slidesToScroll?: Token<number>;
|
88
98
|
/**
|
89
99
|
* If `true`, autoplay will pause when the mouse entries over.
|
90
100
|
*
|
@@ -92,49 +102,39 @@ interface CarouselOptions {
|
|
92
102
|
*/
|
93
103
|
stopMouseEnterAutoplay?: Token<boolean>;
|
94
104
|
/**
|
95
|
-
* If `true`,
|
105
|
+
* If `true`, display the carousel control buttons.
|
96
106
|
*
|
97
107
|
* @default true
|
98
108
|
*/
|
99
|
-
|
100
|
-
/**
|
101
|
-
* The CSS `width` property.
|
102
|
-
*/
|
103
|
-
slideSize?: CSSUIProps["width"];
|
104
|
-
/**
|
105
|
-
* Props for carousel inner element.
|
106
|
-
*/
|
107
|
-
innerProps?: HTMLUIProps;
|
109
|
+
withControls?: Token<boolean>;
|
108
110
|
/**
|
109
|
-
* If `true`, display the carousel
|
111
|
+
* If `true`, display the carousel indicator buttons.
|
110
112
|
*
|
111
113
|
* @default true
|
112
114
|
*/
|
113
|
-
|
115
|
+
withIndicators?: Token<boolean>;
|
114
116
|
/**
|
115
|
-
* Props for carousel control element.
|
117
|
+
* Props for next of the carousel control element.
|
116
118
|
*/
|
117
|
-
|
119
|
+
controlNextProps?: CarouselControlProps;
|
118
120
|
/**
|
119
121
|
* Props for previous of the carousel control element.
|
120
122
|
*/
|
121
123
|
controlPrevProps?: CarouselControlProps;
|
122
124
|
/**
|
123
|
-
* Props for
|
124
|
-
*/
|
125
|
-
controlNextProps?: CarouselControlProps;
|
126
|
-
/**
|
127
|
-
* If `true`, display the carousel indicator buttons.
|
128
|
-
*
|
129
|
-
* @default true
|
125
|
+
* Props for carousel control element.
|
130
126
|
*/
|
131
|
-
|
127
|
+
controlProps?: CarouselControlProps;
|
132
128
|
/**
|
133
129
|
* Props for carousel indicators element.
|
134
130
|
*/
|
135
131
|
indicatorsProps?: CarouselIndicatorsProps;
|
132
|
+
/**
|
133
|
+
* Props for carousel inner element.
|
134
|
+
*/
|
135
|
+
innerProps?: HTMLUIProps;
|
136
136
|
}
|
137
|
-
interface CarouselProps extends ThemeProps<"Carousel">, Omit<HTMLUIProps, "
|
137
|
+
interface CarouselProps extends ThemeProps<"Carousel">, Omit<HTMLUIProps, "draggable" | "onChange">, Pick<UseCarouselProps, "controlRef" | "defaultIndex" | "index" | "onChange" | "onScrollProgress" | "watchDrag" | "watchResize" | "watchSlides">, CarouselOptions {
|
138
138
|
}
|
139
139
|
/**
|
140
140
|
* `Carousel` is a component that displays multiple elements like a slideshow.
|