-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathuseCarouselNavImageButton.ts
More file actions
97 lines (86 loc) · 3.01 KB
/
useCarouselNavImageButton.ts
File metadata and controls
97 lines (86 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
'use client';
import { type ARIAButtonElement, type ARIAButtonSlotProps, useARIAButtonProps } from '@fluentui/react-aria';
import {
getIntrinsicElementProps,
isHTMLElement,
slot,
useEventCallback,
useIsomorphicLayoutEffect,
useMergedRefs,
} from '@fluentui/react-utilities';
import * as React from 'react';
import { useCarouselNavIndexContext } from '../CarouselNav/CarouselNavIndexContext';
import { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';
import type { CarouselNavImageButtonProps, CarouselNavImageButtonState } from './CarouselNavImageButton.types';
/**
* Create the state required to render CarouselNavImageButton.
*
* The returned state can be modified with hooks such as useCarouselNavImageButtonStyles_unstable,
* before being passed to renderCarouselNavImageButton_unstable.
*
* @param props - props from this instance of CarouselNavImageButton
* @param ref - reference to root HTMLButtonElement | HTMLAnchorElement of CarouselNavImageButton
*/
export const useCarouselNavImageButton_unstable = (
props: CarouselNavImageButtonProps,
ref: React.Ref<ARIAButtonElement>,
): CarouselNavImageButtonState => {
const { onClick, as = 'button' } = props;
const index = useCarouselNavIndexContext();
const selectPageByIndex = useCarouselContext(ctx => ctx.selectPageByIndex);
const selected = useCarouselContext(ctx => ctx.activeIndex === index);
const subscribeForValues = useCarouselContext(ctx => ctx.subscribeForValues);
const handleClick: ARIAButtonSlotProps['onClick'] = useEventCallback(event => {
onClick?.(event);
if (!event.defaultPrevented && isHTMLElement(event.target)) {
selectPageByIndex(event, index);
}
});
const buttonRef = React.useRef<HTMLElement>(undefined);
const _carouselButton = slot.always<ARIAButtonSlotProps>(
getIntrinsicElementProps(as, useARIAButtonProps(props.as, props)),
{
elementType: 'button',
defaultProps: {
ref: useMergedRefs(ref, buttonRef),
role: 'tab',
type: 'button',
'aria-selected': selected,
focusGroupStart: selected,
},
},
);
useIsomorphicLayoutEffect(() => {
return subscribeForValues(data => {
const controlList = data.groupIndexList?.[index] ?? [];
const _controlledSlideIds = controlList
.map((slideIndex: number) => {
return data.slideNodes[slideIndex].id;
})
.join(' ');
if (buttonRef.current) {
buttonRef.current.setAttribute('aria-controls', _controlledSlideIds);
}
});
}, [subscribeForValues, index]);
// Override onClick
_carouselButton.onClick = handleClick;
const image = slot.always(
getIntrinsicElementProps('img', {
'aria-hidden': true, // Hidden as button is responsible for navigation description
alt: '',
role: 'presentation',
...props.image,
}),
{ elementType: 'img' },
);
return {
components: {
root: 'button',
image: 'img',
},
root: _carouselButton,
image,
selected,
};
};