@fluentui/react-carousel 9.3.1 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -2
- package/dist/index.d.ts +2 -2
- package/lib/components/Carousel/useCarousel.js +2 -1
- package/lib/components/Carousel/useCarousel.js.map +1 -1
- package/lib/components/CarouselAutoplayButton/useCarouselAutoplayButton.js +4 -8
- package/lib/components/CarouselAutoplayButton/useCarouselAutoplayButton.js.map +1 -1
- package/lib/components/CarouselButton/useCarouselButton.js +1 -2
- package/lib/components/CarouselButton/useCarouselButton.js.map +1 -1
- package/lib/components/CarouselContext.types.js.map +1 -1
- package/lib/components/CarouselViewport/useCarouselViewport.js +45 -2
- package/lib/components/CarouselViewport/useCarouselViewport.js.map +1 -1
- package/lib/components/useEmblaCarousel.js +82 -68
- package/lib/components/useEmblaCarousel.js.map +1 -1
- package/lib-commonjs/components/Carousel/useCarousel.js +2 -1
- package/lib-commonjs/components/Carousel/useCarousel.js.map +1 -1
- package/lib-commonjs/components/CarouselAutoplayButton/useCarouselAutoplayButton.js +3 -7
- package/lib-commonjs/components/CarouselAutoplayButton/useCarouselAutoplayButton.js.map +1 -1
- package/lib-commonjs/components/CarouselButton/useCarouselButton.js +1 -1
- package/lib-commonjs/components/CarouselButton/useCarouselButton.js.map +1 -1
- package/lib-commonjs/components/CarouselContext.types.js.map +1 -1
- package/lib-commonjs/components/CarouselViewport/useCarouselViewport.js +44 -1
- package/lib-commonjs/components/CarouselViewport/useCarouselViewport.js.map +1 -1
- package/lib-commonjs/components/useEmblaCarousel.js +81 -68
- package/lib-commonjs/components/useEmblaCarousel.js.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/useEmblaCarousel.ts"],"sourcesContent":["import { type EventHandler, useControllableState, useEventCallback } from '@fluentui/react-utilities';\nimport EmblaCarousel, { EmblaPluginType, type EmblaCarouselType, type EmblaOptionsType } from 'embla-carousel';\nimport * as React from 'react';\n\nimport { carouselCardClassNames } from './CarouselCard/useCarouselCardStyles.styles';\nimport { carouselSliderClassNames } from './CarouselSlider/useCarouselSliderStyles.styles';\nimport { CarouselMotion, CarouselUpdateData, CarouselVisibilityEventDetail } from '../Carousel';\nimport Autoplay from 'embla-carousel-autoplay';\nimport Fade from 'embla-carousel-fade';\nimport { pointerEventPlugin } from './pointerEvents';\nimport type { CarouselIndexChangeData } from './CarouselContext.types';\n\nconst sliderClassname = `.${carouselSliderClassNames.root}`;\n\nconst DEFAULT_EMBLA_OPTIONS: EmblaOptionsType = {\n containScroll: 'trimSnaps',\n inViewThreshold: 0.99,\n watchDrag: false,\n skipSnaps: true,\n\n container: sliderClassname,\n slides: `.${carouselCardClassNames.root}`,\n};\n\nexport const EMBLA_VISIBILITY_EVENT = 'embla:visibilitychange';\n\nexport function setTabsterDefault(element: Element, isDefault: boolean) {\n const tabsterAttr = element.getAttribute('data-tabster');\n\n if (tabsterAttr) {\n const tabsterAttributes = JSON.parse(tabsterAttr);\n if (tabsterAttributes.focusable) {\n // If tabster.focusable isn't present, we will ignore.\n tabsterAttributes.focusable.isDefault = isDefault;\n element.setAttribute('data-tabster', JSON.stringify(tabsterAttributes));\n }\n }\n}\n\nexport function useEmblaCarousel(\n options: Pick<EmblaOptionsType, 'align' | 'direction' | 'loop' | 'slidesToScroll' | 'watchDrag' | 'containScroll'> & {\n defaultActiveIndex: number | undefined;\n activeIndex: number | undefined;\n motion?: CarouselMotion;\n onDragIndexChange?: EventHandler<CarouselIndexChangeData>;\n },\n) {\n const { align, direction, loop, slidesToScroll, watchDrag, containScroll, motion, onDragIndexChange } = options;\n const [activeIndex, setActiveIndex] = useControllableState({\n defaultState: options.defaultActiveIndex,\n state: options.activeIndex,\n initialState: 0,\n });\n\n const onDragEvent = useEventCallback((event: PointerEvent | MouseEvent, index: number) => {\n onDragIndexChange?.(event, { event, type: 'drag', index });\n });\n\n const emblaOptions = React.useRef<EmblaOptionsType>({\n align,\n direction,\n loop,\n slidesToScroll,\n startIndex: activeIndex,\n watchDrag,\n containScroll,\n });\n\n const emblaApi = React.useRef<EmblaCarouselType | null>(null);\n const autoplayRef = React.useRef<boolean>(false);\n\n const resetAutoplay = React.useCallback(() => {\n emblaApi.current?.plugins().autoplay.reset();\n }, []);\n\n /* Our autoplay button, which is required by standards for autoplay to be enabled, will handle controlled state */\n const enableAutoplay = React.useCallback(\n (autoplay: boolean) => {\n autoplayRef.current = autoplay;\n if (autoplay) {\n emblaApi.current?.plugins().autoplay.play();\n // Reset after play to ensure timing and any focus/mouse pause state is reset.\n resetAutoplay();\n } else {\n emblaApi.current?.plugins().autoplay.stop();\n }\n },\n [resetAutoplay],\n );\n\n const getPlugins = React.useCallback(() => {\n const plugins: EmblaPluginType[] = [\n Autoplay({\n playOnInit: autoplayRef.current,\n stopOnInteraction: !autoplayRef.current,\n stopOnMouseEnter: true,\n stopOnFocusIn: true,\n }),\n ];\n\n // Optionally add Fade plugin\n if (motion === 'fade') {\n plugins.push(Fade());\n }\n\n if (watchDrag) {\n plugins.push(\n pointerEventPlugin({\n onSelectViaDrag: onDragEvent,\n }),\n );\n }\n\n return plugins;\n }, [motion, onDragEvent, watchDrag]);\n\n // Listeners contains callbacks for UI elements that may require state update based on embla changes\n const listeners = React.useRef(new Set<(data: CarouselUpdateData) => void>());\n const subscribeForValues = React.useCallback((listener: (data: CarouselUpdateData) => void) => {\n listeners.current.add(listener);\n\n return () => {\n listeners.current.delete(listener);\n };\n }, []);\n\n const handleReinit = useEventCallback(() => {\n const nodes: HTMLElement[] = emblaApi.current?.slideNodes() ?? [];\n const groupIndexList: number[][] = emblaApi.current?.internalEngine().slideRegistry ?? [];\n const navItemsCount = groupIndexList.length > 0 ? groupIndexList.length : nodes.length;\n\n const data: CarouselUpdateData = {\n navItemsCount,\n activeIndex: emblaApi.current?.selectedScrollSnap() ?? 0,\n groupIndexList,\n slideNodes: nodes,\n };\n\n emblaApi.current?.scrollTo(activeIndex, false);\n for (const listener of listeners.current) {\n listener(data);\n }\n });\n\n const viewportRef: React.RefObject<HTMLDivElement> = React.useRef(null);\n const containerRef: React.RefObject<HTMLDivElement> = React.useMemo(() => {\n let currentElement: HTMLDivElement | null = null;\n\n const handleIndexChange = () => {\n const newIndex = emblaApi.current?.selectedScrollSnap() ?? 0;\n const slides = emblaApi.current?.slideNodes();\n const actualIndex = emblaApi.current?.internalEngine().slideRegistry[newIndex][0] ?? 0;\n\n // We set the active or first index of group on-screen as the selected tabster index\n slides?.forEach((slide, slideIndex) => {\n setTabsterDefault(slide, slideIndex === actualIndex);\n });\n setActiveIndex(newIndex);\n };\n\n const handleVisibilityChange = () => {\n const cardElements = emblaApi.current?.slideNodes();\n const visibleIndexes = emblaApi.current?.slidesInView() ?? [];\n\n cardElements?.forEach((cardElement, index) => {\n cardElement.dispatchEvent(\n new CustomEvent<CarouselVisibilityEventDetail>(EMBLA_VISIBILITY_EVENT, {\n bubbles: false,\n detail: { isVisible: visibleIndexes.includes(index) },\n }),\n );\n });\n };\n\n const plugins = getPlugins();\n\n return {\n set current(newElement: HTMLDivElement | null) {\n if (currentElement) {\n emblaApi.current?.off('slidesInView', handleVisibilityChange);\n emblaApi.current?.off('select', handleIndexChange);\n emblaApi.current?.off('reInit', handleReinit);\n emblaApi.current?.destroy();\n }\n\n // Use direct viewport if available, else fallback to container (includes Carousel controls).\n const wrapperElement = viewportRef.current ?? newElement;\n if (wrapperElement) {\n currentElement = wrapperElement;\n emblaApi.current = EmblaCarousel(\n wrapperElement,\n {\n ...DEFAULT_EMBLA_OPTIONS,\n ...emblaOptions.current,\n },\n plugins,\n );\n\n emblaApi.current?.on('reInit', handleReinit);\n emblaApi.current?.on('slidesInView', handleVisibilityChange);\n emblaApi.current?.on('select', handleIndexChange);\n }\n },\n };\n }, [getPlugins, setActiveIndex, handleReinit]);\n\n const carouselApi = React.useMemo(\n () => ({\n scrollToElement: (element: HTMLElement, jump?: boolean) => {\n const cardElements = emblaApi.current?.slideNodes();\n const groupIndexList = emblaApi.current?.internalEngine().slideRegistry ?? [];\n const cardIndex = cardElements?.indexOf(element) ?? 0;\n const groupIndex = groupIndexList.findIndex(group => {\n return group.includes(cardIndex);\n });\n const indexFocus = groupIndex ?? cardIndex;\n emblaApi.current?.scrollTo(indexFocus, jump);\n\n return indexFocus;\n },\n scrollToIndex: (index: number, jump?: boolean) => {\n emblaApi.current?.scrollTo(index, jump);\n },\n scrollInDirection: (dir: 'prev' | 'next') => {\n if (dir === 'prev') {\n emblaApi.current?.scrollPrev();\n } else {\n emblaApi.current?.scrollNext();\n }\n\n return emblaApi.current?.selectedScrollSnap() ?? 0;\n },\n }),\n [],\n );\n\n React.useEffect(() => {\n // Scroll to controlled values on update\n // If active index is out of bounds, re-init will handle instead\n const currentActiveIndex = emblaApi.current?.selectedScrollSnap() ?? 0;\n const slideLength = emblaApi.current?.slideNodes()?.length ?? 0;\n emblaOptions.current.startIndex = activeIndex;\n if (activeIndex < slideLength && activeIndex !== currentActiveIndex) {\n emblaApi.current?.scrollTo(activeIndex);\n }\n }, [activeIndex]);\n\n React.useEffect(() => {\n const plugins = getPlugins();\n\n emblaOptions.current = {\n startIndex: emblaOptions.current.startIndex,\n align,\n direction,\n loop,\n slidesToScroll,\n watchDrag,\n containScroll,\n };\n emblaApi.current?.reInit(\n {\n ...DEFAULT_EMBLA_OPTIONS,\n ...emblaOptions.current,\n },\n plugins,\n );\n }, [align, direction, loop, slidesToScroll, watchDrag, containScroll, getPlugins]);\n\n return {\n activeIndex,\n carouselApi,\n viewportRef,\n containerRef,\n subscribeForValues,\n enableAutoplay,\n resetAutoplay,\n };\n}\n"],"names":["useControllableState","useEventCallback","EmblaCarousel","React","carouselCardClassNames","carouselSliderClassNames","Autoplay","Fade","pointerEventPlugin","sliderClassname","root","DEFAULT_EMBLA_OPTIONS","containScroll","inViewThreshold","watchDrag","skipSnaps","container","slides","EMBLA_VISIBILITY_EVENT","setTabsterDefault","element","isDefault","tabsterAttr","getAttribute","tabsterAttributes","JSON","parse","focusable","setAttribute","stringify","useEmblaCarousel","options","align","direction","loop","slidesToScroll","motion","onDragIndexChange","activeIndex","setActiveIndex","defaultState","defaultActiveIndex","state","initialState","onDragEvent","event","index","type","emblaOptions","useRef","startIndex","emblaApi","autoplayRef","resetAutoplay","useCallback","current","plugins","autoplay","reset","enableAutoplay","play","stop","getPlugins","playOnInit","stopOnInteraction","stopOnMouseEnter","stopOnFocusIn","push","onSelectViaDrag","listeners","Set","subscribeForValues","listener","add","delete","handleReinit","nodes","slideNodes","groupIndexList","internalEngine","slideRegistry","navItemsCount","length","data","selectedScrollSnap","scrollTo","viewportRef","containerRef","useMemo","currentElement","handleIndexChange","newIndex","actualIndex","forEach","slide","slideIndex","handleVisibilityChange","cardElements","visibleIndexes","slidesInView","cardElement","dispatchEvent","CustomEvent","bubbles","detail","isVisible","includes","newElement","off","destroy","wrapperElement","on","carouselApi","scrollToElement","jump","cardIndex","indexOf","groupIndex","findIndex","group","indexFocus","scrollToIndex","scrollInDirection","dir","scrollPrev","scrollNext","useEffect","currentActiveIndex","slideLength","reInit"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/components/useEmblaCarousel.ts"],"sourcesContent":["import { type EventHandler, useControllableState, useEventCallback } from '@fluentui/react-utilities';\nimport EmblaCarousel, { EmblaPluginType, type EmblaCarouselType, type EmblaOptionsType } from 'embla-carousel';\nimport * as React from 'react';\n\nimport { carouselCardClassNames } from './CarouselCard/useCarouselCardStyles.styles';\nimport { carouselSliderClassNames } from './CarouselSlider/useCarouselSliderStyles.styles';\nimport { CarouselMotion, CarouselUpdateData, CarouselVisibilityEventDetail } from '../Carousel';\nimport Autoplay from 'embla-carousel-autoplay';\nimport Fade from 'embla-carousel-fade';\nimport { pointerEventPlugin } from './pointerEvents';\nimport type { CarouselIndexChangeData } from './CarouselContext.types';\n\ntype EmblaEventHandler = Parameters<EmblaCarouselType['on']>[1];\n\nconst sliderClassname = `.${carouselSliderClassNames.root}`;\n\nconst DEFAULT_EMBLA_OPTIONS: EmblaOptionsType = {\n containScroll: 'trimSnaps',\n inViewThreshold: 0.99,\n watchDrag: false,\n skipSnaps: true,\n\n container: sliderClassname,\n slides: `.${carouselCardClassNames.root}`,\n};\n\nexport const EMBLA_VISIBILITY_EVENT = 'embla:visibilitychange';\n\nexport function setTabsterDefault(element: Element, isDefault: boolean) {\n const tabsterAttr = element.getAttribute('data-tabster');\n\n if (tabsterAttr) {\n const tabsterAttributes = JSON.parse(tabsterAttr);\n if (tabsterAttributes.focusable) {\n // If tabster.focusable isn't present, we will ignore.\n tabsterAttributes.focusable.isDefault = isDefault;\n element.setAttribute('data-tabster', JSON.stringify(tabsterAttributes));\n }\n }\n}\n\nexport function useEmblaCarousel(\n options: Pick<EmblaOptionsType, 'align' | 'direction' | 'loop' | 'slidesToScroll' | 'watchDrag' | 'containScroll'> & {\n defaultActiveIndex: number | undefined;\n activeIndex: number | undefined;\n motion?: CarouselMotion;\n onDragIndexChange?: EventHandler<CarouselIndexChangeData>;\n onAutoplayIndexChange?: EventHandler<CarouselIndexChangeData>;\n },\n) {\n const {\n align,\n direction,\n loop,\n slidesToScroll,\n watchDrag,\n containScroll,\n motion,\n onDragIndexChange,\n onAutoplayIndexChange,\n } = options;\n const [activeIndex, setActiveIndex] = useControllableState({\n defaultState: options.defaultActiveIndex,\n state: options.activeIndex,\n initialState: 0,\n });\n\n const onDragEvent = useEventCallback((event: PointerEvent | MouseEvent, index: number) => {\n onDragIndexChange?.(event, { event, type: 'drag', index });\n });\n\n const emblaOptions = React.useRef<EmblaOptionsType>({\n align,\n direction,\n loop,\n slidesToScroll,\n startIndex: activeIndex,\n watchDrag,\n containScroll,\n });\n\n const emblaApi = React.useRef<EmblaCarouselType | null>(null);\n const autoplayRef = React.useRef<boolean>(false);\n\n const resetAutoplay = React.useCallback(() => {\n emblaApi.current?.plugins().autoplay?.reset();\n }, []);\n\n const getPlugins = React.useCallback(() => {\n const plugins: EmblaPluginType[] = [];\n\n plugins.push(\n Autoplay({\n playOnInit: autoplayRef.current,\n /* stopOnInteraction: false causes autoplay to restart on interaction end*/\n /* we'll handle this logic to ensure autoplay state is respected */\n stopOnInteraction: true,\n stopOnFocusIn: false, // We'll handle this one manually to prevent conflicts with tabster\n stopOnMouseEnter: false, // We will handle this manually to align functionality\n }),\n );\n\n // Optionally add Fade plugin\n if (motion === 'fade') {\n plugins.push(Fade());\n }\n\n if (watchDrag) {\n plugins.push(\n pointerEventPlugin({\n onSelectViaDrag: onDragEvent,\n }),\n );\n }\n\n return plugins;\n }, [motion, onDragEvent, watchDrag]);\n\n /* This function enables autoplay to pause/play without affecting underlying state\n * Useful for pausing on focus etc. without having to reinitialize or set autoplay to off\n */\n const enableAutoplay = React.useCallback(\n (autoplay: boolean, temporary?: boolean) => {\n if (!temporary) {\n autoplayRef.current = autoplay;\n }\n\n if (autoplay && autoplayRef.current) {\n // Autoplay should only enable in the case where underlying state is true, temporary should not override\n emblaApi.current?.plugins().autoplay?.play();\n // Reset after play to ensure timing and any focus/mouse pause state is reset.\n resetAutoplay();\n } else if (!autoplay) {\n emblaApi.current?.plugins().autoplay?.stop();\n }\n },\n [resetAutoplay],\n );\n\n // Listeners contains callbacks for UI elements that may require state update based on embla changes\n const listeners = React.useRef(new Set<(data: CarouselUpdateData) => void>());\n const subscribeForValues = React.useCallback((listener: (data: CarouselUpdateData) => void) => {\n listeners.current.add(listener);\n\n return () => {\n listeners.current.delete(listener);\n };\n }, []);\n\n const handleReinit = useEventCallback(() => {\n const nodes: HTMLElement[] = emblaApi.current?.slideNodes() ?? [];\n const groupIndexList: number[][] = emblaApi.current?.internalEngine().slideRegistry ?? [];\n const navItemsCount = groupIndexList.length > 0 ? groupIndexList.length : nodes.length;\n\n const data: CarouselUpdateData = {\n navItemsCount,\n activeIndex: emblaApi.current?.selectedScrollSnap() ?? 0,\n groupIndexList,\n slideNodes: nodes,\n };\n\n emblaApi.current?.scrollTo(activeIndex, false);\n for (const listener of listeners.current) {\n listener(data);\n }\n });\n\n const handleIndexChange: EmblaEventHandler = useEventCallback((_, eventType) => {\n const newIndex = emblaApi.current?.selectedScrollSnap() ?? 0;\n const slides = emblaApi.current?.slideNodes();\n const actualIndex = emblaApi.current?.internalEngine().slideRegistry[newIndex][0] ?? 0;\n\n // We set the active or first index of group on-screen as the selected tabster index\n slides?.forEach((slide, slideIndex) => {\n setTabsterDefault(slide, slideIndex === actualIndex);\n });\n setActiveIndex(newIndex);\n\n if (eventType === 'autoplay:select') {\n const noopEvent = new Event('autoplay');\n onAutoplayIndexChange?.(noopEvent, { event: noopEvent, type: 'autoplay', index: newIndex });\n }\n });\n\n const viewportRef: React.RefObject<HTMLDivElement> = React.useRef(null);\n const containerRef: React.RefObject<HTMLDivElement> = React.useMemo(() => {\n let currentElement: HTMLDivElement | null = null;\n\n const handleVisibilityChange = () => {\n const cardElements = emblaApi.current?.slideNodes();\n const visibleIndexes = emblaApi.current?.slidesInView() ?? [];\n\n cardElements?.forEach((cardElement, index) => {\n cardElement.dispatchEvent(\n new CustomEvent<CarouselVisibilityEventDetail>(EMBLA_VISIBILITY_EVENT, {\n bubbles: false,\n detail: { isVisible: visibleIndexes.includes(index) },\n }),\n );\n });\n };\n\n // Get plugins using autoplayRef to prevent state change recreating EmblaCarousel\n const plugins = getPlugins();\n\n return {\n set current(newElement: HTMLDivElement | null) {\n if (currentElement) {\n emblaApi.current?.off('slidesInView', handleVisibilityChange);\n emblaApi.current?.off('select', handleIndexChange);\n emblaApi.current?.off('reInit', handleReinit);\n emblaApi.current?.off('autoplay:select', handleIndexChange);\n emblaApi.current?.destroy();\n }\n\n // Use direct viewport if available, else fallback to container (includes Carousel controls).\n currentElement = viewportRef.current ?? newElement;\n if (currentElement) {\n emblaApi.current = EmblaCarousel(\n currentElement,\n {\n ...DEFAULT_EMBLA_OPTIONS,\n ...emblaOptions.current,\n },\n plugins,\n );\n\n emblaApi.current?.on('reInit', handleReinit);\n emblaApi.current?.on('slidesInView', handleVisibilityChange);\n emblaApi.current?.on('select', handleIndexChange);\n emblaApi.current?.on('autoplay:select', handleIndexChange);\n }\n },\n };\n }, [getPlugins, handleIndexChange, handleReinit]);\n\n const carouselApi = React.useMemo(\n () => ({\n scrollToElement: (element: HTMLElement, jump?: boolean) => {\n const cardElements = emblaApi.current?.slideNodes();\n const groupIndexList = emblaApi.current?.internalEngine().slideRegistry ?? [];\n const cardIndex = cardElements?.indexOf(element) ?? 0;\n const groupIndex = groupIndexList.findIndex(group => {\n return group.includes(cardIndex);\n });\n const indexFocus = groupIndex ?? cardIndex;\n emblaApi.current?.scrollTo(indexFocus, jump);\n\n return indexFocus;\n },\n scrollToIndex: (index: number, jump?: boolean) => {\n emblaApi.current?.scrollTo(index, jump);\n },\n scrollInDirection: (dir: 'prev' | 'next') => {\n if (dir === 'prev') {\n emblaApi.current?.scrollPrev();\n } else {\n emblaApi.current?.scrollNext();\n }\n\n return emblaApi.current?.selectedScrollSnap() ?? 0;\n },\n }),\n [],\n );\n\n React.useEffect(() => {\n const plugins = getPlugins();\n\n emblaOptions.current = {\n startIndex: emblaOptions.current.startIndex,\n align,\n direction,\n loop,\n slidesToScroll,\n watchDrag,\n containScroll,\n };\n\n emblaApi.current?.reInit(\n {\n ...DEFAULT_EMBLA_OPTIONS,\n ...emblaOptions.current,\n },\n plugins,\n );\n }, [align, containScroll, direction, getPlugins, loop, slidesToScroll, watchDrag]);\n\n React.useEffect(() => {\n // Scroll to controlled values on update\n // If active index is out of bounds, re-init will handle instead\n const currentActiveIndex = emblaApi.current?.selectedScrollSnap() ?? 0;\n const slideLength = emblaApi.current?.slideNodes()?.length ?? 0;\n emblaOptions.current.startIndex = activeIndex;\n if (activeIndex < slideLength && activeIndex !== currentActiveIndex) {\n emblaApi.current?.scrollTo(activeIndex);\n }\n }, [activeIndex]);\n\n return {\n activeIndex,\n carouselApi,\n viewportRef,\n containerRef,\n subscribeForValues,\n enableAutoplay,\n resetAutoplay,\n };\n}\n"],"names":["useControllableState","useEventCallback","EmblaCarousel","React","carouselCardClassNames","carouselSliderClassNames","Autoplay","Fade","pointerEventPlugin","sliderClassname","root","DEFAULT_EMBLA_OPTIONS","containScroll","inViewThreshold","watchDrag","skipSnaps","container","slides","EMBLA_VISIBILITY_EVENT","setTabsterDefault","element","isDefault","tabsterAttr","getAttribute","tabsterAttributes","JSON","parse","focusable","setAttribute","stringify","useEmblaCarousel","options","align","direction","loop","slidesToScroll","motion","onDragIndexChange","onAutoplayIndexChange","activeIndex","setActiveIndex","defaultState","defaultActiveIndex","state","initialState","onDragEvent","event","index","type","emblaOptions","useRef","startIndex","emblaApi","autoplayRef","resetAutoplay","useCallback","current","plugins","autoplay","reset","getPlugins","push","playOnInit","stopOnInteraction","stopOnFocusIn","stopOnMouseEnter","onSelectViaDrag","enableAutoplay","temporary","play","stop","listeners","Set","subscribeForValues","listener","add","delete","handleReinit","nodes","slideNodes","groupIndexList","internalEngine","slideRegistry","navItemsCount","length","data","selectedScrollSnap","scrollTo","handleIndexChange","_","eventType","newIndex","actualIndex","forEach","slide","slideIndex","noopEvent","Event","viewportRef","containerRef","useMemo","currentElement","handleVisibilityChange","cardElements","visibleIndexes","slidesInView","cardElement","dispatchEvent","CustomEvent","bubbles","detail","isVisible","includes","newElement","off","destroy","on","carouselApi","scrollToElement","jump","cardIndex","indexOf","groupIndex","findIndex","group","indexFocus","scrollToIndex","scrollInDirection","dir","scrollPrev","scrollNext","useEffect","reInit","currentActiveIndex","slideLength"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -27,7 +27,8 @@ function useCarousel_unstable(props, ref) {
|
|
|
27
27
|
watchDrag: draggable,
|
|
28
28
|
containScroll: whitespace ? false : 'keepSnaps',
|
|
29
29
|
motion,
|
|
30
|
-
onDragIndexChange: onActiveIndexChange
|
|
30
|
+
onDragIndexChange: onActiveIndexChange,
|
|
31
|
+
onAutoplayIndexChange: onActiveIndexChange
|
|
31
32
|
});
|
|
32
33
|
const selectPageByElement = (0, _reactutilities.useEventCallback)((event, element, jump)=>{
|
|
33
34
|
const foundIndex = carouselApi.scrollToElement(element, jump);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Carousel/useCarousel.ts"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport {\n getIntrinsicElementProps,\n slot,\n useEventCallback,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { CarouselProps, CarouselState } from './Carousel.types';\nimport type { CarouselContextValue } from '../CarouselContext.types';\nimport { useEmblaCarousel } from '../useEmblaCarousel';\nimport { useAnnounce } from '@fluentui/react-shared-contexts';\n\n/**\n * Create the state required to render Carousel.\n *\n * The returned state can be modified with hooks such as useCarouselStyles_unstable,\n * before being passed to renderCarousel_unstable.\n *\n * @param props - props from this instance of Carousel\n * @param ref - reference to root HTMLDivElement of Carousel\n */\nexport function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDivElement>): CarouselState {\n 'use no memo';\n\n const {\n align = 'center',\n circular = false,\n onActiveIndexChange,\n groupSize = 'auto',\n draggable = false,\n whitespace = false,\n announcement,\n motion = 'slide',\n } = props;\n\n const { dir } = useFluent();\n const { activeIndex, carouselApi, containerRef, viewportRef, subscribeForValues, enableAutoplay, resetAutoplay } =\n useEmblaCarousel({\n align,\n direction: dir,\n loop: circular,\n slidesToScroll: groupSize,\n defaultActiveIndex: props.defaultActiveIndex,\n activeIndex: props.activeIndex,\n watchDrag: draggable,\n containScroll: whitespace ? false : 'keepSnaps',\n motion,\n onDragIndexChange: onActiveIndexChange,\n });\n\n const selectPageByElement: CarouselContextValue['selectPageByElement'] = useEventCallback((event, element, jump) => {\n const foundIndex = carouselApi.scrollToElement(element, jump);\n onActiveIndexChange?.(event, { event, type: 'focus', index: foundIndex });\n\n return foundIndex;\n });\n\n const selectPageByIndex: CarouselContextValue['selectPageByIndex'] = useEventCallback((event, index, jump) => {\n carouselApi.scrollToIndex(index, jump);\n\n onActiveIndexChange?.(event, { event, type: 'click', index });\n });\n\n const selectPageByDirection: CarouselContextValue['selectPageByDirection'] = useEventCallback((event, direction) => {\n const nextPageIndex = carouselApi.scrollInDirection(direction);\n onActiveIndexChange?.(event, { event, type: 'click', index: nextPageIndex });\n\n return nextPageIndex;\n });\n\n const mergedContainerRef = useMergedRefs(ref, containerRef);\n\n // Announce carousel updates\n const announcementTextRef = React.useRef<string>('');\n const totalNavLength = React.useRef<number>(0);\n const navGroupRef = React.useRef<number[][]>([]);\n\n const { announce } = useAnnounce();\n\n const updateAnnouncement = useEventCallback(() => {\n if (totalNavLength.current <= 0 || !announcement) {\n // Ignore announcements until slides discovered\n return;\n }\n\n const announcementText = announcement(activeIndex, totalNavLength.current, navGroupRef.current);\n\n if (announcementText !== announcementTextRef.current) {\n announcementTextRef.current = announcementText;\n announce(announcementText, { polite: true });\n }\n });\n\n useIsomorphicLayoutEffect(() => {\n // Subscribe to any non-index carousel state changes\n return subscribeForValues(data => {\n if (totalNavLength.current <= 0 && data.navItemsCount > 0 && announcement) {\n const announcementText = announcement(data.activeIndex, data.navItemsCount, data.groupIndexList);\n // Initialize our string to prevent updateAnnouncement from reading an initial load\n announcementTextRef.current = announcementText;\n }\n totalNavLength.current = data.navItemsCount;\n navGroupRef.current = data.groupIndexList;\n updateAnnouncement();\n });\n }, [subscribeForValues, updateAnnouncement, announcement]);\n\n useIsomorphicLayoutEffect(() => {\n updateAnnouncement();\n }, [activeIndex, updateAnnouncement]);\n\n return {\n components: {\n root: 'div',\n },\n root: slot.always(\n getIntrinsicElementProps('div', {\n ref: mergedContainerRef,\n role: 'region',\n ...props,\n }),\n { elementType: 'div' },\n ),\n\n activeIndex,\n circular,\n containerRef: mergedContainerRef,\n viewportRef,\n selectPageByElement,\n selectPageByDirection,\n selectPageByIndex,\n subscribeForValues,\n enableAutoplay,\n resetAutoplay,\n };\n}\n"],"names":["useCarousel_unstable","props","ref","align","circular","onActiveIndexChange","groupSize","draggable","whitespace","announcement","motion","dir","useFluent","activeIndex","carouselApi","containerRef","viewportRef","subscribeForValues","enableAutoplay","resetAutoplay","useEmblaCarousel","direction","loop","slidesToScroll","defaultActiveIndex","watchDrag","containScroll","onDragIndexChange","selectPageByElement","useEventCallback","event","element","jump","foundIndex","scrollToElement","type","index","selectPageByIndex","scrollToIndex","selectPageByDirection","nextPageIndex","scrollInDirection","mergedContainerRef","useMergedRefs","announcementTextRef","React","useRef","totalNavLength","navGroupRef","announce","useAnnounce","updateAnnouncement","current","announcementText","polite","useIsomorphicLayoutEffect","data","navItemsCount","groupIndexList","components","root","slot","always","getIntrinsicElementProps","role","elementType"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../src/components/Carousel/useCarousel.ts"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport {\n getIntrinsicElementProps,\n slot,\n useEventCallback,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { CarouselProps, CarouselState } from './Carousel.types';\nimport type { CarouselContextValue } from '../CarouselContext.types';\nimport { useEmblaCarousel } from '../useEmblaCarousel';\nimport { useAnnounce } from '@fluentui/react-shared-contexts';\n\n/**\n * Create the state required to render Carousel.\n *\n * The returned state can be modified with hooks such as useCarouselStyles_unstable,\n * before being passed to renderCarousel_unstable.\n *\n * @param props - props from this instance of Carousel\n * @param ref - reference to root HTMLDivElement of Carousel\n */\nexport function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDivElement>): CarouselState {\n 'use no memo';\n\n const {\n align = 'center',\n circular = false,\n onActiveIndexChange,\n groupSize = 'auto',\n draggable = false,\n whitespace = false,\n announcement,\n motion = 'slide',\n } = props;\n\n const { dir } = useFluent();\n const { activeIndex, carouselApi, containerRef, viewportRef, subscribeForValues, enableAutoplay, resetAutoplay } =\n useEmblaCarousel({\n align,\n direction: dir,\n loop: circular,\n slidesToScroll: groupSize,\n defaultActiveIndex: props.defaultActiveIndex,\n activeIndex: props.activeIndex,\n watchDrag: draggable,\n containScroll: whitespace ? false : 'keepSnaps',\n motion,\n onDragIndexChange: onActiveIndexChange,\n onAutoplayIndexChange: onActiveIndexChange,\n });\n\n const selectPageByElement: CarouselContextValue['selectPageByElement'] = useEventCallback((event, element, jump) => {\n const foundIndex = carouselApi.scrollToElement(element, jump);\n onActiveIndexChange?.(event, { event, type: 'focus', index: foundIndex });\n\n return foundIndex;\n });\n\n const selectPageByIndex: CarouselContextValue['selectPageByIndex'] = useEventCallback((event, index, jump) => {\n carouselApi.scrollToIndex(index, jump);\n\n onActiveIndexChange?.(event, { event, type: 'click', index });\n });\n\n const selectPageByDirection: CarouselContextValue['selectPageByDirection'] = useEventCallback((event, direction) => {\n const nextPageIndex = carouselApi.scrollInDirection(direction);\n onActiveIndexChange?.(event, { event, type: 'click', index: nextPageIndex });\n\n return nextPageIndex;\n });\n\n const mergedContainerRef = useMergedRefs(ref, containerRef);\n\n // Announce carousel updates\n const announcementTextRef = React.useRef<string>('');\n const totalNavLength = React.useRef<number>(0);\n const navGroupRef = React.useRef<number[][]>([]);\n\n const { announce } = useAnnounce();\n\n const updateAnnouncement = useEventCallback(() => {\n if (totalNavLength.current <= 0 || !announcement) {\n // Ignore announcements until slides discovered\n return;\n }\n\n const announcementText = announcement(activeIndex, totalNavLength.current, navGroupRef.current);\n\n if (announcementText !== announcementTextRef.current) {\n announcementTextRef.current = announcementText;\n announce(announcementText, { polite: true });\n }\n });\n\n useIsomorphicLayoutEffect(() => {\n // Subscribe to any non-index carousel state changes\n return subscribeForValues(data => {\n if (totalNavLength.current <= 0 && data.navItemsCount > 0 && announcement) {\n const announcementText = announcement(data.activeIndex, data.navItemsCount, data.groupIndexList);\n // Initialize our string to prevent updateAnnouncement from reading an initial load\n announcementTextRef.current = announcementText;\n }\n totalNavLength.current = data.navItemsCount;\n navGroupRef.current = data.groupIndexList;\n updateAnnouncement();\n });\n }, [subscribeForValues, updateAnnouncement, announcement]);\n\n useIsomorphicLayoutEffect(() => {\n updateAnnouncement();\n }, [activeIndex, updateAnnouncement]);\n\n return {\n components: {\n root: 'div',\n },\n root: slot.always(\n getIntrinsicElementProps('div', {\n ref: mergedContainerRef,\n role: 'region',\n ...props,\n }),\n { elementType: 'div' },\n ),\n\n activeIndex,\n circular,\n containerRef: mergedContainerRef,\n viewportRef,\n selectPageByElement,\n selectPageByDirection,\n selectPageByIndex,\n subscribeForValues,\n enableAutoplay,\n resetAutoplay,\n };\n}\n"],"names":["useCarousel_unstable","props","ref","align","circular","onActiveIndexChange","groupSize","draggable","whitespace","announcement","motion","dir","useFluent","activeIndex","carouselApi","containerRef","viewportRef","subscribeForValues","enableAutoplay","resetAutoplay","useEmblaCarousel","direction","loop","slidesToScroll","defaultActiveIndex","watchDrag","containScroll","onDragIndexChange","onAutoplayIndexChange","selectPageByElement","useEventCallback","event","element","jump","foundIndex","scrollToElement","type","index","selectPageByIndex","scrollToIndex","selectPageByDirection","nextPageIndex","scrollInDirection","mergedContainerRef","useMergedRefs","announcementTextRef","React","useRef","totalNavLength","navGroupRef","announce","useAnnounce","updateAnnouncement","current","announcementText","polite","useIsomorphicLayoutEffect","data","navItemsCount","groupIndexList","components","root","slot","always","getIntrinsicElementProps","role","elementType"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -23,16 +23,12 @@ const useCarouselAutoplayButton_unstable = (props, ref)=>{
|
|
|
23
23
|
});
|
|
24
24
|
const enableAutoplay = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.enableAutoplay);
|
|
25
25
|
_react.useEffect(()=>{
|
|
26
|
+
// Initialize carousel autoplay based on button state
|
|
27
|
+
enableAutoplay(autoplay);
|
|
26
28
|
return ()=>{
|
|
27
|
-
// We
|
|
29
|
+
// We uninitialize autoplay if the button gets unmounted.
|
|
28
30
|
enableAutoplay(false);
|
|
29
31
|
};
|
|
30
|
-
}, [
|
|
31
|
-
enableAutoplay
|
|
32
|
-
]);
|
|
33
|
-
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
|
|
34
|
-
// Enable/disable autoplay on state change
|
|
35
|
-
enableAutoplay(autoplay);
|
|
36
32
|
}, [
|
|
37
33
|
autoplay,
|
|
38
34
|
enableAutoplay
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CarouselAutoplayButton/useCarouselAutoplayButton.tsx"],"sourcesContent":["import type { ARIAButtonElement } from '@fluentui/react-aria';\nimport { useToggleButton_unstable } from '@fluentui/react-button';\nimport { PlayCircleRegular, PauseCircleRegular } from '@fluentui/react-icons';\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/components/CarouselAutoplayButton/useCarouselAutoplayButton.tsx"],"sourcesContent":["import type { ARIAButtonElement } from '@fluentui/react-aria';\nimport { useToggleButton_unstable } from '@fluentui/react-button';\nimport { PlayCircleRegular, PauseCircleRegular } from '@fluentui/react-icons';\nimport { mergeCallbacks, slot, useControllableState, useEventCallback } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { CarouselAutoplayButtonProps, CarouselAutoplayButtonState } from './CarouselAutoplayButton.types';\nimport { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';\n\n/**\n * Create the state required to render CarouselAutoplayButton.\n *\n * The returned state can be modified with hooks such as useCarouselAutoplayButtonStyles_unstable,\n * before being passed to renderCarouselAutoplayButton_unstable.\n *\n * @param props - props from this instance of CarouselAutoplayButton\n * @param ref - reference to root HTMLDivElement of CarouselAutoplayButton\n */\nexport const useCarouselAutoplayButton_unstable = (\n props: CarouselAutoplayButtonProps,\n ref: React.Ref<ARIAButtonElement>,\n): CarouselAutoplayButtonState => {\n const { onCheckedChange, checked, defaultChecked } = props;\n\n const [autoplay, setAutoplay] = useControllableState({\n state: checked,\n defaultState: defaultChecked,\n initialState: false,\n });\n const enableAutoplay = useCarouselContext(ctx => ctx.enableAutoplay);\n\n React.useEffect(() => {\n // Initialize carousel autoplay based on button state\n enableAutoplay(autoplay);\n\n return () => {\n // We uninitialize autoplay if the button gets unmounted.\n enableAutoplay(false);\n };\n }, [autoplay, enableAutoplay]);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement & HTMLAnchorElement>) => {\n if (event.isDefaultPrevented()) {\n return;\n }\n\n const newValue = !autoplay;\n\n setAutoplay(newValue);\n onCheckedChange?.(event, { event, type: 'click', checked: newValue });\n };\n\n return {\n // We lean on react-button class to handle styling and icon enhancements\n ...useToggleButton_unstable(\n {\n icon: slot.optional(props.icon, {\n defaultProps: {\n children: autoplay ? <PauseCircleRegular /> : <PlayCircleRegular />,\n },\n renderByDefault: true,\n elementType: 'span',\n }),\n ...props,\n checked: autoplay,\n onClick: useEventCallback(mergeCallbacks(handleClick, props.onClick)),\n },\n ref as React.Ref<HTMLButtonElement>,\n ),\n };\n};\n"],"names":["useCarouselAutoplayButton_unstable","props","ref","onCheckedChange","checked","defaultChecked","autoplay","setAutoplay","useControllableState","state","defaultState","initialState","enableAutoplay","useCarouselContext","ctx","React","useEffect","handleClick","event","isDefaultPrevented","newValue","type","useToggleButton_unstable","icon","slot","optional","defaultProps","children","createElement","PauseCircleRegular","PlayCircleRegular","renderByDefault","elementType","onClick","useEventCallback","mergeCallbacks"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAkBaA;;;eAAAA;;;;6BAjB4B;4BACa;gCACuB;iEACtD;iCAG2C;AAW3D,MAAMA,qCAAqC,CAChDC,OACAC;IAEA,MAAM,EAAEC,eAAe,EAAEC,OAAO,EAAEC,cAAc,EAAE,GAAGJ;IAErD,MAAM,CAACK,UAAUC,YAAY,GAAGC,IAAAA,oCAAAA,EAAqB;QACnDC,OAAOL;QACPM,cAAcL;QACdM,cAAc;IAChB;IACA,MAAMC,iBAAiBC,IAAAA,4CAAAA,EAAmBC,CAAAA,MAAOA,IAAIF,cAAc;IAEnEG,OAAMC,SAAS,CAAC;QACd,qDAAqD;QACrDJ,eAAeN;QAEf,OAAO;YACL,yDAAyD;YACzDM,eAAe;QACjB;IACF,GAAG;QAACN;QAAUM;KAAe;IAE7B,MAAMK,cAAc,CAACC;QACnB,IAAIA,MAAMC,kBAAkB,IAAI;YAC9B;QACF;QAEA,MAAMC,WAAW,CAACd;QAElBC,YAAYa;QACZjB,oBAAAA,QAAAA,oBAAAA,KAAAA,IAAAA,KAAAA,IAAAA,gBAAkBe,OAAO;YAAEA;YAAOG,MAAM;YAASjB,SAASgB;QAAS;IACrE;IAEA,OAAO;QACL,wEAAwE;QACxE,GAAGE,IAAAA,qCAAAA,EACD;YACEC,MAAMC,oBAAAA,CAAKC,QAAQ,CAACxB,MAAMsB,IAAI,EAAE;gBAC9BG,cAAc;oBACZC,UAAUrB,WAAAA,WAAAA,GAAWS,OAAAa,aAAA,CAACC,8BAAAA,EAAAA,QAAAA,WAAAA,GAAwBd,OAAAa,aAAA,CAACE,6BAAAA,EAAAA;gBACjD;gBACAC,iBAAiB;gBACjBC,aAAa;YACf;YACA,GAAG/B,KAAK;YACRG,SAASE;YACT2B,SAASC,IAAAA,gCAAAA,EAAiBC,IAAAA,8BAAAA,EAAelB,aAAahB,MAAMgC,OAAO;QACrE,GACA/B,IACD;IACH;AACF"}
|
|
@@ -21,7 +21,7 @@ const useCarouselButton_unstable = (props, ref)=>{
|
|
|
21
21
|
// Locally tracks the total number of slides, will only update if this changes.
|
|
22
22
|
const [totalSlides, setTotalSlides] = _react.useState(0);
|
|
23
23
|
const { dir } = (0, _reactsharedcontexts.useFluent_unstable)();
|
|
24
|
-
const buttonRef =
|
|
24
|
+
const buttonRef = _react.useRef();
|
|
25
25
|
const circular = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.circular);
|
|
26
26
|
const containerRef = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.containerRef);
|
|
27
27
|
const selectPageByDirection = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.selectPageByDirection);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CarouselButton/useCarouselButton.tsx"],"sourcesContent":["import { type ARIAButtonElement } from '@fluentui/react-aria';\nimport { useButton_unstable } from '@fluentui/react-button';\nimport { ChevronLeftRegular, ChevronRightRegular } from '@fluentui/react-icons';\nimport {\n mergeCallbacks,\n useEventCallback,\n slot,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';\nimport type { CarouselButtonProps, CarouselButtonState } from './CarouselButton.types';\nimport type { CarouselUpdateData } from '../Carousel/Carousel.types';\nimport { carouselButtonClassNames } from './useCarouselButtonStyles.styles';\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/components/CarouselButton/useCarouselButton.tsx"],"sourcesContent":["import { type ARIAButtonElement } from '@fluentui/react-aria';\nimport { useButton_unstable } from '@fluentui/react-button';\nimport { ChevronLeftRegular, ChevronRightRegular } from '@fluentui/react-icons';\nimport {\n mergeCallbacks,\n useEventCallback,\n slot,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';\nimport type { CarouselButtonProps, CarouselButtonState } from './CarouselButton.types';\nimport type { CarouselUpdateData } from '../Carousel/Carousel.types';\nimport { carouselButtonClassNames } from './useCarouselButtonStyles.styles';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\n/**\n * Create the state required to render CarouselButton.\n *\n * The returned state can be modified with hooks such as useCarouselButtonStyles_unstable,\n * before being passed to renderCarouselButton_unstable.\n *\n * @param props - props from this instance of CarouselButton\n * @param ref - reference to root HTMLDivElement of CarouselButton\n */\nexport const useCarouselButton_unstable = (\n props: CarouselButtonProps,\n ref: React.Ref<ARIAButtonElement>,\n): CarouselButtonState => {\n const { navType = 'next' } = props;\n\n // Locally tracks the total number of slides, will only update if this changes.\n const [totalSlides, setTotalSlides] = React.useState(0);\n\n const { dir } = useFluent();\n const buttonRef = React.useRef<HTMLButtonElement>();\n const circular = useCarouselContext(ctx => ctx.circular);\n const containerRef = useCarouselContext(ctx => ctx.containerRef);\n const selectPageByDirection = useCarouselContext(ctx => ctx.selectPageByDirection);\n const subscribeForValues = useCarouselContext(ctx => ctx.subscribeForValues);\n const resetAutoplay = useCarouselContext(ctx => ctx.resetAutoplay);\n\n const isTrailing = useCarouselContext(ctx => {\n if (circular) {\n return false;\n }\n\n if (navType === 'prev') {\n return ctx.activeIndex === 0;\n }\n\n return ctx.activeIndex === totalSlides - 1;\n });\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement & HTMLAnchorElement>) => {\n if (event.isDefaultPrevented()) {\n return;\n }\n\n const nextIndex = selectPageByDirection(event, navType);\n\n let _trailing = false;\n if (navType === 'prev') {\n _trailing = nextIndex === 0;\n } else {\n _trailing = nextIndex === totalSlides - 1;\n }\n\n if (!circular && _trailing && containerRef?.current) {\n // Focus non-disabled element\n const buttonRefs: NodeListOf<HTMLButtonElement> = containerRef.current.querySelectorAll(\n `.${carouselButtonClassNames.root}`,\n );\n buttonRefs.forEach(_buttonRef => {\n if (_buttonRef !== buttonRef.current) {\n _buttonRef.focus();\n }\n });\n }\n\n resetAutoplay();\n };\n\n useIsomorphicLayoutEffect(() => {\n return subscribeForValues((data: CarouselUpdateData) => {\n setTotalSlides(data.navItemsCount);\n });\n }, [subscribeForValues]);\n\n const nextArrowIcon = dir === 'ltr' ? <ChevronRightRegular /> : <ChevronLeftRegular />;\n const prevArrowIcon = dir === 'ltr' ? <ChevronLeftRegular /> : <ChevronRightRegular />;\n\n return {\n navType,\n // We lean on react-button class to handle styling and icon enhancements\n ...useButton_unstable(\n {\n icon: slot.optional(props.icon, {\n defaultProps: {\n children: navType === 'next' ? nextArrowIcon : prevArrowIcon,\n },\n renderByDefault: true,\n elementType: 'span',\n }),\n disabled: isTrailing,\n tabIndex: isTrailing ? -1 : 0,\n 'aria-disabled': isTrailing,\n appearance: 'subtle',\n ...props,\n onClick: useEventCallback(mergeCallbacks(handleClick, props.onClick)),\n },\n useMergedRefs(ref, buttonRef) as React.Ref<HTMLButtonElement>,\n ),\n };\n};\n"],"names":["useCarouselButton_unstable","props","ref","navType","totalSlides","setTotalSlides","React","useState","dir","useFluent","buttonRef","useRef","circular","useCarouselContext","ctx","containerRef","selectPageByDirection","subscribeForValues","resetAutoplay","isTrailing","activeIndex","handleClick","event","isDefaultPrevented","nextIndex","_trailing","current","buttonRefs","querySelectorAll","carouselButtonClassNames","root","forEach","_buttonRef","focus","useIsomorphicLayoutEffect","data","navItemsCount","nextArrowIcon","createElement","ChevronRightRegular","ChevronLeftRegular","prevArrowIcon","useButton_unstable","icon","slot","optional","defaultProps","children","renderByDefault","elementType","disabled","tabIndex","appearance","onClick","useEventCallback","mergeCallbacks","useMergedRefs"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CarouselContext.types.ts"],"sourcesContent":["import type { EventData } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { CarouselUpdateData } from '../Carousel';\n\nexport type CarouselIndexChangeData = (\n | EventData<'click', React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>>\n | EventData<'focus', React.FocusEvent>\n | EventData<'drag', PointerEvent | MouseEvent>\n) & {\n /**\n * The index to be set after event has occurred.\n */\n index: number;\n};\n\nexport type CarouselContextValue = {\n activeIndex: number;\n circular: boolean;\n selectPageByElement: (event: React.FocusEvent, element: HTMLElement, jump?: boolean) => number;\n selectPageByDirection: (\n event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,\n direction: 'next' | 'prev',\n ) => number;\n selectPageByIndex: (\n event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,\n value: number,\n jump?: boolean,\n ) => void;\n subscribeForValues: (listener: (data: CarouselUpdateData) => void) => () => void;\n enableAutoplay: (autoplay: boolean) => void;\n resetAutoplay: () => void;\n // Container with controls passed to carousel engine\n containerRef?: React.RefObject<HTMLDivElement>;\n // Viewport without controls used for interactive functionality (draggable, pause autoplay etc.)\n viewportRef?: React.RefObject<HTMLDivElement>;\n};\n\n/**\n * Context shared between Carousel and its children components\n */\nexport type CarouselContextValues = {\n carousel: CarouselContextValue;\n};\n"],"names":[],"rangeMappings":";;;;;","mappings":";;;;;iEACuB"}
|
|
1
|
+
{"version":3,"sources":["../src/components/CarouselContext.types.ts"],"sourcesContent":["import type { EventData } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { CarouselUpdateData } from '../Carousel';\n\nexport type CarouselIndexChangeData = (\n | EventData<'click', React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>>\n | EventData<'focus', React.FocusEvent>\n | EventData<'drag', PointerEvent | MouseEvent>\n | EventData<'autoplay', Event>\n) & {\n /**\n * The index to be set after event has occurred.\n */\n index: number;\n};\n\nexport type CarouselContextValue = {\n activeIndex: number;\n circular: boolean;\n selectPageByElement: (event: React.FocusEvent, element: HTMLElement, jump?: boolean) => number;\n selectPageByDirection: (\n event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,\n direction: 'next' | 'prev',\n ) => number;\n selectPageByIndex: (\n event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,\n value: number,\n jump?: boolean,\n ) => void;\n subscribeForValues: (listener: (data: CarouselUpdateData) => void) => () => void;\n enableAutoplay: (autoplay: boolean, temporary?: boolean) => void;\n resetAutoplay: () => void;\n // Container with controls passed to carousel engine\n containerRef?: React.RefObject<HTMLDivElement>;\n // Viewport without controls used for interactive functionality (draggable, pause autoplay etc.)\n viewportRef?: React.RefObject<HTMLDivElement>;\n};\n\n/**\n * Context shared between Carousel and its children components\n */\nexport type CarouselContextValues = {\n carousel: CarouselContextValue;\n};\n"],"names":[],"rangeMappings":";;;;;","mappings":";;;;;iEACuB"}
|
|
@@ -13,7 +13,46 @@ const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
|
13
13
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
14
14
|
const _CarouselContext = require("../CarouselContext");
|
|
15
15
|
const useCarouselViewport_unstable = (props, ref)=>{
|
|
16
|
+
const hasFocus = _react.useRef(false);
|
|
17
|
+
const hasMouse = _react.useRef(false);
|
|
16
18
|
const viewportRef = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.viewportRef);
|
|
19
|
+
const enableAutoplay = (0, _CarouselContext.useCarouselContext_unstable)((ctx)=>ctx.enableAutoplay);
|
|
20
|
+
const handleFocusCapture = _react.useCallback((e)=>{
|
|
21
|
+
hasFocus.current = true;
|
|
22
|
+
// Will pause autoplay when focus is captured within viewport (if autoplay is initialized)
|
|
23
|
+
enableAutoplay(false, true);
|
|
24
|
+
}, [
|
|
25
|
+
enableAutoplay
|
|
26
|
+
]);
|
|
27
|
+
const handleBlurCapture = _react.useCallback((e)=>{
|
|
28
|
+
// Will enable autoplay (if initialized) when focus exits viewport
|
|
29
|
+
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
30
|
+
hasFocus.current = false;
|
|
31
|
+
if (!hasMouse.current) {
|
|
32
|
+
enableAutoplay(true, true);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}, [
|
|
36
|
+
enableAutoplay
|
|
37
|
+
]);
|
|
38
|
+
const handleMouseEnter = _react.useCallback((event)=>{
|
|
39
|
+
hasMouse.current = true;
|
|
40
|
+
enableAutoplay(false, true);
|
|
41
|
+
}, [
|
|
42
|
+
enableAutoplay
|
|
43
|
+
]);
|
|
44
|
+
const handleMouseLeave = _react.useCallback((event)=>{
|
|
45
|
+
hasMouse.current = false;
|
|
46
|
+
if (!hasFocus.current) {
|
|
47
|
+
enableAutoplay(true, true);
|
|
48
|
+
}
|
|
49
|
+
}, [
|
|
50
|
+
enableAutoplay
|
|
51
|
+
]);
|
|
52
|
+
const onFocusCapture = (0, _reactutilities.mergeCallbacks)(props.onFocusCapture, handleFocusCapture);
|
|
53
|
+
const onBlurCapture = (0, _reactutilities.mergeCallbacks)(props.onBlurCapture, handleBlurCapture);
|
|
54
|
+
const onMouseEnter = (0, _reactutilities.mergeCallbacks)(props.onMouseEnter, handleMouseEnter);
|
|
55
|
+
const onMouseLeave = (0, _reactutilities.mergeCallbacks)(props.onMouseLeave, handleMouseLeave);
|
|
17
56
|
return {
|
|
18
57
|
components: {
|
|
19
58
|
root: 'div'
|
|
@@ -23,7 +62,11 @@ const useCarouselViewport_unstable = (props, ref)=>{
|
|
|
23
62
|
role: 'presentation',
|
|
24
63
|
// Draggable ensures dragging is supported (even if not enabled)
|
|
25
64
|
draggable: true,
|
|
26
|
-
...props
|
|
65
|
+
...props,
|
|
66
|
+
onFocusCapture,
|
|
67
|
+
onBlurCapture,
|
|
68
|
+
onMouseEnter,
|
|
69
|
+
onMouseLeave
|
|
27
70
|
}), {
|
|
28
71
|
elementType: 'div'
|
|
29
72
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CarouselViewport/useCarouselViewport.ts"],"sourcesContent":["import * as React from 'react';\nimport { getIntrinsicElementProps, slot, useMergedRefs } from '@fluentui/react-utilities';\nimport type { CarouselViewportProps, CarouselViewportState } from './CarouselViewport.types';\nimport { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';\n\n/**\n * Create the state required to render CarouselViewport.\n *\n * The returned state can be modified with hooks such as useCarouselViewportStyles_unstable,\n * before being passed to renderCarouselViewport_unstable.\n *\n * @param props - props from this instance of CarouselViewport\n * @param ref - reference to root HTMLDivElement of CarouselViewport\n */\nexport const useCarouselViewport_unstable = (\n props: CarouselViewportProps,\n ref: React.Ref<HTMLDivElement>,\n): CarouselViewportState => {\n const viewportRef = useCarouselContext(ctx => ctx.viewportRef);\n\n return {\n components: {\n root: 'div',\n },\n root: slot.always(\n getIntrinsicElementProps('div', {\n ref: useMergedRefs(ref, viewportRef),\n role: 'presentation',\n // Draggable ensures dragging is supported (even if not enabled)\n draggable: true,\n ...props,\n }),\n { elementType: 'div' },\n ),\n };\n};\n"],"names":["useCarouselViewport_unstable","props","ref","viewportRef","useCarouselContext","ctx","components","root","slot","always","getIntrinsicElementProps","useMergedRefs","role","draggable","elementType"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../src/components/CarouselViewport/useCarouselViewport.ts"],"sourcesContent":["import * as React from 'react';\nimport { getIntrinsicElementProps, mergeCallbacks, slot, useMergedRefs } from '@fluentui/react-utilities';\nimport type { CarouselViewportProps, CarouselViewportState } from './CarouselViewport.types';\nimport { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';\n\n/**\n * Create the state required to render CarouselViewport.\n *\n * The returned state can be modified with hooks such as useCarouselViewportStyles_unstable,\n * before being passed to renderCarouselViewport_unstable.\n *\n * @param props - props from this instance of CarouselViewport\n * @param ref - reference to root HTMLDivElement of CarouselViewport\n */\nexport const useCarouselViewport_unstable = (\n props: CarouselViewportProps,\n ref: React.Ref<HTMLDivElement>,\n): CarouselViewportState => {\n const hasFocus = React.useRef(false);\n const hasMouse = React.useRef(false);\n const viewportRef = useCarouselContext(ctx => ctx.viewportRef);\n const enableAutoplay = useCarouselContext(ctx => ctx.enableAutoplay);\n\n const handleFocusCapture = React.useCallback(\n (e: React.FocusEvent) => {\n hasFocus.current = true;\n // Will pause autoplay when focus is captured within viewport (if autoplay is initialized)\n enableAutoplay(false, true);\n },\n [enableAutoplay],\n );\n\n const handleBlurCapture = React.useCallback(\n (e: React.FocusEvent) => {\n // Will enable autoplay (if initialized) when focus exits viewport\n if (!e.currentTarget.contains(e.relatedTarget)) {\n hasFocus.current = false;\n if (!hasMouse.current) {\n enableAutoplay(true, true);\n }\n }\n },\n [enableAutoplay],\n );\n\n const handleMouseEnter = React.useCallback(\n (event: React.MouseEvent) => {\n hasMouse.current = true;\n enableAutoplay(false, true);\n },\n [enableAutoplay],\n );\n const handleMouseLeave = React.useCallback(\n (event: React.MouseEvent) => {\n hasMouse.current = false;\n if (!hasFocus.current) {\n enableAutoplay(true, true);\n }\n },\n [enableAutoplay],\n );\n\n const onFocusCapture = mergeCallbacks(props.onFocusCapture, handleFocusCapture);\n const onBlurCapture = mergeCallbacks(props.onBlurCapture, handleBlurCapture);\n const onMouseEnter = mergeCallbacks(props.onMouseEnter, handleMouseEnter);\n const onMouseLeave = mergeCallbacks(props.onMouseLeave, handleMouseLeave);\n\n return {\n components: {\n root: 'div',\n },\n root: slot.always(\n getIntrinsicElementProps('div', {\n ref: useMergedRefs(ref, viewportRef),\n role: 'presentation',\n // Draggable ensures dragging is supported (even if not enabled)\n draggable: true,\n ...props,\n onFocusCapture,\n onBlurCapture,\n onMouseEnter,\n onMouseLeave,\n }),\n { elementType: 'div' },\n ),\n };\n};\n"],"names":["useCarouselViewport_unstable","props","ref","hasFocus","React","useRef","hasMouse","viewportRef","useCarouselContext","ctx","enableAutoplay","handleFocusCapture","useCallback","e","current","handleBlurCapture","currentTarget","contains","relatedTarget","handleMouseEnter","event","handleMouseLeave","onFocusCapture","mergeCallbacks","onBlurCapture","onMouseEnter","onMouseLeave","components","root","slot","always","getIntrinsicElementProps","useMergedRefs","role","draggable","elementType"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAcaA;;;eAAAA;;;;iEAdU;gCACuD;iCAEZ;AAW3D,MAAMA,+BAA+B,CAC1CC,OACAC;IAEA,MAAMC,WAAWC,OAAMC,MAAM,CAAC;IAC9B,MAAMC,WAAWF,OAAMC,MAAM,CAAC;IAC9B,MAAME,cAAcC,IAAAA,4CAAAA,EAAmBC,CAAAA,MAAOA,IAAIF,WAAW;IAC7D,MAAMG,iBAAiBF,IAAAA,4CAAAA,EAAmBC,CAAAA,MAAOA,IAAIC,cAAc;IAEnE,MAAMC,qBAAqBP,OAAMQ,WAAW,CAC1C,CAACC;QACCV,SAASW,OAAO,GAAG;QACnB,0FAA0F;QAC1FJ,eAAe,OAAO;IACxB,GACA;QAACA;KAAe;IAGlB,MAAMK,oBAAoBX,OAAMQ,WAAW,CACzC,CAACC;QACC,kEAAkE;QAClE,IAAI,CAACA,EAAEG,aAAa,CAACC,QAAQ,CAACJ,EAAEK,aAAa,GAAG;YAC9Cf,SAASW,OAAO,GAAG;YACnB,IAAI,CAACR,SAASQ,OAAO,EAAE;gBACrBJ,eAAe,MAAM;YACvB;QACF;IACF,GACA;QAACA;KAAe;IAGlB,MAAMS,mBAAmBf,OAAMQ,WAAW,CACxC,CAACQ;QACCd,SAASQ,OAAO,GAAG;QACnBJ,eAAe,OAAO;IACxB,GACA;QAACA;KAAe;IAElB,MAAMW,mBAAmBjB,OAAMQ,WAAW,CACxC,CAACQ;QACCd,SAASQ,OAAO,GAAG;QACnB,IAAI,CAACX,SAASW,OAAO,EAAE;YACrBJ,eAAe,MAAM;QACvB;IACF,GACA;QAACA;KAAe;IAGlB,MAAMY,iBAAiBC,IAAAA,8BAAAA,EAAetB,MAAMqB,cAAc,EAAEX;IAC5D,MAAMa,gBAAgBD,IAAAA,8BAAAA,EAAetB,MAAMuB,aAAa,EAAET;IAC1D,MAAMU,eAAeF,IAAAA,8BAAAA,EAAetB,MAAMwB,YAAY,EAAEN;IACxD,MAAMO,eAAeH,IAAAA,8BAAAA,EAAetB,MAAMyB,YAAY,EAAEL;IAExD,OAAO;QACLM,YAAY;YACVC,MAAM;QACR;QACAA,MAAMC,oBAAAA,CAAKC,MAAM,CACfC,IAAAA,wCAAAA,EAAyB,OAAO;YAC9B7B,KAAK8B,IAAAA,6BAAAA,EAAc9B,KAAKK;YACxB0B,MAAM;YACN,gEAAgE;YAChEC,WAAW;YACX,GAAGjC,KAAK;YACRqB;YACAE;YACAC;YACAC;QACF,IACA;YAAES,aAAa;QAAM;IAEzB;AACF"}
|
|
@@ -51,7 +51,7 @@ function setTabsterDefault(element, isDefault) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
function useEmblaCarousel(options) {
|
|
54
|
-
const { align, direction, loop, slidesToScroll, watchDrag, containScroll, motion, onDragIndexChange } = options;
|
|
54
|
+
const { align, direction, loop, slidesToScroll, watchDrag, containScroll, motion, onDragIndexChange, onAutoplayIndexChange } = options;
|
|
55
55
|
const [activeIndex, setActiveIndex] = (0, _reactutilities.useControllableState)({
|
|
56
56
|
defaultState: options.defaultActiveIndex,
|
|
57
57
|
state: options.activeIndex,
|
|
@@ -76,32 +76,17 @@ function useEmblaCarousel(options) {
|
|
|
76
76
|
const emblaApi = _react.useRef(null);
|
|
77
77
|
const autoplayRef = _react.useRef(false);
|
|
78
78
|
const resetAutoplay = _react.useCallback(()=>{
|
|
79
|
-
var _emblaApi_current;
|
|
80
|
-
(_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.plugins().autoplay.reset();
|
|
79
|
+
var _emblaApi_current_plugins_autoplay, _emblaApi_current;
|
|
80
|
+
(_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : (_emblaApi_current_plugins_autoplay = _emblaApi_current.plugins().autoplay) === null || _emblaApi_current_plugins_autoplay === void 0 ? void 0 : _emblaApi_current_plugins_autoplay.reset();
|
|
81
81
|
}, []);
|
|
82
|
-
/* Our autoplay button, which is required by standards for autoplay to be enabled, will handle controlled state */ const enableAutoplay = _react.useCallback((autoplay)=>{
|
|
83
|
-
autoplayRef.current = autoplay;
|
|
84
|
-
if (autoplay) {
|
|
85
|
-
var _emblaApi_current;
|
|
86
|
-
(_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.plugins().autoplay.play();
|
|
87
|
-
// Reset after play to ensure timing and any focus/mouse pause state is reset.
|
|
88
|
-
resetAutoplay();
|
|
89
|
-
} else {
|
|
90
|
-
var _emblaApi_current1;
|
|
91
|
-
(_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : _emblaApi_current1.plugins().autoplay.stop();
|
|
92
|
-
}
|
|
93
|
-
}, [
|
|
94
|
-
resetAutoplay
|
|
95
|
-
]);
|
|
96
82
|
const getPlugins = _react.useCallback(()=>{
|
|
97
|
-
const plugins = [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
];
|
|
83
|
+
const plugins = [];
|
|
84
|
+
plugins.push((0, _emblacarouselautoplay.default)({
|
|
85
|
+
playOnInit: autoplayRef.current,
|
|
86
|
+
/* stopOnInteraction: false causes autoplay to restart on interaction end*/ /* we'll handle this logic to ensure autoplay state is respected */ stopOnInteraction: true,
|
|
87
|
+
stopOnFocusIn: false,
|
|
88
|
+
stopOnMouseEnter: false
|
|
89
|
+
}));
|
|
105
90
|
// Optionally add Fade plugin
|
|
106
91
|
if (motion === 'fade') {
|
|
107
92
|
plugins.push((0, _emblacarouselfade.default)());
|
|
@@ -117,6 +102,24 @@ function useEmblaCarousel(options) {
|
|
|
117
102
|
onDragEvent,
|
|
118
103
|
watchDrag
|
|
119
104
|
]);
|
|
105
|
+
/* This function enables autoplay to pause/play without affecting underlying state
|
|
106
|
+
* Useful for pausing on focus etc. without having to reinitialize or set autoplay to off
|
|
107
|
+
*/ const enableAutoplay = _react.useCallback((autoplay, temporary)=>{
|
|
108
|
+
if (!temporary) {
|
|
109
|
+
autoplayRef.current = autoplay;
|
|
110
|
+
}
|
|
111
|
+
if (autoplay && autoplayRef.current) {
|
|
112
|
+
var _emblaApi_current_plugins_autoplay, _emblaApi_current;
|
|
113
|
+
(_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : (_emblaApi_current_plugins_autoplay = _emblaApi_current.plugins().autoplay) === null || _emblaApi_current_plugins_autoplay === void 0 ? void 0 : _emblaApi_current_plugins_autoplay.play();
|
|
114
|
+
// Reset after play to ensure timing and any focus/mouse pause state is reset.
|
|
115
|
+
resetAutoplay();
|
|
116
|
+
} else if (!autoplay) {
|
|
117
|
+
var _emblaApi_current_plugins_autoplay1, _emblaApi_current1;
|
|
118
|
+
(_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : (_emblaApi_current_plugins_autoplay1 = _emblaApi_current1.plugins().autoplay) === null || _emblaApi_current_plugins_autoplay1 === void 0 ? void 0 : _emblaApi_current_plugins_autoplay1.stop();
|
|
119
|
+
}
|
|
120
|
+
}, [
|
|
121
|
+
resetAutoplay
|
|
122
|
+
]);
|
|
120
123
|
// Listeners contains callbacks for UI elements that may require state update based on embla changes
|
|
121
124
|
const listeners = _react.useRef(new Set());
|
|
122
125
|
const subscribeForValues = _react.useCallback((listener)=>{
|
|
@@ -144,22 +147,30 @@ function useEmblaCarousel(options) {
|
|
|
144
147
|
listener(data);
|
|
145
148
|
}
|
|
146
149
|
});
|
|
150
|
+
const handleIndexChange = (0, _reactutilities.useEventCallback)((_, eventType)=>{
|
|
151
|
+
var _emblaApi_current, _emblaApi_current1, _emblaApi_current2;
|
|
152
|
+
var _emblaApi_current_selectedScrollSnap;
|
|
153
|
+
const newIndex = (_emblaApi_current_selectedScrollSnap = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.selectedScrollSnap()) !== null && _emblaApi_current_selectedScrollSnap !== void 0 ? _emblaApi_current_selectedScrollSnap : 0;
|
|
154
|
+
const slides = (_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : _emblaApi_current1.slideNodes();
|
|
155
|
+
var _emblaApi_current_internalEngine_slideRegistry_newIndex_;
|
|
156
|
+
const actualIndex = (_emblaApi_current_internalEngine_slideRegistry_newIndex_ = (_emblaApi_current2 = emblaApi.current) === null || _emblaApi_current2 === void 0 ? void 0 : _emblaApi_current2.internalEngine().slideRegistry[newIndex][0]) !== null && _emblaApi_current_internalEngine_slideRegistry_newIndex_ !== void 0 ? _emblaApi_current_internalEngine_slideRegistry_newIndex_ : 0;
|
|
157
|
+
// We set the active or first index of group on-screen as the selected tabster index
|
|
158
|
+
slides === null || slides === void 0 ? void 0 : slides.forEach((slide, slideIndex)=>{
|
|
159
|
+
setTabsterDefault(slide, slideIndex === actualIndex);
|
|
160
|
+
});
|
|
161
|
+
setActiveIndex(newIndex);
|
|
162
|
+
if (eventType === 'autoplay:select') {
|
|
163
|
+
const noopEvent = new Event('autoplay');
|
|
164
|
+
onAutoplayIndexChange === null || onAutoplayIndexChange === void 0 ? void 0 : onAutoplayIndexChange(noopEvent, {
|
|
165
|
+
event: noopEvent,
|
|
166
|
+
type: 'autoplay',
|
|
167
|
+
index: newIndex
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
147
171
|
const viewportRef = _react.useRef(null);
|
|
148
172
|
const containerRef = _react.useMemo(()=>{
|
|
149
173
|
let currentElement = null;
|
|
150
|
-
const handleIndexChange = ()=>{
|
|
151
|
-
var _emblaApi_current, _emblaApi_current1, _emblaApi_current2;
|
|
152
|
-
var _emblaApi_current_selectedScrollSnap;
|
|
153
|
-
const newIndex = (_emblaApi_current_selectedScrollSnap = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.selectedScrollSnap()) !== null && _emblaApi_current_selectedScrollSnap !== void 0 ? _emblaApi_current_selectedScrollSnap : 0;
|
|
154
|
-
const slides = (_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : _emblaApi_current1.slideNodes();
|
|
155
|
-
var _emblaApi_current_internalEngine_slideRegistry_newIndex_;
|
|
156
|
-
const actualIndex = (_emblaApi_current_internalEngine_slideRegistry_newIndex_ = (_emblaApi_current2 = emblaApi.current) === null || _emblaApi_current2 === void 0 ? void 0 : _emblaApi_current2.internalEngine().slideRegistry[newIndex][0]) !== null && _emblaApi_current_internalEngine_slideRegistry_newIndex_ !== void 0 ? _emblaApi_current_internalEngine_slideRegistry_newIndex_ : 0;
|
|
157
|
-
// We set the active or first index of group on-screen as the selected tabster index
|
|
158
|
-
slides === null || slides === void 0 ? void 0 : slides.forEach((slide, slideIndex)=>{
|
|
159
|
-
setTabsterDefault(slide, slideIndex === actualIndex);
|
|
160
|
-
});
|
|
161
|
-
setActiveIndex(newIndex);
|
|
162
|
-
};
|
|
163
174
|
const handleVisibilityChange = ()=>{
|
|
164
175
|
var _emblaApi_current, _emblaApi_current1;
|
|
165
176
|
const cardElements = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.slideNodes();
|
|
@@ -174,35 +185,37 @@ function useEmblaCarousel(options) {
|
|
|
174
185
|
}));
|
|
175
186
|
});
|
|
176
187
|
};
|
|
188
|
+
// Get plugins using autoplayRef to prevent state change recreating EmblaCarousel
|
|
177
189
|
const plugins = getPlugins();
|
|
178
190
|
return {
|
|
179
191
|
set current (newElement){
|
|
180
192
|
if (currentElement) {
|
|
181
|
-
var _emblaApi_current, _emblaApi_current1, _emblaApi_current2, _emblaApi_current3;
|
|
193
|
+
var _emblaApi_current, _emblaApi_current1, _emblaApi_current2, _emblaApi_current3, _emblaApi_current4;
|
|
182
194
|
(_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.off('slidesInView', handleVisibilityChange);
|
|
183
195
|
(_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : _emblaApi_current1.off('select', handleIndexChange);
|
|
184
196
|
(_emblaApi_current2 = emblaApi.current) === null || _emblaApi_current2 === void 0 ? void 0 : _emblaApi_current2.off('reInit', handleReinit);
|
|
185
|
-
(_emblaApi_current3 = emblaApi.current) === null || _emblaApi_current3 === void 0 ? void 0 : _emblaApi_current3.
|
|
197
|
+
(_emblaApi_current3 = emblaApi.current) === null || _emblaApi_current3 === void 0 ? void 0 : _emblaApi_current3.off('autoplay:select', handleIndexChange);
|
|
198
|
+
(_emblaApi_current4 = emblaApi.current) === null || _emblaApi_current4 === void 0 ? void 0 : _emblaApi_current4.destroy();
|
|
186
199
|
}
|
|
187
200
|
var _viewportRef_current;
|
|
188
201
|
// Use direct viewport if available, else fallback to container (includes Carousel controls).
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
var
|
|
192
|
-
|
|
193
|
-
emblaApi.current = (0, _emblacarousel.default)(wrapperElement, {
|
|
202
|
+
currentElement = (_viewportRef_current = viewportRef.current) !== null && _viewportRef_current !== void 0 ? _viewportRef_current : newElement;
|
|
203
|
+
if (currentElement) {
|
|
204
|
+
var _emblaApi_current5, _emblaApi_current6, _emblaApi_current7, _emblaApi_current8;
|
|
205
|
+
emblaApi.current = (0, _emblacarousel.default)(currentElement, {
|
|
194
206
|
...DEFAULT_EMBLA_OPTIONS,
|
|
195
207
|
...emblaOptions.current
|
|
196
208
|
}, plugins);
|
|
197
|
-
(
|
|
198
|
-
(
|
|
199
|
-
(
|
|
209
|
+
(_emblaApi_current5 = emblaApi.current) === null || _emblaApi_current5 === void 0 ? void 0 : _emblaApi_current5.on('reInit', handleReinit);
|
|
210
|
+
(_emblaApi_current6 = emblaApi.current) === null || _emblaApi_current6 === void 0 ? void 0 : _emblaApi_current6.on('slidesInView', handleVisibilityChange);
|
|
211
|
+
(_emblaApi_current7 = emblaApi.current) === null || _emblaApi_current7 === void 0 ? void 0 : _emblaApi_current7.on('select', handleIndexChange);
|
|
212
|
+
(_emblaApi_current8 = emblaApi.current) === null || _emblaApi_current8 === void 0 ? void 0 : _emblaApi_current8.on('autoplay:select', handleIndexChange);
|
|
200
213
|
}
|
|
201
214
|
}
|
|
202
215
|
};
|
|
203
216
|
}, [
|
|
204
217
|
getPlugins,
|
|
205
|
-
|
|
218
|
+
handleIndexChange,
|
|
206
219
|
handleReinit
|
|
207
220
|
]);
|
|
208
221
|
const carouselApi = _react.useMemo(()=>({
|
|
@@ -237,22 +250,6 @@ function useEmblaCarousel(options) {
|
|
|
237
250
|
return (_emblaApi_current_selectedScrollSnap = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.selectedScrollSnap()) !== null && _emblaApi_current_selectedScrollSnap !== void 0 ? _emblaApi_current_selectedScrollSnap : 0;
|
|
238
251
|
}
|
|
239
252
|
}), []);
|
|
240
|
-
_react.useEffect(()=>{
|
|
241
|
-
var _emblaApi_current, _emblaApi_current_slideNodes, _emblaApi_current1;
|
|
242
|
-
var _emblaApi_current_selectedScrollSnap;
|
|
243
|
-
// Scroll to controlled values on update
|
|
244
|
-
// If active index is out of bounds, re-init will handle instead
|
|
245
|
-
const currentActiveIndex = (_emblaApi_current_selectedScrollSnap = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.selectedScrollSnap()) !== null && _emblaApi_current_selectedScrollSnap !== void 0 ? _emblaApi_current_selectedScrollSnap : 0;
|
|
246
|
-
var _emblaApi_current_slideNodes_length;
|
|
247
|
-
const slideLength = (_emblaApi_current_slideNodes_length = (_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : (_emblaApi_current_slideNodes = _emblaApi_current1.slideNodes()) === null || _emblaApi_current_slideNodes === void 0 ? void 0 : _emblaApi_current_slideNodes.length) !== null && _emblaApi_current_slideNodes_length !== void 0 ? _emblaApi_current_slideNodes_length : 0;
|
|
248
|
-
emblaOptions.current.startIndex = activeIndex;
|
|
249
|
-
if (activeIndex < slideLength && activeIndex !== currentActiveIndex) {
|
|
250
|
-
var _emblaApi_current2;
|
|
251
|
-
(_emblaApi_current2 = emblaApi.current) === null || _emblaApi_current2 === void 0 ? void 0 : _emblaApi_current2.scrollTo(activeIndex);
|
|
252
|
-
}
|
|
253
|
-
}, [
|
|
254
|
-
activeIndex
|
|
255
|
-
]);
|
|
256
253
|
_react.useEffect(()=>{
|
|
257
254
|
var _emblaApi_current;
|
|
258
255
|
const plugins = getPlugins();
|
|
@@ -271,12 +268,28 @@ function useEmblaCarousel(options) {
|
|
|
271
268
|
}, plugins);
|
|
272
269
|
}, [
|
|
273
270
|
align,
|
|
271
|
+
containScroll,
|
|
274
272
|
direction,
|
|
273
|
+
getPlugins,
|
|
275
274
|
loop,
|
|
276
275
|
slidesToScroll,
|
|
277
|
-
watchDrag
|
|
278
|
-
|
|
279
|
-
|
|
276
|
+
watchDrag
|
|
277
|
+
]);
|
|
278
|
+
_react.useEffect(()=>{
|
|
279
|
+
var _emblaApi_current, _emblaApi_current_slideNodes, _emblaApi_current1;
|
|
280
|
+
var _emblaApi_current_selectedScrollSnap;
|
|
281
|
+
// Scroll to controlled values on update
|
|
282
|
+
// If active index is out of bounds, re-init will handle instead
|
|
283
|
+
const currentActiveIndex = (_emblaApi_current_selectedScrollSnap = (_emblaApi_current = emblaApi.current) === null || _emblaApi_current === void 0 ? void 0 : _emblaApi_current.selectedScrollSnap()) !== null && _emblaApi_current_selectedScrollSnap !== void 0 ? _emblaApi_current_selectedScrollSnap : 0;
|
|
284
|
+
var _emblaApi_current_slideNodes_length;
|
|
285
|
+
const slideLength = (_emblaApi_current_slideNodes_length = (_emblaApi_current1 = emblaApi.current) === null || _emblaApi_current1 === void 0 ? void 0 : (_emblaApi_current_slideNodes = _emblaApi_current1.slideNodes()) === null || _emblaApi_current_slideNodes === void 0 ? void 0 : _emblaApi_current_slideNodes.length) !== null && _emblaApi_current_slideNodes_length !== void 0 ? _emblaApi_current_slideNodes_length : 0;
|
|
286
|
+
emblaOptions.current.startIndex = activeIndex;
|
|
287
|
+
if (activeIndex < slideLength && activeIndex !== currentActiveIndex) {
|
|
288
|
+
var _emblaApi_current2;
|
|
289
|
+
(_emblaApi_current2 = emblaApi.current) === null || _emblaApi_current2 === void 0 ? void 0 : _emblaApi_current2.scrollTo(activeIndex);
|
|
290
|
+
}
|
|
291
|
+
}, [
|
|
292
|
+
activeIndex
|
|
280
293
|
]);
|
|
281
294
|
return {
|
|
282
295
|
activeIndex,
|