|
@@ -1,51 +1,66 @@
|
|
|
-import PropTypes from 'prop-types';
|
|
|
import React from 'react';
|
|
|
import styled from '@emotion/styled';
|
|
|
|
|
|
import DropdownBubble from 'app/components/dropdownBubble';
|
|
|
import DropdownButton from 'app/components/dropdownButton';
|
|
|
-import DropdownMenu from 'app/components/dropdownMenu';
|
|
|
+import DropdownMenu, {GetActorPropsFn} from 'app/components/dropdownMenu';
|
|
|
import MenuItem from 'app/components/menuItem';
|
|
|
+import theme from 'app/utils/theme';
|
|
|
+
|
|
|
+type DefaultProps = {
|
|
|
+ /**
|
|
|
+ * Should the menu contents always be rendered? Defaults to true.
|
|
|
+ * Set to false to have menu contents removed from the DOM on close.
|
|
|
+ */
|
|
|
+ alwaysRenderMenu: boolean;
|
|
|
+ /**
|
|
|
+ * Width of the menu. Defaults to 100% of the button width.
|
|
|
+ */
|
|
|
+ menuWidth: string;
|
|
|
+};
|
|
|
+
|
|
|
+type Props = DefaultProps & {
|
|
|
+ /**
|
|
|
+ * String or element for the button contents.
|
|
|
+ */
|
|
|
+ label?: React.ReactNode;
|
|
|
+ /**
|
|
|
+ * A closure that returns a styled button. Function will get {isOpen, getActorProps}
|
|
|
+ * as arguments. Use this if you need to style/replace the dropdown button.
|
|
|
+ */
|
|
|
+ button?: (props: {isOpen: boolean; getActorProps: GetActorPropsFn}) => React.ReactNode;
|
|
|
+ /**
|
|
|
+ * Align the dropdown menu to the right. (Default aligns to left)
|
|
|
+ */
|
|
|
+ alignRight?: boolean;
|
|
|
+ /**
|
|
|
+ * Props to pass to DropdownButton
|
|
|
+ */
|
|
|
+ buttonProps?: React.ComponentProps<typeof DropdownButton>;
|
|
|
+ /**
|
|
|
+ * This makes the dropdown menu blend (e.g. corners are not rounded) with its
|
|
|
+ * actor (opener) component
|
|
|
+ */
|
|
|
+ blendWithActor?: boolean;
|
|
|
+};
|
|
|
|
|
|
/*
|
|
|
* A higher level dropdown component that helps with building complete dropdowns
|
|
|
* including the button + menu options. Use the `button` or `label` prop to set
|
|
|
* the button content and `children` to provide menu options.
|
|
|
*/
|
|
|
-class DropdownControl extends React.Component {
|
|
|
- static propTypes = {
|
|
|
- // String or element for the button contents.
|
|
|
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
|
|
- // A closure that returns a styled button. Function will get {isOpen, getActorProps}
|
|
|
- // as arguments. Use this if you need to style/replace the dropdown button.
|
|
|
- button: PropTypes.func,
|
|
|
- // Width of the menu. Defaults to 100% of the button width.
|
|
|
- menuWidth: PropTypes.string,
|
|
|
- // Height offset for the menu. Defaults to 39px as standard buttons are
|
|
|
- // 40px tall
|
|
|
- menuOffset: PropTypes.string,
|
|
|
- // Should the menu contents always be rendered? Defaults to true.
|
|
|
- // Set to false to have menu contents removed from the DOM on close.
|
|
|
- alwaysRenderMenu: PropTypes.bool,
|
|
|
- // Align the dropdown menu to the right. (Default aligns to left)
|
|
|
- alignRight: PropTypes.bool,
|
|
|
- // Props to pass to DropdownButton
|
|
|
- buttonProps: PropTypes.object,
|
|
|
- // This makes the dropdown menu blend (e.g. corners are not rounded) with its
|
|
|
- // actor (opener) component
|
|
|
- blendWithActor: PropTypes.bool,
|
|
|
- };
|
|
|
-
|
|
|
- static defaultProps = {
|
|
|
+class DropdownControl extends React.Component<Props> {
|
|
|
+ static defaultProps: DefaultProps = {
|
|
|
alwaysRenderMenu: true,
|
|
|
menuWidth: '100%',
|
|
|
};
|
|
|
|
|
|
- renderButton(isOpen, getActorProps) {
|
|
|
+ renderButton(isOpen: boolean, getActorProps: GetActorPropsFn) {
|
|
|
const {label, button, buttonProps} = this.props;
|
|
|
if (button) {
|
|
|
return button({isOpen, getActorProps});
|
|
|
}
|
|
|
+
|
|
|
return (
|
|
|
<StyledDropdownButton {...getActorProps(buttonProps)} isOpen={isOpen}>
|
|
|
{label}
|
|
@@ -58,10 +73,10 @@ class DropdownControl extends React.Component {
|
|
|
children,
|
|
|
alwaysRenderMenu,
|
|
|
alignRight,
|
|
|
- menuOffset,
|
|
|
menuWidth,
|
|
|
blendWithActor,
|
|
|
} = this.props;
|
|
|
+ const alignMenu = alignRight ? 'right' : 'left';
|
|
|
|
|
|
return (
|
|
|
<Container>
|
|
@@ -71,12 +86,12 @@ class DropdownControl extends React.Component {
|
|
|
{this.renderButton(isOpen, getActorProps)}
|
|
|
<Content
|
|
|
{...getMenuProps()}
|
|
|
- alignMenu={alignRight ? 'right' : 'left'}
|
|
|
+ alignMenu={alignMenu}
|
|
|
width={menuWidth}
|
|
|
- menuOffset={menuOffset}
|
|
|
isOpen={isOpen}
|
|
|
blendCorner
|
|
|
blendWithActor={blendWithActor}
|
|
|
+ theme={theme}
|
|
|
>
|
|
|
{children}
|
|
|
</Content>
|
|
@@ -98,7 +113,7 @@ const StyledDropdownButton = styled(DropdownButton)`
|
|
|
white-space: nowrap;
|
|
|
`;
|
|
|
|
|
|
-const Content = styled(DropdownBubble.withComponent('div'))`
|
|
|
+const Content = styled(DropdownBubble)<{isOpen: boolean}>`
|
|
|
display: ${p => (p.isOpen ? 'block' : 'none')};
|
|
|
border-top: 0;
|
|
|
top: 100%;
|