From a93a8b3e9a28c624fc409ec1936ab185e64daee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Thu, 12 Feb 2026 21:26:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E4=BC=98=E5=8C=96=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=88=B3=E5=B7=A5=E5=85=B7=EF=BC=8C=E4=BC=98=E5=8C=96CopyButto?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entrypoints/background.ts | 59 +- entrypoints/popup/App.css | 2 +- entrypoints/popup/components/CopyButton.tsx | 159 ++-- .../popup/components/DatetimeToTimestamp.tsx | 202 +++-- entrypoints/popup/components/Navbar.tsx | 14 +- .../popup/components/TimestampExecution.tsx | 116 +-- .../popup/components/TimestampToDatetime.tsx | 255 ++++--- entrypoints/popup/pages/RecordeReplayPage.tsx | 11 +- package-lock.json | 701 +++++++++++++++++- package.json | 4 + 10 files changed, 1124 insertions(+), 399 deletions(-) diff --git a/entrypoints/background.ts b/entrypoints/background.ts index 189c7d4..8de3338 100644 --- a/entrypoints/background.ts +++ b/entrypoints/background.ts @@ -59,8 +59,17 @@ export default defineBackground(() => { .then((res) => { sendResponse(res); }) - .catch(() => { - console.error('Failed to check status in content script'); + .catch((error: Error) => { + if (error.message.includes('restricted URL')) { + console.warn( + 'Could not check status: on a restricted page.', + error.message, + ); + } else if (error.message.includes('No active tab found')) { + console.warn('Could not check status: no active tab found.'); + } else { + console.error('Failed to check status in content script', error); + } sendResponse({ ok: false }); }); return true; @@ -73,8 +82,17 @@ export default defineBackground(() => { await chrome.runtime.sendMessage({ type: messages.popup.to.started }); sendResponse({ ok: true }); }) - .catch(() => { - console.error('Failed to start recording in content script'); + .catch((error: Error) => { + if (error.message.includes('restricted URL')) { + console.warn( + 'Could not start recording: on a restricted page.', + error.message, + ); + } else if (error.message.includes('No active tab found')) { + console.warn('Could not start recording: no active tab found.'); + } else { + console.error('Failed to start recording in content script', error); + } sendResponse({ ok: false }); }); } @@ -87,7 +105,17 @@ export default defineBackground(() => { downloadHtmlInBackground(events); sendResponse({ ok: true }); }) - .catch(() => { + .catch((error: Error) => { + if (error.message.includes('restricted URL')) { + console.warn( + 'Could not stop recording: on a restricted page.', + error.message, + ); + } else if (error.message.includes('No active tab found')) { + console.warn('Could not stop recording: no active tab found.'); + } else { + console.error('Failed to stop recording in content script', error); + } sendResponse({ ok: false }); }); } @@ -115,6 +143,27 @@ export default defineBackground(() => { currentWindow: true, }); const activeTab = activeTabs[0]; + + if (!activeTab) { + throw new Error('No active tab found.'); + } + + // 检查URL是否受限 + if (activeTab?.url) { + const restrictedProtocols = [ + 'chrome:', + 'chrome-extension:', + 'about:', + 'edge:', + 'view-source:', + 'data:', + 'file:', + ]; + if (restrictedProtocols.some((protocol) => activeTab.url!.startsWith(protocol))) { + throw new Error(`Cannot send message to a restricted URL: ${activeTab.url}`); + } + } + const sendTo = message.activeTabId || activeTab.id; try { return await chrome.tabs.sendMessage(sendTo!, message); diff --git a/entrypoints/popup/App.css b/entrypoints/popup/App.css index ba8e741..4ac0fca 100644 --- a/entrypoints/popup/App.css +++ b/entrypoints/popup/App.css @@ -32,7 +32,7 @@ body { margin: 0 auto; padding: 20px; font-family: Arial, sans-serif; - width: 100%; + width: 380px; min-width: 320px; min-height: 100%; box-sizing: border-box; diff --git a/entrypoints/popup/components/CopyButton.tsx b/entrypoints/popup/components/CopyButton.tsx index 20d467e..fd196bf 100644 --- a/entrypoints/popup/components/CopyButton.tsx +++ b/entrypoints/popup/components/CopyButton.tsx @@ -1,90 +1,133 @@ -import { useEffect, useState, useCallback } from 'react'; +import { useState, useCallback, FC, ReactNode, useEffect } from 'react'; +import Button, { ButtonProps } from '@mui/material/Button'; +import Snackbar from '@mui/material/Snackbar'; +import Alert, { AlertColor } from '@mui/material/Alert'; +import ContentCopyIcon from '@mui/icons-material/ContentCopy'; +import CheckIcon from '@mui/icons-material/Check'; -const CopyButton = ({ - text = '要复制的文本', - buttonText = '复制文本', - className = 'action-btn', +type CopyStatus = 'idle' | 'copying' | 'success' | 'error'; + +interface CopyButtonProps extends Omit { + textToCopy: string | number; + buttonText?: ReactNode; + successMessage?: string; + errorMessage?: string; + variant?: ButtonProps['variant']; +} + +const CopyButton: FC = ({ + textToCopy, + buttonText = '复制', successMessage = '复制成功!', errorMessage = '复制失败,请手动复制。', - copyingMessage = '复制中...', + variant = 'contained', + ...buttonProps }) => { - const [status, setStatus] = useState('idle'); // 'idle' | 'copying' | 'success' | 'error' + const [status, setStatus] = useState('idle'); + const [openSnackbar, setOpenSnackbar] = useState(false); + const [snackbarContent, setSnackbarContent] = useState<{ + message: string; + severity: AlertColor; + } | null>(null); useEffect(() => { - let timer: number; if (status === 'success' || status === 'error') { - timer = window.setTimeout(() => { - setStatus('idle'); - }, 2000); + const timer = setTimeout(() => setStatus('idle'), 2000); + return () => clearTimeout(timer); } - - return () => clearTimeout(timer); + return undefined; }, [status]); const performCopy = useCallback(async () => { - if (!text) { + if (!textToCopy) { console.warn('没有提供要复制的文本'); return false; } - - const safeText = String(text); - - if (navigator.clipboard && navigator.clipboard.writeText) { - try { - await navigator.clipboard.writeText(safeText); - return true; - } catch (err) { - console.error('使用 Clipboard API 复制失败:', err); - return false; - } + const safeText = String(textToCopy); + try { + await navigator.clipboard.writeText(safeText); + return true; + } catch (err) { + console.error('使用 Clipboard API 复制失败:', err); + return false; } - - return false; - }, [text]); + }, [textToCopy]); const handleClick = useCallback(async () => { - setStatus('copying'); + if (status !== 'idle') return; + setStatus('copying'); + let isSuccess = false; try { - const isSuccess = await performCopy(); - setStatus(isSuccess ? 'success' : 'error'); + [isSuccess] = await Promise.all([ + performCopy(), + new Promise((resolve) => setTimeout(resolve, 300)), + ]); } catch (error) { console.error('复制时出错:', error); - setStatus('error'); + isSuccess = false; + } finally { + const newStatus = isSuccess ? 'success' : 'error'; + setStatus(newStatus); + setSnackbarContent({ + message: isSuccess ? successMessage : errorMessage, + severity: newStatus, + }); + setOpenSnackbar(true); } - }, [performCopy]); + }, [performCopy, status, successMessage, errorMessage]); - // 根据状态计算当前显示的文本 - const currentText = - status === 'success' - ? successMessage - : status === 'error' - ? errorMessage - : status === 'copying' - ? copyingMessage - : buttonText; + const handleCloseSnackbar = (_event?: Event | React.SyntheticEvent, reason?: string) => { + if (reason === 'clickaway') return; + setOpenSnackbar(false); + }; - // 动态样式:只在非默认状态下覆盖颜色,平时让 className 控制 - const getStyle = () => { + const renderButtonIcon = () => { if (status === 'success') { - return { backgroundColor: '#4CAF50', color: 'white' }; + return ; } - if (status === 'error') { - return { backgroundColor: '#f44336', color: 'white' }; - } - - return {}; + return ; }; return ( - + <> + + + {snackbarContent ? ( + + {snackbarContent.message} + + ) : undefined} + + ); }; diff --git a/entrypoints/popup/components/DatetimeToTimestamp.tsx b/entrypoints/popup/components/DatetimeToTimestamp.tsx index 52885c0..8a6893e 100644 --- a/entrypoints/popup/components/DatetimeToTimestamp.tsx +++ b/entrypoints/popup/components/DatetimeToTimestamp.tsx @@ -1,26 +1,19 @@ import { useState, useCallback } from 'react'; import dayjs from '@/utils/dayjs'; +import { + Button, + TextField, + Select, + MenuItem, + FormControl, + InputLabel, + Paper, + Typography, + Stack, + Box, + SelectChangeEvent, +} from '@mui/material'; -/** - * 日期时间转时间戳组件 - * - * 功能特性: - * 1. 将日期时间字符串转换为时间戳 - * 2. 支持多种时区选择 - * 3. 支持毫秒和秒单位切换 - * 4. 提供输入验证和错误提示 - * 5. 实时单位转换 - * - * @component - * @example - * ```jsx - * - * ``` - * - * @returns {JSX.Element} 日期时间转时间戳组件 - */ - -// 常用时区列表 const TIME_ZONE_LIST = [ 'America/New_York', 'America/Chicago', @@ -42,48 +35,32 @@ const TIME_ZONE_LIST = [ 'Pacific/Auckland', ]; -// 时间戳单位选项 const TIMESTAMP_UNITS = [ - { value: 'milliseconds', label: '毫秒(ms)' }, - { value: 'seconds', label: '秒(s)' }, + { value: 'milliseconds', label: '毫秒 (ms)' }, + { value: 'seconds', label: '秒 (s)' }, ]; export function DatetimeToTimestamp() { const [dateValue, setDateValue] = useState(() => dayjs().format('YYYY/MM/DD HH:mm:ss')); - const [selectedZone, setSelectedZone] = useState('Asia/Shanghai'); - const [result, setResult] = useState(''); - const [unit, setUnit] = useState('milliseconds'); - const [error, setError] = useState(''); const performConversion = useCallback( (currentDate: string, zone: string, currentUnit: string) => { - try { - if (!currentDate) { - setError('请输入有效的日期时间'); - return ''; - } - - const timestamp = dayjs.tz(currentDate, zone); - - if (!timestamp.isValid()) { - setError('无效的日期时间格式'); - return ''; - } - - setError(''); - - const ms = timestamp.valueOf(); - return currentUnit === TIMESTAMP_UNITS[0].value - ? ms.toString() - : Math.floor(ms / 1000).toString(); - } catch (err) { - console.error('转换错误:', err); + if (!currentDate) { + setError('请输入有效的日期时间'); return ''; } + const timestamp = dayjs.tz(currentDate, zone); + if (!timestamp.isValid()) { + setError('无效的日期时间格式'); + return ''; + } + setError(''); + const ms = timestamp.valueOf(); + return currentUnit === 'milliseconds' ? ms.toString() : Math.floor(ms / 1000).toString(); }, [], ); @@ -93,15 +70,10 @@ export function DatetimeToTimestamp() { setResult(newResult); }, [dateValue, selectedZone, unit, performConversion]); - /** - * 处理时间戳单位变化 - */ const handleUnitChange = useCallback( - (e: React.ChangeEvent) => { + (e: SelectChangeEvent) => { const newUnit = e.target.value; setUnit(newUnit); - - // 如果已有结果,重新计算 if (result) { setResult(performConversion(dateValue, selectedZone, newUnit) || ''); } @@ -109,77 +81,79 @@ export function DatetimeToTimestamp() { [dateValue, selectedZone, result, performConversion], ); - return ( -
-

日期时间转时间戳

+ const handleZoneChange = useCallback((e: SelectChangeEvent) => { + setSelectedZone(e.target.value); + }, []); -
-
- + + 日期时间转时间戳 + + + + { setDateValue(e.target.value); if (error) setError(''); }} - aria-label="输入要转换的日期时间" - title="支持格式: YYYY-MM-DD HH:mm:ss" + error={!!error} + helperText={error || '格式: YYYY/MM/DD HH:mm:ss'} + fullWidth + variant="outlined" /> - -
+ + 时区 + + + - {error && ( -
- ⚠️ {error} -
- )} - -
- -
+ + -
- + - -
-
-
+ + 单位 + + + + + ); } diff --git a/entrypoints/popup/components/Navbar.tsx b/entrypoints/popup/components/Navbar.tsx index 8e190eb..c965751 100644 --- a/entrypoints/popup/components/Navbar.tsx +++ b/entrypoints/popup/components/Navbar.tsx @@ -1,5 +1,8 @@ import { NavLink } from 'react-router-dom'; import { useState, useEffect, ReactNode } from 'react'; +import { IconButton } from '@mui/material'; +import MenuIcon from '@mui/icons-material/Menu'; +import CloseIcon from '@mui/icons-material/Close'; interface RouteItem { path: string; @@ -76,16 +79,13 @@ function Navbar({ items = [] }: NavbarProps) { ))} - + {isMenuOpen ? : } + )} diff --git a/entrypoints/popup/components/TimestampExecution.tsx b/entrypoints/popup/components/TimestampExecution.tsx index efb9217..279562a 100644 --- a/entrypoints/popup/components/TimestampExecution.tsx +++ b/entrypoints/popup/components/TimestampExecution.tsx @@ -1,5 +1,6 @@ import { useEffect, useState, useCallback } from 'react'; import CopyButton from './CopyButton'; +import { Button, Paper, Typography, Stack, Box } from '@mui/material'; /** * 时间戳显示和执行组件 @@ -13,109 +14,110 @@ import CopyButton from './CopyButton'; * @returns {JSX.Element} 时间戳组件 */ export function TimestampExecution() { - /** @type {[number, function]} 当前时间戳(毫秒)和更新函数 */ - const [currentTimestamp, setCurrentTimestamp] = useState(() => Math.floor(Date.now())); - - /** @type {[boolean, function]} 是否显示毫秒(true=毫秒,false=秒) */ + const [currentTimestamp, setCurrentTimestamp] = useState(() => + Math.floor(Date.now()), + ); const [showMilliseconds, setShowMilliseconds] = useState(true); - - /** @type {[boolean, function]} 时间戳是否正在自动更新 */ const [isRunningTimestamp, setIsRunningTimestamp] = useState(true); - /** - * 计算显示的时间戳值 - * @type {number} - */ const displayTimestamp = showMilliseconds ? currentTimestamp : Math.floor(currentTimestamp / 1000); const unitText = showMilliseconds ? '毫秒' : '秒'; - /** - * 定时更新时间戳的副作用 - * 根据 isRunningTimestamp 和 showMilliseconds 控制定时器的启停和间隔 - */ useEffect(() => { let timer: number; - if (isRunningTimestamp) { const interval = showMilliseconds ? 100 : 1000; timer = window.setInterval(() => { setCurrentTimestamp(Math.floor(Date.now())); }, interval); } - - // 清理函数 return () => clearInterval(timer); }, [isRunningTimestamp, showMilliseconds]); - /** - * 切换时间戳显示单位(毫秒/秒) - */ const toggleUnit = useCallback(() => { setShowMilliseconds((prev) => !prev); }, []); - /** - * 切换时间戳自动更新状态(启动/停止) - */ const toggleTimestamp = useCallback(() => { setIsRunningTimestamp((prev) => !prev); }, []); - /** - * 切换单位按钮的辅助文本 - * @type {string} - */ - const unitButtonLabel = showMilliseconds ? '切换为秒显示' : '切换为毫秒显示'; - - /** - * 启动/停止按钮的辅助文本 - * @type {string} - */ - const toggleButtonLabel = isRunningTimestamp ? '停止时间戳自动更新' : '开始时间戳自动更新'; - - /** - * 启动/停止按钮的显示文本 - * @type {string} - */ + const unitButtonLabel = showMilliseconds + ? '切换为秒显示' + : '切换为毫秒显示'; + const toggleButtonLabel = isRunningTimestamp + ? '停止时间戳自动更新' + : '开始时间戳自动更新'; const toggleButtonText = isRunningTimestamp ? '停止' : '开始'; return ( -
-
- {displayTimestamp} - {unitText} -
+ + + + {displayTimestamp} + + + {unitText} + + -
- + - -
-
+ + + ); } diff --git a/entrypoints/popup/components/TimestampToDatetime.tsx b/entrypoints/popup/components/TimestampToDatetime.tsx index 264c9ef..ed464a2 100644 --- a/entrypoints/popup/components/TimestampToDatetime.tsx +++ b/entrypoints/popup/components/TimestampToDatetime.tsx @@ -1,19 +1,24 @@ import { useState, useCallback } from 'react'; +import dayjs from 'dayjs'; +import { + Button, + TextField, + Select, + MenuItem, + FormControl, + InputLabel, + Paper, + Typography, + Stack, + Box, + SelectChangeEvent, +} from '@mui/material'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; -/** - * 时间戳转日期时间组件 - * - * 功能特性: - * 1. 将时间戳转换为日期时间字符串 - * 2. 支持多种时区选择 - * 3. 支持毫秒和秒单位切换 - * 4. 提供输入验证和错误提示 - * ``` - * - * @returns {JSX.Element} 时间戳转日期时间组件 - */ +dayjs.extend(utc); +dayjs.extend(timezone); -// 常用时区列表 const TIME_ZONE_LIST = [ 'America/New_York', 'America/Chicago', @@ -35,10 +40,9 @@ const TIME_ZONE_LIST = [ 'Pacific/Auckland', ]; -// 时间戳单位选项 const TIMESTAMP_UNITS = [ - { value: 'milliseconds', label: '毫秒(ms)' }, - { value: 'seconds', label: '秒(s)' }, + { value: 'milliseconds', label: '毫秒 (ms)' }, + { value: 'seconds', label: '秒 (s)' }, ]; export function TimestampToDatetime() { @@ -48,136 +52,129 @@ export function TimestampToDatetime() { const [selectedZone, setSelectedZone] = useState('Asia/Shanghai'); const [error, setError] = useState(''); - const performConversion = useCallback( - (timestampValue: string, selectedZone: string, unit: string) => { - if (!timestampValue || timestampValue.trim() === '') { - setError('请输入有效的日期时间'); - return ''; - } - - try { - const numberValue = Number(timestampValue); - if (isNaN(numberValue)) { - setError('时间戳必须是数字'); - return ''; - } - - const d = unit === TIMESTAMP_UNITS[0].value ? dayjs(numberValue) : dayjs.unix(numberValue); - - if (!d.isValid()) { - setError('无效的时间戳格式'); - return ''; - } - - const dateTime = d.tz(selectedZone).format('YYYY/MM/DD HH:mm:ss'); - - setError(''); - return dateTime; - } catch (err) { - console.error('转换错误:', err); - return ''; - } - }, - [], - ); + const performConversion = useCallback((val: string, zone: string, u: string) => { + if (!val || val.trim() === '') { + setError('请输入有效的时间戳'); + return ''; + } + const numberValue = Number(val); + if (isNaN(numberValue)) { + setError('时间戳必须是数字'); + return ''; + } + const d = u === 'milliseconds' ? dayjs(numberValue) : dayjs.unix(numberValue); + if (!d.isValid()) { + setError('无效的时间戳格式'); + return ''; + } + setError(''); + return d.tz(zone).format('YYYY/MM/DD HH:mm:ss'); + }, []); const handleConvert = useCallback(() => { const newResult = performConversion(timestampValue, selectedZone, unit); setTimestampResult(newResult); }, [timestampValue, selectedZone, unit, performConversion]); - /** - * 处理时间戳输入变化 - */ - const handleInputChange = useCallback((e) => { - setTimestampValue(e.target.value); - setError(''); // 清除错误信息 - }, []); + const handleInputChange = useCallback( + (e: React.ChangeEvent) => { + setTimestampValue(e.target.value); + if (error) setError(''); + }, + [error], + ); - /** - * 处理时区选择变化 - */ - const handleZoneChange = useCallback((e: React.ChangeEvent) => { - const newZone = e.target.value; - setSelectedZone(newZone); - }, []); + const handleZoneChange = useCallback( + (e: SelectChangeEvent) => { + const newZone = e.target.value; + setSelectedZone(newZone); + if (timestampResult) { + const newResult = performConversion(timestampValue, newZone, unit); + setTimestampResult(newResult || ''); + } + }, + [performConversion, timestampResult, timestampValue, unit], + ); - /** - * 处理时间戳单位变化 - */ - const handleUnitChange = useCallback((e: React.ChangeEvent) => { - const newUnit = e.target.value; - setUnit(newUnit); - }, []); + const handleUnitChange = useCallback( + (e: SelectChangeEvent) => { + const newUnit = e.target.value; + setUnit(newUnit); + if (timestampResult) { + const newResult = performConversion(timestampValue, selectedZone, newUnit); + setTimestampResult(newResult || ''); + } + }, + [performConversion, timestampResult, timestampValue, selectedZone], + ); return ( -
-

时间戳转日期时间

- -
-
- + + 时间戳转日期时间 + + + + - -
+ + 单位 + + + - {error && ( -
- ⚠️ {error} -
- )} - -
- -
+ + -
- + - -
-
-
+ + 时区 + + + + + ); } diff --git a/entrypoints/popup/pages/RecordeReplayPage.tsx b/entrypoints/popup/pages/RecordeReplayPage.tsx index 6055090..6d42dc0 100644 --- a/entrypoints/popup/pages/RecordeReplayPage.tsx +++ b/entrypoints/popup/pages/RecordeReplayPage.tsx @@ -1,6 +1,7 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useMemo } from 'react'; import { AppState } from '../types'; import { messages } from '@/utils/messages'; +import { Button } from '@mui/material'; const RecordeReplayPage = () => { const [status, setStatus] = useState(AppState.READ); @@ -53,12 +54,14 @@ const RecordeReplayPage = () => { return (
- +
); diff --git a/package-lock.json b/package-lock.json index 0f7b715..6235753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,10 @@ "version": "0.0.0", "hasInstallScript": true, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/icons-material": "^7.3.8", + "@mui/material": "^7.3.8", "@rrweb/all": "^2.0.0-alpha.18", "@rrweb/rrweb-plugin-console-record": "^2.0.0-alpha.18", "@rrweb/rrweb-plugin-console-replay": "^2.0.0-alpha.18", @@ -223,7 +227,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.6.tgz", "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.6", @@ -257,7 +260,6 @@ "version": "7.28.0", "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -267,7 +269,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@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", @@ -309,7 +310,6 @@ "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -352,7 +352,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.6.tgz", "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.6" @@ -409,7 +408,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@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", @@ -424,7 +422,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.6.tgz", "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.28.6", @@ -443,7 +440,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.6.tgz", "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -513,6 +509,179 @@ } } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmmirror.com/@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/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.2", "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", @@ -1227,7 +1396,6 @@ "version": "0.3.13", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1249,7 +1417,6 @@ "version": "3.1.2", "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1270,20 +1437,326 @@ "version": "1.5.5", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.8.tgz", + "integrity": "sha512-s9UHZo7QJVly7gNArEZkbbsimHqJZhElgBpXIJdehZ4OWXt+CCr0SBDgUCDJnQrqpd1dWK2dLq5rmO4mCBmI3w==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/icons-material/-/icons-material-7.3.8.tgz", + "integrity": "sha512-88sWg/UJc1X82OMO+ISR4E3P58I3BjFVg0qkmDu7OWlN8VijneZD3ylFA+ImxuPjMHW3SHosfSJYy1fztoz0fw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.3.8", + "@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/icons-material/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/material": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/material/-/material-7.3.8.tgz", + "integrity": "sha512-QKd1RhDXE1hf2sQDNayA9ic9jGkEgvZOf0tTkJxlBPG8ns8aS4rS8WwYURw2x5y3739p0HauUXX9WbH7UufFLw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/core-downloads-tracker": "^7.3.8", + "@mui/system": "^7.3.8", + "@mui/types": "^7.4.11", + "@mui/utils": "^7.3.8", + "@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.3", + "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": "^7.3.8", + "@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/material/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.2.4", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.2.4.tgz", + "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/private-theming/-/private-theming-7.3.8.tgz", + "integrity": "sha512-du5dlPZ9XL3xW2apHoGDXBI+QLtyVJGrXNCfcNYfP/ojkz1RQ0rRV6VG9Rkm1DqEFRG8mjjTL7zmE1Bvn1eR4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/utils": "^7.3.8", + "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/private-theming/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/styled-engine/-/styled-engine-7.3.8.tgz", + "integrity": "sha512-JHAeXQzS0tJ+Fq3C6J4TVDsW+yKhO4uuxuiLaopNStJeQYBIUCXpKYyUCcgXym4AmhbznQnv9RlHywSH6b0FOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@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/styled-engine/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/system": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/system/-/system-7.3.8.tgz", + "integrity": "sha512-hoFRj4Zw2Km8DPWZp/nKG+ao5Jw5LSk2m/e4EGc6M3RRwXKEkMSG4TgtfVJg7dS2homRwtdXSMW+iRO0ZJ4+IA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/private-theming": "^7.3.8", + "@mui/styled-engine": "^7.3.8", + "@mui/types": "^7.4.11", + "@mui/utils": "^7.3.8", + "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/system/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/types": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/@mui/types/-/types-7.4.11.tgz", + "integrity": "sha512-fZ2xO9D08IKOxO2oUBi1nnVKH6oJUD+64cnv4YAaFoC0E5+i1+S5AHbNqqvZlYYsbPEQ6qEVwuBqY3jl5W4G+Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/utils": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/@mui/utils/-/utils-7.3.8.tgz", + "integrity": "sha512-kZRcE2620CBGr+XI8YMmwPj6WIPwSF7uMJjvSfqd8zXVvlz0MCJbzRRUGNf8NgflCLthdji2DdS643TeyJ3+nA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/types": "^7.4.11", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.3" + }, + "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/utils/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.2.4", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.2.4.tgz", + "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==", + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1367,6 +1840,16 @@ "node": ">=12" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@remix-run/router": { "version": "1.23.2", "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.23.2.tgz", @@ -2018,6 +2501,18 @@ "undici-types": "~7.16.0" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.9", "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.9.tgz", @@ -2037,6 +2532,15 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmmirror.com/@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/unist": { "version": "2.0.11", "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz", @@ -2819,6 +3323,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/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/babel-plugin-macros/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bail": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/bail/-/bail-1.0.5.tgz", @@ -3109,7 +3648,6 @@ "version": "3.1.0", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3468,6 +4006,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", @@ -3606,6 +4153,61 @@ "dev": true, "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/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/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/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/cosmiconfig/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/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/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3942,6 +4544,16 @@ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "license": "MIT" }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -4131,7 +4743,6 @@ "version": "1.3.4", "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -4882,6 +5493,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/find-up/-/find-up-5.0.0.tgz", @@ -5010,7 +5627,6 @@ "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5398,7 +6014,6 @@ "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5424,6 +6039,21 @@ "hermes-estree": "0.25.1" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", @@ -5508,7 +6138,6 @@ "version": "3.3.1", "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -5648,7 +6277,6 @@ "version": "0.2.1", "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, "license": "MIT" }, "node_modules/is-async-function": { @@ -5744,7 +6372,6 @@ "version": "2.16.1", "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -6340,7 +6967,6 @@ "version": "3.1.0", "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -7899,7 +8525,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/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" @@ -7970,9 +8595,17 @@ "version": "1.0.7", "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/pathe/-/pathe-2.0.3.tgz", @@ -8491,6 +9124,22 @@ "react-dom": ">=16.8" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmmirror.com/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/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", @@ -8698,7 +9347,6 @@ "version": "4.0.0", "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -9567,6 +10215,12 @@ "inline-style-parser": "0.1.1" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", @@ -9584,7 +10238,6 @@ "version": "1.0.0", "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index e1f2cd5..612f4a6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,10 @@ "lint": "eslint . --max-warnings=0" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/icons-material": "^7.3.8", + "@mui/material": "^7.3.8", "@rrweb/all": "^2.0.0-alpha.18", "@rrweb/rrweb-plugin-console-record": "^2.0.0-alpha.18", "@rrweb/rrweb-plugin-console-replay": "^2.0.0-alpha.18",