-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathuseCarouselNavButton.ts
More file actions
95 lines (82 loc) · 3 KB
/
useCarouselNavButton.ts
File metadata and controls
95 lines (82 loc) · 3 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
'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 { useCarouselContext_unstable as useCarouselContext } from '../CarouselContext';
import { useCarouselNavContext } from '../CarouselNav/CarouselNavContext';
import { useCarouselNavIndexContext } from '../CarouselNav/CarouselNavIndexContext';
import type { CarouselNavButtonProps, CarouselNavButtonState } from './CarouselNavButton.types';
/**
* Create the state required to render CarouselNavButton.
*
* The returned state can be modified with hooks such as useCarouselNavButtonStyles_unstable,
* before being passed to renderCarouselNavButton_unstable.
*
* @param props - props from this instance of CarouselNavButton
* @param ref - reference to root HTMLDivElement of CarouselNavButton
*/
export const useCarouselNavButton_unstable = (
props: CarouselNavButtonProps,
ref: React.Ref<ARIAButtonElement>,
): CarouselNavButtonState => {
const { onClick, as = 'button' } = props;
const { appearance } = useCarouselNavContext();
const index = useCarouselNavIndexContext();
const selectPageByIndex = useCarouselContext(ctx => ctx.selectPageByIndex);
const selected = useCarouselContext(ctx => ctx.activeIndex === index);
const subscribeForValues = useCarouselContext(ctx => ctx.subscribeForValues);
const resetAutoplay = useCarouselContext(ctx => ctx.resetAutoplay);
const handleClick: ARIAButtonSlotProps['onClick'] = useEventCallback(event => {
onClick?.(event);
if (!event.defaultPrevented && isHTMLElement(event.target)) {
selectPageByIndex(event, index);
}
// Ensure any autoplay timers are extended/reset
resetAutoplay();
});
const buttonRef = React.useRef<HTMLElement>(undefined);
const _carouselButton = slot.always<ARIAButtonSlotProps & { focusGroupStart?: boolean }>(
getIntrinsicElementProps(as, useARIAButtonProps(props.as, props)),
{
elementType: 'button',
defaultProps: {
ref: useMergedRefs(ref, buttonRef),
role: 'tab',
type: 'button',
'aria-selected': selected,
focusGroupStart: true,
},
},
);
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);
}
});
}, [index, subscribeForValues]);
// Override onClick
_carouselButton.onClick = handleClick;
const state: CarouselNavButtonState = {
selected,
appearance,
components: {
root: 'button',
},
root: _carouselButton,
};
return state;
};