diff --git a/src-docs/src/views/icon/icon_example.js b/src-docs/src/views/icon/icon_example.js index f2434a8059e..49b1f0f1fe3 100644 --- a/src-docs/src/views/icon/icon_example.js +++ b/src-docs/src/views/icon/icon_example.js @@ -82,7 +82,7 @@ import IconTypes from './icon_types'; const iconTypesSource = require('!!raw-loader!./icon_types'); const iconTypesSnippet = [``, ``, - ``, + ``, `Works in other components too`]; export const IconExample = { @@ -278,7 +278,8 @@ export const IconExample = { text: (

The type prop can accept a valid enum, string or React SVG Element. When using a custom SVG, please make sure - it sits on a square canvas and preferably utilizes one of EUI's sizes (16x16, 32x32...etc). + it sits on a square canvas and preferably utilizes one of EUI's sizes (16x16, 32x32...etc). For IE11 compatibility, the SVG + file must contain a viewBox.

), source: [{ diff --git a/src-docs/src/views/icon/icon_types.js b/src-docs/src/views/icon/icon_types.js index 516e8acb4b7..de6d023aaa8 100644 --- a/src-docs/src/views/icon/icon_types.js +++ b/src-docs/src/views/icon/icon_types.js @@ -38,7 +38,7 @@ export default () => ( > @@ -72,7 +72,7 @@ export default () => ( - http://some.svg + http://some.svg {`{reactSvg}`} diff --git a/src/components/badge/badge.js b/src/components/badge/badge.js index 1dbee4f66f9..c450f2f585d 100644 --- a/src/components/badge/badge.js +++ b/src/components/badge/badge.js @@ -7,7 +7,7 @@ import { isColorDark, hexToRgb } from '../../services/color'; import { EuiKeyboardAccessible } from '../accessibility'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -150,7 +150,7 @@ EuiBadge.propTypes = { /** * Accepts any string from our icon library */ - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, /** * The side of the badge the icon should sit diff --git a/src/components/badge/beta_badge/beta_badge.js b/src/components/badge/beta_badge/beta_badge.js index dc3fd66d4bb..6b96853ec86 100644 --- a/src/components/badge/beta_badge/beta_badge.js +++ b/src/components/badge/beta_badge/beta_badge.js @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { EuiToolTip } from '../../tool_tip'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../../icon'; @@ -78,7 +78,7 @@ EuiBetaBadge.propTypes = { /** * Supply an icon type if the badge should just be an icon */ - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, /** * Content for the tooltip diff --git a/src/components/button/button.js b/src/components/button/button.js index c4abbc5ff71..e10fe06609c 100644 --- a/src/components/button/button.js +++ b/src/components/button/button.js @@ -9,7 +9,7 @@ import { import { getSecureRelForTarget } from '../../services'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -152,7 +152,7 @@ EuiButton.propTypes = { /** * See EuiIcon */ - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, iconSide: PropTypes.oneOf(ICON_SIDES), /** diff --git a/src/components/button/button_empty/button_empty.js b/src/components/button/button_empty/button_empty.js index b9935e1a814..724564378d9 100644 --- a/src/components/button/button_empty/button_empty.js +++ b/src/components/button/button_empty/button_empty.js @@ -9,7 +9,7 @@ import { import { getSecureRelForTarget } from '../../../services'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../../icon'; @@ -150,7 +150,7 @@ export const EuiButtonEmpty = ({ EuiButtonEmpty.propTypes = { children: PropTypes.node, className: PropTypes.string, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, iconSide: PropTypes.oneOf(ICON_SIDES), color: PropTypes.oneOf(COLORS), size: PropTypes.oneOf(SIZES), diff --git a/src/components/button/button_icon/button_icon.js b/src/components/button/button_icon/button_icon.js index 5cdca391d01..852ae927e4f 100644 --- a/src/components/button/button_icon/button_icon.js +++ b/src/components/button/button_icon/button_icon.js @@ -6,7 +6,7 @@ import { getSecureRelForTarget } from '../../../services'; import { ICON_SIZES, - ICON_TYPES, + IconPropType, EuiIcon, } from '../../icon'; @@ -107,7 +107,7 @@ export const EuiButtonIcon = ({ EuiButtonIcon.propTypes = { children: PropTypes.node, className: PropTypes.string, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, iconSize: PropTypes.oneOf(ICON_SIZES), color: PropTypes.oneOf(COLORS), isDisabled: PropTypes.bool, diff --git a/src/components/call_out/call_out.js b/src/components/call_out/call_out.js index 644904dde9f..d95ad7f4eb4 100644 --- a/src/components/call_out/call_out.js +++ b/src/components/call_out/call_out.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -94,7 +94,7 @@ EuiCallOut.propTypes = { children: PropTypes.node, className: PropTypes.string, title: PropTypes.node, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, color: PropTypes.oneOf(COLORS), size: PropTypes.oneOf(SIZES), }; diff --git a/src/components/date_picker/date_picker_range.js b/src/components/date_picker/date_picker_range.js index b3e20b5e9a3..f8944bd0c45 100644 --- a/src/components/date_picker/date_picker_range.js +++ b/src/components/date_picker/date_picker_range.js @@ -6,7 +6,7 @@ import classNames from 'classnames'; import { EuiText } from '../text'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -91,7 +91,7 @@ EuiDatePickerRange.propTypes = { */ iconType: PropTypes.oneOfType([ PropTypes.bool, - PropTypes.oneOf(ICON_TYPES), + IconPropType, ]), fullWidth: PropTypes.bool, /** diff --git a/src/components/empty_prompt/empty_prompt.js b/src/components/empty_prompt/empty_prompt.js index 26ba32374e3..eb40aab6d2a 100644 --- a/src/components/empty_prompt/empty_prompt.js +++ b/src/components/empty_prompt/empty_prompt.js @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { TITLE_SIZES } from '../title/title'; import { EuiFlexGroup, EuiFlexItem } from '../flex'; import { EuiSpacer } from '../spacer'; -import { EuiIcon, COLORS, TYPES } from '../icon/icon'; +import { EuiIcon, COLORS, IconPropType } from '../icon/icon'; import { EuiText, EuiTextColor } from '../text'; import { EuiTitle } from '../title'; @@ -116,7 +116,7 @@ export const EuiEmptyPrompt = ({ }; EuiEmptyPrompt.propTypes = { - iconType: PropTypes.oneOf(TYPES), + iconType: IconPropType, /** * Pass `null` to use original icon color diff --git a/src/components/filter_group/filter_button.js b/src/components/filter_group/filter_button.js index 5d8b00b3fa8..4c761495a57 100644 --- a/src/components/filter_group/filter_button.js +++ b/src/components/filter_group/filter_button.js @@ -11,7 +11,7 @@ import { } from '../button/button_empty'; import { - ICON_TYPES, + IconPropType, } from '../icon'; export const EuiFilterButton = ({ @@ -95,7 +95,7 @@ EuiFilterButton.propTypes = { /** * Use any one of our icons */ - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, iconSide: PropTypes.oneOf(ICON_SIDES), color: PropTypes.oneOf(COLORS), /** diff --git a/src/components/header/header_logo.js b/src/components/header/header_logo.js index c918cb223bb..2513733c468 100644 --- a/src/components/header/header_logo.js +++ b/src/components/header/header_logo.js @@ -4,6 +4,7 @@ import classNames from 'classnames'; import { EuiIcon, + IconPropType, } from '../icon'; export const EuiHeaderLogo = ({ iconType, iconTitle, href, children, className, ...rest }) => { @@ -28,7 +29,7 @@ export const EuiHeaderLogo = ({ iconType, iconTitle, href, children, className, EuiHeaderLogo.propTypes = { href: PropTypes.string, children: PropTypes.node, - iconType: PropTypes.string, + iconType: IconPropType, iconTitle: PropTypes.string, }; diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 115da7b5456..1a3319a0f56 100644 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -4,6 +4,7 @@ import React, { ReactElement, SVGAttributes, } from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; import { CommonProps, Omit, keysOf } from '../common'; @@ -316,9 +317,16 @@ const typeToPathMap = { tokenNamespace: 'tokens/tokenNamespace', }; -export const TYPES: IconType[] = keysOf(typeToPathMap); +export const TYPES = keysOf(typeToPathMap); -export type IconType = keyof typeof typeToPathMap; +export type EuiIconType = keyof typeof typeToPathMap; + +export type IconType = EuiIconType | string | ReactElement; + +export const IconPropType = PropTypes.oneOfType([ + PropTypes.string, + PropTypes.node, +]); const colorToClassMap = { default: null, @@ -361,7 +369,7 @@ export interface EuiIconProps { /** * `Enum` is any of the named icons listed in the docs, `Element` is any React SVG element, and `string` is usually a URL to an SVG file */ - type: IconType | ReactElement | string; + type: IconType; /** * One of EUI's color palette or a valid CSS color value https://developer.mozilla.org/en-US/docs/Web/CSS/color_value. * Note that coloring only works if your SVG is removed of fill attributes. @@ -374,15 +382,15 @@ export interface EuiIconProps { } type Props = CommonProps & - Omit, 'color'> & + Omit, keyof EuiIconProps> & EuiIconProps; interface State { - icon: undefined | ReactElement | string; + icon: undefined | ReactElement | string; isLoading: boolean; } -function isIconType(x: EuiIconProps['type']): x is IconType { +function isEuiIconType(x: EuiIconProps['type']): x is EuiIconType { return typeof x === 'string' && typeToPathMap.hasOwnProperty(x); } @@ -390,7 +398,7 @@ function getInitialIcon(icon: EuiIconProps['type']) { if (icon == null) { return undefined; } - if (isIconType(icon)) { + if (isEuiIconType(icon)) { return undefined; } return icon; @@ -403,7 +411,7 @@ export class EuiIcon extends Component { const initialIcon = getInitialIcon(this.props.type); let isLoading = false; - if (isIconType(this.props.type)) { + if (isEuiIconType(this.props.type)) { isLoading = true; import('./assets/' + typeToPathMap[this.props.type] + '.js').then( ({ icon }) => { @@ -447,6 +455,7 @@ export class EuiIcon extends Component { // These icons are a little special and get some extra CSS flexibility const isAppIcon = type && + typeof type === 'string' && (/.+App$/.test(type) || /.+Job$/.test(type) || type === 'dataVisualizer'); const classes = classNames( diff --git a/src/components/icon/index.ts b/src/components/icon/index.ts index 93fcbec7e9c..46954d7aea4 100644 --- a/src/components/icon/index.ts +++ b/src/components/icon/index.ts @@ -3,6 +3,7 @@ export { IconColor, IconSize, IconType, + IconPropType, TYPES as ICON_TYPES, SIZES as ICON_SIZES, COLORS as ICON_COLORS, diff --git a/src/components/key_pad_menu/key_pad_menu_item.js b/src/components/key_pad_menu/key_pad_menu_item.js index bb777e10330..fd3b63be621 100644 --- a/src/components/key_pad_menu/key_pad_menu_item.js +++ b/src/components/key_pad_menu/key_pad_menu_item.js @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { EuiBetaBadge } from '../../components/badge/beta_badge'; import { - ICON_TYPES, + IconPropType, } from '../icon'; const renderContent = (children, label, betaBadgeLabel, betaBadgeTooltipContent, betaBadgeIconType) => ( @@ -43,7 +43,7 @@ const commonPropTypes = { /** * Supply an icon type if the badge should just be an icon */ - betaBadgeIconType: PropTypes.oneOf(ICON_TYPES), + betaBadgeIconType: IconPropType, /** * Add a description to the beta badge (will appear in a tooltip) diff --git a/src/components/list_group/list_group_item.js b/src/components/list_group/list_group_item.js index e15ed76617f..95444f5f776 100644 --- a/src/components/list_group/list_group_item.js +++ b/src/components/list_group/list_group_item.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiButtonIcon } from '../button'; -import { ICON_TYPES, EuiIcon } from '../icon'; +import { IconPropType, EuiIcon } from '../icon'; import { EuiToolTip } from '../tool_tip'; const sizeToClassNameMap = { @@ -182,7 +182,7 @@ EuiListGroupItem.propTypes = { /** * Adds `EuiIcon` of `EuiIcon.type` */ - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, /** * Custom node to pass as the icon. Cannot be used in conjunction @@ -200,7 +200,7 @@ EuiListGroupItem.propTypes = { * pass `alwaysShow` if you don't want the default behavior of only showing on hover */ extraAction: PropTypes.shape({ - iconType: PropTypes.oneOf(ICON_TYPES).isRequired, + iconType: IconPropType.isRequired, alwaysShow: PropTypes.bool, }), diff --git a/src/components/table/table_header_button.js b/src/components/table/table_header_button.js index 76551d3d4a8..78cee5e7d5b 100644 --- a/src/components/table/table_header_button.js +++ b/src/components/table/table_header_button.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -44,5 +44,5 @@ export const EuiTableHeaderButton = ({ EuiTableHeaderButton.propTypes = { children: PropTypes.node, className: PropTypes.string, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, }; diff --git a/src/components/toast/global_toast_list.js b/src/components/toast/global_toast_list.js index 61f557679e5..3ea252dd4fe 100644 --- a/src/components/toast/global_toast_list.js +++ b/src/components/toast/global_toast_list.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { Timer } from '../../services/time'; -import { ICON_TYPES } from '../icon'; +import { IconPropType } from '../icon'; import { EuiGlobalToastListItem } from './global_toast_list_item'; import { EuiToast } from './toast'; @@ -38,7 +38,7 @@ export class EuiGlobalToastList extends Component { title: PropTypes.string, text: PropTypes.node, color: PropTypes.string, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, toastLifeTimeMs: PropTypes.number, }).isRequired), dismissToast: PropTypes.func.isRequired, diff --git a/src/components/toast/toast.js b/src/components/toast/toast.js index 192cafa1f1e..208c4cea1ae 100644 --- a/src/components/toast/toast.js +++ b/src/components/toast/toast.js @@ -6,7 +6,7 @@ import { EuiScreenReaderOnly } from '../accessibility'; import { EuiI18n } from '../i18n'; import { - ICON_TYPES, + IconPropType, EuiIcon, } from '../icon'; @@ -110,7 +110,7 @@ export const EuiToast = ({ title, color, iconType, onClose, children, className, EuiToast.propTypes = { title: PropTypes.node, - iconType: PropTypes.oneOf(ICON_TYPES), + iconType: IconPropType, color: PropTypes.oneOf(COLORS), onClose: PropTypes.func, children: PropTypes.node, diff --git a/src/components/token/token.js b/src/components/token/token.js index 59d270c1a4e..9824915fc9b 100644 --- a/src/components/token/token.js +++ b/src/components/token/token.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { ICON_TYPES, EuiIcon } from '../icon'; +import { IconPropType, EuiIcon } from '../icon'; import { TOKEN_MAP } from './token_map'; const sizeToClassMap = { @@ -93,7 +93,7 @@ EuiToken.propTypes = { /** * An EUI icon type */ - iconType: PropTypes.oneOf(ICON_TYPES).isRequired, + iconType: IconPropType.isRequired, /** * Size of the token */