Skip to content

Commit

Permalink
Merge pull request #10 from BQXBQX/dev-bqx
Browse files Browse the repository at this point in the history
Dev bqx
  • Loading branch information
BQXBQX authored Feb 3, 2024
2 parents c63ab90 + 09270bf commit e354706
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 71 deletions.
11 changes: 11 additions & 0 deletions packages/competition/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,14 @@
top: -10px;
font-size: 16px;
}

.item {
height: 400px;
width: 400px;
background-color: aqua;
}
.container {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
12 changes: 3 additions & 9 deletions packages/competition/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import { Button, CarouselItem, showToast } from "@sast/oj-ui";
import { Sheet, Carousel } from "@sast/oj-ui";
import { useState } from "react";
import { Button, showToast } from "../../ui/dist";
import "./App.css";

function App() {
const [visible, setVisible] = useState<boolean>(false);

const hello = () => {
showToast({ content: <>hello</> });
};
return (
<>
<Button onClick={hello}>showToast</Button>
<Button onClick={() => showToast()}>showToast</Button>
</>
);
}
Expand Down
1 change: 1 addition & 0 deletions packages/competition/src/pages/page1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// consyt
2 changes: 1 addition & 1 deletion packages/ui/lib/Button/Button.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ export const ShowToastButton: Story = {
args: {
...defaultProps,
children: 'Click Me!',
onClick: showToast,
onClick: () => showToast({ type: 'error' }),
},
};
75 changes: 47 additions & 28 deletions packages/ui/lib/Toast/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from 'classnames';
import React, { useState, type ReactNode } from 'react';
import React, { useState, type ReactNode, useEffect } from 'react';
import styles from './Toast.module.scss';

export interface ToastProps {
Expand All @@ -19,6 +19,10 @@ export interface ToastProps {
* The footer of the Toast.
*/
footer?: React.ReactNode;
/**
* onChange of the toast
*/
close?: () => void;
}

export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
Expand All @@ -32,11 +36,15 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
</span>
),
footer = null,
close,
...rest
},
ref,
) => {
const [visible, setVisble] = useState(true);
const [innerVisible, setInnerVisible] = useState(true);

// console.log(close);

const toastClass = classNames(
styles['base'],
Expand All @@ -45,40 +53,51 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
styles[visible ? 'visible' : ''],
);

useEffect(() => {
if (!visible) {
setTimeout(() => {
setInnerVisible(false);
close();
}, 300);
}
}, [visible, close]);

return (
<>
<div style={{ padding: '10px' }}>
<div
ref={ref}
className={toastClass}
{...rest}
>
<div className={`${styles['sider']} ${styles[`${type}Sider`]}`}></div>
<div>
<div className={styles['header']}>
{/* 将type一键大写,作为标题呈现 */}
<div>{type.toUpperCase()}</div>
<div
className={styles['closeButton']}
onClick={() => setVisble(false)}
>
<svg
className={styles['icon']}
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
{innerVisible && (
<div style={{ padding: '10px' }}>
<div
ref={ref}
className={toastClass}
{...rest}
>
<div className={`${styles['sider']} ${styles[`${type}Sider`]}`}></div>
<div>
<div className={styles['header']}>
{/* 将type一键大写,作为标题呈现 */}
<div>{type.toUpperCase()}</div>
<div
className={styles['closeButton']}
onClick={() => setVisble(false)}
>
<path d="M512 128C300.8 128 128 300.8 128 512s172.8 384 384 384 384-172.8 384-384S723.2 128 512 128zM672 627.2c12.8 12.8 12.8 32 0 44.8s-32 12.8-44.8 0L512 556.8l-115.2 115.2c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8L467.2 512 352 396.8C339.2 384 339.2 364.8 352 352s32-12.8 44.8 0L512 467.2l115.2-115.2c12.8-12.8 32-12.8 44.8 0s12.8 32 0 44.8L556.8 512 672 627.2z"></path>
</svg>
<svg
className={styles['icon']}
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
>
<path d="M512 128C300.8 128 128 300.8 128 512s172.8 384 384 384 384-172.8 384-384S723.2 128 512 128zM672 627.2c12.8 12.8 12.8 32 0 44.8s-32 12.8-44.8 0L512 556.8l-115.2 115.2c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8L467.2 512 352 396.8C339.2 384 339.2 364.8 352 352s32-12.8 44.8 0L512 467.2l115.2-115.2c12.8-12.8 32-12.8 44.8 0s12.8 32 0 44.8L556.8 512 672 627.2z"></path>
</svg>
</div>
</div>
<div className={styles['content']}>{content}</div>
{footer && <div className={styles['footer']}>{footer}</div>}
</div>
<div className={styles['content']}>{content}</div>
{footer && <div className={styles['footer']}>{footer}</div>}
</div>
</div>
</div>
)}
</>
);
},
Expand Down
119 changes: 86 additions & 33 deletions packages/ui/lib/Toast/showToast.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { createRoot } from 'react-dom/client';
import { Toast } from '.';
import { Toast, type ToastProps } from '.';

import classNames from 'classnames';
import styles from './Toast.module.scss';

let toasts: HTMLDivElement[] = [];
let toastContainer: HTMLDivElement | null = null;

export const showToast = (): void => {
const state = { slideToasts: null };

export const showToast = (props?: ToastProps) => {
if (!toastContainer) {
toastContainer = document.createElement('div');
document.body.appendChild(toastContainer);
Expand All @@ -20,60 +23,110 @@ export const showToast = (): void => {
const ToastClass: string = classNames(styles['toastShow']);
div.className = ToastClass;

console.log('length', toasts.length, 'container', toasts);

const root = createRoot(div);

root.render(<Toast></Toast>);
const close = () => {
div.remove();
toasts = toasts.filter((toast) => toast !== div);
state.slideToasts = toasts; // 更新 slideToasts 的值
expandSlide(state.slideToasts, div);
};

root.render(
<Toast
{...props}
close={close}
></Toast>,
);

toasts.push(div);
state.slideToasts = toasts; // 更新 slideToasts 的值

// Update the position of existing toasts
toasts.forEach((toast: HTMLDivElement, index: number) => {
toast.style.transform = `translateY(-${(toasts.length - index - 1) * 15}px) scale(${
0.95 ** (toasts.length - index - 1)
})`;
slide(state.slideToasts, div);

div.addEventListener('mouseenter', () => {
// div.classList.add(dataExpandClass);
console.log('show');
expand(toasts);
});
div.addEventListener('mouseleave', () => {
// div.classList.add(dataExpandClass);
console.log('hide');
hide(toasts);
});
});
if (toasts.length > 3) {
toasts.shift();
const firstChild = toastContainer.childNodes[0];
setTimeout(() => {
while (toastContainer.childNodes.length > 3) {
toastContainer.removeChild(toastContainer.firstChild!);
}
}, 300);
}

setTimeout(() => {
const ToastContainerClass: string = classNames(styles['toastHide']);
div.className = ToastContainerClass;
const ToasthideClass: string = classNames(styles['toastHide']);
div.className = ToasthideClass;

setTimeout(() => {
// Only remove the toast if the mouse is not over it
toastContainer?.removeChild(div);
toasts = toasts.filter((toast) => toast !== div);
state.slideToasts = toasts;
}, 280);
}, 4000);
};

const expand = (toasts: any) => {
toasts.forEach((toast: HTMLDivElement, index: number) => {
// Calculate the total height of all previous toasts
const totalHeight = toasts
.slice(0, toasts.length - index - 1)
.reduce((height, toast) => height + toast.offsetHeight, 0);
console.log('totalHeight', totalHeight);
// Move the toast up by the total height of all previous toasts
const expand = (expandToasts: any) => {
expandToasts.forEach((toast: HTMLDivElement, index: number) => {
const totalHeight = expandToasts
.slice(0, expandToasts.length - index - 1)
.reduce((height: any, toast: any) => height + toast.offsetHeight, 0);
toast.style.transform = `translateY(-${totalHeight}px)`;
});
};

const hide = (toasts: any) => {
toasts.forEach((toast: HTMLDivElement, index: number) => {
const hide = (hideToasts: any) => {
hideToasts.forEach((toast: HTMLDivElement, index: number) => {
toast.style.transform = `translateY(-${(hideToasts.length - index - 1) * 15}px) scale(${
0.95 ** (hideToasts.length - index - 1)
})`;
});
};

const slide = (slideToasts: any, div: any) => {
state.slideToasts = slideToasts;

const handleMouseEnter = () => {
expand(state.slideToasts);
};

const handleMouseLeave = () => {
hide(state.slideToasts);
};

state.slideToasts.forEach((toast: HTMLDivElement, index: number) => {
toast.style.transform = `translateY(-${(toasts.length - index - 1) * 15}px) scale(${
0.95 ** (toasts.length - index - 1)
})`;

if (state.slideToasts.length - index === 4) {
toast.style.opacity = '0';
}

div.addEventListener('mouseenter', handleMouseEnter);
div.addEventListener('mouseleave', handleMouseLeave);
});
};

const expandSlide = (slideToasts: any, div: any) => {
state.slideToasts = slideToasts;

const handleMouseEnter = () => {
expand(state.slideToasts);
};

const handleMouseLeave = () => {
hide(state.slideToasts);
};

state.slideToasts.forEach((toast: HTMLDivElement, index: number) => {
const totalHeight = state.slideToasts
.slice(0, state.slideToasts.length - index - 1)
.reduce((height: any, toast: any) => height + toast.offsetHeight, 0);
toast.style.transform = `translateY(-${totalHeight}px)`;

div.addEventListener('mouseenter', handleMouseEnter);
div.addEventListener('mouseleave', handleMouseLeave);
});
};

0 comments on commit e354706

Please sign in to comment.