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

Migrate EuiEmptyPromptand EuiCard to TS #2387

Merged
merged 3 commits into from
Sep 27, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Added `visAreaStacked`, `visBarVerticalStacked`, and `visBarHorizontalStacked` icons to glyph set ([#2379](https://github.com/elastic/eui/pull/2379))
- Adjusted style of beta badge on `EuiKeyPadMenuItem` ([#2375](https://github.com/elastic/eui/pull/2375))
- Migrate `EuiFacetGroup`, `EuiKeyPadMenu` and `EuiCallOut` to TS ([#2382](https://github.com/elastic/eui/pull/2382))
- Migrate `EuiEmptyPrompt`and `EuiCard` to TS ([#2387](https://github.com/elastic/eui/pull/2387))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to master; we just had a release


**Bug fixes**

Expand Down
11 changes: 9 additions & 2 deletions src/components/button/button_empty/button_empty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ import { EuiLoadingSpinner } from '../../loading';
import { getSecureRelForTarget } from '../../../services';
import { IconType, EuiIcon } from '../../icon';

const colorToClassNameMap = {
export type EuiButtonEmptyColor =
| 'primary'
| 'danger'
| 'disabled'
| 'text'
| 'ghost';

const colorToClassNameMap: { [color in EuiButtonEmptyColor]: string } = {
primary: 'euiButtonEmpty--primary',
danger: 'euiButtonEmpty--danger',
disabled: 'euiButtonEmpty--disabled',
Expand Down Expand Up @@ -47,7 +54,7 @@ export const FLUSH_TYPES = keysOf(flushTypeToClassNameMap);
export interface EuiButtonEmptyProps extends CommonProps {
iconType?: IconType;
iconSide?: keyof typeof iconSideToClassNameMap;
color?: keyof typeof colorToClassNameMap;
color?: EuiButtonEmptyColor;
size?: keyof typeof sizeToClassNameMap;
flush?: keyof typeof flushTypeToClassNameMap;
isDisabled?: boolean;
Expand Down
1 change: 1 addition & 0 deletions src/components/button/button_empty/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export {
ICON_SIDES,
EuiButtonEmpty,
EuiButtonEmptyProps,
EuiButtonEmptyColor,
} from './button_empty';
File renamed without changes.
180 changes: 91 additions & 89 deletions src/components/card/card.js → src/components/card/card.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,138 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent, ReactElement, ReactNode } from 'react';
import classNames from 'classnames';
import { getSecureRelForTarget } from '../../services';

import { CommonProps, keysOf } from '../common';
import { getSecureRelForTarget } from '../../services';
import { EuiText } from '../text';
import { EuiTitle } from '../title';
import { EuiBetaBadge } from '../badge/beta_badge';
import { EuiIconProps } from '../icon';
import {
EuiCardSelect,
EuiCardSelectProps,
euiCardSelectableColor,
} from './card_select';
import makeId from '../form/form_row/make_id';

const textAlignToClassNameMap = {
type CardAlignment = 'left' | 'center' | 'right';

const textAlignToClassNameMap: { [alignment in CardAlignment]: string } = {
left: 'euiCard--leftAligned',
center: 'euiCard--centerAligned',
right: 'euiCard--rightAligned',
};

export const ALIGNMENTS = Object.keys(textAlignToClassNameMap);
export const ALIGNMENTS = keysOf(textAlignToClassNameMap);

type CardLayout = 'vertical' | 'horizontal';

const layoutToClassNameMap = {
const layoutToClassNameMap: { [layout in CardLayout]: string } = {
vertical: '',
horizontal: 'euiCard--horizontal',
};

export const LAYOUT_ALIGNMENTS = Object.keys(layoutToClassNameMap);
const oneOfLayouts = PropTypes.oneOf(LAYOUT_ALIGNMENTS);
export const LAYOUT_ALIGNMENTS = keysOf(layoutToClassNameMap);

const cardLayout = (props, propName, componentName, ...rest) => {
const oneOfResult = oneOfLayouts(props, propName, componentName, ...rest);
if (oneOfResult) return oneOfResult;
type EuiCardProps = CommonProps & {
title: NonNullable<ReactNode>;
/**
* Determines the title's heading element. Will force to 'span' if
* the card is a button.
*/
titleElement?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span';
description: NonNullable<ReactNode>;

if (props[propName] === 'horizontal') {
if (props.image || props.footer) {
return new Error(
`${componentName}: '${propName} = horizontal' cannot be used in conjunction with 'image', 'footer', or 'textAlign'.`
);
}
}
/**
* Requires a <EuiIcon> node
*/
icon?: ReactElement<EuiIconProps>;

/**
* Accepts a url in string form
*/
image?: string;

/**
* Accepts any combination of elements
*/
footer?: ReactNode;

/**
* Use only if you want to forego a button in the footer and make the whole card clickable
*/
onClick?: Function;
href?: string;
target?: string;
rel?: string;
textAlign?: CardAlignment;

/**
* Change to "horizontal" if you need the icon to be left of the content
*/
layout?: CardLayout;

/**
* Add a badge to the card to label it as "Beta" or other non-GA state
*/
betaBadgeLabel?: string;

/**
* Add a description to the beta badge (will appear in a tooltip)
*/
betaBadgeTooltipContent?: ReactNode;

/**
* Optional title will be supplied as tooltip title or title attribute otherwise the label will be used
*/
betaBadgeTitle?: string;

/**
* Adds a button to the bottom of the card to allow for in-place selection.
*/
selectable?: EuiCardSelectProps;

/**
* Add a decorative bottom graphic to the card.
* This should be used sparingly, consult the Kibana Design team before use.
*/
bottomGraphic?: ReactNode;

isClickable?: boolean;

isDisabled?: boolean;
};

export const EuiCard = ({
export const EuiCard: FunctionComponent<EuiCardProps> = ({
className,
description,
isDisabled,
title,
titleElement,
titleElement = 'span',
icon,
image,
footer,
onClick,
href,
rel,
target,
textAlign,
textAlign = 'center',
isClickable,
betaBadgeLabel,
betaBadgeTooltipContent,
betaBadgeTitle,
layout,
layout = 'vertical',
bottomGraphic,
selectable,
...rest
}) => {
if (layout === 'horizontal') {
if (image || footer) {
throw new Error(
"EuiCard: layout = horizontal' cannot be used in conjunction with 'image', 'footer', or 'textAlign'."
);
}
}

const selectableColorClass = selectable
? `euiCard--isSelectable--${euiCardSelectableColor(
selectable.color,
Expand Down Expand Up @@ -171,6 +239,7 @@ export const EuiCard = ({
}

return (
// @ts-ignore
<OuterElement
onClick={onClick}
className={classes}
Expand Down Expand Up @@ -205,73 +274,6 @@ export const EuiCard = ({
);
};

EuiCard.propTypes = {
className: PropTypes.string,
title: PropTypes.node.isRequired,
/**
* Determines the title's heading element. Will force to 'span' if
* the card is a button.
*/
titleElement: PropTypes.oneOf(['h2', 'h3', 'h4', 'h5', 'h6', 'span']),
description: PropTypes.node.isRequired,

/**
* Requires a <EuiIcon> node
*/
icon: PropTypes.node,

/**
* Accepts a url in string form
*/
image: PropTypes.string,

/**
* Accepts any combination of elements
*/
footer: PropTypes.node,

/**
* Use only if you want to forego a button in the footer and make the whole card clickable
*/
onClick: PropTypes.func,
href: PropTypes.string,
target: PropTypes.string,
rel: PropTypes.string,
textAlign: PropTypes.oneOf(ALIGNMENTS),

/**
* Change to "horizontal" if you need the icon to be left of the content
*/
layout: cardLayout,

/**
* Add a badge to the card to label it as "Beta" or other non-GA state
*/
betaBadgeLabel: PropTypes.string,

/**
* Add a description to the beta badge (will appear in a tooltip)
*/
betaBadgeTooltipContent: PropTypes.node,

/**
* Optional title will be supplied as tooltip title or title attribute otherwise the label will be used
*/
betaBadgeTitle: PropTypes.string,

/**
* Adds a button to the bottom of the card to allow for in-place selection.
*/
selectable: PropTypes.shape(EuiCardSelectProps),

/**
* Add a decorative bottom graphic to the card.
* This should be used sparingly, consult the Kibana Design team before use.
*/
bottomGraphic: PropTypes.node,
isDisabled: PropTypes.bool,
};

EuiCard.defaultProps = {
textAlign: 'center',
layout: 'vertical',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent, MouseEventHandler, ReactNode } from 'react';
import classNames from 'classnames';

import {
EuiButtonEmpty,
COLORS as BUTTON_EMPTY_COLORS,
} from '../button/button_empty';
import { CommonProps } from '../common';
import { EuiButtonEmpty, EuiButtonEmptyColor } from '../button/button_empty';

import { EuiI18n } from '../i18n';

export const EuiCardSelect = ({
export type EuiCardSelectProps = CommonProps & {
/**
* You must handle the click event in order to have a select button
*/
onClick: MouseEventHandler<HTMLButtonElement>;
/**
* Is in the selected state
*/
isSelected?: boolean;
isDisabled?: boolean;
/**
* Override the default color with one of the available colors from `EuiButtonEmpty`
*/
color?: EuiButtonEmptyColor;
};

export const EuiCardSelect: FunctionComponent<EuiCardSelectProps> = ({
className,
onClick,
isSelected,
Expand Down Expand Up @@ -40,30 +53,11 @@ export const EuiCardSelect = ({
);
};

export const EuiCardSelectProps = {
className: PropTypes.string,
/**
* You must handle the click event in order to have a select button
*/
onClick: PropTypes.func.isRequired,
/**
* Is in the selected state
*/
isSelected: PropTypes.bool,
isDisabled: PropTypes.bool,
/**
* Override the default color with one of the available colors from `EuiButtonEmpty`
*/
color: PropTypes.oneOf(BUTTON_EMPTY_COLORS),
/**
* Override the content (text) of the button
*/
children: PropTypes.node,
};

EuiCardSelect.propTypes = EuiCardSelectProps;

function euiCardSelectableText(isSelected, isDisabled, children) {
function euiCardSelectableText(
isSelected: boolean | undefined,
isDisabled: boolean | undefined,
children: ReactNode
): ReactNode {
if (children) {
return children;
}
Expand All @@ -81,7 +75,10 @@ function euiCardSelectableText(isSelected, isDisabled, children) {
return text;
}

export function euiCardSelectableColor(color, isSelected) {
export function euiCardSelectableColor(
color: EuiButtonEmptyColor | undefined,
isSelected: boolean | undefined
): string {
let calculatedColor;
if (color) {
calculatedColor = color;
Expand Down
1 change: 0 additions & 1 deletion src/components/card/index.d.ts

This file was deleted.

File renamed without changes.
Loading