Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: enhance maintainability and reusability #100

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions example/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './app';
import './index.css';
Expand All @@ -9,7 +8,6 @@ import.meta.globEager('/node_modules/react-simple-toasts/dist/theme/*.css');

toastConfig({
theme: 'dark',
duration: null,
});

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@
"require": "./dist/index.js"
},
"./style.css": "./dist/style.css",
"./style.css.map": "./dist/style.css.map",
"./dist/style.css": "./dist/style.css",
"./dist/style.css.map": "./dist/style.css.map"
"./*": "./*"
},
"typesVersions": {
"*": {
"./*": [
"./*"
]
}
},
"scripts": {
"test": "jest",
Expand Down Expand Up @@ -82,9 +87,6 @@
"files": [
"dist"
],
"engines": {
"node": ">=16.17.0 <=20.x"
},
"sideEffects": [
"*.css"
],
Expand All @@ -99,4 +101,4 @@
"react-toastify"
],
"packageManager": "[email protected]+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
}
}
61 changes: 61 additions & 0 deletions src/component/toast-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { cloneElement, Fragment } from 'react';
import { reverse } from '../lib/utils';
import { ToastComponent, ToastEnterEvent } from '../type/common';

export interface ToastContainerProps {
toastComponentList: ToastComponent[];
onToastEnter: () => void
}

function ToastContainer(props: ToastContainerProps) {
const { toastComponentList, onToastEnter } = props

const handleToastEnter = (t: ToastComponent, e: ToastEnterEvent) => {
toastComponentList.forEach((toast) => {
if (toast.id !== t.id) return;
toast.startCloseTimer();
toast.height = e.height;
});

onToastEnter();
};

return (
<>
{toastComponentList.map((t) => {
const toastComponents = t.position.includes('top')
? reverse(toastComponentList)
: toastComponentList;

const currentIndex = toastComponents.findIndex((toast) => toast.id === t.id);
const bottomToasts = toastComponents
.slice(currentIndex + 1)
.filter((toast) => toast.position === t.position && !toast.isExit);

const bottomToastsHeight = bottomToasts.reduce((acc, toast) => {
return acc + (toast.height ?? 0) + t.gap;
}, 0);

const deltaOffsetX = t.position.includes('left') || t.position.includes('right') ? '0%' : '-50%';
const offsetYAlpha = t.position.includes('top') ? 1 : -1;
const baseOffsetY = bottomToastsHeight * offsetYAlpha;
const deltaOffsetY =
t.position === 'center' ? `calc(-50% - ${baseOffsetY * -1}px)` : `${baseOffsetY}px`;

return (
<Fragment key={t.id}>
{cloneElement(t.component, {
isExit: t.isExit,
deltaOffsetX,
deltaOffsetY,
_onEnter: (event: ToastEnterEvent) => handleToastEnter(t, event),
})}
</Fragment>
);
})}
</>
);
}


export default ToastContainer
56 changes: 35 additions & 21 deletions src/component/toast-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,30 @@ function Loading({ color, children }: LoadingProps) {
}

export interface ToastMessageProps
extends Required<Pick<
ToastOptions,
'className' | 'clickable' | 'position' | 'render' | 'theme' | 'onClick' | 'loadingText' | 'onClose' | 'onCloseStart'
>> {
extends Required<
Pick<
ToastOptions,
| 'className'
| 'clickable'
| 'position'
| 'render'
| 'theme'
| 'onClick'
| 'clickClosable'
| 'offsetX'
| 'offsetY'
| 'zIndex'
| 'loading'
| 'loadingText'
| 'onClose'
| 'onCloseStart'
>
> {
id: number;
message: ReactNode;
isExit?: boolean;
offsetX?: string;
offsetY?: string;
baseOffsetX?: number;
baseOffsetY?: number;
zIndex?: number;
loading?: boolean | Promise<unknown>;
deltaOffsetX?: string;
deltaOffsetY?: string;
_onEnter?: (e: ToastEnterEvent) => void;
}

Expand All @@ -50,15 +61,16 @@ function ToastMessage({
id,
message,
className,
clickable,
clickable: clickableProp,
clickClosable,
position,
isExit,
render,
theme,
offsetX,
offsetY,
baseOffsetX,
baseOffsetY,
deltaOffsetX,
deltaOffsetY,
zIndex,
loading,
loadingText,
Expand All @@ -67,6 +79,8 @@ function ToastMessage({
onCloseStart,
_onEnter,
}: ToastMessageProps): ReactElement {
const clickable = clickableProp || clickClosable;

const messageDOM = useRef<HTMLDivElement>(null);
const hasTopPosition = position?.includes('top');
const hasBottomPosition = position?.includes('bottom');
Expand All @@ -76,23 +90,23 @@ function ToastMessage({
const isCenterPosition = position === ToastPosition.CENTER;
const [isEnter, setIsEnter] = useState(false);
const [messageStyle, setMessageStyle] = useState<React.CSSProperties>({
transform: `translate(${offsetX}, ${
transform: `translate(${deltaOffsetX}, ${
isCenterPosition
? 'calc(50% - 20px)'
: `${parseInt(offsetY || '0') + 20 * (hasTopPosition ? -1 : 1)}px`
: `${parseInt(deltaOffsetY || '0') + 20 * (hasTopPosition ? -1 : 1)}px`
})`,
});
const [localLoading, setLocalLoading] = useState<boolean>(!!loading);
const [loadingColor, setLoadingColor] = useState<string>();

const top = isCenterPosition ? '50%' : hasTopPosition ? baseOffsetY : undefined;
const bottom = hasBottomPosition ? baseOffsetY : undefined;
const right = hasRightPosition ? baseOffsetX : undefined;
const top = isCenterPosition ? '50%' : hasTopPosition ? offsetY : undefined;
const bottom = hasBottomPosition ? offsetY : undefined;
const right = hasRightPosition ? offsetX : undefined;
const left =
hasCenterPosition || isCenterPosition ? '50%' : hasLeftPosition ? baseOffsetX : undefined;
hasCenterPosition || isCenterPosition ? '50%' : hasLeftPosition ? offsetX : undefined;

useIsomorphicLayoutEffect(() => {
const transform = `translate(${offsetX}, ${offsetY})`;
const transform = `translate(${deltaOffsetX}, ${deltaOffsetY})`;

setMessageStyle({
top,
Expand All @@ -103,7 +117,7 @@ function ToastMessage({
transform,
WebkitTransform: transform,
});
}, [offsetX, offsetY, zIndex, top, right, bottom, left]);
}, [deltaOffsetX, deltaOffsetY, zIndex, top, right, bottom, left]);

useIsomorphicLayoutEffect(() => {
if (messageDOM.current?.clientHeight == null || isEnter) return;
Expand Down
Loading