From 512c6e154bb513d1c3cc34280457d22d5829ae96 Mon Sep 17 00:00:00 2001 From: marlon passos Date: Sun, 24 Sep 2023 10:34:46 -0300 Subject: [PATCH 1/2] refactor(Alert): create typscript version of component and now use react hook --- react/{Alert.js => Alert.ts} | 0 react/components/Alert/index.js | 147 ----------------------------- react/components/Alert/index.tsx | 155 +++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 147 deletions(-) rename react/{Alert.js => Alert.ts} (100%) delete mode 100755 react/components/Alert/index.js create mode 100755 react/components/Alert/index.tsx diff --git a/react/Alert.js b/react/Alert.ts similarity index 100% rename from react/Alert.js rename to react/Alert.ts diff --git a/react/components/Alert/index.js b/react/components/Alert/index.js deleted file mode 100755 index f5fff2938..000000000 --- a/react/components/Alert/index.js +++ /dev/null @@ -1,147 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' - -import SuccessIcon from '../icon/Success' -import FailureIcon from '../icon/Failure' -import WarningIcon from '../icon/Warning' -import CloseIcon from '../icon/Close' -import Button from '../Button' -import { withForwardedRef, refShape } from '../../modules/withForwardedRef' - -class Alert extends Component { - constructor(props) { - super(props) - this.firstElementRef = React.createRef() - } - - componentDidMount() { - if (this.props.autoClose && this.props.onClose) { - this.timeout = setTimeout(this.props.onClose, this.props.autoClose) - } - - if (this.props.focusOnOpen) { - this.firstElementRef.current && this.firstElementRef.current.focus() - } - } - - componentWillUnmount() { - clearTimeout(this.timeout) - } - - render() { - const { - type, - onClose, - action, - forwardedRef, - closeIconLabel = 'Close', - } = this.props - const innerVerticalPadding = 'pv3' - let classes = 'ph5 pv4 br2 ' - let showIcon = false - let Icon = 'div' - let color = 'c-on-base' - const handleActionClick = (action && action.onClick) || undefined - const displayAction = action && action.onClick && action.label - - switch (type) { - case 'success': { - showIcon = true - classes += 'bg-success--faded ' - Icon = SuccessIcon - color = 'c-success' - break - } - case 'error': { - showIcon = true - classes += 'bg-danger--faded ' - Icon = FailureIcon - color = 'c-danger' - break - } - default: - case 'warning': { - showIcon = true - classes += 'bg-warning--faded ' - Icon = WarningIcon - color = 'c-warning' - break - } - } - - return ( -
-
-
- {showIcon && ( -
- -
- )} - -
- {this.props.children} -
-
- - {displayAction && ( -
-
- -
-
- )} -
- - {onClose && ( - - )} -
- ) - } -} - -Alert.propTypes = { - /** @ignore Forwarded Ref */ - forwardedRef: refShape, - /** Style of the alert */ - type: PropTypes.oneOf(['success', 'error', 'warning']).isRequired, - /** Content of the alert */ - children: PropTypes.node.isRequired, - /** If this function is defined, a close icon will appear and this function will be called when alert is closed. */ - onClose: PropTypes.func, - /** Time in ms to auto close the alert */ - autoClose: PropTypes.number, - /** Set focus to the first focusable element inside alert, which should be the "action" when available or the "close" button */ - focusOnOpen: PropTypes.bool, - /** If this object is defined, an action button will appear on the right side of the alert. */ - action: PropTypes.shape({ - onClick: PropTypes.func.isRequired, - label: PropTypes.node.isRequired, - }), - /** Defines the title used for hover and accessibility feedback **/ - closeIconLabel: PropTypes.string, -} - -export default withForwardedRef(Alert) diff --git a/react/components/Alert/index.tsx b/react/components/Alert/index.tsx new file mode 100755 index 000000000..50771613e --- /dev/null +++ b/react/components/Alert/index.tsx @@ -0,0 +1,155 @@ +import React, { useEffect, useRef } from 'react' +import PropTypes from 'prop-types' + +import SuccessIcon from '../icon/Success' +import FailureIcon from '../icon/Failure' +import WarningIcon from '../icon/Warning' +import CloseIcon from '../icon/Close' +import Button from '../Button' +import { withForwardedRef, refShape } from '../../modules/withForwardedRef' + +type AlertType = 'success' | 'error' | 'warning' + +interface AlertProps { + type: AlertType + onClose?: () => void + action?: { + onClick: () => void + label: React.ReactNode + } + forwardedRef: refShape + closeIconLabel?: string + autoClose?: number + focusOnOpen?: boolean + children: React.ReactNode +} + +const Alert: React.FC = ({ + type, + onClose, + action, + forwardedRef, + closeIconLabel = 'Close', + autoClose, + focusOnOpen, + children, +}) => { + const firstElementRef = useRef(null) + + useEffect(() => { + let timeout: NodeJS.Timeout | undefined + + if (autoClose && onClose) { + timeout = setTimeout(onClose, autoClose) + } + + if (focusOnOpen) { + firstElementRef.current && firstElementRef.current.focus() + } + + return () => { + if (timeout) { + clearTimeout(timeout) + } + } + }, [autoClose, focusOnOpen, onClose]) + + const innerVerticalPadding = 'pv3' + let classes = 'ph5 pv4 br2 ' + let showIcon = false + let Icon: React.ElementType = 'div' + let color = 'c-on-base' + const handleActionClick = (action && action.onClick) || undefined + const displayAction = action && action.onClick && action.label + + switch (type) { + case 'success': { + showIcon = true + classes += 'bg-success--faded ' + Icon = SuccessIcon + color = 'c-success' + break + } + case 'error': { + showIcon = true + classes += 'bg-danger--faded ' + Icon = FailureIcon + color = 'c-danger' + break + } + default: + case 'warning': { + showIcon = true + classes += 'bg-warning--faded ' + Icon = WarningIcon + color = 'c-warning' + break + } + } + + return ( +
+
+
+ {showIcon && ( +
+ +
+ )} + +
{children}
+
+ + {displayAction && ( +
+
+ +
+
+ )} +
+ + {onClose && ( + + )} +
+ ) +} + +Alert.propTypes = { + forwardedRef: PropTypes.shape({ current: PropTypes.any }), + type: PropTypes.oneOf(['success', 'error', 'warning']).isRequired, + children: PropTypes.node.isRequired, + onClose: PropTypes.func, + autoClose: PropTypes.number, + focusOnOpen: PropTypes.bool, + // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // @ts-ignore + action: PropTypes.shape({ + onClick: PropTypes.func.isRequired, + label: PropTypes.node.isRequired, + }), + closeIconLabel: PropTypes.string, +} + +export default withForwardedRef(Alert) From 097544f5f992c2fe209a93392d09fc5471ea820f Mon Sep 17 00:00:00 2001 From: marlon passos Date: Sun, 24 Sep 2023 11:00:25 -0300 Subject: [PATCH 2/2] fix(Alert): errors to generete types --- react/components/Alert/index.tsx | 54 +++++++++++++++----------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/react/components/Alert/index.tsx b/react/components/Alert/index.tsx index 50771613e..c27e236b5 100755 --- a/react/components/Alert/index.tsx +++ b/react/components/Alert/index.tsx @@ -10,21 +10,31 @@ import { withForwardedRef, refShape } from '../../modules/withForwardedRef' type AlertType = 'success' | 'error' | 'warning' -interface AlertProps { - type: AlertType - onClose?: () => void - action?: { - onClick: () => void - label: React.ReactNode - } - forwardedRef: refShape - closeIconLabel?: string - autoClose?: number - focusOnOpen?: boolean - children: React.ReactNode +const propTypes = { + /** @ignore Forwarded Ref */ + forwardedRef: refShape, + /** Style of the alert */ + type: PropTypes.oneOf(['success', 'error', 'warning']).isRequired, + /** Content of the alert */ + children: PropTypes.node.isRequired, + /** If this function is defined, a close icon will appear and this function will be called when alert is closed. */ + onClose: PropTypes.func, + /** Time in ms to auto close the alert */ + autoClose: PropTypes.number, + /** Set focus to the first focusable element inside alert, which should be the "action" when available or the "close" button */ + focusOnOpen: PropTypes.bool, + /** If this object is defined, an action button will appear on the right side of the alert. */ + action: PropTypes.shape({ + onClick: PropTypes.func.isRequired, + label: PropTypes.node.isRequired, + }), + /** Defines the title used for hover and accessibility feedback **/ + closeIconLabel: PropTypes.string, } -const Alert: React.FC = ({ +export type AlertProps = PropTypes.InferProps + +const Alert: React.FunctionComponent = ({ type, onClose, action, @@ -136,20 +146,6 @@ const Alert: React.FC = ({ ) } -Alert.propTypes = { - forwardedRef: PropTypes.shape({ current: PropTypes.any }), - type: PropTypes.oneOf(['success', 'error', 'warning']).isRequired, - children: PropTypes.node.isRequired, - onClose: PropTypes.func, - autoClose: PropTypes.number, - focusOnOpen: PropTypes.bool, - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore - action: PropTypes.shape({ - onClick: PropTypes.func.isRequired, - label: PropTypes.node.isRequired, - }), - closeIconLabel: PropTypes.string, -} +Alert.propTypes = propTypes -export default withForwardedRef(Alert) +export default withForwardedRef(Alert) as React.FunctionComponent