/
DropdownItem.tsx
140 lines (121 loc) · 3.19 KB
/
DropdownItem.tsx
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React, { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import SelectableContext, { makeEventKey } from './SelectableContext';
import { useBootstrapPrefix } from './ThemeProvider';
import NavContext from './NavContext';
import SafeAnchor from './SafeAnchor';
import {
BsPrefixPropsWithChildren,
BsPrefixRefForwardingComponent,
SelectCallback,
} from './helpers';
export interface DropdownItemProps extends BsPrefixPropsWithChildren {
active?: boolean;
disabled?: boolean;
eventKey?: string;
href?: string;
onClick?: React.MouseEventHandler<this>;
onSelect?: SelectCallback;
}
type DropdownItem = BsPrefixRefForwardingComponent<
typeof SafeAnchor,
DropdownItemProps
>;
const propTypes = {
/** @default 'dropdown-item' */
bsPrefix: PropTypes.string,
/**
* Highlight the menu item as active.
*/
active: PropTypes.bool,
/**
* Disable the menu item, making it unselectable.
*/
disabled: PropTypes.bool,
/**
* Value passed to the `onSelect` handler, useful for identifying the selected menu item.
*/
eventKey: PropTypes.any,
/**
* HTML `href` attribute corresponding to `a.href`.
*/
href: PropTypes.string,
/**
* Callback fired when the menu item is clicked.
*/
onClick: PropTypes.func,
/**
* Callback fired when the menu item is selected.
*
* ```js
* (eventKey: any, event: Object) => any
* ```
*/
onSelect: PropTypes.func,
as: PropTypes.elementType,
};
const defaultProps = {
as: SafeAnchor,
disabled: false,
};
const DropdownItem: DropdownItem = React.forwardRef(
(
{
bsPrefix,
className,
children,
eventKey,
disabled,
href,
onClick,
onSelect,
active: propActive,
as: Component,
...props
}: DropdownItemProps,
ref,
) => {
const prefix = useBootstrapPrefix(bsPrefix, 'dropdown-item');
const onSelectCtx = useContext(SelectableContext);
const navContext = useContext(NavContext);
const { activeKey } = navContext || {};
const key = makeEventKey(eventKey || null, href);
const active =
propActive == null && key != null
? makeEventKey(activeKey) === key
: propActive;
const handleClick = useEventCallback((event) => {
// SafeAnchor handles the disabled case, but we handle it here
// for other components
if (disabled) return;
if (onClick) onClick(event);
if (onSelectCtx) onSelectCtx(key, event);
if (onSelect) onSelect(key, event);
});
return (
// "TS2604: JSX element type 'Component' does not have any construct or call signatures."
// @ts-ignore
<Component
{...props}
ref={ref}
href={href}
disabled={disabled}
className={classNames(
className,
prefix,
active && 'active',
disabled && 'disabled',
)}
onClick={handleClick}
>
{children}
</Component>
);
},
);
DropdownItem.displayName = 'DropdownItem';
DropdownItem.propTypes = propTypes;
DropdownItem.defaultProps = defaultProps;
export default DropdownItem;