1845 lines
42 KiB
JavaScript
1845 lines
42 KiB
JavaScript
/**
|
|
* MetonaToast Styles - 样式管理
|
|
* @module styles
|
|
* @version 2.0.0
|
|
* @description 样式注入、更新和主题管理
|
|
*/
|
|
|
|
import { THEMES } from './constants.js';
|
|
|
|
// 样式缓存
|
|
let injectedStyles = null;
|
|
let styleElement = null;
|
|
|
|
/**
|
|
* 生成CSS样式
|
|
* @param {Object} theme - 主题配置
|
|
* @returns {string} CSS字符串
|
|
*/
|
|
const generateCSS = (theme) => {
|
|
return `
|
|
/* MetonaToast 基础样式 */
|
|
.met-container {
|
|
pointer-events: none;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
box-sizing: border-box;
|
|
padding: 24px;
|
|
max-width: 100vw;
|
|
position: fixed;
|
|
z-index: 9999;
|
|
}
|
|
|
|
/* 位置样式 — 顶部位置用 column-reverse,新 toast 出现在最上方 */
|
|
.met-container.top-left {
|
|
top: 0;
|
|
left: 0;
|
|
align-items: flex-start;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.met-container.top-center {
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
align-items: center;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.met-container.top-right {
|
|
top: 0;
|
|
right: 0;
|
|
align-items: flex-end;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.met-container.bottom-left {
|
|
bottom: 0;
|
|
left: 0;
|
|
align-items: flex-start;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.met-container.bottom-center {
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
align-items: center;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.met-container.bottom-right {
|
|
bottom: 0;
|
|
right: 0;
|
|
align-items: flex-end;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
/* Toast基础样式 */
|
|
.met-toast {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 12px;
|
|
padding: 14px 16px;
|
|
border-radius: 12px;
|
|
box-sizing: border-box;
|
|
backdrop-filter: blur(14px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(14px) saturate(180%);
|
|
font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
|
|
box-shadow 0.25s ease,
|
|
opacity 0.25s ease;
|
|
will-change: transform, opacity;
|
|
flex-shrink: 0;
|
|
pointer-events: auto;
|
|
min-width: 240px;
|
|
max-width: calc(100vw - 48px);
|
|
width: 360px;
|
|
border: 1px solid var(--met-border, rgba(0,0,0,0.06));
|
|
background: var(--met-bg, rgba(255,255,255,0.96));
|
|
color: var(--met-text, #1f2937);
|
|
box-shadow: var(--met-shadow, 0 10px 36px -10px rgba(0,0,0,0.18), 0 4px 14px -4px rgba(0,0,0,0.08));
|
|
}
|
|
|
|
/* 悬停效果 */
|
|
.met-toast:hover {
|
|
box-shadow: var(--met-hover-shadow, 0 14px 48px -10px rgba(0,0,0,0.22), 0 6px 18px -4px rgba(0,0,0,0.10)) !important;
|
|
}
|
|
|
|
/* 可点击状态 */
|
|
.met-toast.met-clickable {
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* 图标样式 */
|
|
.met-icon {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
margin-top: 1px;
|
|
}
|
|
|
|
/* 内容样式 */
|
|
.met-content {
|
|
flex: 1;
|
|
min-width: 0;
|
|
word-wrap: break-word;
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
/* 标题样式 */
|
|
.met-title {
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
letter-spacing: 0.1px;
|
|
}
|
|
|
|
/* 消息样式 */
|
|
.met-message {
|
|
font-size: 13px;
|
|
opacity: 0.85;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* 关闭按钮样式 */
|
|
.met-close {
|
|
flex-shrink: 0;
|
|
background: transparent;
|
|
border: 0;
|
|
padding: 4px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 6px;
|
|
transition: background 0.2s, color 0.2s;
|
|
line-height: 0;
|
|
color: inherit;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.met-close:hover {
|
|
opacity: 1;
|
|
background: var(--met-close-hover-bg, rgba(0,0,0,0.06));
|
|
}
|
|
|
|
/* 进度条样式 - 水平 */
|
|
.met-progress {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
height: 3px;
|
|
overflow: hidden;
|
|
background: var(--met-progress-bg, rgba(0,0,0,0.06));
|
|
border-radius: 0 0 12px 12px;
|
|
}
|
|
|
|
/* 进度条样式 - 垂直 */
|
|
.met-progress-v {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 3px;
|
|
overflow: hidden;
|
|
background: var(--met-progress-bg, rgba(0,0,0,0.06));
|
|
border-radius: 12px 0 0 12px;
|
|
}
|
|
|
|
/* 进度条指示器 - 水平 */
|
|
.met-bar {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
height: 100%;
|
|
width: 100%;
|
|
transform-origin: left;
|
|
transform: scaleX(1);
|
|
}
|
|
|
|
/* 进度条指示器 - 垂直 */
|
|
.met-bar-v {
|
|
position: absolute;
|
|
left: 0;
|
|
bottom: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
transform-origin: bottom;
|
|
transform: scaleY(1);
|
|
}
|
|
|
|
/* 侧边指示器 */
|
|
.met-side {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 4px;
|
|
border-radius: 12px 0 0 12px;
|
|
}
|
|
|
|
/* 加载动画 */
|
|
.met-spin {
|
|
animation: met-rot 1s linear infinite;
|
|
transform-origin: 50% 50%;
|
|
}
|
|
|
|
/* 离开状态 */
|
|
.met-toast.met-leaving {
|
|
pointer-events: none;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* 动画关键帧 */
|
|
@keyframes met-rot {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* === 进入动画:初始隐藏态 === */
|
|
.met-anim-slide.met-toast,
|
|
.met-anim-fade.met-toast,
|
|
.met-anim-scale.met-toast,
|
|
.met-anim-bounce.met-toast,
|
|
.met-anim-flip.met-toast,
|
|
.met-anim-rotate.met-toast,
|
|
.met-anim-zoom.met-toast,
|
|
.met-anim-slideUp.met-toast,
|
|
.met-anim-slideDown.met-toast,
|
|
.met-anim-slideLeft.met-toast,
|
|
.met-anim-slideRight.met-toast {
|
|
opacity: 0;
|
|
}
|
|
|
|
/* === 进入动画:@keyframes 定义 === */
|
|
@keyframes met-slide-in {
|
|
0% { transform: translateX(80px); opacity: 0; }
|
|
65% { transform: translateX(-6px); opacity: 1; }
|
|
100% { transform: translateX(0); opacity: 1; }
|
|
}
|
|
@keyframes met-fade-in {
|
|
0% { opacity: 0; filter: blur(3px); }
|
|
100% { opacity: 1; filter: blur(0); }
|
|
}
|
|
@keyframes met-scale-in {
|
|
0% { transform: scale(0.55); opacity: 0; }
|
|
65% { transform: scale(1.07); opacity: 1; }
|
|
100% { transform: scale(1); opacity: 1; }
|
|
}
|
|
@keyframes met-bounce-in {
|
|
0% { transform: translateY(-80px); opacity: 0; animation-timing-function: ease-in; }
|
|
45% { transform: translateY(14px); opacity: 1; animation-timing-function: ease-out; }
|
|
65% { transform: translateY(-12px); animation-timing-function: ease-in; }
|
|
82% { transform: translateY(4px); animation-timing-function: ease-out; }
|
|
100% { transform: translateY(0); opacity: 1; }
|
|
}
|
|
@keyframes met-flip-in {
|
|
0% { transform: perspective(500px) rotateX(-90deg); opacity: 0; }
|
|
60% { transform: perspective(500px) rotateX(8deg); opacity: 1; }
|
|
85% { transform: perspective(500px) rotateX(-2deg); }
|
|
100% { transform: perspective(500px) rotateX(0); opacity: 1; }
|
|
}
|
|
@keyframes met-rotate-in {
|
|
0% { transform: rotate(-25deg) scale(0.6); opacity: 0; }
|
|
60% { transform: rotate(4deg) scale(1.05); opacity: 1; }
|
|
85% { transform: rotate(-1deg) scale(0.98); }
|
|
100% { transform: rotate(0) scale(1); opacity: 1; }
|
|
}
|
|
@keyframes met-zoom-in {
|
|
0% { transform: scale(0.1); opacity: 0; }
|
|
50% { transform: scale(1.12); opacity: 1; }
|
|
75% { transform: scale(0.94); }
|
|
100% { transform: scale(1); opacity: 1; }
|
|
}
|
|
@keyframes met-slideUp-in {
|
|
0% { transform: translateY(60px); opacity: 0; }
|
|
70% { transform: translateY(-6px); opacity: 1; }
|
|
100% { transform: translateY(0); opacity: 1; }
|
|
}
|
|
@keyframes met-slideDown-in {
|
|
0% { transform: translateY(-60px); opacity: 0; }
|
|
70% { transform: translateY(6px); opacity: 1; }
|
|
100% { transform: translateY(0); opacity: 1; }
|
|
}
|
|
@keyframes met-slideLeft-in {
|
|
0% { transform: translateX(-90px); opacity: 0; }
|
|
65% { transform: translateX(6px); opacity: 1; }
|
|
100% { transform: translateX(0); opacity: 1; }
|
|
}
|
|
@keyframes met-slideRight-in {
|
|
0% { transform: translateX(90px); opacity: 0; }
|
|
65% { transform: translateX(-6px); opacity: 1; }
|
|
100% { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
/* === 进入动画:绑定到 .met-show === */
|
|
.met-anim-slide.met-toast.met-show { animation: met-slide-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-fade.met-toast.met-show { animation: met-fade-in 0.50s ease forwards; }
|
|
.met-anim-scale.met-toast.met-show { animation: met-scale-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
|
|
.met-anim-bounce.met-toast.met-show { animation: met-bounce-in 0.65s ease forwards; }
|
|
.met-anim-flip.met-toast.met-show { animation: met-flip-in 0.50s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-rotate.met-toast.met-show { animation: met-rotate-in 0.50s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-zoom.met-toast.met-show { animation: met-zoom-in 0.50s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
|
|
.met-anim-slideUp.met-toast.met-show { animation: met-slideUp-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-slideDown.met-toast.met-show { animation: met-slideDown-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-slideLeft.met-toast.met-show { animation: met-slideLeft-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
.met-anim-slideRight.met-toast.met-show { animation: met-slideRight-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
|
|
|
/* 响应式设计 */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.met-toast {
|
|
transition: opacity 0.15s !important;
|
|
}
|
|
|
|
.met-toast.met-show {
|
|
animation: none !important;
|
|
opacity: 1 !important;
|
|
}
|
|
|
|
.met-spin {
|
|
animation-duration: 2.5s !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.met-container {
|
|
padding: 12px !important;
|
|
}
|
|
|
|
.met-toast {
|
|
width: 100% !important;
|
|
min-width: 0 !important;
|
|
}
|
|
}
|
|
|
|
/* 暗色主题特定样式 */
|
|
.met-toast.met-theme-dark {
|
|
background: rgba(28, 32, 40, 0.94);
|
|
color: #e6e8eb;
|
|
border-color: rgba(255, 255, 255, 0.08);
|
|
box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.6),
|
|
0 4px 14px -4px rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
.met-toast.met-theme-dark:hover {
|
|
box-shadow: 0 14px 48px -8px rgba(0, 0, 0, 0.6),
|
|
0 6px 18px -4px rgba(0, 0, 0, 0.4) !important;
|
|
}
|
|
|
|
.met-toast.met-theme-dark .met-close:hover {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
|
|
.met-toast.met-theme-dark .met-progress,
|
|
.met-toast.met-theme-dark .met-progress-v {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
|
|
/* 亮色主题特定样式 */
|
|
.met-toast.met-theme-light {
|
|
background: rgba(255, 255, 255, 0.96);
|
|
color: #1f2937;
|
|
border-color: rgba(0, 0, 0, 0.06);
|
|
box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.18),
|
|
0 4px 14px -4px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.met-toast.met-theme-light:hover {
|
|
box-shadow: 0 14px 48px -10px rgba(0, 0, 0, 0.22),
|
|
0 6px 18px -4px rgba(0, 0, 0, 0.10) !important;
|
|
}
|
|
|
|
.met-toast.met-theme-light .met-close:hover {
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
.met-toast.met-theme-light .met-progress,
|
|
.met-toast.met-theme-light .met-progress-v {
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
/* 自定义主题支持 */
|
|
.met-toast[data-theme] {
|
|
--met-bg: var(--met-theme-bg);
|
|
--met-text: var(--met-theme-text);
|
|
--met-border: var(--met-theme-border);
|
|
--met-shadow: var(--met-theme-shadow);
|
|
}
|
|
|
|
/* 动画性能优化 */
|
|
.met-toast {
|
|
backface-visibility: hidden;
|
|
-webkit-backface-visibility: hidden;
|
|
perspective: 1000;
|
|
}
|
|
|
|
/* 滚动条样式 */
|
|
.met-container::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
.met-container::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.met-container::-webkit-scrollbar-thumb {
|
|
background: rgba(0, 0, 0, 0.2);
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.met-container::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
/* 打印样式 */
|
|
@media print {
|
|
.met-container {
|
|
display: none !important;
|
|
}
|
|
.met-toast {
|
|
display: none !important;
|
|
}
|
|
}
|
|
|
|
/* 高对比度模式 */
|
|
@media (forced-colors: active) {
|
|
.met-toast {
|
|
border: 2px solid ButtonText;
|
|
}
|
|
|
|
.met-close {
|
|
border: 1px solid ButtonText;
|
|
}
|
|
}
|
|
|
|
/* 焦点样式 */
|
|
.met-toast:focus-visible {
|
|
outline: 2px solid #3b82f6;
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.met-close:focus-visible {
|
|
outline: 2px solid #3b82f6;
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* 禁用状态 */
|
|
.met-toast:disabled,
|
|
.met-toast[disabled] {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* 加载状态 */
|
|
.met-toast.met-loading {
|
|
cursor: wait;
|
|
}
|
|
|
|
/* 成功状态 */
|
|
.met-toast.met-success {
|
|
border-left: 4px solid #10b981;
|
|
}
|
|
|
|
/* 错误状态 */
|
|
.met-toast.met-error {
|
|
border-left: 4px solid #ef4444;
|
|
}
|
|
|
|
/* 警告状态 */
|
|
.met-toast.met-warning {
|
|
border-left: 4px solid #f59e0b;
|
|
}
|
|
|
|
/* 信息状态 */
|
|
.met-toast.met-info {
|
|
border-left: 4px solid #3b82f6;
|
|
}
|
|
|
|
/* 加载状态 */
|
|
.met-toast.met-loading {
|
|
border-left: 4px solid #6366f1;
|
|
}
|
|
|
|
/* 进度条动画 */
|
|
.met-bar,
|
|
.met-bar-v {
|
|
transition: transform 0.1s linear;
|
|
}
|
|
|
|
/* 容器动画 */
|
|
.met-container {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
/* Toast进入动画 */
|
|
.met-toast.met-enter {
|
|
animation: met-enter 0.3s ease forwards;
|
|
}
|
|
|
|
/* Toast离开动画 */
|
|
.met-toast.met-leave {
|
|
animation: met-leave 0.3s ease forwards;
|
|
}
|
|
|
|
@keyframes met-enter {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
@keyframes met-leave {
|
|
from {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
to {
|
|
opacity: 0;
|
|
transform: translateY(-20px);
|
|
}
|
|
}
|
|
|
|
/* 响应式字体大小 */
|
|
@media (max-width: 768px) {
|
|
.met-toast {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.met-title {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.met-message {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.met-toast {
|
|
font-size: 12px;
|
|
padding: 12px 14px;
|
|
}
|
|
|
|
.met-title {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.met-message {
|
|
font-size: 11px;
|
|
}
|
|
}
|
|
|
|
/* 无障碍支持 */
|
|
.met-toast[role="alert"] {
|
|
/* 警告类型Toast的特殊样式 */
|
|
}
|
|
|
|
.met-toast[role="status"] {
|
|
/* 状态类型Toast的特殊样式 */
|
|
}
|
|
|
|
/* 高对比度模式增强 */
|
|
@media (prefers-contrast: high) {
|
|
.met-toast {
|
|
border-width: 2px;
|
|
}
|
|
|
|
.met-close {
|
|
border: 1px solid currentColor;
|
|
}
|
|
}
|
|
|
|
/* 暗色模式自动检测 */
|
|
@media (prefers-color-scheme: dark) {
|
|
.met-theme-auto .met-toast {
|
|
background: rgba(28, 32, 40, 0.94);
|
|
color: #e6e8eb;
|
|
border-color: rgba(255, 255, 255, 0.08);
|
|
box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.6),
|
|
0 4px 14px -4px rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
.met-theme-auto .met-toast:hover {
|
|
box-shadow: 0 14px 48px -8px rgba(0, 0, 0, 0.6),
|
|
0 6px 18px -4px rgba(0, 0, 0, 0.4) !important;
|
|
}
|
|
|
|
.met-theme-auto .met-close:hover {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
|
|
.met-theme-auto .met-progress,
|
|
.met-theme-auto .met-progress-v {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
}
|
|
|
|
/* 亮色模式自动检测 */
|
|
@media (prefers-color-scheme: light) {
|
|
.met-theme-auto .met-toast {
|
|
background: rgba(255, 255, 255, 0.96);
|
|
color: #1f2937;
|
|
border-color: rgba(0, 0, 0, 0.06);
|
|
box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.18),
|
|
0 4px 14px -4px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.met-theme-auto .met-toast:hover {
|
|
box-shadow: 0 14px 48px -10px rgba(0, 0, 0, 0.22),
|
|
0 6px 18px -4px rgba(0, 0, 0, 0.10) !important;
|
|
}
|
|
|
|
.met-theme-auto .met-close:hover {
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
.met-theme-auto .met-progress,
|
|
.met-theme-auto .met-progress-v {
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
}
|
|
|
|
/* 动画性能优化 */
|
|
.met-toast {
|
|
transform: translateZ(0);
|
|
-webkit-transform: translateZ(0);
|
|
}
|
|
|
|
/* 触摸设备优化 */
|
|
@media (hover: none) {
|
|
.met-toast:hover {
|
|
box-shadow: inherit;
|
|
}
|
|
}
|
|
|
|
/* 滚动时固定位置 */
|
|
.met-container {
|
|
position: fixed;
|
|
z-index: 9999;
|
|
}
|
|
|
|
/* 全屏模式 */
|
|
:fullscreen .met-container {
|
|
z-index: 2147483647;
|
|
}
|
|
|
|
/* 画中画模式 */
|
|
:picture-in-picture .met-container {
|
|
z-index: 2147483647;
|
|
}
|
|
|
|
/* 安全区域适配 */
|
|
@supports (padding: max(0px)) {
|
|
.met-container {
|
|
padding: max(24px, env(safe-area-inset-top))
|
|
max(24px, env(safe-area-inset-right))
|
|
max(24px, env(safe-area-inset-bottom))
|
|
max(24px, env(safe-area-inset-left));
|
|
}
|
|
}
|
|
|
|
/* 暗色模式安全区域 */
|
|
@media (prefers-color-scheme: dark) {
|
|
@supports (padding: max(0px)) {
|
|
.met-container {
|
|
padding: max(24px, env(safe-area-inset-top))
|
|
max(24px, env(safe-area-inset-right))
|
|
max(24px, env(safe-area-inset-bottom))
|
|
max(24px, env(safe-area-inset-left));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 高分辨率屏幕优化 */
|
|
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
|
.met-toast {
|
|
border-width: 0.5px;
|
|
}
|
|
}
|
|
|
|
/* 触摸设备优化 */
|
|
@media (hover: none) and (pointer: coarse) {
|
|
.met-toast {
|
|
min-height: 48px;
|
|
}
|
|
|
|
.met-close {
|
|
min-width: 48px;
|
|
min-height: 48px;
|
|
}
|
|
}
|
|
|
|
/* 键盘导航优化 */
|
|
.met-toast:focus {
|
|
outline: 2px solid #3b82f6;
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.met-toast:focus:not(:focus-visible) {
|
|
outline: none;
|
|
}
|
|
|
|
.met-toast:focus-visible {
|
|
outline: 2px solid #3b82f6;
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* 减少动画模式 */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.met-toast {
|
|
transition: opacity 0.15s ease !important;
|
|
animation: none !important;
|
|
}
|
|
|
|
.met-bar,
|
|
.met-bar-v {
|
|
transition: none !important;
|
|
}
|
|
|
|
.met-container {
|
|
transition: none !important;
|
|
}
|
|
}
|
|
|
|
/* 高对比度模式 */
|
|
@media (prefers-contrast: high) {
|
|
.met-toast {
|
|
border-width: 3px;
|
|
border-style: solid;
|
|
}
|
|
|
|
.met-close {
|
|
border: 2px solid currentColor;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.met-progress,
|
|
.met-progress-v {
|
|
height: 4px;
|
|
}
|
|
|
|
.met-bar,
|
|
.met-bar-v {
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
/* 低分辨率屏幕优化 */
|
|
@media (max-resolution: 1dppx) {
|
|
.met-toast {
|
|
border-width: 1px;
|
|
}
|
|
}
|
|
|
|
/* 触摸设备优化 */
|
|
@media (hover: none) and (pointer: coarse) {
|
|
.met-toast {
|
|
min-height: 52px;
|
|
padding: 16px 18px;
|
|
}
|
|
|
|
.met-close {
|
|
min-width: 52px;
|
|
min-height: 52px;
|
|
padding: 8px;
|
|
}
|
|
|
|
.met-icon {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
}
|
|
|
|
/* 大屏幕优化 */
|
|
@media (min-width: 1200px) {
|
|
.met-toast {
|
|
width: 400px;
|
|
}
|
|
}
|
|
|
|
/* 超大屏幕优化 */
|
|
@media (min-width: 1920px) {
|
|
.met-toast {
|
|
width: 440px;
|
|
}
|
|
}
|
|
|
|
/* 小屏幕优化 */
|
|
@media (max-width: 320px) {
|
|
.met-toast {
|
|
width: 100%;
|
|
min-width: 0;
|
|
padding: 12px 14px;
|
|
}
|
|
|
|
.met-container {
|
|
padding: 8px;
|
|
}
|
|
}
|
|
|
|
/* 横屏优化 */
|
|
@media (orientation: landscape) and (max-height: 500px) {
|
|
.met-container {
|
|
padding: 12px 24px;
|
|
}
|
|
|
|
.met-toast {
|
|
min-height: 44px;
|
|
padding: 10px 14px;
|
|
}
|
|
}
|
|
|
|
/* 竖屏优化 */
|
|
@media (orientation: portrait) and (max-width: 500px) {
|
|
.met-container {
|
|
padding: 12px;
|
|
}
|
|
|
|
.met-toast {
|
|
width: 100%;
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
/* 无障碍支持 */
|
|
.met-toast[aria-live="assertive"] {
|
|
/* 紧急通知样式 */
|
|
}
|
|
|
|
.met-toast[aria-live="polite"] {
|
|
/* 普通通知样式 */
|
|
}
|
|
|
|
/* 焦点陷阱 */
|
|
.met-toast:focus-within {
|
|
/* 包含焦点元素的Toast样式 */
|
|
}
|
|
|
|
/* 加载状态 */
|
|
.met-toast[aria-busy="true"] {
|
|
cursor: wait;
|
|
}
|
|
|
|
/* 禁用状态 */
|
|
.met-toast[aria-disabled="true"] {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* 隐藏状态 */
|
|
.met-toast[aria-hidden="true"] {
|
|
display: none;
|
|
}
|
|
|
|
/* 展开状态 */
|
|
.met-toast[aria-expanded="true"] {
|
|
/* 展开状态样式 */
|
|
}
|
|
|
|
/* 选中状态 */
|
|
.met-toast[aria-selected="true"] {
|
|
/* 选中状态样式 */
|
|
}
|
|
|
|
/* 按下状态 */
|
|
.met-toast:active {
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
/* 加载状态动画 */
|
|
.met-toast.met-loading::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: linear-gradient(
|
|
90deg,
|
|
transparent,
|
|
rgba(255, 255, 255, 0.1),
|
|
transparent
|
|
);
|
|
animation: met-loading 1.5s infinite;
|
|
}
|
|
|
|
@keyframes met-loading {
|
|
0% {
|
|
transform: translateX(-100%);
|
|
}
|
|
100% {
|
|
transform: translateX(100%);
|
|
}
|
|
}
|
|
|
|
/* 成功状态动画 */
|
|
.met-toast.met-success::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 4px;
|
|
height: 100%;
|
|
background: #10b981;
|
|
border-radius: 12px 0 0 12px;
|
|
animation: met-success 0.3s ease;
|
|
}
|
|
|
|
@keyframes met-success {
|
|
from {
|
|
transform: scaleY(0);
|
|
}
|
|
to {
|
|
transform: scaleY(1);
|
|
}
|
|
}
|
|
|
|
/* 错误状态动画 */
|
|
.met-toast.met-error::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 4px;
|
|
height: 100%;
|
|
background: #ef4444;
|
|
border-radius: 12px 0 0 12px;
|
|
animation: met-error 0.3s ease;
|
|
}
|
|
|
|
@keyframes met-error {
|
|
from {
|
|
transform: scaleY(0);
|
|
}
|
|
to {
|
|
transform: scaleY(1);
|
|
}
|
|
}
|
|
|
|
/* 警告状态动画 */
|
|
.met-toast.met-warning::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 4px;
|
|
height: 100%;
|
|
background: #f59e0b;
|
|
border-radius: 12px 0 0 12px;
|
|
animation: met-warning 0.3s ease;
|
|
}
|
|
|
|
@keyframes met-warning {
|
|
from {
|
|
transform: scaleY(0);
|
|
}
|
|
to {
|
|
transform: scaleY(1);
|
|
}
|
|
}
|
|
|
|
/* 信息状态动画 */
|
|
.met-toast.met-info::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 4px;
|
|
height: 100%;
|
|
background: #3b82f6;
|
|
border-radius: 12px 0 0 12px;
|
|
animation: met-info 0.3s ease;
|
|
}
|
|
|
|
@keyframes met-info {
|
|
from {
|
|
transform: scaleY(0);
|
|
}
|
|
to {
|
|
transform: scaleY(1);
|
|
}
|
|
}
|
|
|
|
/* 加载状态动画 */
|
|
.met-toast.met-loading::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 4px;
|
|
height: 100%;
|
|
background: #6366f1;
|
|
border-radius: 12px 0 0 12px;
|
|
animation: met-loading-bar 1s infinite;
|
|
}
|
|
|
|
@keyframes met-loading-bar {
|
|
0% {
|
|
transform: scaleY(0);
|
|
transform-origin: top;
|
|
}
|
|
50% {
|
|
transform: scaleY(1);
|
|
transform-origin: top;
|
|
}
|
|
51% {
|
|
transform-origin: bottom;
|
|
}
|
|
100% {
|
|
transform: scaleY(0);
|
|
transform-origin: bottom;
|
|
}
|
|
}
|
|
|
|
/* 进度条脉冲动画 */
|
|
.met-bar,
|
|
.met-bar-v {
|
|
animation: met-pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes met-pulse {
|
|
0%, 100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
/* Toast堆叠效果 */
|
|
.met-toast + .met-toast {
|
|
margin-top: 8px;
|
|
}
|
|
|
|
/* Toast分组 */
|
|
.met-toast-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
/* Toast头部 */
|
|
.met-toast-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
/* Toast底部 */
|
|
.met-toast-footer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
/* Toast操作按钮 */
|
|
.met-toast-action {
|
|
background: transparent;
|
|
border: 1px solid currentColor;
|
|
padding: 6px 12px;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
opacity: 0.7;
|
|
transition: opacity 0.2s;
|
|
}
|
|
|
|
.met-toast-action:hover {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Toast进度文本 */
|
|
.met-toast-progress-text {
|
|
font-size: 12px;
|
|
opacity: 0.7;
|
|
margin-left: 8px;
|
|
}
|
|
|
|
/* Toast时间戳 */
|
|
.met-toast-timestamp {
|
|
font-size: 11px;
|
|
opacity: 0.5;
|
|
margin-left: auto;
|
|
}
|
|
|
|
/* Toast头像 */
|
|
.met-toast-avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Toast图片 */
|
|
.met-toast-image {
|
|
max-width: 100%;
|
|
max-height: 200px;
|
|
border-radius: 8px;
|
|
margin-top: 8px;
|
|
object-fit: cover;
|
|
}
|
|
|
|
/* Toast视频 */
|
|
.met-toast-video {
|
|
max-width: 100%;
|
|
max-height: 200px;
|
|
border-radius: 8px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
/* Toast音频 */
|
|
.met-toast-audio {
|
|
width: 100%;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
/* Toast代码块 */
|
|
.met-toast-code {
|
|
background: rgba(0, 0, 0, 0.05);
|
|
padding: 8px 12px;
|
|
border-radius: 6px;
|
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
font-size: 12px;
|
|
margin-top: 8px;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-code {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
/* Toast引用 */
|
|
.met-toast-quote {
|
|
border-left: 3px solid currentColor;
|
|
padding-left: 12px;
|
|
margin-top: 8px;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* Toast列表 */
|
|
.met-toast-list {
|
|
margin: 8px 0 0 0;
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.met-toast-list li {
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
/* Toast表格 */
|
|
.met-toast-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 8px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.met-toast-table th,
|
|
.met-toast-table td {
|
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
padding: 6px 8px;
|
|
text-align: left;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-table th,
|
|
.met-theme-dark .met-toast-table td {
|
|
border-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-table th {
|
|
background: rgba(0, 0, 0, 0.05);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-table th {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
/* Toast分割线 */
|
|
.met-toast-divider {
|
|
height: 1px;
|
|
background: rgba(0, 0, 0, 0.1);
|
|
margin: 12px 0;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-divider {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
/* Toast标签 */
|
|
.met-toast-tag {
|
|
display: inline-block;
|
|
background: rgba(0, 0, 0, 0.05);
|
|
padding: 2px 8px;
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
margin-right: 4px;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-tag {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
/* Toast徽章 */
|
|
.met-toast-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: #3b82f6;
|
|
color: white;
|
|
padding: 2px 8px;
|
|
border-radius: 10px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
min-width: 20px;
|
|
height: 20px;
|
|
}
|
|
|
|
/* Toast进度环 */
|
|
.met-toast-progress-ring {
|
|
width: 40px;
|
|
height: 40px;
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.met-toast-progress-ring circle {
|
|
fill: none;
|
|
stroke-width: 3;
|
|
stroke-linecap: round;
|
|
}
|
|
|
|
.met-toast-progress-ring .met-progress-ring-bg {
|
|
stroke: rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.met-theme-dark .met-toast-progress-ring .met-progress-ring-bg {
|
|
stroke: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-progress-ring .met-progress-ring-fill {
|
|
stroke: #3b82f6;
|
|
stroke-dasharray: 100;
|
|
stroke-dashoffset: 100;
|
|
transition: stroke-dashoffset 0.3s ease;
|
|
}
|
|
|
|
/* Toast滑块 */
|
|
.met-toast-slider {
|
|
width: 100%;
|
|
height: 4px;
|
|
background: rgba(0, 0, 0, 0.1);
|
|
border-radius: 2px;
|
|
margin-top: 8px;
|
|
position: relative;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-slider {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-slider-fill {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
height: 100%;
|
|
background: #3b82f6;
|
|
border-radius: 2px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
/* Toast开关 */
|
|
.met-toast-switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 36px;
|
|
height: 20px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.met-toast-switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
|
|
.met-toast-switch-slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.1);
|
|
border-radius: 20px;
|
|
transition: 0.3s;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-switch-slider {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-switch-slider:before {
|
|
content: '';
|
|
position: absolute;
|
|
height: 16px;
|
|
width: 16px;
|
|
left: 2px;
|
|
bottom: 2px;
|
|
background: white;
|
|
border-radius: 50%;
|
|
transition: 0.3s;
|
|
}
|
|
|
|
.met-toast-switch input:checked + .met-toast-switch-slider {
|
|
background: #3b82f6;
|
|
}
|
|
|
|
.met-toast-switch input:checked + .met-toast-switch-slider:before {
|
|
transform: translateX(16px);
|
|
}
|
|
|
|
/* Toast复选框 */
|
|
.met-toast-checkbox {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-top: 8px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.met-toast-checkbox input {
|
|
width: 16px;
|
|
height: 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Toast单选框 */
|
|
.met-toast-radio {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-top: 8px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.met-toast-radio input {
|
|
width: 16px;
|
|
height: 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Toast输入框 */
|
|
.met-toast-input {
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
margin-top: 8px;
|
|
background: transparent;
|
|
color: inherit;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-input {
|
|
border-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-input:focus {
|
|
outline: none;
|
|
border-color: #3b82f6;
|
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
}
|
|
|
|
/* Toast文本域 */
|
|
.met-toast-textarea {
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
margin-top: 8px;
|
|
background: transparent;
|
|
color: inherit;
|
|
resize: vertical;
|
|
min-height: 80px;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-textarea {
|
|
border-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-textarea:focus {
|
|
outline: none;
|
|
border-color: #3b82f6;
|
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
}
|
|
|
|
/* Toast选择框 */
|
|
.met-toast-select {
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
margin-top: 8px;
|
|
background: transparent;
|
|
color: inherit;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-select {
|
|
border-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.met-toast-select:focus {
|
|
outline: none;
|
|
border-color: #3b82f6;
|
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
}
|
|
|
|
/* Toast下拉菜单 */
|
|
.met-toast-dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.met-toast-dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background: ${theme.bg};
|
|
min-width: 160px;
|
|
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
|
border-radius: 8px;
|
|
z-index: 1;
|
|
padding: 8px 0;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
.met-theme-dark .met-toast-dropdown-content {
|
|
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.met-toast-dropdown:hover .met-toast-dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.met-toast-dropdown-item {
|
|
padding: 8px 16px;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.met-toast-dropdown-item:hover {
|
|
background: rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.met-theme-dark .met-toast-dropdown-item:hover {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
/* Toast工具提示 */
|
|
.met-toast-tooltip {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.met-toast-tooltip .met-toast-tooltip-text {
|
|
visibility: hidden;
|
|
width: 120px;
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
text-align: center;
|
|
border-radius: 6px;
|
|
padding: 6px 8px;
|
|
position: absolute;
|
|
z-index: 1;
|
|
bottom: 125%;
|
|
left: 50%;
|
|
margin-left: -60px;
|
|
opacity: 0;
|
|
transition: opacity 0.3s;
|
|
font-size: 12px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.met-theme-dark .met-toast-tooltip .met-toast-tooltip-text {
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.met-toast-tooltip:hover .met-toast-tooltip-text {
|
|
visibility: visible;
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Toast弹出框 */
|
|
.met-toast-popover {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.met-toast-popover .met-toast-popover-content {
|
|
visibility: hidden;
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
border-radius: 8px;
|
|
padding: 12px 16px;
|
|
position: absolute;
|
|
z-index: 1;
|
|
bottom: 125%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
opacity: 0;
|
|
transition: opacity 0.3s;
|
|
min-width: 200px;
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.met-theme-dark .met-toast-popover .met-toast-popover-content {
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
.met-toast-popover:hover .met-toast-popover-content {
|
|
visibility: visible;
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Toast模态框 */
|
|
.met-toast-modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 10000;
|
|
}
|
|
|
|
.met-toast-modal-content {
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
border-radius: 12px;
|
|
padding: 24px;
|
|
max-width: 500px;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
/* Toast抽屉 */
|
|
.met-toast-drawer {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 10000;
|
|
}
|
|
|
|
.met-toast-drawer-content {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
width: 300px;
|
|
height: 100%;
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
padding: 24px;
|
|
transform: translateX(100%);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.met-toast-drawer.open .met-toast-drawer-content {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
/* Toast通知栏 */
|
|
.met-toast-notification-bar {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
padding: 12px 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
z-index: 9999;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
/* Toast状态栏 */
|
|
.met-toast-status-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: ${theme.bg};
|
|
color: ${theme.text};
|
|
padding: 8px 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
z-index: 9999;
|
|
font-size: 12px;
|
|
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
|
}
|
|
`;
|
|
};
|
|
|
|
/**
|
|
* 注入样式
|
|
* @param {Object} theme - 主题配置
|
|
*/
|
|
export const injectStyles = (theme = THEMES.light) => {
|
|
// 检查是否在浏览器环境
|
|
if (typeof document === 'undefined') return;
|
|
|
|
// 检查是否已注入
|
|
if (styleElement && document.getElementById('metona-toast-styles')) {
|
|
return;
|
|
}
|
|
|
|
// 生成CSS
|
|
const css = generateCSS(theme);
|
|
|
|
// 创建样式元素
|
|
styleElement = document.createElement('style');
|
|
styleElement.id = 'metona-toast-styles';
|
|
styleElement.textContent = css.replace(/\s+/g, ' ');
|
|
|
|
// 添加到文档头
|
|
document.head.appendChild(styleElement);
|
|
|
|
// 缓存样式
|
|
injectedStyles = css;
|
|
};
|
|
|
|
/**
|
|
* 更新样式
|
|
* @param {Object} theme - 新主题配置
|
|
*/
|
|
export const updateStyles = (theme) => {
|
|
if (!styleElement) {
|
|
injectStyles(theme);
|
|
return;
|
|
}
|
|
|
|
const css = generateCSS(theme);
|
|
styleElement.textContent = css.replace(/\s+/g, ' ');
|
|
injectedStyles = css;
|
|
};
|
|
|
|
/**
|
|
* 移除样式
|
|
*/
|
|
export const removeStyles = () => {
|
|
if (styleElement && styleElement.parentNode) {
|
|
styleElement.parentNode.removeChild(styleElement);
|
|
}
|
|
|
|
styleElement = null;
|
|
injectedStyles = null;
|
|
};
|
|
|
|
/**
|
|
* 获取当前样式
|
|
* @returns {string|null} 当前CSS字符串
|
|
*/
|
|
export const getStyles = () => {
|
|
return injectedStyles;
|
|
};
|
|
|
|
/**
|
|
* 检查样式是否已注入
|
|
* @returns {boolean} 是否已注入
|
|
*/
|
|
export const isStylesInjected = () => {
|
|
return !!styleElement && !!document.getElementById('metona-toast-styles');
|
|
};
|
|
|
|
/**
|
|
* 重置样式
|
|
*/
|
|
export const resetStyles = () => {
|
|
removeStyles();
|
|
injectStyles();
|
|
};
|
|
|
|
/**
|
|
* 添加自定义CSS
|
|
* @param {string} css - CSS字符串
|
|
*/
|
|
export const addCustomCSS = (css) => {
|
|
if (!styleElement) {
|
|
injectStyles();
|
|
}
|
|
|
|
const customStyle = document.createElement('style');
|
|
customStyle.id = 'metona-toast-custom-styles';
|
|
customStyle.textContent = css;
|
|
document.head.appendChild(customStyle);
|
|
};
|
|
|
|
/**
|
|
* 移除自定义CSS
|
|
*/
|
|
export const removeCustomCSS = () => {
|
|
const customStyle = document.getElementById('metona-toast-custom-styles');
|
|
if (customStyle && customStyle.parentNode) {
|
|
customStyle.parentNode.removeChild(customStyle);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 生成主题变量
|
|
* @param {Object} theme - 主题配置
|
|
* @returns {string} CSS变量字符串
|
|
*/
|
|
export const generateThemeVariables = (theme) => {
|
|
return `
|
|
:root {
|
|
--met-theme-bg: ${theme.bg};
|
|
--met-theme-text: ${theme.text};
|
|
--met-theme-border: ${theme.border};
|
|
--met-theme-shadow: ${theme.shadow};
|
|
--met-theme-hover-shadow: ${theme.hoverShadow};
|
|
--met-theme-progress-bg: ${theme.progressBg};
|
|
--met-theme-close-hover-bg: ${theme.closeHoverBg};
|
|
}
|
|
`;
|
|
};
|
|
|
|
/**
|
|
* 应用主题变量
|
|
* @param {Object} theme - 主题配置
|
|
*/
|
|
export const applyThemeVariables = (theme) => {
|
|
const css = generateThemeVariables(theme);
|
|
addCustomCSS(css);
|
|
};
|
|
|
|
/**
|
|
* 清除主题变量
|
|
*/
|
|
export const clearThemeVariables = () => {
|
|
removeCustomCSS();
|
|
};
|
|
|
|
/**
|
|
* 获取系统主题
|
|
* @returns {string} 系统主题
|
|
*/
|
|
export const getSystemTheme = () => {
|
|
if (typeof window === 'undefined') return 'light';
|
|
|
|
return window.matchMedia &&
|
|
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
? 'dark'
|
|
: 'light';
|
|
};
|
|
|
|
/**
|
|
* 监听系统主题变化
|
|
* @param {Function} callback - 回调函数
|
|
* @returns {Function} 取消监听函数
|
|
*/
|
|
export const watchSystemTheme = (callback) => {
|
|
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
return () => {};
|
|
}
|
|
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
const handler = (e) => {
|
|
callback(e.matches ? 'dark' : 'light');
|
|
};
|
|
|
|
mediaQuery.addEventListener('change', handler);
|
|
|
|
return () => {
|
|
mediaQuery.removeEventListener('change', handler);
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 自动应用系统主题
|
|
* @returns {Function} 取消监听函数
|
|
*/
|
|
export const autoApplySystemTheme = () => {
|
|
const applyTheme = (theme) => {
|
|
updateStyles(THEMES[theme]);
|
|
applyThemeVariables(THEMES[theme]);
|
|
};
|
|
|
|
// 应用当前系统主题
|
|
applyTheme(getSystemTheme());
|
|
|
|
// 监听系统主题变化
|
|
return watchSystemTheme(applyTheme);
|
|
};
|