diff --git a/src/components/index.d.ts b/src/components/index.d.ts index 0841f75163c..47da07187d0 100644 --- a/src/components/index.d.ts +++ b/src/components/index.d.ts @@ -3,7 +3,6 @@ /// /// /// -/// /// declare module '@elastic/eui' { diff --git a/src/components/modal/__snapshots__/confirm_modal.test.js.snap b/src/components/modal/__snapshots__/confirm_modal.test.tsx.snap similarity index 97% rename from src/components/modal/__snapshots__/confirm_modal.test.js.snap rename to src/components/modal/__snapshots__/confirm_modal.test.tsx.snap index ec4fc631bb1..cdfebf3a559 100644 --- a/src/components/modal/__snapshots__/confirm_modal.test.js.snap +++ b/src/components/modal/__snapshots__/confirm_modal.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renders EuiConfirmModal 1`] = ` +exports[`EuiConfirmModal renders EuiConfirmModal 1`] = ` Array [
, -
, -
-
- -
- children -
-
-
, -
, -] -`; diff --git a/src/components/modal/confirm_modal.tsx b/src/components/modal/confirm_modal.tsx index 4b79ffc6a4a..1eac57d229e 100644 --- a/src/components/modal/confirm_modal.tsx +++ b/src/components/modal/confirm_modal.tsx @@ -1,7 +1,12 @@ -import React, { FunctionComponent, ReactNode, useEffect } from 'react'; +import React, { + FunctionComponent, + ReactNode, + useEffect, + useState, +} from 'react'; import classnames from 'classnames'; -import { EuiModal } from './modal'; +import { EuiModal, EuiModalProps } from './modal'; import { EuiModalFooter } from './modal_footer'; import { EuiModalHeader } from './modal_header'; import { EuiModalHeaderTitle } from './modal_header_title'; @@ -11,12 +16,20 @@ import { EuiButton, EuiButtonEmpty } from '../button'; import { EuiText } from '../text'; -export interface EuiConfirmModalProps { +export interface EuiConfirmModalProps + extends Omit< + EuiModalProps, + 'children' | 'initialFocus' | 'onClose' | 'title' + > { children?: ReactNode; title?: ReactNode; cancelButtonText?: ReactNode; confirmButtonText?: ReactNode; - onCancel: (event: React.MouseEvent) => void; + onCancel: ( + event?: + | React.KeyboardEvent + | React.MouseEvent + ) => void; onConfirm?: (event: React.MouseEvent) => void; confirmButtonDisabled?: boolean; className?: string; @@ -42,31 +55,29 @@ export interface EuiConfirmModalProps { export const CONFIRM_BUTTON = 'confirm'; export const CANCEL_BUTTON = 'cancel'; -export const EuiConfirmModal: FunctionComponent = ( - props: EuiConfirmModalProps -) => { - const { - children, - title, - onCancel, - onConfirm, - cancelButtonText, - confirmButtonText, - confirmButtonDisabled, - className, - buttonColor = 'primary', - defaultFocusedButton, - ...rest - } = props; - - let cancelButton: any; - let confirmButton: any; +export const EuiConfirmModal: FunctionComponent = ({ + children, + title, + onCancel, + onConfirm, + cancelButtonText, + confirmButtonText, + confirmButtonDisabled, + className, + buttonColor = 'primary', + defaultFocusedButton, + ...rest +}) => { + const [cancelButton, setCancelButton] = useState< + HTMLButtonElement | HTMLAnchorElement | null + >(null); + const [confirmButton, setConfirmButton] = useState( + null + ); useEffect(() => { // We have to do this instead of using `autoFocus` because React's polyfill for auto-focusing // elements conflicts with the focus-trap logic we have on EuiModal. - const { defaultFocusedButton } = props; - // Wait a beat for the focus-trap to complete, and then set focus to the right button. Check that // the buttons exist first, because it's possible the modal has been closed already. requestAnimationFrame(() => { @@ -76,10 +87,11 @@ export const EuiConfirmModal: FunctionComponent = ( confirmButton.focus(); } }); - }, [cancelButton, confirmButton, props]); + }); - const confirmRef = (node: any) => (confirmButton = node); - const cancelRef = (node: any) => (cancelButton = node); + const confirmRef = (node: HTMLButtonElement | null) => setConfirmButton(node); + const cancelRef = (node: HTMLButtonElement | HTMLAnchorElement | null) => + setCancelButton(node); const classes = classnames('euiModal--confirmation', className); diff --git a/src/components/modal/index.d.ts b/src/components/modal/index.d.ts deleted file mode 100644 index 970a0f4e334..00000000000 --- a/src/components/modal/index.d.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { CommonProps } from '../common'; -import { FocusTarget } from '../focus_trap'; - -import { ReactNode, FunctionComponent, HTMLAttributes } from 'react'; - -import { ButtonColor } from '../button'; - -import { EuiModalFooterProps } from './modal_footer'; -import { EuiModalHeaderProps } from './modal_header'; -import { EuiModalBodyProps } from './modal_body'; -import { EuiModalHeaderTitleProps } from './modal_header_title'; - -declare module '@elastic/eui' { - /** - * Modal type defs - * - * @see './modal.js' - */ - export interface EuiModalProps { - onClose: () => void; - /** - * Sets the max-width of the modal, - * set to `true` to use the default size, - * set to `false` to not restrict the width, - * set to a number for a custom width in px, - * set to a string for a custom width in custom measurement. - */ - maxWidth?: boolean | number | string; - - /** - * Specifies what element should initially have focus; - * Can be a DOM node, or a selector string (which will be passed to document.querySelector() to find the DOM node), or a function that returns a DOM node. - */ - initialFocus?: FocusTarget; - } - - export const EuiModal: FunctionComponent< - CommonProps & HTMLAttributes & EuiModalProps - >; - - /** - * Confirm modal type defs - * - * @see './confirm_modal.js' - */ - - // index.js re-exports values from confirm_modal.js with these names. - export const EUI_MODAL_CONFIRM_BUTTON: 'confirm'; - export const EUI_MODAL_CANCEL_BUTTON: 'cancel'; - - export interface EuiConfirmModalProps { - buttonColor?: ButtonColor; - cancelButtonText?: ReactNode; - confirmButtonText?: ReactNode; - confirmButtonDisabled?: boolean; - defaultFocusedButton?: 'confirm' | 'cancel'; - title?: ReactNode; - onCancel?: () => void; - onConfirm?: () => void; - /** - * Sets the max-width of the modal, - * set to `true` to use the default size, - * set to `false` to not restrict the width, - * set to a number for a custom width in px, - * set to a string for a custom width in custom measurement. - */ - maxWidth?: boolean | number | string; - } - - // `title` from the React defs conflicts with our definition above - export const EuiConfirmModal: FunctionComponent< - CommonProps & - Omit, 'title'> & - EuiConfirmModalProps - >; - - /** - * Modal body type defs - * - * @see './modal_body.js' - */ - export const EuiModalBody: EuiModalBodyProps; - - /** - * Modal footer type defs - * - * @see './modal_footer.js' - */ - export const EuiModalFooter: EuiModalFooterProps; - - /** - * Modal header type defs - * - * @see './modal_header.js' - */ - export const EuiModalHeader: EuiModalHeaderProps; - - /** - * Modal header title type defs - * - * @see './modal_header_title.js' - */ - export const EuiModalHeaderTitle: EuiModalHeaderTitleProps; -} diff --git a/src/components/modal/index.ts b/src/components/modal/index.ts index 7446470c826..de7fb9a2e59 100644 --- a/src/components/modal/index.ts +++ b/src/components/modal/index.ts @@ -5,7 +5,10 @@ export { CANCEL_BUTTON as EUI_MODAL_CANCEL_BUTTON, } from './confirm_modal'; export { EuiModal, EuiModalProps } from './modal'; -export { EuiModalFooter } from './modal_footer'; -export { EuiModalHeader } from './modal_header'; -export { EuiModalBody } from './modal_body'; -export { EuiModalHeaderTitle } from './modal_header_title'; +export { EuiModalFooter, EuiModalFooterProps } from './modal_footer'; +export { EuiModalHeader, EuiModalHeaderProps } from './modal_header'; +export { EuiModalBody, EuiModalBodyProps } from './modal_body'; +export { + EuiModalHeaderTitle, + EuiModalHeaderTitleProps, +} from './modal_header_title'; diff --git a/src/components/modal/modal.tsx b/src/components/modal/modal.tsx index fcc9c559f8d..6ba0ec5067e 100644 --- a/src/components/modal/modal.tsx +++ b/src/components/modal/modal.tsx @@ -12,7 +12,11 @@ import { EuiI18n } from '../i18n'; export interface EuiModalProps extends HTMLAttributes { className?: string; children: ReactNode; - onClose: (event?: any) => void; + onClose: ( + event?: + | React.KeyboardEvent + | React.MouseEvent + ) => void; /** * Sets the max-width of the modal. * Set to `true` to use the default (`euiBreakpoints 'm'`), @@ -25,19 +29,15 @@ export interface EuiModalProps extends HTMLAttributes { initialFocus?: HTMLElement | (() => HTMLElement) | string; } -export const EuiModal: FunctionComponent = ( - props: EuiModalProps -) => { - const { - className, - children, - initialFocus, - onClose, // eslint-disable-line no-unused-vars - maxWidth = true, - style, - ...rest - } = props; - +export const EuiModal: FunctionComponent = ({ + className, + children, + initialFocus, + onClose, + maxWidth = true, + style, + ...rest +}) => { const onKeyDown = (event: React.KeyboardEvent) => { if (event.keyCode === keyCodes.ESCAPE) { event.preventDefault(); @@ -70,7 +70,7 @@ export const EuiModal: FunctionComponent = ( style={newStyle || style} {...rest}> - {(closeModal: any) => ( + {(closeModal: string) => (