forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCheckboxSelect.tsx
More file actions
127 lines (116 loc) · 3.83 KB
/
CheckboxSelect.tsx
File metadata and controls
127 lines (116 loc) · 3.83 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
import { forwardRef, useEffect, useState } from 'react';
import { Badge } from '@patternfly/react-core/dist/esm/components/Badge';
import { MenuToggle, MenuToggleElement, MenuToggleProps } from '@patternfly/react-core/dist/esm/components/MenuToggle';
import {
Select,
SelectList,
SelectOption,
SelectOptionProps,
SelectProps
} from '@patternfly/react-core/dist/esm/components/Select';
export interface CheckboxSelectOption extends Omit<SelectOptionProps, 'content'> {
/** Content of the select option. */
content: React.ReactNode;
/** Value of the select option. */
value: string | number;
}
export interface CheckboxSelectProps extends Omit<SelectProps, 'toggle' | 'onToggle'> {
/** @hide Forwarded ref */
innerRef?: React.Ref<any>;
/** Initial options of the select. */
initialOptions?: CheckboxSelectOption[];
/** Callback triggered on selection. */
onSelect?: (_event: React.MouseEvent<Element, MouseEvent>, value?: string | number) => void;
/** Callback triggered when the select opens or closes. */
onToggle?: (nextIsOpen: boolean) => void;
/** Flag indicating the select should be disabled. */
isDisabled?: boolean;
/** Content of the toggle. Defaults to a string with badge count of selected options. */
toggleContent?: React.ReactNode;
/** Width of the toggle. */
toggleWidth?: string;
/** Additional props passed to the toggle. */
toggleProps?: MenuToggleProps;
}
const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
innerRef,
initialOptions,
isDisabled,
onSelect: passedOnSelect,
onToggle,
toggleContent,
toggleWidth = '200px',
toggleProps,
...props
}: CheckboxSelectProps) => {
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<string[]>([]);
useEffect(() => {
const selectedOptions = initialOptions?.filter((option) => option.selected);
setSelected(selectedOptions?.map((selectedOption) => String(selectedOption.value)) ?? []);
}, [initialOptions]);
const checkboxSelectOptions = initialOptions?.map((option) => {
const { content, value, ...props } = option;
const isSelected = selected.includes(`${value}`);
return (
<SelectOption value={value} key={value} hasCheckbox isSelected={isSelected} {...props}>
{content}
</SelectOption>
);
});
const onToggleClick = () => {
onToggle && onToggle(!isOpen);
setIsOpen(!isOpen);
};
const onSelect = (event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
const valueString = `${value}`;
if (selected.includes(valueString)) {
setSelected((prevSelected) => prevSelected.filter((item) => item !== valueString));
} else {
setSelected((prevSelected) => [...prevSelected, valueString]);
}
passedOnSelect && passedOnSelect(event, value);
};
const defaultToggleContent = (
<>
Filter by status
{selected.length > 0 && <Badge isRead>{selected.length}</Badge>}
</>
);
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle
ref={toggleRef}
onClick={onToggleClick}
isExpanded={isOpen}
isDisabled={isDisabled}
style={
{
width: toggleWidth
} as React.CSSProperties
}
{...toggleProps}
>
{toggleContent || defaultToggleContent}
</MenuToggle>
);
return (
<Select
isOpen={isOpen}
selected={selected}
onSelect={onSelect}
onOpenChange={(isOpen) => {
onToggle && onToggle(isOpen);
setIsOpen(isOpen);
}}
toggle={toggle}
ref={innerRef}
role="menu"
{...props}
>
<SelectList>{checkboxSelectOptions}</SelectList>
</Select>
);
};
export const CheckboxSelect = forwardRef((props: CheckboxSelectProps, ref: React.Ref<any>) => (
<CheckboxSelectBase {...props} innerRef={ref} />
));