Move notification to function component

This commit is contained in:
Labhansh Agrawal 2023-07-24 23:27:44 +05:30
parent f38b357887
commit 57c781b951
2 changed files with 85 additions and 98 deletions

View file

@ -1,118 +1,109 @@
import React from 'react';
import type {NotificationProps, NotificationState} from '../hyper';
import React, {forwardRef, useEffect, useRef, useState} from 'react';
import type {NotificationProps} from '../hyper';
export default class Notification extends React.PureComponent<
React.PropsWithChildren<NotificationProps>,
NotificationState
> {
dismissTimer!: NodeJS.Timeout;
constructor(props: NotificationProps) {
super(props);
this.state = {
dismissing: false
};
}
const Notification = forwardRef<HTMLDivElement, React.PropsWithChildren<NotificationProps>>((props, ref) => {
const dismissTimer = useRef<NodeJS.Timeout | undefined>(undefined);
const [dismissing, setDismissing] = useState(false);
componentDidMount() {
if (this.props.dismissAfter) {
this.setDismissTimer();
}
}
useEffect(() => {
setDismissTimer();
}, []);
componentDidUpdate(prevProps: NotificationProps, prevState: NotificationState) {
useEffect(() => {
// if we have a timer going and the notification text
// changed we reset the timer
if (this.props.text !== prevProps.text) {
if (prevProps.dismissAfter) {
this.resetDismissTimer();
}
if (prevState.dismissing) {
this.setState({dismissing: false});
}
}
}
resetDismissTimer();
setDismissing(false);
}, [props.text]);
handleDismiss = () => {
this.setState({dismissing: true});
const handleDismiss = () => {
setDismissing(true);
};
onElement = (el: HTMLDivElement | null) => {
const onElement = (el: HTMLDivElement | null) => {
if (el) {
el.addEventListener('webkitTransitionEnd', () => {
if (this.state.dismissing) {
this.props.onDismiss();
if (dismissing) {
props.onDismiss();
}
});
const {backgroundColor} = this.props;
const {backgroundColor} = props;
if (backgroundColor) {
el.style.setProperty('background-color', backgroundColor, 'important');
}
if (ref) {
if (typeof ref === 'function') ref(el);
else ref.current = el;
}
}
};
setDismissTimer() {
this.dismissTimer = setTimeout(() => {
this.handleDismiss();
}, this.props.dismissAfter);
}
const setDismissTimer = () => {
if (typeof props.dismissAfter === 'number') {
dismissTimer.current = setTimeout(() => {
handleDismiss();
}, props.dismissAfter);
}
};
resetDismissTimer() {
clearTimeout(this.dismissTimer);
this.setDismissTimer();
}
const resetDismissTimer = () => {
clearTimeout(dismissTimer.current);
setDismissTimer();
};
componentWillUnmount() {
clearTimeout(this.dismissTimer);
}
useEffect(() => {
return () => {
clearTimeout(dismissTimer.current);
};
}, []);
render() {
const {backgroundColor, color} = this.props;
const opacity = this.state.dismissing ? 0 : 1;
return (
<div ref={this.onElement} style={{opacity, backgroundColor, color}} className="notification_indicator">
{this.props.customChildrenBefore}
{this.props.children || this.props.text}
{this.props.userDismissable ? (
<a
className="notification_dismissLink"
onClick={this.handleDismiss}
style={{color: this.props.userDismissColor}}
>
[x]
</a>
) : null}
{this.props.customChildren}
const {backgroundColor, color} = props;
const opacity = dismissing ? 0 : 1;
return (
<div ref={onElement} style={{opacity, backgroundColor, color}} className="notification_indicator">
{props.customChildrenBefore}
{props.children || props.text}
{props.userDismissable ? (
<a className="notification_dismissLink" onClick={handleDismiss} style={{color: props.userDismissColor}}>
[x]
</a>
) : null}
{props.customChildren}
<style jsx>{`
.notification_indicator {
display: inline-block;
cursor: default;
-webkit-user-select: none;
background: rgba(255, 255, 255, 0.2);
padding: 8px 14px 9px;
margin-left: 10px;
transition: 150ms opacity ease;
color: #fff;
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}
<style jsx>{`
.notification_indicator {
display: inline-block;
cursor: default;
-webkit-user-select: none;
background: rgba(255, 255, 255, 0.2);
padding: 8px 14px 9px;
margin-left: 10px;
transition: 150ms opacity ease;
color: #fff;
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}
.notification_dismissLink {
position: relative;
left: 4px;
cursor: pointer;
font-weight: 600;
color: currentColor;
transition: font-weight 0.1s ease-in-out;
}
.notification_dismissLink {
position: relative;
left: 4px;
cursor: pointer;
font-weight: 600;
color: currentColor;
transition: font-weight 0.1s ease-in-out;
}
.notification_dismissLink:hover,
.notification_dismissLink:focus {
font-weight: 900;
}
`}</style>
</div>
);
}
}
.notification_dismissLink:hover,
.notification_dismissLink:focus {
font-weight: 900;
}
`}</style>
</div>
);
});
Notification.displayName = 'Notification';
export default Notification;

4
lib/hyper.d.ts vendored
View file

@ -259,10 +259,6 @@ export type NotificationProps = {
userDismissColor?: string;
} & extensionProps;
export type NotificationState = {
dismissing: boolean;
};
export type SplitPaneProps = {
borderColor: string;
direction: 'horizontal' | 'vertical';