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

4
lib/hyper.d.ts vendored
View file

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