@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.
Files changed (25) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/dist/index.d.ts +2 -2
  3. package/lib/components/Carousel/useCarousel.js +2 -1
  4. package/lib/components/Carousel/useCarousel.js.map +1 -1
  5. package/lib/components/CarouselAutoplayButton/useCarouselAutoplayButton.js +4 -8
  6. package/lib/components/CarouselAutoplayButton/useCarouselAutoplayButton.js.map +1 -1
  7. package/lib/components/CarouselButton/useCarouselButton.js +1 -2
  8. package/lib/components/CarouselButton/useCarouselButton.js.map +1 -1
  9. package/lib/components/CarouselContext.types.js.map +1 -1
  10. package/lib/components/CarouselViewport/useCarouselViewport.js +45 -2
  11. package/lib/components/CarouselViewport/useCarouselViewport.js.map +1 -1
  12. package/lib/components/useEmblaCarousel.js +82 -68
  13. package/lib/components/useEmblaCarousel.js.map +1 -1
  14. package/lib-commonjs/components/Carousel/useCarousel.js +2 -1
  15. package/lib-commonjs/components/Carousel/useCarousel.js.map +1 -1
  16. package/lib-commonjs/components/CarouselAutoplayButton/useCarouselAutoplayButton.js +3 -7
  17. package/lib-commonjs/components/CarouselAutoplayButton/useCarouselAutoplayButton.js.map +1 -1
  18. package/lib-commonjs/components/CarouselButton/useCarouselButton.js +1 -1
  19. package/lib-commonjs/components/CarouselButton/useCarouselButton.js.map +1 -1
  20. package/lib-commonjs/components/CarouselContext.types.js.map +1 -1
  21. package/lib-commonjs/components/CarouselViewport/useCarouselViewport.js +44 -1
  22. package/lib-commonjs/components/CarouselViewport/useCarouselViewport.js.map +1 -1
  23. package/lib-commonjs/components/useEmblaCarousel.js +81 -68
  24. package/lib-commonjs/components/useEmblaCarousel.js.map +1 -1
  25. 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
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 disable autoplay if the button gets unmounted.
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 {\n mergeCallbacks,\n slot,\n useControllableState,\n useEventCallback,\n useIsomorphicLayoutEffect,\n} 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 return () => {\n // We disable autoplay if the button gets unmounted.\n enableAutoplay(false);\n };\n }, [enableAutoplay]);\n\n useIsomorphicLayoutEffect(() => {\n // Enable/disable autoplay on state change\n enableAutoplay(autoplay);\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","useIsomorphicLayoutEffect","handleClick","event","isDefaultPrevented","newValue","type","useToggleButton_unstable","icon","slot","optional","defaultProps","children","createElement","PauseCircleRegular","PlayCircleRegular","renderByDefault","elementType","onClick","useEventCallback","mergeCallbacks"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAwBaA;;;eAAAA;;;;6BAvB4B;4BACa;gCAO/C;iEACgB;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,OAAO;YACL,oDAAoD;YACpDJ,eAAe;QACjB;IACF,GAAG;QAACA;KAAe;IAEnBK,IAAAA,yCAAAA,EAA0B;QACxB,0CAA0C;QAC1CL,eAAeN;IACjB,GAAG;QAACA;QAAUM;KAAe;IAE7B,MAAMM,cAAc,CAACC;QACnB,IAAIA,MAAMC,kBAAkB,IAAI;YAC9B;QACF;QAEA,MAAMC,WAAW,CAACf;QAElBC,YAAYc;QACZlB,oBAAAA,QAAAA,oBAAAA,KAAAA,IAAAA,KAAAA,IAAAA,gBAAkBgB,OAAO;YAAEA;YAAOG,MAAM;YAASlB,SAASiB;QAAS;IACrE;IAEA,OAAO;QACL,wEAAwE;QACxE,GAAGE,IAAAA,qCAAAA,EACD;YACEC,MAAMC,oBAAAA,CAAKC,QAAQ,CAACzB,MAAMuB,IAAI,EAAE;gBAC9BG,cAAc;oBACZC,UAAUtB,WAAAA,WAAAA,GAAWS,OAAAc,aAAA,CAACC,8BAAAA,EAAAA,QAAAA,WAAAA,GAAwBf,OAAAc,aAAA,CAACE,6BAAAA,EAAAA;gBACjD;gBACAC,iBAAiB;gBACjBC,aAAa;YACf;YACA,GAAGhC,KAAK;YACRG,SAASE;YACT4B,SAASC,IAAAA,gCAAAA,EAAiBC,IAAAA,8BAAAA,EAAelB,aAAajB,MAAMiC,OAAO;QACrE,GACAhC,IACD;IACH;AACF"}
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 = (0, _react.useRef)();
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 { useRef } from 'react';\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 = 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
+ {"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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAcaA;;;eAAAA;;;;iEAdU;gCACuC;iCAEI;AAW3D,MAAMA,+BAA+B,CAC1CC,OACAC;IAEA,MAAMC,cAAcC,IAAAA,4CAAAA,EAAmBC,CAAAA,MAAOA,IAAIF,WAAW;IAE7D,OAAO;QACLG,YAAY;YACVC,MAAM;QACR;QACAA,MAAMC,oBAAAA,CAAKC,MAAM,CACfC,IAAAA,wCAAAA,EAAyB,OAAO;YAC9BR,KAAKS,IAAAA,6BAAAA,EAAcT,KAAKC;YACxBS,MAAM;YACN,gEAAgE;YAChEC,WAAW;YACX,GAAGZ,KAAK;QACV,IACA;YAAEa,aAAa;QAAM;IAEzB;AACF"}
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
- (0, _emblacarouselautoplay.default)({
99
- playOnInit: autoplayRef.current,
100
- stopOnInteraction: !autoplayRef.current,
101
- stopOnMouseEnter: true,
102
- stopOnFocusIn: true
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.destroy();
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
- const wrapperElement = (_viewportRef_current = viewportRef.current) !== null && _viewportRef_current !== void 0 ? _viewportRef_current : newElement;
190
- if (wrapperElement) {
191
- var _emblaApi_current4, _emblaApi_current5, _emblaApi_current6;
192
- currentElement = wrapperElement;
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
- (_emblaApi_current4 = emblaApi.current) === null || _emblaApi_current4 === void 0 ? void 0 : _emblaApi_current4.on('reInit', handleReinit);
198
- (_emblaApi_current5 = emblaApi.current) === null || _emblaApi_current5 === void 0 ? void 0 : _emblaApi_current5.on('slidesInView', handleVisibilityChange);
199
- (_emblaApi_current6 = emblaApi.current) === null || _emblaApi_current6 === void 0 ? void 0 : _emblaApi_current6.on('select', handleIndexChange);
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
- setActiveIndex,
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
- containScroll,
279
- getPlugins
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,