Private
Public Access
1
0
Files

100 lines
3.9 KiB
JavaScript

'use client';
import { useFocusableGroup } from '@fluentui/react-tabster';
import { getIntrinsicElementProps, isHTMLElement, mergeCallbacks, slot, useMergedRefs, useId } from '@fluentui/react-utilities';
import * as React from 'react';
import { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';
import { EMBLA_VISIBILITY_EVENT } from '../useEmblaCarousel';
import { carouselCardClassNames } from './useCarouselCardStyles.styles';
import { useCarouselSliderContext } from '../CarouselSlider/CarouselSliderContext';
/**
* Create the state required to render CarouselCard.
*
* The returned state can be modified with hooks such as useCarouselCardStyles_unstable,
* before being passed to renderCarouselCard_unstable.
*
* @param props - props from this instance of CarouselCard
* @param ref - reference to root HTMLDivElement of CarouselCard
*/ export const useCarouselCard_unstable = (props, ref)=>{
const { autoSize } = props;
const elementRef = React.useRef(null);
const isMouseEvent = React.useRef(false);
const selectPageByElement = useCarouselContext((ctx)=>ctx.selectPageByElement);
const containerRef = useCarouselContext((ctx)=>ctx.containerRef);
const { cardFocus } = useCarouselSliderContext();
const focusAttr = useFocusableGroup({
tabBehavior: 'limited'
});
const focusAttrProps = cardFocus ? {
...focusAttr,
tabIndex: 0
} : {};
// We attach a unique card id if user does not provide
const id = useId(carouselCardClassNames.root, props.id);
React.useEffect(()=>{
const element = elementRef.current;
if (element) {
const listener = (_e)=>{
const event = _e;
// When there is no tab index present, only current cards should be visible to accessibility
if (!cardFocus) {
const hidden = !event.detail.isVisible;
element.ariaHidden = hidden.toString();
element.inert = hidden;
}
};
element.addEventListener(EMBLA_VISIBILITY_EVENT, listener);
return ()=>{
element.removeEventListener(EMBLA_VISIBILITY_EVENT, listener);
};
}
}, [
cardFocus
]);
const handleFocus = React.useCallback((e)=>{
if (!e.defaultPrevented && isHTMLElement(e.currentTarget) && !isMouseEvent.current) {
var // We want to prevent any browser scroll intervention for 'offscreen' focus
_containerRef_current;
containerRef === null || containerRef === void 0 ? void 0 : (_containerRef_current = containerRef.current) === null || _containerRef_current === void 0 ? void 0 : _containerRef_current.scrollTo(0, 0);
selectPageByElement(e, e.currentTarget, false);
}
// Mouse focus event has been consumed
isMouseEvent.current = false;
}, [
selectPageByElement,
containerRef
]);
const handlePointerDown = (e)=>{
if (!e.defaultPrevented) {
isMouseEvent.current = true;
}
};
const handlePointerUp = (e)=>{
if (!e.defaultPrevented) {
isMouseEvent.current = false;
}
};
const onFocusCapture = mergeCallbacks(props.onFocusCapture, handleFocus);
const onPointerUp = mergeCallbacks(props.onPointerUp, handlePointerUp);
const onPointerDown = mergeCallbacks(props.onPointerDown, handlePointerDown);
const state = {
autoSize,
components: {
root: 'div'
},
root: slot.always(getIntrinsicElementProps('div', {
ref: useMergedRefs(elementRef, ref),
role: 'tabpanel',
tabIndex: cardFocus ? 0 : undefined,
...props,
id,
onFocusCapture,
onPointerUp,
onPointerDown,
...focusAttrProps
}), {
elementType: 'div'
})
};
return state;
};