Skip to content

Commit

Permalink
lib: Make SimpleSelect and CheckboxSelect generic in the option value…
Browse files Browse the repository at this point in the history
… type
  • Loading branch information
mvollmer committed Dec 19, 2024
1 parent d042abb commit 86e9063
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 32 deletions.
26 changes: 12 additions & 14 deletions pkg/lib/cockpit-components-checkbox-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,22 @@ import {
SelectProps
} from '@patternfly/react-core';

export interface CheckboxSelectOption extends Omit<SelectOptionProps, 'content'> {
export interface CheckboxSelectOption<T> extends Omit<SelectOptionProps, 'content'> {
/** Content of the select option. */
content: React.ReactNode;
/** Value of the select option. */
value: unknown;
value: T;
}

export interface CheckboxSelectProps extends Omit<SelectProps, 'toggle' | 'onSelect'> {
export interface CheckboxSelectProps<T> extends Omit<SelectProps, 'toggle' | 'onSelect'> {
/** @hide Forwarded ref */
innerRef?: React.Ref<any>;
/** Options of the select. */
options?: CheckboxSelectOption[];
options?: CheckboxSelectOption<T>[];
/** Currently checked options */
selected: unknown[];
selected: T[];
/** Callback triggered when checking or unchecking an option. */
onSelect: (value: unknown, checked: boolean) => void;
onSelect: (value: T, checked: boolean) => void;
/** Callback triggered when the select opens or closes. */
onToggle?: (nextIsOpen: boolean) => void;
/** Flag indicating the select should be disabled. */
Expand All @@ -94,7 +94,7 @@ export interface CheckboxSelectProps extends Omit<SelectProps, 'toggle' | 'onSel
noBadge?: boolean,
}

const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
export function CheckboxSelect<T>({
innerRef,
options,
selected,
Expand All @@ -106,7 +106,7 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
toggleProps,
noBadge = false,
...props
}: CheckboxSelectProps) => {
}: CheckboxSelectProps<T>) {
const [isOpen, setIsOpen] = React.useState(false);

const checkboxSelectOptions = options?.map((option) => {
Expand All @@ -126,8 +126,10 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
};

const _onSelect = (event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
if (value && event)
onSelect(value, (event.target as HTMLInputElement).checked);
if (value && event) {
// https://github.com/patternfly/patternfly-react/issues/11361
onSelect(value as T, (event.target as HTMLInputElement).checked);
}
};

const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
Expand Down Expand Up @@ -169,7 +171,3 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
</Select>
);
};

export const CheckboxSelect = React.forwardRef((props: CheckboxSelectProps, ref: React.Ref<any>) => (
<CheckboxSelectBase {...props} innerRef={ref} />
));
34 changes: 16 additions & 18 deletions pkg/lib/cockpit-components-simple-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,27 @@ export interface SimpleSelectDividerOption {
key: string | number;
};

export interface SimpleSelectMenuOption extends Omit<SelectOptionProps, 'content'> {
export interface SimpleSelectMenuOption<T> extends Omit<SelectOptionProps, 'content'> {
decorator?: undefined;

/** Content of the select option. */
content: React.ReactNode;
/** Value of the select option. */
value: unknown;
value: T;
}

export type SimpleSelectOption = SimpleSelectMenuOption |
SimpleSelectDividerOption;
export type SimpleSelectOption<T> = SimpleSelectMenuOption<T> |
SimpleSelectDividerOption;

export interface SimpleSelectProps extends Omit<SelectProps, 'toggle' | 'onSelect'> {
export interface SimpleSelectProps<T> extends Omit<SelectProps, 'toggle' | 'onSelect'> {
/** @hide Forwarded ref */
innerRef?: React.Ref<any>;
/** Initial options of the select. */
options: SimpleSelectOption[];
options: SimpleSelectOption<T>[];
/** Selected option */
selected: unknown;
/** Callback triggered on selection. */
onSelect: (selection: unknown) => void;
onSelect: (selection: T) => void;
/** Callback triggered when the select opens or closes. */
onToggle?: (nextIsOpen: boolean) => void;
/** Flag indicating the select should be disabled. */
Expand All @@ -104,7 +104,7 @@ export interface SimpleSelectProps extends Omit<SelectProps, 'toggle' | 'onSelec
toggleProps?: MenuToggleProps;
}

const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
export function SimpleSelect<T>({
innerRef,
options,
selected,
Expand All @@ -116,10 +116,10 @@ const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
toggleProps,
placeholder = '',
...props
}: SimpleSelectProps) => {
}: SimpleSelectProps<T>) {
const [isOpen, setIsOpen] = React.useState(false);

const simpleSelectOptions = options.map((option, index) => {
const simpleSelectOptions = options.map(option => {
if (option.decorator == "divider")
return <Divider key={option.key} component="li" />;
const { content, value, key, ...props } = option;
Expand All @@ -135,9 +135,11 @@ const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
setIsOpen(!isOpen);
};

const _onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: unknown) => {
if (value)
onSelect(value);
const _onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
if (value) {
// https://github.com/patternfly/patternfly-react/issues/11361
onSelect(value as T);
}
onToggle && onToggle(true);
setIsOpen(false);
};
Expand All @@ -146,7 +148,7 @@ const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
if (toggleContent)
content = toggleContent;
else if (selected)
content = options.find((o): o is SimpleSelectMenuOption => !o.decorator && o.value == selected)?.content;
content = options.find((o): o is SimpleSelectMenuOption<T> => !o.decorator && o.value == selected)?.content;

const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle
Expand Down Expand Up @@ -184,8 +186,4 @@ const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
);
};

export const SimpleSelect = React.forwardRef((props: SimpleSelectProps, ref: React.Ref<any>) => (
<SimpleSelectBase {...props} innerRef={ref} />
));

SimpleSelect.displayName = 'SimpleSelect';

0 comments on commit 86e9063

Please sign in to comment.