移除 MUI 依赖,简化配置文件,重写 ThemeModeProvider

This commit is contained in:
雨霖铃
2026-05-22 00:53:12 +08:00
parent e2dd5f5915
commit 6763cd7862
5 changed files with 41 additions and 1604 deletions
+5 -862
View File
@@ -1,6 +1,3 @@
import type { Theme } from '@mui/material';
import { alpha } from '@mui/material';
export const DATE_FORMAT = 'YYYY/MM/DD HH:mm:ss';
export const ZONES = ['Asia/Shanghai', 'America/New_York', 'Europe/London'] as const;
@@ -8,59 +5,29 @@ export const ZONES = ['Asia/Shanghai', 'America/New_York', 'Europe/London'] as c
export type UnitType = 'ms' | 's';
export type ZoneType = (typeof ZONES)[number];
/**
* 符合 WCAG AA 标准(4.5:1 对比度)的主题颜色体系
* 所有颜色都经过对比度计算,确保可访问性
*
* 注意:这些颜色是品牌色源,实际组件应优先使用 theme.palette.* 令牌,
* 以便在亮色/暗色模式下自动切换。
*/
export const THEME_COLORS = {
// 主要颜色 - 蓝色系
// 主色 #1976d2 在白底对比度 4.89:1 ✓
primary: '#1976d2',
primaryDark: '#1565c0',
primaryLight: '#42a5f5',
// 成功颜色 - 深绿色系(原 #4caf50 对比度仅 2.88:1,不达标)
// 新颜色 #2e7d32 在白底对比度 4.63:1 ✓
success: '#2e7d32',
successDark: '#1b5e20',
successLight: '#4caf50',
// 警告颜色 - 深橙色系(原 #ff9800 对比度仅 1.61:1,严重不达标)
// 新颜色 #e65100 在白底对比度 4.63:1 ✓
warning: '#e65100',
warningDark: '#bf360c',
warningLight: '#ff9800',
// 错误颜色 - 深红色系
// 主色 #c62828 在白底对比度 5.71:1 ✓
error: '#c62828',
errorDark: '#b71c1c',
errorLight: '#f44336',
// 紫色系(原 #9c27b0 对比度仅 2.23:1,不达标)
// 新颜色 #6a1b9a 在白底对比度 4.63:1 ✓
purple: '#6a1b9a',
purpleDark: '#4a148c',
purpleLight: '#9c27b0',
// 靛蓝色系
// #303f9f 在白底对比度 7.01:1 ✓
indigo: '#303f9f',
indigoDark: '#1a237e',
indigoLight: '#7986cb',
// 中性色
white: '#FFFFFF',
black: '#000000',
} as const;
/**
* 语义化的状态颜色别名
* 提供直观的状态表示,提高代码可读性
*/
export const STATUS_COLORS = {
success: THEME_COLORS.success,
warning: THEME_COLORS.warning,
@@ -68,846 +35,22 @@ export const STATUS_COLORS = {
info: THEME_COLORS.primary,
} as const;
/**
* 暗色模式下自动加深 alpha 值的辅助函数
*/
export const surfaceTint = (theme: Theme, color: string, baseAlpha: number) =>
alpha(color, theme.palette.mode === 'dark' ? Math.min(baseAlpha + 0.1, 0.9) : baseAlpha);
/**
* 时间戳转换页面样式
*/
export const timestampPageStyles = {
primaryColor: THEME_COLORS.primary,
INPUT_STYLE: {
'& .MuiOutlinedInput-root': {
bgcolor: 'background.paper',
borderRadius: 3,
border: '1px solid',
borderColor: 'divider',
transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',
'& fieldset': { border: 'none' },
'&:hover': { borderColor: 'action.active', bgcolor: 'action.hover' },
'&.Mui-focused': {
bgcolor: 'background.paper',
borderColor: 'primary.main',
boxShadow: (theme: Theme) => `0 0 0 4px ${alpha(theme.palette.primary.main, 0.1)}`,
},
'&.Mui-error': {
borderColor: 'error.main',
boxShadow: (theme: Theme) => `0 0 0 4px ${alpha(theme.palette.error.main, 0.1)}`,
},
},
'& .MuiInputBase-input': {
py: 1.4,
px: 2,
fontSize: '0.9rem',
fontFamily: 'monospace',
fontWeight: 600,
},
},
SELECT_MENU_PROPS: {
PaperProps: {
sx: { borderRadius: 3, mt: 1, boxShadow: '0 12px 32px rgba(0,0,0,0.1)' },
},
},
cardBg: (theme: Theme) => alpha(theme.palette.primary.main, 0.04),
cardBorder: (theme: Theme) => alpha(theme.palette.primary.main, 0.1),
switcherBg: (theme: Theme) => alpha(theme.palette.primary.main, 0.08),
switcherBorder: (theme: Theme) => alpha(theme.palette.primary.main, 0.1),
mutedText: (theme: Theme) => alpha(theme.palette.primary.main, 0.4),
resultBg: (theme: Theme) => alpha(theme.palette.primary.main, 0.05),
buttonHover: (theme: Theme) => `0 8px 24px ${alpha(theme.palette.primary.main, 0.2)}`,
/** 统一转换工作台外卡 */
CONVERSION_CARD: {
p: 2.5,
borderRadius: 4,
bgcolor: 'background.paper',
border: '1px solid',
borderColor: 'divider',
boxShadow: '0 4px 16px rgba(0,0,0,0.04)',
},
/** 桌面端左右分栏布局 (md 断点开始等宽分栏,两栏卡片等高) */
LAYOUT_GRID: {
display: 'grid',
gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' },
gap: 2,
alignItems: 'stretch',
},
/** 右栏结果卡片(独立卡片样式,与左栏等高) */
RESULT_COLUMN_CARD: {
p: 2.5,
borderRadius: 4,
bgcolor: 'background.paper',
border: '1px solid',
borderColor: 'divider',
boxShadow: '0 4px 16px rgba(0,0,0,0.04)',
height: '100%',
display: 'flex',
flexDirection: 'column',
},
/** 结果区空状态占位(桌面端右栏未转换时) */
RESULT_EMPTY_PLACEHOLDER: {
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'text.disabled',
fontSize: '0.85rem',
fontWeight: 600,
py: 6,
textAlign: 'center',
},
/** 立即转换按钮(缩小+居中,融入卡片) */
CONVERT_BUTTON: {
display: 'block',
mx: 'auto',
mt: 2,
mb: 0.5,
maxWidth: 240,
width: '100%',
py: 1.1,
fontSize: '0.85rem',
borderRadius: 3,
},
/** 单位切换器样式 */
UNIT_SWITCHER_CONTAINER: {
flexShrink: 0,
width: 160,
display: 'flex',
bgcolor: 'action.hover',
p: 0.5,
borderRadius: 3.5,
border: '1px solid',
borderColor: 'divider',
},
UNIT_SWITCHER_ITEM: (active: boolean) => ({
flex: 1,
py: 0.8,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
borderRadius: 3,
cursor: 'pointer',
fontSize: '0.75rem',
fontWeight: 800,
transition: 'all 0.2s',
bgcolor: active ? 'background.paper' : 'transparent',
color: active ? 'primary.main' : 'text.disabled',
boxShadow: active ? '0 2px 8px rgba(0,0,0,0.05)' : 'none',
}),
/** LiveClock 参考条样式(瘦身为单行) */
LIVE_CLOCK_CARD: (theme: Theme) => ({
display: 'flex',
alignItems: 'center',
gap: 1.5,
px: 1.6,
py: 0.8,
mb: 2,
bgcolor: alpha(theme.palette.primary.main, 0.04),
borderRadius: 3,
border: '1px solid',
borderColor: alpha(theme.palette.primary.main, 0.1),
}),
LIVE_CLOCK_LABEL: {
color: 'primary.main',
fontWeight: 800,
fontSize: '0.65rem',
textTransform: 'uppercase',
letterSpacing: 1,
whiteSpace: 'nowrap',
},
LIVE_CLOCK_VALUE: {
flex: 1,
fontWeight: 800,
color: 'primary.main',
fontFamily: 'monospace',
fontSize: '0.95rem',
letterSpacing: '-0.5px',
lineHeight: 1.2,
overflow: 'hidden',
textOverflow: 'ellipsis',
},
LIVE_CLOCK_ICON_BUTTON: {
color: 'primary.main',
bgcolor: 'background.paper',
boxShadow: '0 2px 4px rgba(0,0,0,0.05)',
'&:hover': { bgcolor: 'primary.main', color: 'primary.contrastText' },
},
/** ResultView 样式 */
RESULT_LABEL: {
color: 'text.secondary',
mb: 1.2,
display: 'block',
fontWeight: 800,
fontSize: '0.7rem',
},
RESULT_MAIN_BOX: (theme: Theme) => ({
bgcolor: alpha(theme.palette.primary.main, 0.12),
p: 2.2,
borderRadius: 4,
position: 'relative',
mb: 2,
border: '1px solid',
borderColor: alpha(theme.palette.primary.main, 0.2),
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}),
RESULT_MAIN_TEXT: {
fontFamily: 'monospace',
fontWeight: 800,
color: 'primary.main',
wordBreak: 'break-all',
pr: 4,
fontSize: '1.35rem',
letterSpacing: '-0.5px',
lineHeight: 1.2,
},
RESULT_EXTRA_STACK: (theme: Theme) => ({
bgcolor: alpha(theme.palette.primary.main, 0.05),
p: 2,
borderRadius: 4,
border: '1px solid',
borderColor: alpha(theme.palette.primary.main, 0.1),
}),
RESULT_EXTRA_LABEL: {
color: 'text.disabled',
fontWeight: 700,
fontSize: '0.7rem',
pr: 2,
whiteSpace: 'nowrap',
},
RESULT_EXTRA_VALUE: {
fontFamily: 'monospace',
color: 'primary.main',
fontWeight: 600,
fontSize: '0.75rem',
wordBreak: 'break-all',
textAlign: 'right',
},
} as const;
};
/**
* 存储清理页面样式
*/
export const storageCleanerPageStyles = {
warningColor: THEME_COLORS.warning,
warningDark: THEME_COLORS.warningDark,
warningBg: (theme: Theme) => surfaceTint(theme, theme.palette.warning.main, 0.05),
errorBorder: (theme: Theme) => `1px solid ${surfaceTint(theme, theme.palette.error.main, 0.2)}`,
errorBg: (theme: Theme) => surfaceTint(theme, theme.palette.error.main, 0.05),
/** 选项网格容器 */
OPTIONS_GRID_CONTAINER: {
mb: 3,
border: '1px solid',
borderColor: 'divider',
borderRadius: 4,
bgcolor: 'background.paper',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.05)',
transition: 'all 0.2s',
overflow: 'hidden',
'&:hover': {
boxShadow: '0 6px 16px rgba(0, 0, 0, 0.08)',
},
},
OPTIONS_GRID_FOOTER: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
px: 2.7,
py: 0.8,
borderBottomLeftRadius: 4,
borderBottomRightRadius: 4,
transition: 'all 0.2s',
'&:hover': {
bgcolor: 'action.hover',
},
},
OPTIONS_GRID_CHECKBOX: {
p: 0.6,
mr: 0,
'& .MuiSvgIcon-root': {
fontSize: 18,
transition: 'transform 0.2s',
},
'&:hover .MuiSvgIcon-root': {
transform: 'scale(1.1)',
},
},
/** 选项项 */
OPTION_ITEM: (checked: boolean) => (theme: Theme) => ({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
py: 1,
px: { xs: 1, sm: 1.5 },
borderRadius: 3,
transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',
bgcolor: checked ? surfaceTint(theme, theme.palette.warning.main, 0.05) : 'transparent',
border: `1px solid ${checked ? surfaceTint(theme, theme.palette.warning.main, 0.2) : 'transparent'}`,
'&:hover': {
bgcolor: checked ? surfaceTint(theme, theme.palette.warning.main, 0.1) : 'action.hover',
transform: 'translateY(-1px)',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
},
}),
OPTION_ITEM_LABEL: (checked: boolean) => ({
fontSize: '0.75rem',
display: 'block',
lineHeight: 1.2,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
transition: 'color 0.2s',
color: checked ? 'warning.main' : 'text.primary',
}),
OPTION_ITEM_SIZE: {
color: 'text.secondary',
fontSize: '0.65rem',
fontWeight: 600,
display: 'block',
mt: 0.3,
lineHeight: 1,
whiteSpace: 'nowrap',
opacity: 0.8,
},
OPTION_ITEM_NO_DATA: {
color: 'text.disabled',
fontSize: '0.65rem',
fontWeight: 500,
display: 'block',
mt: 0.3,
lineHeight: 1,
fontStyle: 'italic',
},
OPTION_ITEM_CHECKBOX: {
p: 0.6,
'& .MuiSvgIcon-root': {
fontSize: 18,
transition: 'transform 0.2s',
},
'&:hover .MuiSvgIcon-root': {
transform: 'scale(1.1)',
},
},
/** 自动刷新切换 */
AUTO_REFRESH_CONTAINER: {
mb: 3,
p: 1.5,
borderRadius: 4,
bgcolor: 'background.paper',
border: '1px solid',
borderColor: 'divider',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.05)',
transition: 'all 0.2s',
'&:hover': {
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08)',
},
},
AUTO_REFRESH_SWITCH: {
'& .MuiSwitch-track': {
borderRadius: 20,
},
'& .MuiSwitch-thumb': {
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
transition: 'all 0.2s',
},
'&:hover .MuiSwitch-thumb': {
transform: 'scale(1.1)',
},
},
/** DomainHeader */
DOMAIN_HEADER_BADGE: (theme: Theme) => ({
bgcolor: surfaceTint(theme, theme.palette.warning.main, 0.15),
color: 'warning.main',
px: 1.5,
py: 0.3,
borderRadius: 2,
fontWeight: 800,
fontSize: '0.7rem',
boxShadow: `0 2px 4px ${surfaceTint(theme, theme.palette.warning.main, 0.2)}`,
transition: 'all 0.2s',
'&:hover': {
bgcolor: surfaceTint(theme, theme.palette.warning.main, 0.25),
},
}),
DOMAIN_HEADER_ICON: (theme: Theme) => ({
p: 1.2,
borderRadius: 3,
boxShadow: `0 2px 8px ${surfaceTint(theme, theme.palette.warning.main, 0.15)}`,
transition: 'all 0.2s',
'&:hover': {
bgcolor: surfaceTint(theme, theme.palette.warning.main, 0.15),
transform: 'scale(1.05)',
},
}),
/** ErrorDisplay */
ERROR_DISPLAY_CONTAINER: {
py: 8,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: { xs: 'auto', sm: '400px' },
textAlign: 'center',
},
ERROR_DISPLAY_BOX: (theme: Theme) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 4,
p: 4,
boxShadow: `0 8px 24px ${surfaceTint(theme, theme.palette.error.main, 0.15)}`,
border: '1px solid',
borderColor: surfaceTint(theme, theme.palette.error.main, 0.2),
bgcolor: surfaceTint(theme, theme.palette.error.main, 0.05),
}),
/** CleaningResult */
CLEANING_RESULT_ALERT: {
borderRadius: 3,
py: 1,
px: 2,
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08)',
'& .MuiAlert-message': {
fontSize: '0.8rem',
fontWeight: 600,
lineHeight: 1.4,
},
'& .MuiAlert-icon': {
fontSize: '1.2rem',
mr: 1,
},
},
/** StorageCleanerConfirm Dialog */
CONFIRM_DIALOG_PAPER: {
borderRadius: 6,
backgroundImage: 'none',
boxShadow: '0 24px 64px -12px rgba(0, 0, 0, 0.18)',
p: 1.5,
bgcolor: 'background.paper',
},
CONFIRM_DIALOG_TITLE: {
textAlign: 'center',
pt: 4,
pb: 1,
fontWeight: 900,
letterSpacing: '-0.5px',
fontSize: '1.35rem',
color: 'text.primary',
},
CONFIRM_DIALOG_CONTENT: {
textAlign: 'center',
pb: 2,
},
CONFIRM_DIALOG_DESC: {
mb: 3.5,
fontWeight: 500,
fontSize: '0.9rem',
},
CONFIRM_DIALOG_CHIP: (theme: Theme) => ({
bgcolor: surfaceTint(theme, theme.palette.warning.main, 0.04),
fontWeight: 700,
color: 'warning.main',
fontSize: '0.75rem',
border: '1px solid',
borderColor: surfaceTint(theme, theme.palette.warning.main, 0.15),
borderRadius: 2.5,
height: 'auto',
'& .MuiChip-label': { px: 1.2, py: 0.6 },
}),
CONFIRM_DIALOG_WARNING_BOX: (theme: Theme) => ({
display: 'inline-flex',
alignItems: 'center',
gap: 1,
bgcolor: surfaceTint(theme, theme.palette.error.main, 0.05),
color: 'error.main',
px: 2,
py: 0.8,
borderRadius: 3,
border: '1px dashed',
borderColor: surfaceTint(theme, theme.palette.error.main, 0.2),
}),
CONFIRM_DIALOG_WARNING_TEXT: {
fontWeight: 800,
display: 'flex',
alignItems: 'center',
gap: 0.5,
fontSize: '0.75rem',
},
CONFIRM_DIALOG_CANCEL: {
boxShadow: '0 0 1px 1px rgba(0, 0, 0, 0.1)',
color: 'text.secondary',
'&:hover': {
bgcolor: 'action.hover',
color: 'text.primary',
},
},
CONFIRM_DIALOG_CONFIRM: {
bgcolor: 'warning.main',
'&:hover': {
bgcolor: 'warning.dark',
},
},
} as const;
};
/**
* 二维码工具页面样式
*/
export const qrCodePageStyles = {
primaryColor: THEME_COLORS.success,
/** 桌面端左右分栏布局 (md 断点开始等宽分栏,两栏卡片等高) */
LAYOUT_GRID: {
display: 'grid',
gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' },
gap: 2,
alignItems: 'stretch',
},
/** 桌面端 grid item 包装:撑满 grid row 并把高度传给 Accordion */
GRID_CELL: {
display: 'flex',
flexDirection: 'column',
height: '100%',
'& > .MuiAccordion-root': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
} as const,
/** 桌面端 Accordion 强展开样式:隐藏箭头,禁用 hover/cursor,等高填充 */
ACCORDION_DESKTOP: {
borderRadius: 4,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
height: '100%',
display: 'flex',
flexDirection: 'column',
overflow: 'hidden',
'&:before': { display: 'none' },
'& .MuiAccordionSummary-root': {
cursor: 'default',
},
'& .MuiAccordionSummary-expandIconWrapper': {
display: 'none',
},
// 让 Collapse 整条链都 flex 撑满,否则 Details 拿不到剩余高度
'& .MuiCollapse-root': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
'& .MuiCollapse-wrapper': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
'& .MuiCollapse-wrapperInner': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
'& .MuiAccordion-region': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
'& .MuiAccordionDetails-root': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
'& .MuiAccordionDetails-root > .MuiStack-root': {
flex: 1,
},
'& .qr-flex-grow': {
flex: 1,
display: 'flex',
flexDirection: 'column',
},
} as const,
/** 加载状态容器 */
LOADING_CONTAINER: {
py: 4,
maxWidth: 400,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: 200,
} as const,
/** Accordion 容器 */
ACCORDION: {
borderRadius: 4,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
overflow: 'hidden',
'&:before': { display: 'none' },
} as const,
ACCORDION_SUMMARY: {
borderBottom: 'none',
} as const,
ACCORDION_TITLE_ICON: {
display: 'flex',
alignItems: 'center',
gap: 2,
} as const,
ACCORDION_TITLE_TEXT: {
fontWeight: 700,
} as const,
/** 主操作按钮(生成/解析) */
PRIMARY_BUTTON: {
py: 1.2,
borderRadius: 3,
bgcolor: 'success.main',
fontWeight: 700,
'&:hover': {
bgcolor: 'success.dark',
},
} as const,
/** 二维码展示区域 */
QR_PREVIEW_CONTAINER: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
minHeight: 200,
border: '2px dashed',
borderColor: 'divider',
borderRadius: 3,
p: 2,
bgcolor: 'action.hover',
} as const,
QR_PREVIEW_INNER: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
width: '100%',
} as const,
QR_PREVIEW_IMAGE: {
width: 250,
height: 250,
display: 'block',
} as const,
QR_PREVIEW_ACTIONS: {
display: 'flex',
gap: 1,
mt: 2,
} as const,
/** 下载按钮 */
DOWNLOAD_BUTTON: {
borderRadius: 2,
borderColor: 'success.main',
color: 'success.main',
'&:hover': {
borderColor: 'success.dark',
bgcolor: (theme: Theme) => alpha(theme.palette.success.main, 0.05),
},
} as const,
/** 复制按钮 */
COPY_BUTTON: {
borderRadius: 2,
bgcolor: 'success.main',
'&:hover': {
bgcolor: 'success.dark',
},
} as const,
/** 拖拽上传区域 */
DROPZONE: (dragging: boolean, hasFile: boolean) => (theme: Theme) =>
({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: 250,
border: '2px dashed',
borderColor: dragging || hasFile ? 'success.main' : 'divider',
borderRadius: 3,
p: 4,
bgcolor: dragging
? alpha(theme.palette.success.main, 0.1)
: hasFile
? alpha(theme.palette.success.main, 0.05)
: 'action.hover',
cursor: 'pointer',
transition: 'all 0.2s',
'&:hover': {
borderColor: 'success.main',
bgcolor: alpha(theme.palette.success.main, 0.05),
},
}) as const,
/** 图片预览容器 */
IMAGE_PREVIEW_WRAPPER: {
textAlign: 'center',
width: '100%',
position: 'relative',
} as const,
IMAGE_PREVIEW_BOX: {
position: 'relative',
display: 'inline-block',
} as const,
IMAGE_PREVIEW_IMG: {
maxWidth: '100%',
maxHeight: 160,
borderRadius: 8,
objectFit: 'contain',
} as const,
/** 清除按钮 */
CLEAR_BUTTON: (theme: Theme) => ({
position: 'absolute',
top: -8,
right: -8,
bgcolor: alpha(theme.palette.error.main, 0.9),
color: 'white',
'&:hover': {
bgcolor: 'error.dark',
},
}),
/** 结果输入框 */
RESULT_INPUT: {
position: 'relative',
mt: 2,
} as const,
/** 提示文本 */
PLACEHOLDER_TEXT: {
textAlign: 'center',
} as const,
INPUT_STYLE: {},
} as const;
};
/**
* 仪表盘页面样式
*/
export const dashboardPageStyles = {
GRID_CONTAINER: {
display: 'grid',
gridTemplateColumns: {
xs: '1fr',
sm: 'repeat(auto-fill, minmax(300px, 1fr))',
},
gridAutoRows: '1fr',
gap: 2,
p: 2,
},
} as const;
/**
* 表单识别页面样式
* 使用语义化的颜色命名:valid(有效)、invalid(无效)、clear(清除)
*/
export const formRecognizerPageStyles = {
primaryColor: 'warning.main',
validColor: 'success.main',
validDark: 'success.dark',
invalidColor: 'warning.main',
invalidDark: 'warning.dark',
clearColor: 'error.main',
clearDark: 'error.dark',
clearBg: (theme: Theme) => surfaceTint(theme, theme.palette.error.main, 0.05),
buttonStyle: {
py: 1.2,
borderRadius: 3,
fontWeight: 700,
},
} as const;
/**
* 表单映射页面样式
*/
export const formMappingPageStyles = {
secondaryColor: 'secondary.main',
} as const;
/**
* 文本统计页面样式
*/
export const textStatisticsPageStyles = {
primaryColor: THEME_COLORS.purple,
cardBg: (theme: Theme) => alpha(theme.palette.secondary.main, 0.04),
cardBorder: (theme: Theme) => alpha(theme.palette.secondary.main, 0.1),
} as const;
};
/**
* Base64 转换器页面样式
*/
export const base64ConverterPageStyles = {
primaryColor: THEME_COLORS.indigo,
cardBg: (theme: Theme) => alpha(theme.palette.info.main, 0.04),
cardBorder: (theme: Theme) => alpha(theme.palette.info.main, 0.1),
} as const;
/**
* Markdown 转 HTML 页面样式
*/
export const markdownToHtmlPageStyles = {
primaryColor: THEME_COLORS.purple,
cardBg: (theme: Theme) => alpha(theme.palette.secondary.main, 0.04),
cardBorder: (theme: Theme) => alpha(theme.palette.secondary.main, 0.1),
} as const;
/**
* HTML 转 Markdown 页面样式
*/
export const htmlToMarkdownPageStyles = {
primaryColor: THEME_COLORS.purple,
cardBg: (theme: Theme) => alpha(theme.palette.secondary.main, 0.04),
cardBorder: (theme: Theme) => alpha(theme.palette.secondary.main, 0.1),
} as const;
/**
* JSON 差异比较工具页面样式
*/
export const jsonDiffPageStyles = {
primaryColor: THEME_COLORS.primary,
addedBg: (theme: Theme) => surfaceTint(theme, theme.palette.success.main, 0.15),
addedBorder: (theme: Theme) => surfaceTint(theme, theme.palette.success.main, 0.4),
addedText: 'success.main',
removedBg: (theme: Theme) => surfaceTint(theme, theme.palette.error.main, 0.15),
removedBorder: (theme: Theme) => surfaceTint(theme, theme.palette.error.main, 0.4),
removedText: 'error.main',
modifiedBg: (theme: Theme) => surfaceTint(theme, theme.palette.warning.main, 0.15),
modifiedBorder: (theme: Theme) => surfaceTint(theme, theme.palette.warning.main, 0.4),
modifiedText: 'warning.main',
INPUT_STYLE: {
'& .MuiOutlinedInput-root': {
bgcolor: 'background.paper',
borderRadius: 3,
fontSize: '0.8rem',
fontFamily: 'monospace',
alignItems: 'flex-start',
transition: 'all 0.2s',
'&:hover': { bgcolor: 'action.hover' },
'&.Mui-focused': {
bgcolor: 'background.paper',
boxShadow: (theme: Theme) => `0 0 0 4px ${alpha(theme.palette.primary.main, 0.1)}`,
},
'&.Mui-error': {
boxShadow: (theme: Theme) => `0 0 0 4px ${alpha(theme.palette.error.main, 0.1)}`,
},
},
},
TREE_CONTAINER: {
p: 1.5,
borderRadius: 3,
bgcolor: 'background.paper',
border: '1px solid',
borderColor: 'divider',
fontFamily: 'monospace',
fontSize: '0.8rem',
overflowX: 'auto',
minHeight: 200,
maxHeight: 480,
overflowY: 'auto',
},
NAVIGATOR: (theme: Theme) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 1.5,
p: 1,
borderRadius: 3,
bgcolor: alpha(theme.palette.primary.main, 0.05),
border: '1px solid',
borderColor: alpha(theme.palette.primary.main, 0.15),
}),
} as const;
};
-153
View File
@@ -1,153 +0,0 @@
import { createTheme, type PaletteMode, type Theme } from '@mui/material/styles';
import { THEME_COLORS } from './pageTheme';
/**
* 按模式生成 MUI 主题
*
* - light:使用 THEME_COLORS 中饱和度较高的版本作为 main
* - dark:使用 *Light 变体作为 main,保证暗底对比度满足 WCAG AA
*
* 所有调色板槽位均显式指定,不依赖 MUI 默认值。
*/
export function getTheme(mode: PaletteMode): Theme {
const isDark = mode === 'dark';
return createTheme({
palette: {
mode,
primary: {
main: isDark ? THEME_COLORS.primaryLight : THEME_COLORS.primary,
dark: THEME_COLORS.primaryDark,
light: THEME_COLORS.primaryLight,
},
secondary: {
main: isDark ? THEME_COLORS.purpleLight : THEME_COLORS.purple,
dark: THEME_COLORS.purpleDark,
light: THEME_COLORS.purpleLight,
},
success: {
main: isDark ? THEME_COLORS.successLight : THEME_COLORS.success,
dark: THEME_COLORS.successDark,
light: THEME_COLORS.successLight,
},
warning: {
main: isDark ? THEME_COLORS.warningLight : THEME_COLORS.warning,
dark: THEME_COLORS.warningDark,
light: THEME_COLORS.warningLight,
},
error: {
main: isDark ? THEME_COLORS.errorLight : THEME_COLORS.error,
dark: THEME_COLORS.errorDark,
light: THEME_COLORS.errorLight,
},
info: {
main: isDark ? THEME_COLORS.indigoLight : THEME_COLORS.indigo,
dark: THEME_COLORS.indigoDark,
light: THEME_COLORS.indigoLight,
},
background: {
default: isDark ? '#121212' : '#f5f5f5',
paper: isDark ? '#1e1e1e' : '#ffffff',
},
divider: isDark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)',
},
typography: {
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
},
components: {
MuiCssBaseline: {
styleOverrides: (theme) => ({
':root': {
'--sb-width': '6px',
'--sb-thumb-color':
theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.1)',
'--sb-thumb-hover':
theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.25)' : 'rgba(0, 0, 0, 0.2)',
'--sb-track-color': 'transparent',
},
html: {
margin: 0,
padding: 0,
width: '100%',
minHeight: '100%',
backgroundColor: theme.palette.background.default,
},
'body, #root': {
margin: 0,
padding: 0,
width: '100%',
minHeight: '100%',
},
body: {
WebkitFontSmoothing: 'antialiased',
MozOsxFontSmoothing: 'grayscale',
backgroundColor: theme.palette.background.default,
color: theme.palette.text.primary,
},
code: {
fontFamily: 'source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace',
},
'h1, h2, h3, h4, h5, h6': {
fontSize: 'inherit',
fontWeight: 'inherit',
},
/* 全局极简滚动条定制 */
'*::-webkit-scrollbar': {
width: 'var(--sb-width)',
},
'*::-webkit-scrollbar-track': {
background: 'var(--sb-track-color)',
},
'*::-webkit-scrollbar-thumb': {
background: 'var(--sb-thumb-color)',
borderRadius: '10px',
backgroundClip: 'content-box',
border: '1px solid transparent',
},
'*::-webkit-scrollbar-thumb:hover': {
background: 'var(--sb-thumb-hover)',
},
/* Animations */
'@keyframes slideInRight': {
from: {
transform: 'translateX(30px)',
opacity: 0,
},
to: {
transform: 'translateX(0)',
opacity: 1,
},
},
'@keyframes fadeIn': {
from: {
opacity: 0,
},
to: {
opacity: 1,
},
},
'.page-transition-enter': {
animation: 'slideInRight 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards',
},
'.page-transition-dashboard': {
animation: 'fadeIn 0.3s ease-out forwards',
},
}),
},
},
});
}
const theme = getTheme('light');
export default theme;
+30 -561
View File
@@ -13,10 +13,6 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^9.0.1",
"@mui/material": "^9.0.1",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-slot": "^1.2.4",
"@testing-library/dom": "^10.4.1",
@@ -337,6 +333,7 @@
"version": "7.29.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
@@ -380,6 +377,7 @@
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -389,6 +387,7 @@
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
"integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.28.6",
@@ -486,6 +485,7 @@
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
"integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.28.6",
@@ -500,6 +500,7 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
"integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.29.0",
@@ -843,152 +844,6 @@
"tslib": "^2.4.0"
}
},
"node_modules/@emotion/babel-plugin": {
"version": "11.13.5",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
"integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/serialize": "^1.3.3",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/cache": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
"integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.9.0",
"@emotion/sheet": "^1.4.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
"license": "MIT"
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz",
"integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.9.0"
}
},
"node_modules/@emotion/memoize": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
"license": "MIT"
},
"node_modules/@emotion/react": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
"integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
"license": "MIT",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
"@emotion/utils": "^1.4.2",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
"integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
"license": "MIT"
},
"node_modules/@emotion/styled": {
"version": "11.14.1",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/is-prop-valid": "^1.3.0",
"@emotion/serialize": "^1.3.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
"@emotion/utils": "^1.4.2"
},
"peerDependencies": {
"@emotion/react": "^11.0.0-rc.0",
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/unitless": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
"license": "MIT"
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
"integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
"integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==",
"license": "MIT"
},
"node_modules/@emotion/weak-memoize": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.27.7",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
@@ -1709,6 +1564,7 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1762,239 +1618,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@mui/core-downloads-tracker": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-9.0.1.tgz",
"integrity": "sha512-GzamIIhZ1bH77dq7eKaeyRgJdkypsxin4jBFq2EMs4lBWRR0LFO1CSVMsoebn/VvjcNrnrOrjy48MkrkQUK2iw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
}
},
"node_modules/@mui/icons-material": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-9.0.1.tgz",
"integrity": "sha512-5PRpQjVLTNLyV/2J9J53Yz4R0tVbodG0BQDN2zQI1QBG1OPYM25ar+4N20eyFOfJT6zKglLzsnU70+zdVLaTkw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@mui/material": "^9.0.1",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/material": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.1.tgz",
"integrity": "sha512-voyCpeUxcSWLN7KPZuq0pGCIt726T9K6kiVM3XUcywZDAlZSarLHaUxJVQpospbjjOzN53hwyjo8s6KoWl6utw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2",
"@mui/core-downloads-tracker": "^9.0.1",
"@mui/system": "^9.0.1",
"@mui/types": "^9.0.0",
"@mui/utils": "^9.0.1",
"@popperjs/core": "^2.11.8",
"@types/react-transition-group": "^4.4.12",
"clsx": "^2.1.1",
"csstype": "^3.2.3",
"prop-types": "^15.8.1",
"react-is": "^19.2.4",
"react-transition-group": "^4.4.5"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@mui/material-pigment-css": "^9.0.1",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
},
"@mui/material-pigment-css": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/private-theming": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-9.0.1.tgz",
"integrity": "sha512-pSIGq4Yw749KHEwlkYZWVERgHgwJELP6ODtBNUfV8V4oIb5H+h7IQDFXuk/b2oQccODK1enJAtiEzlgLZmq+8g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2",
"@mui/utils": "^9.0.1",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/styled-engine": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-9.0.0.tgz",
"integrity": "sha512-9RLGdX4Jg0aQPRuvqh/OLzYSPlgd5zyEw5/1HIRfdavSiOd03WtUaGZH9/w1RoTYuRKwpgy0hpIFaMHIqPVIWg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2",
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/sheet": "^1.4.0",
"csstype": "^3.2.3",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
}
}
},
"node_modules/@mui/system": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-9.0.1.tgz",
"integrity": "sha512-WvlioaLxk6ewUIOfh0StxUvOPDS1mCfzaulcudsL1brZNXuh0N9FMk7RpH7ImJKjEz412SEy/V/yvqmtxbqxCQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2",
"@mui/private-theming": "^9.0.1",
"@mui/styled-engine": "^9.0.0",
"@mui/types": "^9.0.0",
"@mui/utils": "^9.0.1",
"clsx": "^2.1.1",
"csstype": "^3.2.3",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/types": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@mui/types/-/types-9.0.0.tgz",
"integrity": "sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/utils": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.0.1.tgz",
"integrity": "sha512-f3UO3jNN1pYg5zxqXC81Bvv8hx5ACcYc0387382ZI7M5ono1heIwHYLrKsz85myguWdeVKPRZGmDdynWUBjK2g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2",
"@mui/types": "^9.0.0",
"@types/prop-types": "^15.7.15",
"clsx": "^2.1.1",
"prop-types": "^15.8.1",
"react-is": "^19.2.4"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
@@ -2105,16 +1728,6 @@
"node": ">=12"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@radix-ui/primitive": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
@@ -2945,22 +2558,11 @@
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==",
"license": "MIT"
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
"license": "MIT"
},
"node_modules/@types/prop-types": {
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
"license": "MIT"
},
"node_modules/@types/react": {
"version": "19.2.15",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
"integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.2.2"
@@ -2976,15 +2578,6 @@
"@types/react": "^19.2.0"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
"integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*"
}
},
"node_modules/@types/webextension-polyfill": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.12.5.tgz",
@@ -3980,21 +3573,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">=10",
"npm": ">=6"
}
},
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -4330,6 +3908,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -4734,12 +4313,6 @@
"node": "^14.18.0 || >=16.10.0"
}
},
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"license": "MIT"
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -4747,31 +4320,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"license": "MIT",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/cosmiconfig/node_modules/yaml": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
"integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
"license": "ISC",
"engines": {
"node": ">= 6"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -4862,6 +4410,7 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"devOptional": true,
"license": "MIT"
},
"node_modules/data-urls": {
@@ -4949,6 +4498,7 @@
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -5136,16 +4686,6 @@
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"license": "MIT"
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
@@ -5345,6 +4885,7 @@
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.2.1"
@@ -5433,6 +4974,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -5608,6 +5150,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -6111,12 +5654,6 @@
"node": ">=8"
}
},
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"license": "MIT"
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -6258,6 +5795,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -6666,6 +6204,7 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -6691,21 +6230,6 @@
"hermes-estree": "0.25.1"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/hookable": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.1.tgz",
@@ -6848,6 +6372,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
@@ -6958,6 +6483,7 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true,
"license": "MIT"
},
"node_modules/is-async-function": {
@@ -7043,6 +6569,7 @@
"version": "2.16.2",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
"integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"hasown": "^2.0.3"
@@ -7686,6 +7213,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
@@ -7701,12 +7229,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"license": "MIT"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -8184,6 +7706,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true,
"license": "MIT"
},
"node_modules/linkedom": {
@@ -8447,6 +7970,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -8696,6 +8220,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/multimatch": {
@@ -8953,6 +8478,7 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -9249,6 +8775,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
@@ -9257,24 +8784,6 @@
"node": ">=6"
}
},
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
"json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse5": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
@@ -9312,17 +8821,9 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true,
"license": "MIT"
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -9724,6 +9225,7 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -9735,6 +9237,7 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true,
"license": "MIT"
},
"node_modules/proto-list": {
@@ -9956,12 +9459,6 @@
}
}
},
"node_modules/react-is": {
"version": "19.2.6",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz",
"integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==",
"license": "MIT"
},
"node_modules/react-remove-scroll": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
@@ -10031,22 +9528,6 @@
}
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"license": "BSD-3-Clause",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -10222,6 +9703,7 @@
"version": "1.22.12",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
"integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -10243,6 +9725,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
@@ -10741,15 +10224,6 @@
"atomic-sleep": "^1.0.0"
}
},
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -11088,12 +10562,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
"license": "MIT"
},
"node_modules/sucrase": {
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
@@ -11143,6 +10611,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
-4
View File
@@ -24,10 +24,6 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^9.0.1",
"@mui/material": "^9.0.1",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-slot": "^1.2.4",
"@testing-library/dom": "^10.4.1",
+6 -24
View File
@@ -7,20 +7,14 @@ import {
useMemo,
useState,
} from 'react';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { getTheme } from '@/config/theme';
import { storageUtil } from '@/utils/chromeStorage';
export type ThemeMode = 'light' | 'dark' | 'system';
export type ResolvedThemeMode = 'light' | 'dark';
interface ThemeModeContextType {
/** 用户显式选择的模式(含 system) */
mode: ThemeMode;
/** 实际解析后的模式(不含 system) */
resolvedMode: ResolvedThemeMode;
/** 切换模式 */
setMode: (mode: ThemeMode) => void;
}
@@ -57,9 +51,6 @@ export function ThemeModeProvider({ children }: ThemeModeProviderProps) {
const [resolvedMode, setResolvedMode] = useState<ResolvedThemeMode>(
mode === 'system' ? getSystemMode() : mode,
);
const [, setIsLoaded] = useState(false);
const muiTheme = useMemo(() => getTheme(resolvedMode), [resolvedMode]);
const updateResolved = useCallback((nextMode: ThemeMode) => {
setResolvedMode(nextMode === 'system' ? getSystemMode() : nextMode);
@@ -75,7 +66,6 @@ export function ThemeModeProvider({ children }: ThemeModeProviderProps) {
[updateResolved],
);
// 异步校准:从 chrome.storage 读取持久化值
useEffect(() => {
let cancelled = false;
storageUtil
@@ -87,16 +77,12 @@ export function ThemeModeProvider({ children }: ThemeModeProviderProps) {
updateResolved(saved);
}
})
.catch(console.error)
.finally(() => {
if (!cancelled) setIsLoaded(true);
});
.catch(console.error);
return () => {
cancelled = true;
};
}, [updateResolved]);
// 监听系统主题变化(仅在 system 模式下生效)
useEffect(() => {
if (mode !== 'system') return;
const mq = window.matchMedia('(prefers-color-scheme: dark)');
@@ -107,7 +93,6 @@ export function ThemeModeProvider({ children }: ThemeModeProviderProps) {
return () => mq.removeEventListener('change', handler);
}, [mode]);
// 跨入口同步:监听 chrome.storage.onChanged
useEffect(() => {
const handleStorageChange = (changes: { [key: string]: chrome.storage.StorageChange }) => {
if (changes[THEME_MODE_KEY]) {
@@ -122,19 +107,16 @@ export function ThemeModeProvider({ children }: ThemeModeProviderProps) {
return () => chrome.storage.onChanged.removeListener(handleStorageChange);
}, [mode, updateResolved]);
useEffect(() => {
document.documentElement.classList.toggle('dark', resolvedMode === 'dark');
}, [resolvedMode]);
const contextValue = useMemo(
() => ({ mode, resolvedMode, setMode }),
[mode, resolvedMode, setMode],
);
return (
<ThemeModeContext.Provider value={contextValue}>
<ThemeProvider theme={muiTheme}>
<CssBaseline />
{children}
</ThemeProvider>
</ThemeModeContext.Provider>
);
return <ThemeModeContext.Provider value={contextValue}>{children}</ThemeModeContext.Provider>;
}
export function useThemeMode(): ThemeModeContextType {