@spaced-out/ui-design-system
Version:
Sense UI components library
162 lines (141 loc) • 4.11 kB
Flow
// @flow strict
import * as React from 'react';
import type {MenuClassNames, MenuLabelTooltip} from '../../types/menu';
import type {ClickAwayRefType} from '../../utils/click-away';
import {getSelectedKeysFromSelectedOption} from '../../utils/menu';
import type {ButtonProps} from '../Button';
import type {AnchorType} from '../ButtonDropdown';
import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu';
import type {OptionButtonTooltipProps} from './OptionButton';
import {OptionButton} from './OptionButton';
type ClassNames = $ReadOnly<{
wrapper?: string,
baseButtonWrapper?: string,
baseButtonIcon?: string,
optionsButtonWrapper?: string,
optionsButtonIcon?: string,
dropdownContainer?: string,
}>;
export type SimpleOptionButtonRef = {
selectedKeys?: Array<string>,
};
export type SimpleOptionButtonProps = {
// Input props
...ButtonProps,
classNames?: ClassNames,
tooltip?: OptionButtonTooltipProps,
anchorPosition?: AnchorType,
tooltip?: OptionButtonTooltipProps,
menuSize?: 'small' | 'medium',
// Menu props
options?: Array<MenuOption>,
optionsVariant?: MenuOptionsVariant,
allowSearch?: boolean,
selectedKeys?: Array<string>,
menuVirtualization?: Virtualization,
header?: React.Node,
footer?: React.Node,
menuClassNames?: MenuClassNames,
showLabelTooltip?: MenuLabelTooltip,
allowWrap?: boolean,
// events
onOptionSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed,
onButtonClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
onMenuOpen?: () => mixed,
onMenuClose?: () => mixed,
// Resolvers
resolveLabel?: (option: MenuOption) => string | React.Node,
resolveSecondaryLabel?: (option: MenuOption) => string | React.Node,
clickAwayRef?: ClickAwayRefType,
...
};
const SimpleOptionButtonBase = (props: SimpleOptionButtonProps, ref) => {
const {
size = 'small',
classNames,
tooltip,
anchorPosition,
options,
optionsVariant,
allowSearch,
selectedKeys,
onOptionSelect,
onButtonClick,
onMenuOpen,
onMenuClose,
resolveLabel,
resolveSecondaryLabel,
children,
menuSize = 'small',
menuVirtualization,
header,
footer,
menuClassNames,
showLabelTooltip,
clickAwayRef,
allowWrap = false,
...buttonProps
} = props;
const [optionButtonSelectedKeys, setOptionButtonSelectedKeys] =
React.useState(selectedKeys);
React.useEffect(() => {
setOptionButtonSelectedKeys(selectedKeys);
}, [selectedKeys]);
const handleOptionChange = (selectedOption: MenuOption, e) => {
e?.stopPropagation();
let newSelectedKeys = [selectedOption.key];
if (optionsVariant === 'checkbox') {
newSelectedKeys = getSelectedKeysFromSelectedOption(
selectedOption,
optionButtonSelectedKeys,
);
} else {
newSelectedKeys = [selectedOption.key];
}
setOptionButtonSelectedKeys(newSelectedKeys);
setTimeout(() => {
onOptionSelect?.(selectedOption, e);
});
};
React.useImperativeHandle(ref, () => ({
selectedKeys: optionButtonSelectedKeys,
}));
return (
<OptionButton
{...buttonProps}
tooltip={tooltip}
onButtonClick={onButtonClick}
anchorPosition={anchorPosition}
classNames={classNames}
size={size}
onOptionSelect={handleOptionChange}
onMenuOpen={onMenuOpen}
onMenuClose={onMenuClose}
clickAwayRef={clickAwayRef}
menu={{
isFluid: false,
options,
selectedKeys: optionButtonSelectedKeys,
optionsVariant,
allowSearch,
resolveLabel,
resolveSecondaryLabel,
size: menuSize,
virtualization: menuVirtualization,
header,
footer,
classNames: menuClassNames,
showLabelTooltip,
allowWrap,
}}
>
{children}
</OptionButton>
);
};
export const SimpleOptionButton: React.AbstractComponent<
SimpleOptionButtonProps,
SimpleOptionButtonRef,
> = React.forwardRef<SimpleOptionButtonProps, SimpleOptionButtonRef>(
SimpleOptionButtonBase,
);