Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TS button onClick clean up #2282

Merged
merged 3 commits into from
Sep 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

**Bug fixes**

- Removed extra right side margin in 'EuiSuperDatePicker' ([#2236](https://github.com/elastic/eui/pull/2236))
- Removed extra right side margin in `EuiSuperDatePicker` ([#2236](https://github.com/elastic/eui/pull/2236))
- Fix incorrect `onClick` type for `EuiButtonEmpty` ([#2282](https://github.com/elastic/eui/pull/2282))

## [`13.7.0`](https://github.com/elastic/eui/tree/v13.7.0)

Expand Down
28 changes: 17 additions & 11 deletions src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ import React, {
ButtonHTMLAttributes,
FunctionComponent,
HTMLAttributes,
MouseEventHandler,
Ref,
} from 'react';
import classNames from 'classnames';

import { CommonProps, ExclusiveUnion, keysOf } from '../common';
import {
CommonProps,
ExclusiveUnion,
PropsForAnchor,
PropsForButton,
keysOf,
} from '../common';
import { EuiLoadingSpinner } from '../loading';

import { getSecureRelForTarget } from '../../services';
Expand Down Expand Up @@ -65,18 +70,19 @@ export interface EuiButtonProps extends CommonProps {
textProps?: HTMLAttributes<HTMLSpanElement>;
}

type EuiButtonPropsForAnchor = EuiButtonProps &
AnchorHTMLAttributes<HTMLAnchorElement> & {
href?: string;
onClick?: MouseEventHandler<HTMLAnchorElement>;
type EuiButtonPropsForAnchor = PropsForAnchor<
EuiButtonProps,
{
buttonRef?: Ref<HTMLAnchorElement>;
};
}
>;

type EuiButtonPropsForButton = EuiButtonProps &
ButtonHTMLAttributes<HTMLButtonElement> & {
onClick?: MouseEventHandler<HTMLButtonElement>;
type EuiButtonPropsForButton = PropsForButton<
EuiButtonProps,
{
buttonRef?: Ref<HTMLButtonElement>;
};
}
>;

export type Props = ExclusiveUnion<
EuiButtonPropsForAnchor,
Expand Down
24 changes: 18 additions & 6 deletions src/components/button/button_empty/button_empty.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React, { FunctionComponent, HTMLAttributes } from 'react';
import classNames from 'classnames';

import { CommonProps, keysOf, NoArgCallback } from '../../common';
import {
CommonProps,
ExclusiveUnion,
PropsForAnchor,
PropsForButton,
keysOf,
} from '../../common';
import { EuiLoadingSpinner } from '../../loading';
import { getSecureRelForTarget } from '../../../services';
import { IconType, EuiIcon } from '../../icon';
Expand Down Expand Up @@ -38,7 +44,7 @@ const flushTypeToClassNameMap = {

export const FLUSH_TYPES = keysOf(flushTypeToClassNameMap);

export interface EuiButtonEmptyProps {
export interface EuiButtonEmptyProps extends CommonProps {
iconType?: IconType;
iconSide?: keyof typeof iconSideToClassNameMap;
color?: keyof typeof colorToClassNameMap;
Expand All @@ -48,7 +54,6 @@ export interface EuiButtonEmptyProps {
href?: string;
target?: string;
rel?: string;
onClick?: NoArgCallback<void>;

/**
* Adds/swaps for loading spinner & disables
Expand All @@ -68,7 +73,14 @@ export interface EuiButtonEmptyProps {
textProps?: Partial<HTMLAttributes<HTMLSpanElement>>;
}

type Props = CommonProps & EuiButtonEmptyProps;
type EuiButtonEmptyPropsForAnchor = PropsForAnchor<EuiButtonEmptyProps>;

type EuiButtonEmptyPropsForButton = PropsForButton<EuiButtonEmptyProps>;

type Props = ExclusiveUnion<
EuiButtonEmptyPropsForAnchor,
EuiButtonEmptyPropsForButton
>;

export const EuiButtonEmpty: FunctionComponent<Props> = ({
children,
Expand Down Expand Up @@ -148,7 +160,7 @@ export const EuiButtonEmpty: FunctionComponent<Props> = ({
target={target}
rel={secureRel}
ref={buttonRef}
{...rest}>
{...rest as EuiButtonEmptyPropsForAnchor}>
{innerNode}
</a>
);
Expand All @@ -160,7 +172,7 @@ export const EuiButtonEmpty: FunctionComponent<Props> = ({
className={classes}
type={type}
ref={buttonRef}
{...rest}>
{...rest as EuiButtonEmptyPropsForButton}>
{innerNode}
</button>
);
Expand Down
28 changes: 17 additions & 11 deletions src/components/button/button_icon/button_icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import React, {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
FunctionComponent,
MouseEventHandler,
Ref,
} from 'react';
import classNames from 'classnames';

import { getSecureRelForTarget } from '../../../services';
import { CommonProps, ExclusiveUnion, keysOf } from '../../common';
import {
CommonProps,
ExclusiveUnion,
PropsForAnchor,
PropsForButton,
keysOf,
} from '../../common';

import { IconType, IconSize, EuiIcon } from '../../icon';

Expand All @@ -34,18 +39,19 @@ export interface EuiButtonIconProps extends CommonProps {
iconSize?: IconSize;
}

type EuiButtonIconPropsForAnchor = EuiButtonIconProps &
AnchorHTMLAttributes<HTMLAnchorElement> & {
href: string;
onClick?: MouseEventHandler<HTMLAnchorElement>;
type EuiButtonIconPropsForAnchor = PropsForAnchor<
EuiButtonIconProps,
{
buttonRef?: Ref<HTMLAnchorElement>;
};
}
>;

export type EuiButtonIconPropsForButton = EuiButtonIconProps &
ButtonHTMLAttributes<HTMLButtonElement> & {
onClick?: MouseEventHandler<HTMLButtonElement>;
export type EuiButtonIconPropsForButton = PropsForButton<
EuiButtonIconProps,
{
buttonRef?: Ref<HTMLButtonElement>;
};
}
>;

type Props = ExclusiveUnion<
EuiButtonIconPropsForAnchor,
Expand Down
32 changes: 31 additions & 1 deletion src/components/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Component, FunctionComponent, SFC } from 'react';
import {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
Component,
FunctionComponent,
MouseEventHandler,
SFC,
} from 'react';

export interface CommonProps {
className?: string;
Expand Down Expand Up @@ -110,3 +117,26 @@ export type DisambiguateSet<T, U> = {
export type ExclusiveUnion<T, U> = (T | U) extends object // if there are any shared keys between T and U
? (DisambiguateSet<T, U> & U) | (DisambiguateSet<U, T> & T) // otherwise the TS union is already unique
: T | U;

/**
* For components that conditionally render <button> or <a>
* Convenience types for extending base props (T) and
* element-specific props (P) with standard clickable properties
*
* These will likely be used together, along with `ExclusiveUnion`:
*
* type AnchorLike = PropsForAnchor<BaseProps>
* type ButtonLike = PropsForButton<BaseProps>
* type ComponentProps = ExlcusiveUnion<AnchorLike, ButtonLike>
* const Component: FunctionComponent<ComponentProps> ...
*/
export type PropsForAnchor<T, P = {}> = T &
AnchorHTMLAttributes<HTMLAnchorElement> & {
href?: string;
onClick?: MouseEventHandler<HTMLAnchorElement>;
} & P;

export type PropsForButton<T, P = {}> = T &
ButtonHTMLAttributes<HTMLButtonElement> & {
onClick?: MouseEventHandler<HTMLButtonElement>;
} & P;
20 changes: 15 additions & 5 deletions src/components/filter_group/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Component, FunctionComponent, ButtonHTMLAttributes } from 'react';

import { CommonProps } from '../common';
import {
CommonProps,
ExclusiveUnion,
PropsForAnchor,
PropsForButton,
} from '../common';
import { EuiButtonEmptyProps } from '../button';
import { EuiFilterGroupProps } from './filter_group';

Expand All @@ -11,23 +16,28 @@ declare module '@elastic/eui' {
* @see './filter_button.js'
*/

export interface EuiFilterButtonProps {
export interface EuiFilterButtonProps extends EuiButtonEmptyProps {
numFilters?: number;
numActiveFilters?: number;
hasActiveFilters?: boolean;
isSelected?: boolean;
isDisabled?: boolean;
type?: string;
grow?: boolean;
withNext?: boolean;
/**
* _DEPRECATED use `withNext`_
*/
noDivider?: boolean;
}
export const EuiFilterButton: FunctionComponent<
EuiButtonEmptyProps & EuiFilterButtonProps
type EuiFilterButtonPropsForAnchor = PropsForAnchor<EuiFilterButtonProps>;

type EuiFilterButtonPropsForButton = PropsForButton<EuiFilterButtonProps>;

type Props = ExclusiveUnion<
EuiFilterButtonPropsForAnchor,
EuiFilterButtonPropsForButton
>;
export const EuiFilterButton: FunctionComponent<Props>;

/**
* Filter group type defs
Expand Down
19 changes: 14 additions & 5 deletions src/components/pagination/pagination_button.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { FunctionComponent } from 'react';
import classNames from 'classnames';

import { CommonProps, Omit } from '../common';
import { ExclusiveUnion, PropsForAnchor, PropsForButton } from '../common';
import { EuiButtonEmpty, EuiButtonEmptyProps } from '../button';

export interface EuiPaginationButtonProps {
export interface EuiPaginationButtonProps extends EuiButtonEmptyProps {
isActive?: boolean;
/**
* For ellipsis or other non-clickable buttons.
Expand All @@ -13,9 +13,18 @@ export interface EuiPaginationButtonProps {
hideOnMobile?: boolean;
}

type Props = CommonProps &
Omit<EuiButtonEmptyProps, 'size' | 'color'> &
EuiPaginationButtonProps;
type EuiPaginationButtonPropsForAnchor = PropsForAnchor<
EuiPaginationButtonProps
>;

type EuiPaginationButtonPropsForButton = PropsForButton<
EuiPaginationButtonProps
>;

type Props = ExclusiveUnion<
EuiPaginationButtonPropsForAnchor,
EuiPaginationButtonPropsForButton
>;

export const EuiPaginationButton: FunctionComponent<Props> = ({
children,
Expand Down