expo-popcore-old/utils/alert.tsx

186 lines
4.9 KiB
TypeScript

interface AlertButton {
text: string;
onPress?: () => void;
style?: 'default' | 'cancel' | 'destructive';
}
class PlatformAlert {
alert(title: string, message?: string, buttons?: AlertButton[]) {
const overlay = this.createOverlay();
const modal = this.createModal(title, message, buttons, overlay);
document.body.appendChild(overlay);
overlay.appendChild(modal);
requestAnimationFrame(() => {
overlay.style.opacity = '1';
modal.style.transform = 'translateY(0)';
});
}
private createOverlay(): HTMLDivElement {
const overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'fixed',
top: '0',
left: '0',
right: '0',
bottom: '0',
backgroundColor: 'rgba(5, 5, 5, 0.68)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: '9999',
opacity: '0',
transition: 'opacity 200ms ease-out',
});
return overlay;
}
private createModal(
title: string,
message?: string,
buttons?: AlertButton[],
overlay?: HTMLDivElement
): HTMLDivElement {
const modal = document.createElement('div');
Object.assign(modal.style, {
backgroundColor: '#121216',
borderRadius: '24px',
padding: '28px',
maxWidth: '360px',
width: 'calc(100% - 56px)',
border: '1px solid #1D1E24',
transform: 'translateY(20px)',
transition: 'transform 200ms ease-out',
});
const titleEl = document.createElement('div');
Object.assign(titleEl.style, {
fontSize: '18px',
fontWeight: '700',
color: '#F6F7FA',
marginBottom: message ? '12px' : '24px',
textAlign: 'center',
});
titleEl.textContent = title;
modal.appendChild(titleEl);
if (message) {
const messageEl = document.createElement('div');
Object.assign(messageEl.style, {
fontSize: '15px',
lineHeight: '1.5',
color: 'rgba(255, 255, 255, 0.75)',
marginBottom: '24px',
textAlign: 'center',
});
messageEl.textContent = message;
modal.appendChild(messageEl);
}
const buttonContainer = document.createElement('div');
Object.assign(buttonContainer.style, {
display: 'flex',
gap: '12px',
flexDirection: buttons && buttons.length > 2 ? 'column' : 'row',
});
const buttonList = buttons && buttons.length > 0 ? buttons : [{ text: '确定', style: 'default' as const }];
buttonList.forEach((btn) => {
const button = document.createElement('button');
const isDestructive = btn.style === 'destructive';
const isCancel = btn.style === 'cancel';
Object.assign(button.style, {
flex: '1',
padding: '14px 20px',
borderRadius: '999px',
border: isCancel ? '1px solid #1D1E24' : 'none',
backgroundColor: isDestructive ? '#FF4444' : isCancel ? '#101014' : '#D1FE17',
color: isDestructive ? '#FFFFFF' : isCancel ? '#8E9098' : '#050505',
fontSize: '16px',
fontWeight: '700',
cursor: 'pointer',
transition: 'all 150ms ease-out',
});
button.textContent = btn.text;
button.onmouseover = () => {
button.style.opacity = '0.85';
button.style.transform = 'translateY(-1px)';
};
button.onmouseout = () => {
button.style.opacity = '1';
button.style.transform = 'translateY(0)';
};
button.onclick = () => {
this.closeModal(overlay!);
btn.onPress?.();
};
buttonContainer.appendChild(button);
});
modal.appendChild(buttonContainer);
return modal;
}
private closeModal(overlay: HTMLDivElement) {
overlay.style.opacity = '0';
const modal = overlay.querySelector('div') as HTMLDivElement;
if (modal) {
modal.style.transform = 'translateY(20px)';
}
setTimeout(() => {
overlay.remove();
}, 200);
}
toast(message: string, duration: number = 2000) {
const toast = document.createElement('div');
Object.assign(toast.style, {
position: 'fixed',
bottom: '80px',
left: '50%',
transform: 'translateX(-50%) translateY(20px)',
backgroundColor: '#18181D',
color: '#F6F7FA',
padding: '14px 24px',
borderRadius: '999px',
fontSize: '15px',
fontWeight: '600',
border: '1px solid #1D1E24',
zIndex: '10000',
opacity: '0',
transition: 'all 200ms ease-out',
maxWidth: 'calc(100% - 56px)',
textAlign: 'center',
});
toast.textContent = message;
document.body.appendChild(toast);
requestAnimationFrame(() => {
toast.style.opacity = '1';
toast.style.transform = 'translateX(-50%) translateY(0)';
});
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transform = 'translateX(-50%) translateY(20px)';
setTimeout(() => {
toast.remove();
}, 200);
}, duration);
}
}
export const Alert = new PlatformAlert();