forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimpleDropdown.tsx
More file actions
139 lines (128 loc) · 4.56 KB
/
SimpleDropdown.tsx
File metadata and controls
139 lines (128 loc) · 4.56 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
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
import { forwardRef, useState, FunctionComponent, Ref, MouseEvent as ReactMouseEvent, CSSProperties } from 'react';
import {
Dropdown,
DropdownItem,
DropdownList,
DropdownItemProps,
DropdownProps
} from '@patternfly/react-core/dist/esm/components/Dropdown';
import { MenuToggle, MenuToggleElement, MenuToggleProps } from '@patternfly/react-core/dist/esm/components/MenuToggle';
import { Divider } from '@patternfly/react-core/dist/esm/components/Divider';
import { OUIAProps } from '@patternfly/react-core/dist/esm/helpers';
export interface SimpleDropdownItem extends Omit<DropdownItemProps, 'content'> {
/** Content of the dropdown item. If the isDivider prop is true, this prop will be ignored. */
content?: React.ReactNode;
/** Unique identifier for the dropdown item, which is used in the dropdown onSelect callback */
value: string | number;
/** Callback for when the dropdown item is clicked. */
onClick?: (event?: any) => void;
/** URL to redirect to when the dropdown item is clicked. */
to?: string;
/** Flag indicating whether the dropdown item should render as a divider. If true, the item will be rendered without
* the dropdown item wrapper.
*/
isDivider?: boolean;
}
export interface SimpleDropdownProps extends Omit<DropdownProps, 'toggle' | 'onToggle'>, OUIAProps {
/** Initial items of the dropdown. */
initialItems?: SimpleDropdownItem[];
/** @hide Forwarded ref */
innerRef?: React.Ref<any>;
/** Flag indicating the dropdown should be disabled. */
isDisabled?: boolean;
/** Flag indicated whether the dropdown toggle should take up the full width of its parent. */
isToggleFullWidth?: boolean;
/** Callback triggered when any dropdown item is clicked. */
onSelect?: (event?: React.MouseEvent<Element, MouseEvent>, value?: SimpleDropdownItem['value']) => void;
/** Callback triggered when the dropdown toggle opens or closes. */
onToggle?: (nextIsOpen: boolean) => void;
/** Flag indicating the dropdown toggle should be focused after a dropdown item is clicked. */
shouldFocusToggleOnSelect?: boolean;
/** Adds an accessible name to the dropdown toggle. Required when the dropdown toggle does not
* have any text content.
*/
toggleAriaLabel?: string;
/** Content of the toggle. */
toggleContent: React.ReactNode;
/** Variant style of the dropdown toggle. */
toggleVariant?: 'default' | 'plain' | 'plainText';
/** Width of the toggle. */
toggleWidth?: string;
/** Additional props passed to the toggle. */
toggleProps?: MenuToggleProps;
}
const SimpleDropdownBase: FunctionComponent<SimpleDropdownProps> = ({
innerRef,
initialItems,
onSelect: onSelectProp,
onToggle: onToggleProp,
isDisabled,
toggleAriaLabel,
toggleContent,
isToggleFullWidth,
toggleVariant = 'default',
toggleWidth,
toggleProps,
shouldFocusToggleOnSelect,
...props
}: SimpleDropdownProps) => {
const [isOpen, setIsOpen] = useState(false);
const onSelect = (event: ReactMouseEvent<Element, MouseEvent>, value: string | number) => {
onSelectProp && onSelectProp(event, value);
onToggleProp && onToggleProp(false);
setIsOpen(false);
};
const onToggle = () => {
onToggleProp && onToggleProp(!isOpen);
setIsOpen(!isOpen);
};
const dropdownToggle = (toggleRef: Ref<MenuToggleElement>) => (
<MenuToggle
ref={toggleRef}
onClick={onToggle}
isExpanded={isOpen}
isDisabled={isDisabled}
variant={toggleVariant}
aria-label={toggleAriaLabel}
isFullWidth={isToggleFullWidth}
style={
{
width: toggleWidth
} as CSSProperties
}
{...toggleProps}
>
{toggleContent}
</MenuToggle>
);
const dropdownSimpleItems = initialItems?.map((item) => {
const { content, onClick, to, value, isDivider, ...itemProps } = item;
return isDivider ? (
<Divider component="li" key={value} />
) : (
<DropdownItem onClick={onClick} to={to} key={value} value={value} {...itemProps}>
{content}
</DropdownItem>
);
});
return (
<Dropdown
toggle={dropdownToggle}
isOpen={isOpen}
onSelect={onSelect}
shouldFocusToggleOnSelect={shouldFocusToggleOnSelect}
onOpenChange={(isOpen) => {
onToggleProp && onToggleProp(isOpen);
setIsOpen(isOpen);
}}
ref={innerRef}
{...props}
>
<DropdownList>{dropdownSimpleItems}</DropdownList>
</Dropdown>
);
};
export const SimpleDropdown = forwardRef((props: SimpleDropdownProps, ref: Ref<any>) => (
<SimpleDropdownBase {...props} innerRef={ref} />
));
SimpleDropdown.displayName = 'SimpleDropdown';