commit ff9c7cd218af75daf60b418a6c3ed9cb139fb948 Author: tianhao Date: Tue Jun 16 12:39:36 2026 +0800 init: MetonaToast v2.0.0 基线 — 已完成改进(模板抽象/constants拆分/测试增强) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b044cb7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +coverage/ +.DS_Store diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..d8520e3 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmmirror.com diff --git a/README.md b/README.md new file mode 100644 index 0000000..000ca26 --- /dev/null +++ b/README.md @@ -0,0 +1,232 @@ +# MetonaToast + +轻量、零依赖、精致美观的 Toast 通知库。 + +[![npm version](https://img.shields.io/npm/v/metona-toast.svg)](https://www.npmjs.com/package/metona-toast) +[![bundle size](https://img.shields.io/bundlephobia/minzip/metona-toast)](https://bundlephobia.com/package/metona-toast) +[![license](https://img.shields.io/npm/l/metona-toast.svg)](https://github.com/metona/metona-toast/blob/main/LICENSE) + +## 特性 + +- **零依赖** — 纯原生 JavaScript,gzip 后不到 10KB +- **80+ 图标类型** — success/error/warning/info/loading 及更多扩展类型 +- **11 种动画** — slide/fade/scale/bounce/flip/rotate/zoom/slideUp/slideDown/slideLeft/slideRight,每种效果明显不同 +- **主题系统** — light/dark/auto/warm 四种内置主题,支持 `registerTheme()` 注册自定义主题 +- **国际化** — 内置 zh-CN / en-US 完整翻译,可通过 `addTranslations()` 扩展 +- **插件系统** — 3 款预设插件 (keyboard/persistence/accessibility) + 自定义插件 +- **可拖拽关闭** — 拖动 Toast 任意方向即可关闭 +- **TypeScript** — 完整类型定义 + +## 安装 + +```bash +npm install metona-toast +``` + +### 引用方式 + +```javascript +// ES Module +import MeToast from 'metona-toast'; + +// CommonJS +const MeToast = require('metona-toast'); +``` + +```html + + + + + + + + +``` + +## 快速开始 + +```javascript +import MeToast from 'metona-toast'; + +// 基础用法 +MeToast.success('操作成功!'); +MeToast.error('操作失败!'); +MeToast.warning('请注意检查'); +MeToast.info('系统维护中'); + +// 带标题 +MeToast.success({ title: '保存成功', message: '文件已同步到云端' }); + +// 加载 → 成功链式转换 +const loading = MeToast.loading('正在提交...'); +setTimeout(() => loading.success('提交成功!'), 2000); + +// Promise 风格 +await MeToast.promise(fetch('/api/data'), { + loading: '加载中...', + success: '加载完成!', + error: '加载失败', +}); +``` + +## 全局配置 + +```javascript +MeToast.configure({ + position: 'top-right', // top-left | top-center | top-right | bottom-left | bottom-center | bottom-right + duration: 4000, // 显示时长(ms),0 为不自动关闭 + max: 6, // 同时最多显示条数 + theme: 'auto', // light | dark | auto | warm + animation: 'slide', // slide | fade | scale | bounce | flip | rotate | zoom | slideUp | slideDown | slideLeft | slideRight + pauseOnHover: true, // 悬停暂停计时 + closeOnClick: true, // 点击关闭 + showProgress: true, // 显示进度条 + draggable: true, // 允许拖拽关闭 + locale: 'zh-CN', // 语言 +}); +``` + +## 动画效果 + +11 种动画,每种感官差异明显: + +| 动画 | 效果描述 | +|------|----------| +| `slide` | 从右侧滑入 + 轻微过冲回弹 | +| `fade` | 纯淡入(blur→清晰),从容优雅 | +| `scale` | 弹性放大(0.55→1.07→1.0) | +| `bounce` | 从天而降四段弹跳 | +| `flip` | 3D 翻转入场 + 回摆 | +| `rotate` | 旋转摇摆进入 | +| `zoom` | 从中心爆发式弹出 | +| `slideUp` | 从下方弹入 | +| `slideDown` | 从上方弹入 | +| `slideLeft` | 从左侧滑入 | +| `slideRight` | 从右侧滑入 | + +```javascript +MeToast.success('弹跳动画', { animation: 'bounce' }); + +// 注册自定义动画 +MeToast.animations.register('myAnim', { + enter: { transform: 'rotate(-30deg) scale(0.5)', opacity: 0 }, + leave: { transform: 'rotate(0) scale(1)', opacity: 1 }, + duration: 500, + easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', +}); +``` + +## 主题 + +```javascript +// 切换主题 +MeToast.themes.switchTheme('dark'); +MeToast.themes.switchTheme('warm'); + +// 注册自定义主题 +MeToast.themes.registerTheme('ocean', { + bg: 'rgba(240, 249, 255, 0.96)', + text: '#0c4a6e', + border: 'rgba(14, 165, 233, 0.2)', + shadow: '0 10px 36px -10px rgba(14, 165, 233, 0.18)', + hoverShadow: '0 14px 48px -10px rgba(14, 165, 233, 0.22)', + progressBg: 'rgba(14, 165, 233, 0.1)', + closeHoverBg: 'rgba(14, 165, 233, 0.1)', +}); +MeToast.themes.switchTheme('ocean'); +``` + +## 高级功能 + +```javascript +// 确认对话框 → Promise +const ok = await MeToast.confirm('确定删除?', { confirmText: '删除', confirmColor: '#ef4444' }); + +// 输入对话框 → Promise +const name = await MeToast.prompt('请输入姓名', { placeholder: '请输入...' }); + +// 进度条 +const p = MeToast.progress('上传中...'); +p.setProgress(60); +p.complete('上传完成!'); + +// 倒计时({seconds} 自动替换) +MeToast.countdown('操作将在 {seconds} 秒后执行', 5, { + onComplete: () => MeToast.success('已执行'), +}); + +// 队列展示(顺序逐个) +await MeToast.queue(['步骤一', '步骤二', '步骤三'], { delay: 800 }); + +// 堆叠展示(同时错峰) +MeToast.stack(['消息1', '消息2', '消息3'], { stagger: 150 }); +``` + +## 插件 + +```javascript +// 安装预设插件 +MeToast.use('keyboard'); // ESC 关闭所有 Toast +MeToast.use('persistence'); // 配置持久化到 localStorage +MeToast.use('accessibility'); // 屏幕阅读器朗读公告 + +// 自定义插件(通过 install 中注册 Toast 生命周期钩子) +import MeToast, { Toast } from 'metona-toast'; + +MeToast.use({ + name: 'my-plugin', + install() { + Toast.on('afterShow', (toast) => { + console.log('Toast shown:', toast.message); + }); + }, +}); +``` + +## 国际化 + +```javascript +MeToast.i18n.switchLocale('en-US'); + +// 添加语言 +MeToast.i18n.addTranslations('ja', { + success: '成功', + error: 'エラー', + confirm: '確認', + cancel: 'キャンセル', +}); + +// 格式化工具 +MeToast.i18n.formatNumber(1234567); // "1,234,567" +MeToast.i18n.formatCurrency(99, 'CNY'); // "¥99.00" +``` + +## Toast 管理 + +```javascript +MeToast.count(); // 当前数量 +MeToast.getToasts(); // 获取所有实例 +MeToast.dismiss(); // 关闭所有 +MeToast.dismiss(id); // 关闭指定 +MeToast.pauseAll(); // 暂停所有计时 +MeToast.resumeAll(); // 恢复所有计时 +MeToast.destroy(); // 完全销毁 +``` + +## 回调 + +```javascript +MeToast.success({ + message: '操作成功', + onShow: (toast) => console.log('显示:', toast.id), + onClose: (toast) => console.log('关闭:', toast.id), + onClick: (toast) => console.log('点击:', toast.id), +}); +``` + +## License + +MIT diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..3483a00 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,16 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + modules: 'commonjs', + }, + ], + ], + plugins: [ + '@babel/plugin-transform-modules-commonjs', + ], +}; diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..c48e4f5 --- /dev/null +++ b/build.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# MetonaToast 构建脚本 + +echo "🍞 MetonaToast 构建脚本" +echo "========================" + +# 检查Node.js +if ! command -v node &> /dev/null; then + echo "❌ 错误: 未找到Node.js" + exit 1 +fi + +# 检查npm +if ! command -v npm &> /dev/null; then + echo "❌ 错误: 未找到npm" + exit 1 +fi + +echo "✅ Node.js版本: $(node -v)" +echo "✅ npm版本: $(npm -v)" + +# 安装依赖 +echo "" +echo "📦 安装依赖..." +npm install + +if [ $? -ne 0 ]; then + echo "❌ 依赖安装失败" + exit 1 +fi + +echo "✅ 依赖安装完成" + +# 运行测试 +echo "" +echo "🧪 运行测试..." +npm test + +if [ $? -ne 0 ]; then + echo "❌ 测试失败" + exit 1 +fi + +echo "✅ 测试通过" + +# 构建项目 +echo "" +echo "🔨 构建项目..." +npm run build + +if [ $? -ne 0 ]; then + echo "❌ 构建失败" + exit 1 +fi + +echo "✅ 构建完成" + +# 显示构建结果 +echo "" +echo "📊 构建结果:" +echo "========================" +ls -lh dist/ + +echo "" +echo "✅ 构建成功完成!" +echo "" +echo "📁 文件结构:" +echo " - dist/metona-toast.js (UMD格式)" +echo " - dist/metona-toast.esm.js (ES Module格式)" +echo " - dist/metona-toast.cjs.js (CommonJS格式)" +echo " - dist/metona-toast.min.js (压缩版本)" +echo " - dist/metona-toast.d.ts (TypeScript声明)" +echo "" +echo "🚀 使用方法:" +echo " 1. 浏览器: " +echo " 2. ES Module: import MeToast from 'dist/metona-toast.esm.js'" +echo " 3. CommonJS: const MeToast = require('dist/metona-toast.cjs.js')" +echo "" +echo "📝 示例:" +echo " 打开 examples/demo.html 查看完整示例" +echo "" diff --git a/examples/demo.html b/examples/demo.html new file mode 100644 index 0000000..baf5629 --- /dev/null +++ b/examples/demo.html @@ -0,0 +1,395 @@ + + + + + + MetonaToast — 全功能演示 + + + + +
+

MetonaToast

+

轻量 · 零依赖 · 精致美观 — 全功能演示

+
+ + + +
+ + +
+
🎨

图标类型

80+ 内置图标类型

+
+
常用
+
+ + + + + + +
+
+
操作
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
系统 & 设备
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
自然 & 几何
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+
📍

位置

6 种预设位置

+
+
+ + + + + + +
+
+
+ + +
+
🎭

动画效果

11 种动画,每种效果明显不同

+
+
+ + + + + + + + + + + +
+
+
+ + +
+
🎨

主题

四种基础主题,支持 registerTheme() 自定义注册

+
+
基础主题
+
+
浅色 light
+
深色 dark
+
自动 auto
+
暖色 warm
+
+
+
+ + +
+

高级功能

Promise / 确认框 / 输入框 / 进度条 / 倒计时 / 队列 / 堆叠

+
+
+ + + + + + + +
+
+
+ + +
+
🔌

插件系统

3 款预设插件,按需安装

+
+
+ + + +
+
+
+ + +
+
🌍

国际化

切换语言查看效果

+
+
+ + + + + + + + + +
+
+
+ + +
+
🔧

Toast 管理

统计、关闭、清除

+
+
+ + + + + + + +
+
+
+ +
+ + + + + + + diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000..c567689 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,442 @@ + + + + + + MetonaToast — 基础功能与代码示例 + + + + +
+

MetonaToast

+

轻量 · 零依赖 · 精致美观的 Toast 通知库

+
+ 📦 <10KB gzip🎨 80+ 图标🎭 11 动画🌍 国际化🔌 插件 +
+
+ +
+ + +
+

📦 安装与引用

+
+

npm

+
# 安装
+npm install metona-toast
+
+# ES Module
+import MeToast from 'metona-toast';
+
+# CommonJS
+const MeToast = require('metona-toast');
+
+
+

CDN

+
<!-- UMD 开发版 -->
+<script src="https://unpkg.com/metona-toast@2.0.0/dist/metona-toast.js"></script>
+
+<!-- 压缩版(生产环境推荐)-->
+<script src="https://unpkg.com/metona-toast@2.0.0/dist/metona-toast.min.js"></script>
+
+<!-- ES Module 直接引用 -->
+<script type="module">
+  import MeToast from 'https://unpkg.com/metona-toast@2.0.0/dist/metona-toast.esm.js';
+</script>
+
+
+ + +
+

🎯 基础调用

+

五种核心类型,一行代码搞定

+
+
+ + + + + +
+
// 五种类型,一行搞定
+MeToast.success('操作成功!');
+MeToast.error('操作失败!');
+MeToast.warning('请注意检查');
+MeToast.info('系统维护中');
+MeToast.show('默认消息');
+
+
+ + +
+

⚙️ 配置选项

+

标题、位置、时长、主题、动画……灵活可控

+
+
+ + + + + +
+
// 带标题
+MeToast.success({ title: '保存成功', message: '文件已同步到云端' });
+
+// 自定义时长 — 显示10秒
+MeToast.info('显示10秒', { duration: 10000 });
+
+// 自定义位置 — 底部居中
+MeToast.warning('底部居中', { position: 'bottom-center' });
+
+// 手动关闭 — 不自动消失
+MeToast.info('手动关闭', { duration: 0, closeButton: true });
+
+// 自定义动画 — 弹跳效果
+MeToast.success('弹跳动画', { animation: 'bounce' });
+
+
+ + +
+

🔄 Loading 链式转换

+

加载中 → 成功/失败/警告/信息,优雅切换

+
+
+ + +
+
// loading → success
+const loading = MeToast.loading('正在提交...');
+setTimeout(() => loading.success('提交成功!'), 2000);
+
+// loading → error
+const loading = MeToast.loading('正在提交...');
+setTimeout(() => loading.error('提交失败,请重试'), 2000);
+
+
+ + +
+

⛓ Promise 封装

+

一行代码自动处理 loading / success / error

+
+
+ +
+
await MeToast.promise(
+  fetch('/api/data'),
+  {
+    loading: '加载中...',
+    success: '加载完成!',
+    error: '加载失败',
+  }
+);
+
+
+ + +
+

💬 确认框 & 输入框

+

内置对话框,返回 Promise

+
+
+ + +
+
// 确认对话框 → Promise<boolean>
+const ok = await MeToast.confirm('确定删除吗?', {
+  confirmText: '删除',
+  confirmColor: '#ef4444',
+});
+
+// 输入对话框 → Promise<string|null>
+const name = await MeToast.prompt('请输入姓名', {
+  placeholder: '请输入...',
+});
+
+
+ + +
+

📊 进度条 & 倒计时

+

实时更新的进度通知和自动倒计时

+
+
+ + +
+
// 进度条 — 实时更新
+const p = MeToast.progress('上传中...');
+let v = 0;
+const t = setInterval(() => {
+  v += Math.random() * 28;
+  if (v >= 100) { clearInterval(t); p.complete('上传完成!'); }
+  else p.setProgress(v);
+}, 400);
+
+// 倒计时 — {seconds} 自动替换
+MeToast.countdown('{seconds} 秒后执行', 5, {
+  onComplete: () => MeToast.success('已执行'),
+});
+
+
+ + +
+

📋 队列 & 堆叠

+

顺序逐个展示 or 同时错峰展示

+
+
+ + +
+
// 队列 — 一个接一个
+await MeToast.queue(['步骤一', '步骤二', '步骤三'], {
+  delay: 800,
+  duration: 2000,
+  type: 'info',
+});
+
+// 堆叠 — 同时错峰
+MeToast.stack(['消息 1', '消息 2', '消息 3', '消息 4'], {
+  stagger: 150,
+  type: 'info',
+});
+
+
+ + +
+

🔌 插件

+

3 款预设插件,按需安装

+
+
+ + + +
+
// keyboard — ESC 关闭所有 Toast
+MeToast.use('keyboard');
+
+// persistence — 配置持久化(自动保存/加载)
+MeToast.use('persistence');
+
+// accessibility — 屏幕阅读器朗读公告
+MeToast.use('accessibility');
+
+
+ + +
+

🔧 全局配置

+

一次配置,所有 Toast 自动继承

+
+
MeToast.configure({
+  position: 'top-right',       // 默认位置
+  duration: 4000,                // 默认显示时长(ms)
+  max: 6,                        // 同时最多显示条数
+  theme: 'auto',                // light | dark | auto | warm
+  animation: 'slide',            // 默认动画效果
+  pauseOnHover: true,           // 悬停暂停计时
+  closeOnClick: true,           // 点击关闭
+  showProgress: true,           // 显示进度条
+  draggable: true,             // 允许拖拽关闭
+  locale: 'zh-CN',              // 默认语言
+});
+
+
+ + +
+

🎨 主题 & 国际化

+

内置四种主题,支持自定义注册;内置中英文,可扩展

+
+
+ + + + + +
+
// 切换主题(switchTheme + configure 同步全局配置)
+MeToast.themes.switchTheme('warm');
+MeToast.configure({ theme: 'warm' });
+
+// 切换语言 — 英文
+MeToast.i18n.switchLocale('en-US');
+
+// 切换回中文
+MeToast.i18n.switchLocale('zh-CN');
+
+// 注册自定义主题
+MeToast.themes.registerTheme('ocean', {
+  bg: 'rgba(240,249,255,0.96)',
+  text: '#0c4a6e',
+  border: 'rgba(14,165,233,0.2)',
+  shadow: '0 10px 36px -10px rgba(14,165,233,0.18)',
+  hoverShadow: '0 14px 48px -10px rgba(14,165,233,0.22)',
+  progressBg: 'rgba(14,165,233,0.1)',
+  closeHoverBg: 'rgba(14,165,233,0.1)',
+});
+
+
+ + +
+

🔧 Toast 管理

+

查找、关闭、清除、暂停、恢复

+
+
+ + + + + + +
+
MeToast.count();           // 当前数量
+MeToast.getToasts();      // 获取所有实例
+MeToast.dismiss();        // 关闭全部
+MeToast.dismiss(id);      // 关闭指定
+MeToast.pauseAll();       // 暂停全部计时
+MeToast.resumeAll();      // 恢复全部计时
+MeToast.destroy();        // 完全销毁
+
+
+ + +
+

📖 API 速览

+
+ + + + + + + + + + + + + + + + +
方法说明示例
success(msg, opts?)成功通知MeToast.success('保存成功')
error(msg, opts?)错误通知MeToast.error('网络错误')
warning(msg, opts?)警告通知MeToast.warning('请注意')
info(msg, opts?)信息通知MeToast.info('系统维护中')
loading(msg, opts?)加载状态MeToast.loading('加载中...')
promise(p, opts)Promise 自动状态MeToast.promise(fetch(...), opts)
confirm(msg, opts?)确认对话框 → booleanawait MeToast.confirm('删除?')
prompt(msg, opts?)输入对话框 → stringawait MeToast.prompt('姓名?')
progress(msg, opts?)进度条通知MeToast.progress('上传中...')
countdown(msg, s, opts?)倒计时MeToast.countdown('{seconds}s', 10)
queue(msgs, opts?)队列顺序展示MeToast.queue(['a','b','c'])
stack(msgs, opts?)堆叠错峰展示MeToast.stack(['a','b','c'])
configure(opts)全局配置MeToast.configure({duration:5000})
dismiss(id?)关闭 toastMeToast.dismiss()
+
+
+ +
+ + + + + + + diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..1f60f98 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,17 @@ +module.exports = { + testEnvironment: 'jsdom', + transform: { + '^.+\\.js$': 'babel-jest', + }, + transformIgnorePatterns: [ + '/node_modules/(?!(@rollup)/)', + ], + moduleFileExtensions: ['js', 'json'], + collectCoverageFrom: [ + 'src/**/*.js', + '!src/index.js', + ], + coverageDirectory: 'coverage', + coverageReporters: ['text', 'lcov'], + verbose: true, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..56587f7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7444 @@ +{ + "name": "metona-toast", + "version": "2.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "metona-toast", + "version": "2.0.0", + "license": "MIT", + "devDependencies": { + "@babel/core": "^7.22.0", + "@babel/plugin-transform-modules-commonjs": "^7.22.0", + "@babel/preset-env": "^7.22.0", + "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-terser": "^0.4.0", + "@types/jest": "^29.5.0", + "babel-jest": "^29.5.0", + "eslint": "^8.40.0", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "prettier": "^2.8.0", + "rollup": "^3.20.0", + "rollup-plugin-dts": "^5.3.0", + "rollup-plugin-livereload": "^2.0.5", + "rollup-plugin-serve": "^2.0.1", + "typescript": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmmirror.com/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "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", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "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" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "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/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.8", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmmirror.com/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmmirror.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmmirror.com/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmmirror.com/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/node": { + "version": "25.9.3", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-25.9.3.tgz", + "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmmirror.com/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmmirror.com/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmmirror.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmmirror.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.37", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", + "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "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" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmmirror.com/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmmirror.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.49.0", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmmirror.com/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.372", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", + "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmmirror.com/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "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" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "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" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "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", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "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" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "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-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmmirror.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "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" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/livereload": { + "version": "0.9.3", + "resolved": "https://registry.npmmirror.com/livereload/-/livereload-0.9.3.tgz", + "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.0", + "livereload-js": "^3.3.1", + "opts": ">= 1.2.0", + "ws": "^7.4.3" + }, + "bin": { + "livereload": "bin/livereload.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/livereload-js": { + "version": "3.4.1", + "resolved": "https://registry.npmmirror.com/livereload-js/-/livereload-js-3.4.1.tgz", + "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==", + "dev": true, + "license": "MIT" + }, + "node_modules/livereload/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmmirror.com/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/opts": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/opts/-/opts-2.0.2.tgz", + "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "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" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "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": "7.3.0", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "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/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.2", + "resolved": "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.13.2.tgz", + "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "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/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.30.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.30.0.tgz", + "integrity": "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz", + "integrity": "sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "magic-string": "^0.30.2" + }, + "engines": { + "node": ">=v14.21.3" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.22.5" + }, + "peerDependencies": { + "rollup": "^3.0", + "typescript": "^4.1 || ^5.0" + } + }, + "node_modules/rollup-plugin-livereload": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz", + "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "livereload": "^0.9.1" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-serve": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/rollup-plugin-serve/-/rollup-plugin-serve-2.0.3.tgz", + "integrity": "sha512-gQKmfQng17+jOsX5tmDanvJkm0f9XLqWVvXsD7NGd1SlneT+U1j/HjslDUXQz6cqwLnVDRc6xF2lj6rre+eeeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime": "^3", + "opener": "1" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smob": { + "version": "1.6.2", + "resolved": "https://registry.npmmirror.com/smob/-/smob-1.6.2.tgz", + "integrity": "sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6bb0802 --- /dev/null +++ b/package.json @@ -0,0 +1,85 @@ +{ + "name": "metona-toast", + "version": "2.0.0", + "description": "轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。", + "main": "dist/metona-toast.js", + "module": "src/index.js", + "types": "types/index.d.ts", + "exports": { + ".": { + "import": "./src/index.js", + "require": "./dist/metona-toast.js", + "types": "./types/index.d.ts" + } + }, + "files": [ + "dist/", + "src/", + "types/", + "README.md", + "LICENSE" + ], + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint src/", + "lint:fix": "eslint src/ --fix", + "format": "prettier --write src/", + "typecheck": "tsc --noEmit", + "prepublishOnly": "npm run build", + "docs": "jsdoc src/ -d docs", + "example": "serve examples/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/metona/metona-toast.git" + }, + "keywords": [ + "toast", + "notification", + "alert", + "message", + "snackbar", + "ui", + "component", + "lightweight", + "zero-dependency" + ], + "author": "metona", + "license": "MIT", + "bugs": { + "url": "https://github.com/metona/metona-toast/issues" + }, + "homepage": "https://github.com/metona/metona-toast#readme", + "devDependencies": { + "@babel/core": "^7.22.0", + "@babel/preset-env": "^7.22.0", + "@babel/plugin-transform-modules-commonjs": "^7.22.0", + "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-terser": "^0.4.0", + "@types/jest": "^29.5.0", + "babel-jest": "^29.5.0", + "eslint": "^8.40.0", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "prettier": "^2.8.0", + "rollup": "^3.20.0", + "rollup-plugin-dts": "^5.3.0", + "rollup-plugin-livereload": "^2.0.5", + "rollup-plugin-serve": "^2.0.1", + "typescript": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead", + "not ie 11" + ] +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..f214ce4 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,135 @@ +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; +import dts from 'rollup-plugin-dts'; +import serve from 'rollup-plugin-serve'; +import livereload from 'rollup-plugin-livereload'; + +const isDev = process.env.ROLLUP_WATCH; +const isProd = process.env.NODE_ENV === 'production'; + +// 基础配置 +const baseConfig = { + input: 'src/index.js', + plugins: [ + resolve(), + commonjs(), + ], +}; + +// 开发服务器配置 +const devPlugins = isDev ? [ + serve({ + open: true, + contentBase: ['examples', 'dist'], + port: 3000, + }), + livereload({ + watch: ['src', 'examples'], + }), +] : []; + +// 生产环境配置 +const prodPlugins = isProd ? [ + terser({ + compress: { + drop_console: true, + drop_debugger: true, + pure_funcs: ['console.log', 'console.warn'], + }, + format: { + comments: false, + }, + }), +] : []; + +// 输出配置 +export default [ + // UMD格式(浏览器) + { + ...baseConfig, + output: { + file: 'dist/metona-toast.js', + format: 'umd', + name: 'MeToast', + exports: 'named', + sourcemap: !isProd, + globals: {}, + }, + plugins: [ + ...baseConfig.plugins, + ...devPlugins, + ...prodPlugins, + ], + }, + + // ESM格式(现代浏览器/打包工具) + { + ...baseConfig, + output: { + file: 'dist/metona-toast.esm.js', + format: 'es', + exports: 'named', + sourcemap: !isProd, + }, + plugins: [ + ...baseConfig.plugins, + ...prodPlugins, + ], + }, + + // CommonJS格式(Node.js) + { + ...baseConfig, + output: { + file: 'dist/metona-toast.cjs.js', + format: 'cjs', + exports: 'named', + sourcemap: !isProd, + }, + plugins: [ + ...baseConfig.plugins, + ...prodPlugins, + ], + }, + + // 压缩版本(UMD) + { + ...baseConfig, + output: { + file: 'dist/metona-toast.min.js', + format: 'umd', + name: 'MeToast', + exports: 'named', + sourcemap: false, + globals: {}, + }, + plugins: [ + ...baseConfig.plugins, + terser({ + compress: { + drop_console: true, + drop_debugger: true, + pure_funcs: ['console.log', 'console.warn'], + passes: 2, + }, + format: { + comments: false, + }, + mangle: { + toplevel: true, + }, + }), + ], + }, + + // TypeScript声明文件 + { + input: 'types/index.d.ts', + output: { + file: 'dist/metona-toast.d.ts', + format: 'es', + }, + plugins: [dts()], + }, +]; diff --git a/serve.sh b/serve.sh new file mode 100644 index 0000000..0ffa3ec --- /dev/null +++ b/serve.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# MetonaToast 本地开发服务器 + +echo "🍞 MetonaToast 开发服务器" +echo "=========================" + +# 检查Python +if command -v python3 &> /dev/null; then + PYTHON=python3 +elif command -v python &> /dev/null; then + PYTHON=python +else + echo "❌ 错误: 未找到Python" + exit 1 +fi + +PORT=${1:-3000} + +echo "✅ Python: $($PYTHON --version 2>&1)" +echo "🌐 启动服务器..." +echo "" +echo "📁 访问地址:" +echo " http://localhost:$PORT/examples/demo.html" +echo " http://localhost:$PORT/examples/index.html" +echo "" +echo "按 Ctrl+C 停止服务器" +echo "" + +cd "$(dirname "$0")" +$PYTHON -m http.server $PORT diff --git a/src/animations.js b/src/animations.js new file mode 100644 index 0000000..9a0196f --- /dev/null +++ b/src/animations.js @@ -0,0 +1,860 @@ +/** + * MetonaToast Animations - 动画管理 + * @module animations + * @version 2.0.0 + * @description 动画效果管理和自定义 + */ + +import { ANIMATIONS } from './constants.js'; + +// 动画缓存 +const animationCache = new Map(); + +/** + * 动画管理器类 + */ +class AnimationManager { + constructor() { + this.animations = new Map(); + this.activeAnimations = new Map(); + this.animationId = 0; + + // 注册默认动画 + this._registerDefaults(); + } + + /** + * 注册默认动画 + */ + _registerDefaults() { + Object.entries(ANIMATIONS).forEach(([name, config]) => { + this.register(name, config); + }); + } + + /** + * 注册动画 + * @param {string} name - 动画名称 + * @param {Object} config - 动画配置 + */ + register(name, config) { + const animation = { + name, + enter: config.enter || {}, + leave: config.leave || {}, + duration: config.duration || 300, + easing: config.easing || 'cubic-bezier(0.4, 0, 0.2, 1)', + delay: config.delay || 0, + iterations: config.iterations || 1, + direction: config.direction || 'normal', + fillMode: config.fillMode || 'forwards', + }; + + this.animations.set(name, animation); + animationCache.set(name, animation); + } + + /** + * 注销动画 + * @param {string} name - 动画名称 + */ + unregister(name) { + this.animations.delete(name); + animationCache.delete(name); + } + + /** + * 获取动画配置 + * @param {string} name - 动画名称 + * @returns {Object|null} 动画配置 + */ + get(name) { + return this.animations.get(name) || ANIMATIONS[name] || null; + } + + /** + * 应用动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + apply(element, animationName, options = {}) { + return new Promise((resolve) => { + const animation = this.get(animationName); + if (!animation) { + resolve(); + return; + } + + const config = { ...animation, ...options }; + const animId = ++this.animationId; + + // 设置初始状态 + Object.assign(element.style, config.enter); + + // 强制重绘 + element.offsetHeight; + + // 创建动画 + const keyframes = [ + { ...config.enter }, + { ...config.leave }, + ]; + + const animationOptions = { + duration: config.duration, + easing: config.easing, + delay: config.delay, + iterations: config.iterations, + direction: config.direction, + fill: config.fillMode, + }; + + // 应用动画 + const anim = element.animate(keyframes, animationOptions); + + // 存储活动动画 + this.activeAnimations.set(animId, { + element, + animation: anim, + config, + }); + + // 动画完成处理 + anim.onfinish = () => { + // 应用最终状态 + Object.assign(element.style, config.leave); + + // 清理 + this.activeAnimations.delete(animId); + + resolve(); + }; + + // 动画取消处理 + anim.oncancel = () => { + this.activeAnimations.delete(animId); + resolve(); + }; + }); + } + + /** + * 应用进入动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + enter(element, animationName, options = {}) { + const animation = this.get(animationName); + if (!animation) { + return Promise.resolve(); + } + + return this.apply(element, animationName, { + ...options, + direction: 'normal', + }); + } + + /** + * 应用离开动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + leave(element, animationName, options = {}) { + const animation = this.get(animationName); + if (!animation) { + return Promise.resolve(); + } + + return this.apply(element, animationName, { + ...options, + direction: 'reverse', + }); + } + + /** + * 取消所有动画 + */ + cancelAll() { + this.activeAnimations.forEach(({ animation }) => { + animation.cancel(); + }); + + this.activeAnimations.clear(); + } + + /** + * 取消元素动画 + * @param {HTMLElement} element - 目标元素 + */ + cancel(element) { + this.activeAnimations.forEach(({ element: el, animation }, id) => { + if (el === element) { + animation.cancel(); + this.activeAnimations.delete(id); + } + }); + } + + /** + * 暂停所有动画 + */ + pauseAll() { + this.activeAnimations.forEach(({ animation }) => { + animation.pause(); + }); + } + + /** + * 恢复所有动画 + */ + resumeAll() { + this.activeAnimations.forEach(({ animation }) => { + animation.play(); + }); + } + + /** + * 暂停元素动画 + * @param {HTMLElement} element - 目标元素 + */ + pause(element) { + this.activeAnimations.forEach(({ element: el, animation }) => { + if (el === element) { + animation.pause(); + } + }); + } + + /** + * 恢复元素动画 + * @param {HTMLElement} element - 目标元素 + */ + resume(element) { + this.activeAnimations.forEach(({ element: el, animation }) => { + if (el === element) { + animation.play(); + } + }); + } + + /** + * 获取活动动画数量 + * @returns {number} 动画数量 + */ + getActiveCount() { + return this.activeAnimations.size; + } + + /** + * 获取所有活动动画 + * @returns {Map} 活动动画映射 + */ + getActiveAnimations() { + return new Map(this.activeAnimations); + } + + /** + * 检查元素是否有活动动画 + * @param {HTMLElement} element - 目标元素 + * @returns {boolean} 是否有活动动画 + */ + hasActiveAnimation(element) { + for (const { element: el } of this.activeAnimations.values()) { + if (el === element) { + return true; + } + } + return false; + } + + /** + * 获取动画配置 + * @returns {Object} 动画配置 + */ + getConfig() { + return { + animations: Array.from(this.animations.keys()), + activeCount: this.getActiveCount(), + }; + } + + /** + * 重置动画管理器 + */ + reset() { + this.cancelAll(); + this.animations.clear(); + this._registerDefaults(); + } + + /** + * 销毁动画管理器 + */ + destroy() { + this.cancelAll(); + this.animations.clear(); + this.activeAnimations.clear(); + } +} + +/** + * 预设动画效果 + */ +const presetAnimations = { + bounce: { + enter: { transform: 'translateY(-80px)', opacity: 0 }, + leave: { transform: 'translateY(20px)', opacity: 1 }, + duration: 650, + easing: 'ease', + }, + slideUp: { + enter: { transform: 'translateY(60px)', opacity: 0 }, + leave: { transform: 'translateY(0)', opacity: 1 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideDown: { + enter: { transform: 'translateY(-60px)', opacity: 0 }, + leave: { transform: 'translateY(0)', opacity: 1 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideLeft: { + enter: { transform: 'translateX(-90px)', opacity: 0 }, + leave: { transform: 'translateX(0)', opacity: 1 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideRight: { + enter: { transform: 'translateX(90px)', opacity: 0 }, + leave: { transform: 'translateX(0)', opacity: 1 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + +}; + +// 注册预设动画 +Object.entries(presetAnimations).forEach(([name, config]) => { + ANIMATIONS[name] = config; +}); + +/** + * 创建动画管理器实例 + * @returns {AnimationManager} 动画管理器实例 + */ +export const createAnimationManager = () => { + return new AnimationManager(); +}; + +// 创建默认实例 +const defaultAnimationManager = createAnimationManager(); + +/** + * 动画工具函数 + */ +export const animationUtils = { + /** + * 应用动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + apply(element, animationName, options = {}) { + return defaultAnimationManager.apply(element, animationName, options); + }, + + /** + * 应用进入动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + enter(element, animationName, options = {}) { + return defaultAnimationManager.enter(element, animationName, options); + }, + + /** + * 应用离开动画 + * @param {HTMLElement} element - 目标元素 + * @param {string} animationName - 动画名称 + * @param {Object} options - 额外选项 + * @returns {Promise} 动画完成Promise + */ + leave(element, animationName, options = {}) { + return defaultAnimationManager.leave(element, animationName, options); + }, + + /** + * 取消所有动画 + */ + cancelAll() { + defaultAnimationManager.cancelAll(); + }, + + /** + * 取消元素动画 + * @param {HTMLElement} element - 目标元素 + */ + cancel(element) { + defaultAnimationManager.cancel(element); + }, + + /** + * 暂停所有动画 + */ + pauseAll() { + defaultAnimationManager.pauseAll(); + }, + + /** + * 恢复所有动画 + */ + resumeAll() { + defaultAnimationManager.resumeAll(); + }, + + /** + * 暂停元素动画 + * @param {HTMLElement} element - 目标元素 + */ + pause(element) { + defaultAnimationManager.pause(element); + }, + + /** + * 恢复元素动画 + * @param {HTMLElement} element - 目标元素 + */ + resume(element) { + defaultAnimationManager.resume(element); + }, + + /** + * 获取活动动画数量 + * @returns {number} 动画数量 + */ + getActiveCount() { + return defaultAnimationManager.getActiveCount(); + }, + + /** + * 检查元素是否有活动动画 + * @param {HTMLElement} element - 目标元素 + * @returns {boolean} 是否有活动动画 + */ + hasActiveAnimation(element) { + return defaultAnimationManager.hasActiveAnimation(element); + }, + + /** + * 注册动画 + * @param {string} name - 动画名称 + * @param {Object} config - 动画配置 + */ + register(name, config) { + defaultAnimationManager.register(name, config); + }, + + /** + * 注销动画 + * @param {string} name - 动画名称 + */ + unregister(name) { + defaultAnimationManager.unregister(name); + }, + + /** + * 获取动画配置 + * @param {string} name - 动画名称 + * @returns {Object|null} 动画配置 + */ + get(name) { + return defaultAnimationManager.get(name); + }, + + /** + * 获取所有动画名称 + * @returns {Array} 动画名称数组 + */ + getAnimationNames() { + return Array.from(defaultAnimationManager.animations.keys()); + }, + + /** + * 获取动画配置 + * @returns {Object} 动画配置 + */ + getConfig() { + return defaultAnimationManager.getConfig(); + }, + + /** + * 重置动画管理器 + */ + reset() { + defaultAnimationManager.reset(); + }, + + /** + * 销毁动画管理器 + */ + destroy() { + defaultAnimationManager.destroy(); + }, +}; + +/** + * 动画预设 + */ +export const animationPresets = presetAnimations; + +/** + * 创建自定义动画 + * @param {Object} config - 动画配置 + * @returns {Object} 动画配置 + */ +export const createAnimation = (config) => { + return { + enter: config.enter || {}, + leave: config.leave || {}, + duration: config.duration || 300, + easing: config.easing || 'cubic-bezier(0.4, 0, 0.2, 1)', + delay: config.delay || 0, + iterations: config.iterations || 1, + direction: config.direction || 'normal', + fillMode: config.fillMode || 'forwards', + }; +}; + +/** + * 组合动画 + * @param {Array} animations - 动画数组 + * @returns {Object} 组合后的动画配置 + */ +export const combineAnimations = (animations) => { + const combined = { + enter: {}, + leave: {}, + duration: 0, + easing: 'cubic-bezier(0.4, 0, 0.2, 1)', + delay: 0, + iterations: 1, + direction: 'normal', + fillMode: 'forwards', + }; + + animations.forEach((anim) => { + if (anim.enter) { + Object.assign(combined.enter, anim.enter); + } + if (anim.leave) { + Object.assign(combined.leave, anim.leave); + } + if (anim.duration) { + combined.duration = Math.max(combined.duration, anim.duration); + } + if (anim.easing) { + combined.easing = anim.easing; + } + if (anim.delay) { + combined.delay = Math.max(combined.delay, anim.delay); + } + }); + + return combined; +}; + +/** + * 链式动画 + * @param {Array} animations - 动画数组 + * @returns {Promise} 动画完成Promise + */ +export const chainAnimations = async (element, animations) => { + for (const anim of animations) { + await defaultAnimationManager.apply(element, anim.name, anim.options); + } +}; + +/** + * 并行动画 + * @param {Array} animations - 动画数组 + * @returns {Promise} 动画完成Promise + */ +export const parallelAnimations = (element, animations) => { + return Promise.all( + animations.map((anim) => + defaultAnimationManager.apply(element, anim.name, anim.options) + ) + ); +}; + +/** + * 延迟动画 + * @param {number} delay - 延迟时间(毫秒) + * @returns {Promise} Promise对象 + */ +export const delayAnimation = (delay) => { + return new Promise((resolve) => setTimeout(resolve, delay)); +}; + +/** + * 动画队列 + */ +export class AnimationQueue { + constructor() { + this.queue = []; + this.isProcessing = false; + } + + /** + * 添加动画到队列 + * @param {Function} animationFn - 动画函数 + * @returns {Promise} 动画完成Promise + */ + add(animationFn) { + return new Promise((resolve, reject) => { + this.queue.push({ + fn: animationFn, + resolve, + reject, + }); + + this._process(); + }); + } + + /** + * 处理队列 + */ + async _process() { + if (this.isProcessing || this.queue.length === 0) { + return; + } + + this.isProcessing = true; + + while (this.queue.length > 0) { + const { fn, resolve, reject } = this.queue.shift(); + + try { + const result = await fn(); + resolve(result); + } catch (error) { + reject(error); + } + } + + this.isProcessing = false; + } + + /** + * 清空队列 + */ + clear() { + this.queue = []; + } + + /** + * 暂停队列 + */ + pause() { + this.isProcessing = true; + } + + /** + * 恢复队列 + */ + resume() { + this.isProcessing = false; + this._process(); + } + + /** + * 获取队列长度 + * @returns {number} 队列长度 + */ + get length() { + return this.queue.length; + } + + /** + * 检查是否正在处理 + * @returns {boolean} 是否正在处理 + */ + get processing() { + return this.isProcessing; + } +} + +/** + * 创建动画队列 + * @returns {AnimationQueue} 动画队列实例 + */ +export const createAnimationQueue = () => { + return new AnimationQueue(); +}; + +/** + * 动画性能监控 + */ +export class AnimationPerformanceMonitor { + constructor() { + this.metrics = { + totalAnimations: 0, + activeAnimations: 0, + averageDuration: 0, + maxDuration: 0, + minDuration: Infinity, + }; + + this.history = []; + } + + /** + * 记录动画开始 + * @param {string} animationName - 动画名称 + */ + recordStart(animationName) { + this.metrics.totalAnimations++; + this.metrics.activeAnimations++; + + this.history.push({ + name: animationName, + startTime: performance.now(), + endTime: null, + duration: null, + }); + } + + /** + * 记录动画结束 + * @param {string} animationName - 动画名称 + */ + recordEnd(animationName) { + this.metrics.activeAnimations--; + + const entry = this.history.find( + (h) => h.name === animationName && h.endTime === null + ); + + if (entry) { + entry.endTime = performance.now(); + entry.duration = entry.endTime - entry.startTime; + + // 更新统计 + this.metrics.maxDuration = Math.max(this.metrics.maxDuration, entry.duration); + this.metrics.minDuration = Math.min(this.metrics.minDuration, entry.duration); + + // 计算平均值 + const completed = this.history.filter((h) => h.duration !== null); + this.metrics.averageDuration = + completed.reduce((sum, h) => sum + h.duration, 0) / completed.length; + } + } + + /** + * 获取指标 + * @returns {Object} 性能指标 + */ + getMetrics() { + return { ...this.metrics }; + } + + /** + * 获取历史记录 + * @returns {Array} 历史记录 + */ + getHistory() { + return [...this.history]; + } + + /** + * 重置监控 + */ + reset() { + this.metrics = { + totalAnimations: 0, + activeAnimations: 0, + averageDuration: 0, + maxDuration: 0, + minDuration: Infinity, + }; + + this.history = []; + } +} + +/** + * 创建性能监控实例 + * @returns {AnimationPerformanceMonitor} 性能监控实例 + */ +export const createPerformanceMonitor = () => { + return new AnimationPerformanceMonitor(); +}; + +/** + * 动画缓存管理 + */ +export const animationCacheManager = { + /** + * 缓存动画 + * @param {string} key - 缓存键 + * @param {Object} animation - 动画配置 + */ + set(key, animation) { + animationCache.set(key, animation); + }, + + /** + * 获取缓存动画 + * @param {string} key - 缓存键 + * @returns {Object|null} 动画配置 + */ + get(key) { + return animationCache.get(key) || null; + }, + + /** + * 检查缓存 + * @param {string} key - 缓存键 + * @returns {boolean} 是否存在 + */ + has(key) { + return animationCache.has(key); + }, + + /** + * 删除缓存 + * @param {string} key - 缓存键 + */ + delete(key) { + animationCache.delete(key); + }, + + /** + * 清空缓存 + */ + clear() { + animationCache.clear(); + }, + + /** + * 获取缓存大小 + * @returns {number} 缓存大小 + */ + size() { + return animationCache.size; + }, +}; + +export { AnimationManager, defaultAnimationManager }; diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..e265193 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,328 @@ +/** + * MetonaToast Constants - 常量定义 + * @module constants + * @version 2.0.0 + * @description 默认配置、颜色、动画、主题等常量 + */ + +/** + * 默认配置 + */ +export const DEFAULTS = Object.freeze({ + // 基础配置 + position: 'top-right', + duration: 4000, + max: 6, + gap: 12, + offset: 24, + + // 交互配置 + pauseOnHover: true, + closeOnClick: true, + draggable: true, + + // 显示配置 + showProgress: true, + progressDirection: 'horizontal', + icon: true, + closeButton: true, + + // 主题配置 + theme: 'auto', + animation: 'slide', + + // 布局配置 + zIndex: 9999, + width: 360, + + // 自定义配置 + className: '', + style: {}, + + // 回调函数 + onShow: null, + onClose: null, + onClick: null, + + // 国际化 + locale: 'zh-CN', + + // 插件 + plugins: [], +}); + +// Icons — 从 icons.js 导入并重新导出(保持向后兼容) +import { ICONS } from './icons.js'; +export { ICONS }; + +/** + * 类型颜色配置 + */ +export const TYPE_COLORS = { + success: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + error: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + warning: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + info: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + loading: { fg: '#6366f1', bg: 'rgba(99, 102, 241, 0.1)' }, + default: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + check: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + x: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + alert: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + question: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + star: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + heart: { fg: '#ec4899', bg: 'rgba(236, 72, 153, 0.1)' }, + bell: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + mail: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + settings: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + user: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + home: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + search: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + plus: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + minus: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + edit: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + trash: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + download: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + upload: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + share: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + link: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + external: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + clock: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + calendar: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + map: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + compass: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + globe: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + wifi: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + cloud: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + sun: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + moon: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + zap: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + activity: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + cpu: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + database: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + server: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + terminal: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + code: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + git: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + package: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + layers: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + grid: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + list: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + filter: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + sort: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + refresh: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + sync: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + power: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + battery: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + bluetooth: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + volume: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + mic: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + camera: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + image: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + video: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + music: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + file: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + folder: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + clipboard: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + save: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + print: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + eye: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + eyeOff: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + lock: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + unlock: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + shield: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + key: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + flag: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + bookmark: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + tag: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + gift: { fg: '#ec4899', bg: 'rgba(236, 72, 153, 0.1)' }, + award: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + target: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + crosshair: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + move: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + maximize: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + minimize: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + copy: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + cut: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + paste: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + rotateCw: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + rotateCcw: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + zoomIn: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + zoomOut: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + crop: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + sliders: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + toggleLeft: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + toggleRight: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + checkCircle: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + xCircle: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + alertCircle: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + infoCircle: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + helpCircle: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + alertTriangle: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + checkSquare: { fg: '#10b981', bg: 'rgba(16, 185, 129, 0.1)' }, + square: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + circle: { fg: '#6b7280', bg: 'rgba(107, 114, 128, 0.1)' }, + triangle: { fg: '#f59e0b', bg: 'rgba(245, 158, 11, 0.1)' }, + hexagon: { fg: '#3b82f6', bg: 'rgba(59, 130, 246, 0.1)' }, + octagon: { fg: '#ef4444', bg: 'rgba(239, 68, 68, 0.1)' }, + pentagon: { fg: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.1)' }, + diamond: { fg: '#ec4899', bg: 'rgba(236, 72, 153, 0.1)' }, +}; + +/** + * 动画配置 + */ +export const ANIMATIONS = { + slide: { + enter: { transform: 'translateX(80px)', opacity: 0 }, + leave: { transform: 'translateX(120%)', opacity: 0 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + fade: { + enter: { opacity: 0, filter: 'blur(3px)' }, + leave: { opacity: 0, filter: 'blur(3px)' }, + duration: 500, + easing: 'ease', + }, + scale: { + enter: { transform: 'scale(0.55)', opacity: 0 }, + leave: { transform: 'scale(0.55)', opacity: 0 }, + duration: 450, + easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', + }, + bounce: { + enter: { transform: 'translateY(-80px)', opacity: 0 }, + leave: { transform: 'translateY(20px)', opacity: 0 }, + duration: 650, + easing: 'ease', + }, + flip: { + enter: { transform: 'perspective(500px) rotateX(-90deg)', opacity: 0 }, + leave: { transform: 'perspective(500px) rotateX(90deg)', opacity: 0 }, + duration: 500, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + rotate: { + enter: { transform: 'rotate(-25deg) scale(0.6)', opacity: 0 }, + leave: { transform: 'rotate(25deg) scale(0.6)', opacity: 0 }, + duration: 500, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + zoom: { + enter: { transform: 'scale(0.1)', opacity: 0 }, + leave: { transform: 'scale(0.1)', opacity: 0 }, + duration: 500, + easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', + }, + slideUp: { + enter: { transform: 'translateY(60px)', opacity: 0 }, + leave: { transform: 'translateY(-120%)', opacity: 0 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideDown: { + enter: { transform: 'translateY(-60px)', opacity: 0 }, + leave: { transform: 'translateY(120%)', opacity: 0 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideLeft: { + enter: { transform: 'translateX(-90px)', opacity: 0 }, + leave: { transform: 'translateX(120%)', opacity: 0 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, + slideRight: { + enter: { transform: 'translateX(90px)', opacity: 0 }, + leave: { transform: 'translateX(-120%)', opacity: 0 }, + duration: 400, + easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + }, +}; + +/** + * 主题配置 + */ +export const THEMES = { + light: { + bg: 'rgba(255, 255, 255, 0.96)', + text: '#1f2937', + border: 'rgba(0, 0, 0, 0.06)', + shadow: '0 10px 36px -10px rgba(0, 0, 0, 0.18), 0 4px 14px -4px rgba(0, 0, 0, 0.08)', + hoverShadow: '0 14px 48px -10px rgba(0, 0, 0, 0.22), 0 6px 18px -4px rgba(0, 0, 0, 0.10)', + progressBg: 'rgba(0, 0, 0, 0.06)', + closeHoverBg: 'rgba(0, 0, 0, 0.06)', + }, + dark: { + bg: 'rgba(28, 32, 40, 0.94)', + text: '#e6e8eb', + border: 'rgba(255, 255, 255, 0.08)', + shadow: '0 10px 36px -10px rgba(0, 0, 0, 0.6), 0 4px 14px -4px rgba(0, 0, 0, 0.4)', + hoverShadow: '0 14px 48px -8px rgba(0, 0, 0, 0.6), 0 6px 18px -4px rgba(0, 0, 0, 0.4)', + progressBg: 'rgba(255, 255, 255, 0.08)', + closeHoverBg: 'rgba(255, 255, 255, 0.08)', + }, + auto: 'auto', + warm: { + bg: 'rgba(255, 251, 235, 0.96)', + text: '#78350f', + border: 'rgba(245, 158, 11, 0.2)', + shadow: '0 10px 36px -10px rgba(245, 158, 11, 0.18), 0 4px 14px -4px rgba(245, 158, 11, 0.08)', + hoverShadow: '0 14px 48px -10px rgba(245, 158, 11, 0.22), 0 6px 18px -4px rgba(245, 158, 11, 0.10)', + progressBg: 'rgba(245, 158, 11, 0.1)', + closeHoverBg: 'rgba(245, 158, 11, 0.1)', + }, +}; + +/** + * 位置配置 + */ +export const POSITIONS = [ + 'top-left', + 'top-center', + 'top-right', + 'bottom-left', + 'bottom-center', + 'bottom-right', +]; + +/** + * 类型配置 + */ +export const TYPES = [ + 'default', 'success', 'error', 'warning', 'info', 'loading', + 'check', 'x', 'alert', 'question', 'star', 'heart', 'bell', 'mail', + 'settings', 'user', 'home', 'search', 'plus', 'minus', 'edit', 'trash', + 'download', 'upload', 'share', 'link', 'external', 'clock', 'calendar', + 'map', 'compass', 'globe', 'wifi', 'cloud', 'sun', 'moon', 'zap', + 'activity', 'cpu', 'database', 'server', 'terminal', 'code', 'git', + 'package', 'layers', 'grid', 'list', 'filter', 'sort', 'refresh', 'sync', + 'power', 'battery', 'bluetooth', 'volume', 'mic', 'camera', 'image', 'video', + 'music', 'file', 'folder', 'clipboard', 'save', 'print', 'eye', 'eyeOff', + 'lock', 'unlock', 'shield', 'key', 'flag', 'bookmark', 'tag', 'gift', + 'award', 'target', 'crosshair', 'move', 'maximize', 'minimize', + 'copy', 'cut', 'paste', 'rotateCw', 'rotateCcw', 'zoomIn', 'zoomOut', + 'crop', 'sliders', 'toggleLeft', 'toggleRight', + 'checkCircle', 'xCircle', 'alertCircle', 'infoCircle', 'helpCircle', + 'alertTriangle', 'checkSquare', 'square', 'circle', 'triangle', + 'hexagon', 'octagon', 'pentagon', 'diamond', +]; + +// Locales — 从 locales.js 导入并重新导出(保持向后兼容) +import { LOCALES } from './locales.js'; +export { LOCALES }; + +/** + * 进度条方向 + */ +export const PROGRESS_DIRECTIONS = ['horizontal', 'vertical']; + +/** + * 动画类型 + */ +export const ANIMATION_TYPES = ['slide', 'fade', 'scale', 'bounce', 'flip', 'rotate', 'zoom', 'slideUp', 'slideDown', 'slideLeft', 'slideRight']; + +/** + * 主题类型 + */ +export const THEME_TYPES = ['light', 'dark', 'auto']; diff --git a/src/core.js b/src/core.js new file mode 100644 index 0000000..2a7bbb6 --- /dev/null +++ b/src/core.js @@ -0,0 +1,1070 @@ +/** + * MetonaToast Core - 核心Toast逻辑 + * @module core + * @version 2.0.0 + * @description 重构后的核心模块,包含Toast类的优化实现 + */ + +import { generateId, escapeHTML, prefersDark } from './utils.js'; +import { DEFAULTS, ICONS, TYPE_COLORS } from './constants.js'; +import { injectStyles } from './styles.js'; +import { getTheme, applyTheme } from './themes.js'; +import { t as i18nT, setCurrentLocale } from './i18n.js'; + +// 模块级共享容器缓存,所有 Toast 实例共用 +const _containerCache = new WeakMap(); + +/** + * 参数标准化工具 + * 支持多种调用方式: + * - success('message') + * - success({ message: 'text' }) + * - success({ title: 'title', message: 'text' }) + * - success('message', { duration: 5000 }) + */ +const normalizeArgs = (args, defaultType = 'default') => { + const [first, second] = args; + + // 情况1: success('message') + if (typeof first === 'string') { + return { + ...second, + type: second?.type || defaultType, + message: first, + }; + } + + // 情况2: success({ message: 'text' }) 或 success({ title: 't', message: 'm' }) + if (first && typeof first === 'object') { + return { + ...first, + type: first.type || defaultType, + }; + } + + // 情况3: success() 无参数 + return { + type: defaultType, + message: '', + }; +}; + +/** + * Toast类 - 核心通知组件 + */ +class Toast { + // 静态钩子系统 + static _hooks = new Map(); + static on(name, fn) { + if (!this._hooks.has(name)) this._hooks.set(name, []); + this._hooks.get(name).push(fn); + return () => this.off(name, fn); + } + static off(name, fn) { + const list = this._hooks.get(name); + if (list) this._hooks.set(name, list.filter(f => f !== fn)); + } + static trigger(name, toast) { + const list = this._hooks.get(name); + if (list) list.forEach(fn => { try { fn(toast); } catch (e) { console.error('Hook error:', name, e); } }); + } + + constructor(opts) { + this.id = opts.id || generateId(); + this.type = opts.type || 'default'; + this.title = opts.title || ''; + this.message = opts.message ?? opts.content ?? ''; + this.html = opts.html || ''; + this.iconHTML = opts.iconHTML || ''; + this.config = { ...DEFAULTS, ...opts }; + this.el = null; + this.barEl = null; + this.rafId = null; + this.remaining = this.config.duration; + this.startedAt = 0; + this.paused = false; + this.closing = false; + this._cleanups = []; + } + + _palette() { + const theme = getTheme(this.config.theme); + const c = TYPE_COLORS[this.type] || TYPE_COLORS.default; + const t = theme === 'dark' + ? { + bg: 'rgba(28,32,40,.94)', + border: 'rgba(255,255,255,.08)', + shadow: '0 10px 36px -10px rgba(0,0,0,.6),0 4px 14px -4px rgba(0,0,0,.4)' + } + : { + bg: 'rgba(255,255,255,.96)', + border: 'rgba(0,0,0,.06)', + shadow: '0 10px 36px -10px rgba(0,0,0,.18),0 4px 14px -4px rgba(0,0,0,.08)' + }; + return { theme, c, t }; + } + + create() { + if (typeof window === 'undefined' || typeof document === 'undefined') return this; + + Toast.trigger('beforeShow', this); + injectStyles(); + + const container = this._getContainer(); + const { theme, c, t } = this._palette(); + + this._limitToasts(container); + + const el = document.createElement('div'); + el.className = this._buildClassName(theme); + el.setAttribute('role', (this.type === 'error' || this.type === 'warning') ? 'alert' : 'status'); + el.setAttribute('aria-live', this.type === 'error' ? 'assertive' : 'polite'); + el.dataset.id = this.id; + + this._applyStyles(el, theme, t); + this._buildContent(el, c); + + this.el = el; + // Chrome bug: column-reverse + appendChild 会导致重叠。改用 column + insertBefore + const pos = this.config.position || 'top-right'; + if (pos.startsWith('top')) { + container.insertBefore(el, container.firstChild); + } else { + container.appendChild(el); + } + + this._bindEvents(el); + this._startTimer(); + + // 进入动画 + requestAnimationFrame(() => { + requestAnimationFrame(() => { + el.classList.add('met-show'); + }); + }); + + if (typeof this.config.onShow === 'function') { + try { + this.config.onShow(this); + } catch (e) { + console.error('onShow callback error:', e); + } + } + + Toast.trigger('afterShow', this); + + return this; + } + + _getContainer() { + const position = this.config.position || 'top-right'; + const zIndex = this.config.zIndex || 9999; + + if (_containerCache.has(document.body)) { + const containers = _containerCache.get(document.body); + if (containers.has(position)) { + return containers.get(position); + } + } else { + _containerCache.set(document.body, new Map()); + } + + const el = document.createElement('div'); + el.className = `met-container ${position}`; + el.setAttribute('aria-label', 'Notifications'); + el.setAttribute('role', 'region'); + + // cssText 完全接管布局,不依赖 CSS class + const posStyles = { + 'top-left': 'top:0;left:0;align-items:flex-start', + 'top-center': 'top:0;left:0;right:0;align-items:center', + 'top-right': 'top:0;right:0;align-items:flex-end', + 'bottom-left': 'bottom:0;left:0;align-items:flex-start', + 'bottom-center':'bottom:0;left:0;right:0;align-items:center', + 'bottom-right': 'bottom:0;right:0;align-items:flex-end', + }; + el.style.cssText = ` + display:flex; + flex-direction:column; + gap:12px; + box-sizing:border-box; + padding:24px; + max-width:100vw; + position:fixed; + z-index:${zIndex}; + pointer-events:none; + ${posStyles[position] || 'top:0;right:0;align-items:flex-end'} + `; + + document.body.appendChild(el); + _containerCache.get(document.body).set(position, el); + + return el; + } + + _limitToasts(container) { + const max = this.config.max || 6; + const list = Array.from(container.querySelectorAll('.met-toast')); + if (list.length >= max) { + const first = list[0]; + const id = first && first.dataset.id; + if (id) { + const old = meToast._toasts.get(id); + if (old) old.close(true); + } + } + } + + _buildClassName(theme) { + // CSS 支持的动画类型,未列出的 fallback 到 slide + const CSS_ANIMS = ['slide','fade','scale','bounce','flip','rotate','zoom', + 'slideUp','slideDown','slideLeft','slideRight']; + const anim = CSS_ANIMS.includes(this.config.animation) ? this.config.animation : 'slide'; + return [ + 'met-toast', + `met-${this.type}`, + `met-theme-${theme}`, + `met-anim-${anim}`, + (this.config.closeOnClick || this.config.draggable) ? 'met-clickable' : '', + this.config.className || '', + ].filter(Boolean).join(' '); + } + + _applyStyles(el, theme, t) { + const widthValue = typeof this.config.width === 'number' + ? `${this.config.width}px` + : (typeof this.config.width === 'string' ? this.config.width : '360px'); + + // 只强制核心布局属性,动画/滤镜/颜色由 CSS class 控制 + const set = (p, v) => el.style.setProperty(p, v, 'important'); + set('position', 'relative'); + set('flex-shrink', '0'); + set('min-width', '240px'); + set('max-width', 'calc(100vw - 48px)'); + set('width', widthValue); + // 用户自定义样式最后应用 + if (this.config.style) { + Object.entries(this.config.style).forEach(([k, v]) => { el.style[k] = v; }); + } + } + + _buildContent(el, c) { + const showIcon = this.config.icon !== false && (this.iconHTML || ICONS[this.type]); + const showClose = this.config.closeButton !== false; + const showProgress = this.config.showProgress !== false && this.config.duration > 0; + const showSide = (!showIcon && this.type !== 'default'); + + const safeTitle = this.title ? `
${escapeHTML(this.title)}
` : ''; + const safeMessage = this.html + ? `
${this.html}
` + : (this.message ? `
${escapeHTML(this.message)}
` : ''); + + const iconHTML = showIcon + ? `
${this.iconHTML || ICONS[this.type]}
` : ''; + const closeHTML = showClose + ? `` + : ''; + const progressHTML = showProgress + ? (this.config.progressDirection === 'vertical' + ? `
` + : `
`) + : ''; + const sideHTML = showSide + ? `
` : ''; + + el.innerHTML = ` + ${iconHTML} + ${sideHTML} +
+ ${safeTitle} + ${safeMessage} +
+ ${closeHTML} + ${progressHTML} + `; + + this.barEl = el.querySelector('.met-bar, .met-bar-v'); + } + + _bindEvents(el) { + const eventHandler = (e) => { + const target = e.target; + + if (target.closest('.met-close')) { + e.stopPropagation(); + this.close(); + return; + } + + if (this.config.closeOnClick && !target.closest('.met-close')) { + if (typeof this.config.onClick === 'function') { + try { + this.config.onClick(this); + } catch (err) { + console.error('onClick callback error:', err); + } + } + this.close(); + return; + } + }; + + el.addEventListener('click', eventHandler); + this._cleanups.push(() => el.removeEventListener('click', eventHandler)); + + if (this.config.pauseOnHover && this.config.duration > 0) { + const mouseEnter = () => this._pause(); + const mouseLeave = () => this._resume(); + + el.addEventListener('mouseenter', mouseEnter); + el.addEventListener('mouseleave', mouseLeave); + + this._cleanups.push(() => { + el.removeEventListener('mouseenter', mouseEnter); + el.removeEventListener('mouseleave', mouseLeave); + }); + } + + if (this.config.draggable) { + this._bindDrag(el); + } + } + + _bindDrag(el) { + let sx = 0, sy = 0, dx = 0, dy = 0, dragging = false; + + const down = (e) => { + if (e.target.closest('.met-close')) return; + dragging = true; + sx = e.clientX; + sy = e.clientY; + el.setPointerCapture(e.pointerId); + el.style.transition = 'none'; + this._pause(); + }; + + const move = (e) => { + if (!dragging) return; + dx = e.clientX - sx; + dy = e.clientY - sy; + el.style.transform = `translate(${dx}px, ${dy}px) rotate(${dx * 0.1}deg)`; + el.style.opacity = String(Math.max(0, 1 - Math.abs(dx) / 200)); + }; + + const up = (e) => { + if (!dragging) return; + dragging = false; + el.releasePointerCapture(e.pointerId); + el.style.transition = ''; + + if (Math.abs(dx) > 120) { + el.style.transform = `translate(${dx * 2}px, ${dy}px) rotate(${dx * 0.2}deg)`; + el.style.opacity = '0'; + setTimeout(() => this.close(true), 250); + } else { + el.style.transform = ''; + el.style.opacity = ''; + this._resume(); + } + dx = dy = 0; + }; + + el.addEventListener('pointerdown', down); + el.addEventListener('pointermove', move); + el.addEventListener('pointerup', up); + el.addEventListener('pointercancel', up); + + this._cleanups.push(() => { + el.removeEventListener('pointerdown', down); + el.removeEventListener('pointermove', move); + el.removeEventListener('pointerup', up); + el.removeEventListener('pointercancel', up); + }); + } + + _startTimer() { + if (this.config.duration <= 0) return; + + this.startedAt = Date.now(); + this.remaining = this.config.duration; + + const tick = () => { + if (this.paused || this.closing) return; + + const elapsed = Date.now() - this.startedAt; + this.remaining = Math.max(0, this.config.duration - elapsed); + + if (this.barEl) { + const ratio = this.remaining / this.config.duration; + const t = this.config.progressDirection === 'vertical' + ? `scaleY(${ratio})` : `scaleX(${ratio})`; + this.barEl.style.transform = t; + } + + if (this.remaining <= 0) { + this.close(); + return; + } + + this.rafId = requestAnimationFrame(tick); + }; + + this.rafId = requestAnimationFrame(tick); + } + + _pause() { + if (this.paused || this.config.duration <= 0) return; + this.paused = true; + cancelAnimationFrame(this.rafId); + this.remaining = Math.max(0, this.config.duration - (Date.now() - this.startedAt)); + } + + _resume() { + if (!this.paused) return; + this.paused = false; + this.startedAt = Date.now() - (this.config.duration - this.remaining); + this._startTimer(); + } + + update(partial) { + Toast.trigger('beforeUpdate', this); + if (partial.type) this.type = partial.type; + if (partial.title !== undefined) this.title = partial.title; + if (partial.message !== undefined) this.message = partial.message; + if (partial.html !== undefined) this.html = partial.html; + + if (!this.el) { Toast.trigger('afterUpdate', this); return this; } + + const content = this.el.querySelector('.met-content'); + if (content) { + const safeTitle = this.title ? `
${escapeHTML(this.title)}
` : ''; + const safeMessage = this.html + ? `
${this.html}
` + : (this.message ? `
${escapeHTML(this.message)}
` : ''); + content.innerHTML = `${safeTitle}${safeMessage}`; + } + + Toast.trigger('afterUpdate', this); + return this; + } + + close(immediate = false) { + if (this.closing) return; + this.closing = true; + + Toast.trigger('beforeClose', this); + cancelAnimationFrame(this.rafId); + this._cleanups.forEach(fn => { try { fn(); } catch (_) {} }); + this._cleanups = []; + + const el = this.el; + if (!el) { + meToast._remove(this.id); + return; + } + + // 立即脱离文档流:记录当前位置,然后设为 absolute,让下方 toast 自然上移 + const container = el.parentNode; + if (container && !immediate) { + const elRect = el.getBoundingClientRect(); + const containerRect = container.getBoundingClientRect(); + el.style.position = 'absolute'; + el.style.top = (elRect.top - containerRect.top) + 'px'; + el.style.left = (elRect.left - containerRect.left) + 'px'; + el.style.width = elRect.width + 'px'; + el.style.margin = '0'; + } + + el.classList.add('met-leaving'); + el.classList.remove('met-show'); + + const pos = this.config.position || 'top-right'; + let transform = 'scale(.96)'; + + if (pos.includes('right')) transform = 'translateX(120%)'; + else if (pos.includes('left')) transform = 'translateX(-120%)'; + else if (pos.startsWith('top')) transform = 'translateY(-20px)'; + else transform = 'translateY(20px)'; + + el.style.transform = transform; + el.style.opacity = '0'; + + setTimeout(() => this._destroy(), immediate ? 0 : 300); + } + + _destroy() { + if (this.el && this.el.parentNode) { + this.el.parentNode.removeChild(this.el); + } + this.el = null; + + if (typeof this.config.onClose === 'function') { + try { + this.config.onClose(this); + } catch (e) { + console.error('onClose callback error:', e); + } + } + + Toast.trigger('afterClose', this); + meToast._remove(this.id); + } +} + +// ========== HTML模板辅助函数 ========== + +/** + * 按钮行模板 — confirm/prompt 共用 + * @param {string} buttons - 按钮HTML + * @returns {string} 按钮行HTML + */ +const _btnRow = (buttons) => ` +
+ ${buttons} +
`; + +/** + * 确认对话框模板 + * @param {Object} opts - 选项 + * @returns {string} HTML + */ +const _confirmHTML = (opts) => { + const confirmText = opts.confirmText || i18nT('confirm'); + const cancelText = opts.cancelText || i18nT('cancel'); + const confirmColor = opts.confirmColor || '#10b981'; + const cancelColor = opts.cancelColor || '#6b7280'; + return _btnRow(` + + + `); +}; + +/** + * 输入对话框模板 + * @param {Object} opts - 选项 + * @returns {string} HTML + */ +const _promptHTML = (opts) => { + const submitText = opts.submitText || i18nT('confirm'); + const cancelText = opts.cancelText || i18nT('cancel'); + const submitColor = opts.submitColor || '#3b82f6'; + const cancelColor = opts.cancelColor || '#6b7280'; + return ` + + ${_btnRow(` + + + `)} + `; +}; + +/** + * 进度条模板 + * @param {Object} opts - 选项 + * @returns {string} HTML + */ +const _progressHTML = (opts) => { + const color = opts.progressColor || '#3b82f6'; + return ` +
+
+
+
0%
+ `; +}; + +/** + * 主对象 + */ +const meToast = { + _toasts: new Map(), + _config: { ...DEFAULTS }, + version: '2.0.0', + + configure(opts) { + if (!opts || typeof opts !== 'object') return this; + this._config = { ...this._config, ...opts }; + + if (opts.theme) { + applyTheme(opts.theme); + } + + if (opts.locale) { + setCurrentLocale(opts.locale); + } + + return this; + }, + + _emit(opts) { + const merged = { ...this._config, ...opts }; + if (merged.content && !merged.message) merged.message = merged.content; + + const t = new Toast(merged); + t.create(); + this._toasts.set(t.id, t); + + return t; + }, + + _remove(id) { + this._toasts.delete(id); + }, + + find(id) { + if (!id) return undefined; + return this._toasts.get(id); + }, + + /** + * 显示默认Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象(当第一个参数是字符串时) + */ + show(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'default'); + return this._emit(normalized); + }, + + /** + * 显示成功Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象 + */ + success(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'success'); + return this._emit(normalized); + }, + + /** + * 显示错误Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象 + */ + error(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'error'); + return this._emit(normalized); + }, + + /** + * 显示警告Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象 + */ + warning(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'warning'); + return this._emit(normalized); + }, + + /** + * 显示信息Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象 + */ + info(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'info'); + return this._emit(normalized); + }, + + /** + * 显示加载Toast + * @param {string|Object} messageOrOpts - 消息字符串或选项对象 + * @param {Object} [opts] - 选项对象 + */ + loading(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'loading'); + normalized.duration = 0; + normalized.closeButton = false; + normalized.showProgress = false; + + const t = this._emit(normalized); + + return { + id: t.id, + success: (msg, o = {}) => this._resolve(t, 'success', msg, o), + error: (msg, o = {}) => this._resolve(t, 'error', msg, o), + info: (msg, o = {}) => this._resolve(t, 'info', msg, o), + warning: (msg, o = {}) => this._resolve(t, 'warning', msg, o), + update: (p) => { t.update(p); return this; }, + dismiss: () => t.close(), + }; + }, + + promise(promise, opts = {}) { + if (!promise || typeof promise.then !== 'function') { + console.error('MeToast.promise: first argument must be a Promise'); + return Promise.reject(new Error('Invalid promise')); + } + + const loadingMsg = opts.loading || i18nT('loading'); + const successMsg = opts.success || i18nT('success'); + const errorMsg = opts.error || i18nT('error'); + + const ctrl = this.loading(loadingMsg); + + return Promise.resolve(promise) + .then((data) => { + ctrl.success(successMsg); + return data; + }) + .catch((err) => { + ctrl.error(errorMsg); + throw err; + }); + }, + + _resolve(loadingToast, type, message, opts) { + const id = loadingToast.id; + const old = this._toasts.get(id); + if (!old) return null; + + const position = old.config.position; + old.close(); + + return this._emit({ ...opts, type, message, position }); + }, + + /** + * 确认对话框 + * @param {string} message - 消息内容 + * @param {Object} [opts] - 选项 + * @returns {Promise} + */ + confirm(message, opts = {}) { + if (typeof message !== 'string') { + console.error('MeToast.confirm: message must be a string'); + return Promise.resolve(false); + } + + return new Promise((resolve) => { + const t = this._emit({ + ...opts, + type: opts.type || 'warning', + message, + duration: 0, + closeButton: false, + closeOnClick: false, + draggable: false, + html: _confirmHTML(opts), + }); + + setTimeout(() => { + const confirmBtn = t.el?.querySelector('.met-confirm-btn'); + const cancelBtn = t.el?.querySelector('.met-cancel-btn'); + + if (confirmBtn) { + confirmBtn.addEventListener('click', () => { + t.close(); + resolve(true); + }); + } + + if (cancelBtn) { + cancelBtn.addEventListener('click', () => { + t.close(); + resolve(false); + }); + } + }, 0); + }); + }, + + /** + * 输入对话框 + * @param {string} message - 消息内容 + * @param {Object} [opts] - 选项 + * @returns {Promise} + */ + prompt(message, opts = {}) { + if (typeof message !== 'string') { + console.error('MeToast.prompt: message must be a string'); + return Promise.resolve(null); + } + + return new Promise((resolve) => { + const t = this._emit({ + ...opts, + type: opts.type || 'info', + message, + duration: 0, + closeButton: false, + closeOnClick: false, + draggable: false, + html: _promptHTML(opts), + }); + + setTimeout(() => { + const input = t.el?.querySelector('.met-input'); + const submitBtn = t.el?.querySelector('.met-submit-btn'); + const cancelBtn = t.el?.querySelector('.met-cancel-btn'); + + if (input) { + input.focus(); + + input.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + t.close(); + resolve(input.value); + } + }); + } + + if (submitBtn) { + submitBtn.addEventListener('click', () => { + t.close(); + resolve(input?.value || null); + }); + } + + if (cancelBtn) { + cancelBtn.addEventListener('click', () => { + t.close(); + resolve(null); + }); + } + }, 0); + }); + }, + + /** + * 进度Toast + * @param {string|Object} messageOrOpts - 消息或选项 + * @param {Object} [opts] - 选项 + * @returns {Object} 控制对象 + */ + progress(messageOrOpts, opts = {}) { + const normalized = normalizeArgs([messageOrOpts, opts], 'info'); + normalized.duration = 0; + normalized.closeButton = false; + normalized.showProgress = false; + + const t = this._emit({ + ...normalized, + html: _progressHTML(opts), + }); + + return { + id: t.id, + + setProgress(percent) { + const fill = t.el?.querySelector('.met-progress-fill'); + const text = t.el?.querySelector('.met-progress-text'); + + if (fill) { + fill.style.width = `${Math.min(100, Math.max(0, percent))}%`; + } + + if (text) { + text.textContent = `${Math.round(percent)}%`; + } + }, + + complete(message) { + this.setProgress(100); + setTimeout(() => { + t.update({ + type: 'success', + message: message || i18nT('success'), + html: '', + }); + setTimeout(() => t.close(), 1000); + }, 300); + }, + + error(message) { + t.update({ + type: 'error', + message: message || i18nT('error'), + html: '', + }); + setTimeout(() => t.close(), 2000); + }, + + dismiss() { + t.close(); + }, + }; + }, + + /** + * 倒计时Toast + * @param {string} message - 消息内容 + * @param {number} seconds - 秒数 + * @param {Object} [opts] - 选项 + * @returns {Object} 控制对象 + */ + countdown(message, seconds = 10, opts = {}) { + if (typeof message !== 'string') { + console.error('MeToast.countdown: message must be a string'); + return { cancel: () => {}, pause: () => {}, resume: () => {} }; + } + + let remaining = Math.max(1, parseInt(seconds) || 10); + let timer = null; + + const t = this._emit({ + ...opts, + type: opts.type || 'warning', + message: message.replace('{seconds}', remaining), + duration: 0, + closeButton: true, + showProgress: false, + }); + + const tick = () => { + remaining--; + + if (remaining <= 0) { + clearInterval(timer); + t.close(); + + if (typeof opts.onComplete === 'function') { + try { + opts.onComplete(); + } catch (e) { + console.error('countdown onComplete error:', e); + } + } + return; + } + + t.update({ + message: message.replace('{seconds}', remaining), + }); + }; + + timer = setInterval(tick, 1000); + + return { + id: t.id, + + cancel() { + clearInterval(timer); + t.close(); + }, + + pause() { + clearInterval(timer); + }, + + resume() { + clearInterval(timer); + timer = setInterval(tick, 1000); + }, + }; + }, + + /** + * 队列Toast + * @param {Array} messages - 消息数组 + * @param {Object} [opts] - 选项 + * @returns {Promise} + */ + queue(messages, opts = {}) { + if (!Array.isArray(messages)) { + console.error('MeToast.queue: messages must be an array'); + return Promise.resolve(); + } + + return new Promise((resolve) => { + let index = 0; + const delay = opts.delay || 1000; + + const showNext = () => { + if (index >= messages.length) { + resolve(); + return; + } + + const message = messages[index]; + index++; + + const msg = typeof message === 'string' ? message : (message?.message || ''); + + this._emit({ + ...opts, + ...((typeof message === 'object' && message !== null) ? message : {}), + message: msg, + duration: opts.duration || 3000, + onClose: () => { + setTimeout(showNext, delay); + }, + }); + }; + + showNext(); + }); + }, + + /** + * 堆叠Toast + * @param {Array} messages - 消息数组 + * @param {Object} [opts] - 选项 + */ + stack(messages, opts = {}) { + if (!Array.isArray(messages)) { + console.error('MeToast.stack: messages must be an array'); + return; + } + + messages.forEach((message, index) => { + setTimeout(() => { + const msg = typeof message === 'string' ? message : (message?.message || ''); + + this._emit({ + ...opts, + ...((typeof message === 'object' && message !== null) ? message : {}), + message: msg, + }); + }, index * (opts.stagger || 100)); + }); + }, + + dismiss(id) { + if (id) { + const t = this._toasts.get(id); + if (t) t.close(); + return; + } + this._toasts.forEach(t => t.close()); + }, + + clear(position) { + this._toasts.forEach(t => { + if (!position || t.config.position === position) t.close(); + }); + }, + + destroy() { + this.dismiss(); + + if (typeof document !== 'undefined') { + const containers = document.querySelectorAll('.met-container'); + containers.forEach(c => c.parentNode && c.parentNode.removeChild(c)); + + const style = document.getElementById('metona-toast-styles'); + if (style) style.parentNode.removeChild(style); + } + + this._toasts.clear(); + }, + + getAll() { + return new Map(this._toasts); + }, + + count() { + return this._toasts.size; + }, +}; + +export { meToast as default, meToast, Toast }; diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 0000000..e6b45a7 --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,1054 @@ +/** + * MetonaToast i18n - 国际化管理 + * @module i18n + * @version 2.0.0 + * @description 多语言支持、语言切换和翻译管理 + */ + +import { LOCALES } from './constants.js'; + +// 当前语言状态 +let currentLocale = 'zh-CN'; +let localeListeners = new Set(); +let fallbackLocale = 'zh-CN'; + +/** + * 获取当前语言 + * @returns {string} 当前语言 + */ +export const getCurrentLocale = () => { + return currentLocale; +}; + +/** + * 设置当前语言 + * @param {string} locale - 语言代码 + */ +export const setCurrentLocale = (locale) => { + if (!LOCALES[locale]) { + console.warn(`Locale "${locale}" not found, falling back to "${fallbackLocale}"`); + locale = fallbackLocale; + } + + currentLocale = locale; + notifyLocaleListeners(locale); + saveLocale(locale); +}; + +/** + * 获取回退语言 + * @returns {string} 回退语言 + */ +export const getFallbackLocale = () => { + return fallbackLocale; +}; + +/** + * 设置回退语言 + * @param {string} locale - 语言代码 + */ +export const setFallbackLocale = (locale) => { + if (!LOCALES[locale]) { + console.warn(`Fallback locale "${locale}" not found`); + return; + } + + fallbackLocale = locale; +}; + +/** + * 翻译函数 + * @param {string} key - 翻译键 + * @param {Object} params - 插值参数 + * @returns {string} 翻译后的字符串 + */ +export const t = (key, params = {}) => { + // 尝试当前语言 + const currentTranslation = getTranslation(currentLocale, key); + if (currentTranslation !== undefined) { + return interpolate(currentTranslation, params); + } + + // 尝试回退语言 + if (currentLocale !== fallbackLocale) { + const fallbackTranslation = getTranslation(fallbackLocale, key); + if (fallbackTranslation !== undefined) { + return interpolate(fallbackTranslation, params); + } + } + + // 返回键名 + console.warn(`Translation missing for key "${key}" in locale "${currentLocale}"`); + return key; +}; + +/** + * 获取翻译 + * @param {string} locale - 语言代码 + * @param {string} key - 翻译键 + * @returns {string|undefined} 翻译字符串 + */ +const getTranslation = (locale, key) => { + const localeData = LOCALES[locale]; + if (!localeData) return undefined; + + // 支持嵌套键 (如 'common.close') + const keys = key.split('.'); + let result = localeData; + + for (const k of keys) { + if (result && typeof result === 'object' && k in result) { + result = result[k]; + } else { + return undefined; + } + } + + return typeof result === 'string' ? result : undefined; +}; + +/** + * 插值函数 + * @param {string} str - 包含占位符的字符串 + * @param {Object} params - 插值参数 + * @returns {string} 插值后的字符串 + */ +const interpolate = (str, params) => { + return str.replace(/\{(\w+)\}/g, (match, key) => { + return params[key] !== undefined ? params[key] : match; + }); +}; + +/** + * 检查翻译是否存在 + * @param {string} key - 翻译键 + * @returns {boolean} 是否存在 + */ +export const hasTranslation = (key) => { + return getTranslation(currentLocale, key) !== undefined || + getTranslation(fallbackLocale, key) !== undefined; +}; + +/** + * 获取所有翻译 + * @param {string} locale - 语言代码 + * @returns {Object} 翻译对象 + */ +export const getTranslations = (locale) => { + return LOCALES[locale] || {}; +}; + +/** + * 添加翻译 + * @param {string} locale - 语言代码 + * @param {Object} translations - 翻译对象 + */ +export const addTranslations = (locale, translations) => { + if (!LOCALES[locale]) { + LOCALES[locale] = {}; + } + + deepMerge(LOCALES[locale], translations); +}; + +/** + * 深度合并对象 + * @param {Object} target - 目标对象 + * @param {Object} source - 源对象 + * @returns {Object} 合并后的对象 + */ +const deepMerge = (target, source) => { + for (const key in source) { + if (source[key] instanceof Object && key in target && target[key] instanceof Object) { + deepMerge(target[key], source[key]); + } else { + target[key] = source[key]; + } + } + return target; +}; + +/** + * 移除翻译 + * @param {string} locale - 语言代码 + * @param {string} key - 翻译键 + */ +export const removeTranslation = (locale, key) => { + const localeData = LOCALES[locale]; + if (!localeData) return; + + const keys = key.split('.'); + let current = localeData; + + for (let i = 0; i < keys.length - 1; i++) { + if (current[keys[i]] && typeof current[keys[i]] === 'object') { + current = current[keys[i]]; + } else { + return; + } + } + + delete current[keys[keys.length - 1]]; +}; + +/** + * 清除翻译 + * @param {string} locale - 语言代码 + */ +export const clearTranslations = (locale) => { + if (LOCALES[locale]) { + LOCALES[locale] = {}; + } +}; + +/** + * 获取支持的语言列表 + * @returns {Array} 语言代码数组 + */ +export const getSupportedLocales = () => { + return Object.keys(LOCALES); +}; + +/** + * 检查语言是否支持 + * @param {string} locale - 语言代码 + * @returns {boolean} 是否支持 + */ +export const isLocaleSupported = (locale) => { + return locale in LOCALES; +}; + +/** + * 获取语言名称 + * @param {string} locale - 语言代码 + * @returns {string} 语言名称 + */ +export const getLocaleName = (locale) => { + const names = { + 'zh-CN': '简体中文', + 'zh-TW': '繁體中文', + 'en-US': 'English (US)', + 'en-GB': 'English (UK)', + 'ja': '日本語', + 'ko': '한국어', + 'fr': 'Français', + 'de': 'Deutsch', + 'es': 'Español', + 'pt': 'Português', + 'ru': 'Русский', + 'ar': 'العربية', + 'hi': 'हिन्दी', + 'th': 'ไทย', + 'vi': 'Tiếng Việt', + 'id': 'Bahasa Indonesia', + 'ms': 'Bahasa Melayu', + 'tr': 'Türkçe', + 'it': 'Italiano', + 'nl': 'Nederlands', + 'pl': 'Polski', + 'uk': 'Українська', + 'cs': 'Čeština', + 'sv': 'Svenska', + 'da': 'Dansk', + 'fi': 'Suomi', + 'nb': 'Norsk', + 'el': 'Ελληνικά', + 'he': 'עברית', + 'hu': 'Magyar', + 'ro': 'Română', + 'bg': 'Български', + 'hr': 'Hrvatski', + 'sk': 'Slovenčina', + 'sl': 'Slovenščina', + 'et': 'Eesti', + 'lv': 'Latviešu', + 'lt': 'Lietuvių', + 'ca': 'Català', + 'gl': 'Galego', + 'eu': 'Euskara', + 'cy': 'Cymraeg', + 'ga': 'Gaeilge', + 'mt': 'Malti', + 'is': 'Íslenska', + 'mk': 'Македонски', + 'sq': 'Shqip', + 'sr': 'Српски', + 'bs': 'Bosanski', + 'me': 'Crnogorski', + 'ka': 'ქართული', + 'hy': 'Հայերեն', + 'az': 'Azərbaycan', + 'uz': "O'zbek", + 'kk': 'Қазақ', + 'ky': 'Кыргыз', + 'tg': 'Тоҷикӣ', + 'tk': 'Türkmen', + 'mn': 'Монгол', + 'ne': 'नेपाली', + 'si': 'සිංහල', + 'my': 'မြန်မာ', + 'km': 'ខ្មែរ', + 'lo': 'ລາວ', + 'am': 'አማርኛ', + 'sw': 'Kiswahili', + 'yo': 'Yorùbá', + 'ig': 'Igbo', + 'ha': 'Hausa', + 'zu': 'isiZulu', + 'af': 'Afrikaans', + 'xh': 'isiXhosa', + 'st': 'Sesotho', + 'tn': 'Setswana', + 'ts': 'Xitsonga', + 'ss': 'siSwati', + 've': 'Tshivenda', + 'nr': 'isiNdebele', + }; + + return names[locale] || locale; +}; + +/** + * 获取语言方向 + * @param {string} locale - 语言代码 + * @returns {string} 语言方向 ('ltr' 或 'rtl') + */ +export const getLocaleDirection = (locale) => { + const rtlLocales = ['ar', 'he', 'fa', 'ur', 'yi', 'ps', 'sd', 'ug']; + return rtlLocales.includes(locale) ? 'rtl' : 'ltr'; +}; + +/** + * 获取语言信息 + * @param {string} locale - 语言代码 + * @returns {Object} 语言信息 + */ +export const getLocaleInfo = (locale) => { + return { + code: locale, + name: getLocaleName(locale), + direction: getLocaleDirection(locale), + isSupported: isLocaleSupported(locale), + isCurrent: locale === currentLocale, + isFallback: locale === fallbackLocale, + }; +}; + +/** + * 获取所有语言信息 + * @returns {Array} 语言信息数组 + */ +export const getAllLocaleInfo = () => { + return getSupportedLocales().map(getLocaleInfo); +}; + +/** + * 保存语言到本地存储 + * @param {string} locale - 语言代码 + */ +export const saveLocale = (locale) => { + if (typeof localStorage !== 'undefined') { + try { + localStorage.setItem('metona-toast-locale', locale); + } catch (e) { + console.warn('Failed to save locale:', e); + } + } +}; + +/** + * 从本地存储加载语言 + * @returns {string} 语言代码 + */ +export const loadLocale = () => { + if (typeof localStorage !== 'undefined') { + try { + return localStorage.getItem('metona-toast-locale') || getDefaultLocale(); + } catch (e) { + console.warn('Failed to load locale:', e); + } + } + return getDefaultLocale(); +}; + +/** + * 获取默认语言 + * @returns {string} 语言代码 + */ +export const getDefaultLocale = () => { + if (typeof navigator !== 'undefined') { + // 尝试从浏览器获取语言 + const browserLocale = navigator.language || navigator.userLanguage; + if (browserLocale && isLocaleSupported(browserLocale)) { + return browserLocale; + } + + // 尝试语言代码的前两位 + const shortLocale = browserLocale?.split('-')[0]; + if (shortLocale && isLocaleSupported(shortLocale)) { + return shortLocale; + } + } + + return fallbackLocale; +}; + +/** + * 初始化国际化系统 + */ +export const initI18n = () => { + const savedLocale = loadLocale(); + setCurrentLocale(savedLocale); +}; + +/** + * 切换语言 + * @param {string} locale - 新语言 + */ +export const switchLocale = (locale) => { + setCurrentLocale(locale); +}; + +/** + * 添加语言监听器 + * @param {Function} listener - 监听器函数 + * @returns {Function} 移除监听器函数 + */ +export const addLocaleListener = (listener) => { + localeListeners.add(listener); + + return () => { + localeListeners.delete(listener); + }; +}; + +/** + * 移除语言监听器 + * @param {Function} listener - 监听器函数 + */ +export const removeLocaleListener = (listener) => { + localeListeners.delete(listener); +}; + +/** + * 通知语言监听器 + * @param {string} locale - 语言代码 + */ +const notifyLocaleListeners = (locale) => { + localeListeners.forEach((listener) => { + try { + listener(locale); + } catch (e) { + console.error('Locale listener error:', e); + } + }); +}; + +/** + * 清除所有语言监听器 + */ +export const clearLocaleListeners = () => { + localeListeners.clear(); +}; + +/** + * 格式化数字 + * @param {number} number - 数字 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatNumber = (number, options = {}) => { + try { + return new Intl.NumberFormat(currentLocale, options).format(number); + } catch (e) { + return number.toString(); + } +}; + +/** + * 格式化货币 + * @param {number} amount - 金额 + * @param {string} currency - 货币代码 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatCurrency = (amount, currency = 'USD', options = {}) => { + try { + return new Intl.NumberFormat(currentLocale, { + style: 'currency', + currency, + ...options, + }).format(amount); + } catch (e) { + return amount.toString(); + } +}; + +/** + * 格式化百分比 + * @param {number} value - 值 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatPercent = (value, options = {}) => { + try { + return new Intl.NumberFormat(currentLocale, { + style: 'percent', + minimumFractionDigits: 0, + maximumFractionDigits: 2, + ...options, + }).format(value / 100); + } catch (e) { + return `${value}%`; + } +}; + +/** + * 格式化日期 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatDate = (date, options = {}) => { + try { + const dateObj = date instanceof Date ? date : new Date(date); + return new Intl.DateTimeFormat(currentLocale, options).format(dateObj); + } catch (e) { + return date.toString(); + } +}; + +/** + * 格式化时间 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatTime = (date, options = {}) => { + return formatDate(date, { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + ...options, + }); +}; + +/** + * 格式化相对时间 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatRelativeTime = (date, options = {}) => { + try { + const dateObj = date instanceof Date ? date : new Date(date); + const now = new Date(); + const diff = dateObj - now; + + const rtf = new Intl.RelativeTimeFormat(currentLocale, { + numeric: 'auto', + ...options, + }); + + const units = [ + { unit: 'year', ms: 365 * 24 * 60 * 60 * 1000 }, + { unit: 'month', ms: 30 * 24 * 60 * 60 * 1000 }, + { unit: 'week', ms: 7 * 24 * 60 * 60 * 1000 }, + { unit: 'day', ms: 24 * 60 * 60 * 1000 }, + { unit: 'hour', ms: 60 * 60 * 1000 }, + { unit: 'minute', ms: 60 * 1000 }, + { unit: 'second', ms: 1000 }, + ]; + + for (const { unit, ms } of units) { + if (Math.abs(diff) >= ms || unit === 'second') { + const value = Math.round(diff / ms); + return rtf.format(value, unit); + } + } + + return date.toString(); + } catch (e) { + return date.toString(); + } +}; + +/** + * 格式化列表 + * @param {Array} list - 列表 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatList = (list, options = {}) => { + try { + return new Intl.ListFormat(currentLocale, options).format(list); + } catch (e) { + return list.join(', '); + } +}; + +/** + * 格式化复数 + * @param {number} count - 数量 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ +export const formatPlural = (count, options = {}) => { + try { + return new Intl.PluralRules(currentLocale, options).select(count); + } catch (e) { + return count === 1 ? 'one' : 'other'; + } +}; + +/** + * 复数翻译 + * @param {string} key - 翻译键 + * @param {number} count - 数量 + * @param {Object} params - 插值参数 + * @returns {string} 翻译后的字符串 + */ +export const plural = (key, count, params = {}) => { + const pluralForm = formatPlural(count); + const pluralKey = `${key}.${pluralForm}`; + + if (hasTranslation(pluralKey)) { + return t(pluralKey, { ...params, count }); + } + + // 尝试通用形式 + if (hasTranslation(key)) { + return t(key, { ...params, count }); + } + + return key; +}; + +/** + * 日期时间格式化选项 + */ +export const dateTimeFormats = { + short: { + year: 'numeric', + month: 'short', + day: 'numeric', + }, + medium: { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + }, + long: { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'long', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + }, + time: { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + }, + date: { + year: 'numeric', + month: 'long', + day: 'numeric', + }, + weekday: { + weekday: 'long', + }, + month: { + month: 'long', + }, + year: { + year: 'numeric', + }, +}; + +/** + * 数字格式化选项 + */ +export const numberFormats = { + integer: { + maximumFractionDigits: 0, + }, + decimal: { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }, + percent: { + style: 'percent', + minimumFractionDigits: 0, + maximumFractionDigits: 2, + }, + currency: { + style: 'currency', + currency: 'USD', + }, +}; + +/** + * 国际化工具 + */ +export const i18nUtils = { + /** + * 翻译 + * @param {string} key - 翻译键 + * @param {Object} params - 插值参数 + * @returns {string} 翻译后的字符串 + */ + t(key, params) { + return t(key, params); + }, + + /** + * 复数翻译 + * @param {string} key - 翻译键 + * @param {number} count - 数量 + * @param {Object} params - 插值参数 + * @returns {string} 翻译后的字符串 + */ + plural(key, count, params) { + return plural(key, count, params); + }, + + /** + * 获取当前语言 + * @returns {string} 当前语言 + */ + getCurrentLocale() { + return getCurrentLocale(); + }, + + /** + * 设置当前语言 + * @param {string} locale - 语言代码 + */ + setCurrentLocale(locale) { + setCurrentLocale(locale); + }, + + /** + * 切换语言 + * @param {string} locale - 新语言 + */ + switchLocale(locale) { + switchLocale(locale); + }, + + /** + * 获取回退语言 + * @returns {string} 回退语言 + */ + getFallbackLocale() { + return getFallbackLocale(); + }, + + /** + * 设置回退语言 + * @param {string} locale - 语言代码 + */ + setFallbackLocale(locale) { + setFallbackLocale(locale); + }, + + /** + * 检查翻译是否存在 + * @param {string} key - 翻译键 + * @returns {boolean} 是否存在 + */ + hasTranslation(key) { + return hasTranslation(key); + }, + + /** + * 获取所有翻译 + * @param {string} locale - 语言代码 + * @returns {Object} 翻译对象 + */ + getTranslations(locale) { + return getTranslations(locale); + }, + + /** + * 添加翻译 + * @param {string} locale - 语言代码 + * @param {Object} translations - 翻译对象 + */ + addTranslations(locale, translations) { + addTranslations(locale, translations); + }, + + /** + * 移除翻译 + * @param {string} locale - 语言代码 + * @param {string} key - 翻译键 + */ + removeTranslation(locale, key) { + removeTranslation(locale, key); + }, + + /** + * 清除翻译 + * @param {string} locale - 语言代码 + */ + clearTranslations(locale) { + clearTranslations(locale); + }, + + /** + * 获取支持的语言列表 + * @returns {Array} 语言代码数组 + */ + getSupportedLocales() { + return getSupportedLocales(); + }, + + /** + * 检查语言是否支持 + * @param {string} locale - 语言代码 + * @returns {boolean} 是否支持 + */ + isLocaleSupported(locale) { + return isLocaleSupported(locale); + }, + + /** + * 获取语言名称 + * @param {string} locale - 语言代码 + * @returns {string} 语言名称 + */ + getLocaleName(locale) { + return getLocaleName(locale); + }, + + /** + * 获取语言方向 + * @param {string} locale - 语言代码 + * @returns {string} 语言方向 + */ + getLocaleDirection(locale) { + return getLocaleDirection(locale); + }, + + /** + * 获取语言信息 + * @param {string} locale - 语言代码 + * @returns {Object} 语言信息 + */ + getLocaleInfo(locale) { + return getLocaleInfo(locale); + }, + + /** + * 获取所有语言信息 + * @returns {Array} 语言信息数组 + */ + getAllLocaleInfo() { + return getAllLocaleInfo(); + }, + + /** + * 格式化数字 + * @param {number} number - 数字 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatNumber(number, options) { + return formatNumber(number, options); + }, + + /** + * 格式化货币 + * @param {number} amount - 金额 + * @param {string} currency - 货币代码 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatCurrency(amount, currency, options) { + return formatCurrency(amount, currency, options); + }, + + /** + * 格式化百分比 + * @param {number} value - 值 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatPercent(value, options) { + return formatPercent(value, options); + }, + + /** + * 格式化日期 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatDate(date, options) { + return formatDate(date, options); + }, + + /** + * 格式化时间 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatTime(date, options) { + return formatTime(date, options); + }, + + /** + * 格式化相对时间 + * @param {Date|number|string} date - 日期 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatRelativeTime(date, options) { + return formatRelativeTime(date, options); + }, + + /** + * 格式化列表 + * @param {Array} list - 列表 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatList(list, options) { + return formatList(list, options); + }, + + /** + * 格式化复数 + * @param {number} count - 数量 + * @param {Object} options - 格式化选项 + * @returns {string} 格式化后的字符串 + */ + formatPlural(count, options) { + return formatPlural(count, options); + }, + + /** + * 添加语言监听器 + * @param {Function} listener - 监听器函数 + * @returns {Function} 移除监听器函数 + */ + addLocaleListener(listener) { + return addLocaleListener(listener); + }, + + /** + * 移除语言监听器 + * @param {Function} listener - 监听器函数 + */ + removeLocaleListener(listener) { + removeLocaleListener(listener); + }, + + /** + * 清除所有语言监听器 + */ + clearLocaleListeners() { + clearLocaleListeners(); + }, + + /** + * 初始化国际化系统 + */ + initI18n() { + initI18n(); + }, + + /** + * 保存语言 + * @param {string} locale - 语言代码 + */ + saveLocale(locale) { + saveLocale(locale); + }, + + /** + * 加载语言 + * @returns {string} 语言代码 + */ + loadLocale() { + return loadLocale(); + }, + + /** + * 获取默认语言 + * @returns {string} 语言代码 + */ + getDefaultLocale() { + return getDefaultLocale(); + }, +}; + +/** + * 预设语言包 + */ +export const presetLocales = { + 'zh-CN': { + name: '简体中文', + nativeName: '简体中文', + direction: 'ltr', + translations: LOCALES['zh-CN'], + }, + + 'en-US': { + name: 'English (US)', + nativeName: 'English (US)', + direction: 'ltr', + translations: LOCALES['en-US'], + }, +}; + +/** + * 创建国际化管理器 + * @returns {Object} 国际化管理器 + */ +export const createI18nManager = () => { + return { + t, + plural, + getCurrentLocale, + setCurrentLocale, + switchLocale, + getFallbackLocale, + setFallbackLocale, + hasTranslation, + getTranslations, + addTranslations, + removeTranslation, + clearTranslations, + getSupportedLocales, + isLocaleSupported, + getLocaleName, + getLocaleDirection, + getLocaleInfo, + getAllLocaleInfo, + formatNumber, + formatCurrency, + formatPercent, + formatDate, + formatTime, + formatRelativeTime, + formatList, + formatPlural, + addLocaleListener, + removeLocaleListener, + clearLocaleListeners, + initI18n, + saveLocale, + loadLocale, + getDefaultLocale, + }; +}; + +export { i18nUtils as default }; diff --git a/src/icons.js b/src/icons.js new file mode 100644 index 0000000..eb8d8c9 --- /dev/null +++ b/src/icons.js @@ -0,0 +1,603 @@ +/** + * MetonaToast Icons — 图标SVG定义 + * @module icons + * @version 2.0.0 + * @description 80+ 内置SVG图标 + */ + +export const ICONS = { + success: ` + + `, + + error: ` + + + + `, + + warning: ` + + + + `, + + info: ` + + + + `, + + loading: ` + + `, + + close: ` + + + `, + + check: ` + + `, + + x: ` + + + `, + + alert: ` + + + + `, + + question: ` + + + + `, + + star: ` + + `, + + heart: ` + + `, + + bell: ` + + + `, + + mail: ` + + + `, + + settings: ` + + + `, + + user: ` + + + `, + + home: ` + + + `, + + search: ` + + + `, + + plus: ` + + + `, + + minus: ` + + `, + + edit: ` + + + `, + + trash: ` + + + + + `, + + download: ` + + + + `, + + upload: ` + + + + `, + + share: ` + + + + + + `, + + link: ` + + + `, + + external: ` + + + + `, + + clock: ` + + + `, + + calendar: ` + + + + + `, + + map: ` + + + + `, + + compass: ` + + + `, + + globe: ` + + + + `, + + wifi: ` + + + + + `, + + cloud: ` + + `, + + sun: ` + + + + + + + + + + `, + + moon: ` + + `, + + zap: ` + + `, + + activity: ` + + `, + + cpu: ` + + + + + + + + + + + `, + + database: ` + + + + `, + + server: ` + + + + + `, + + terminal: ` + + + `, + + code: ` + + + `, + + git: ` + + + + + `, + + package: ` + + + + + `, + + layers: ` + + + + `, + + grid: ` + + + + + `, + + list: ` + + + + + + + `, + + filter: ` + + `, + + sort: ` + + + `, + + refresh: ` + + + + `, + + sync: ` + + + + `, + + power: ` + + + `, + + battery: ` + + + `, + + bluetooth: ` + + `, + + volume: ` + + + `, + + mic: ` + + + + + `, + + camera: ` + + + `, + + image: ` + + + + `, + + video: ` + + + `, + + music: ` + + + + `, + + file: ` + + + `, + + folder: ` + + `, + + clipboard: ` + + + `, + + save: ` + + + + `, + + print: ` + + + + `, + + eye: ` + + + `, + + eyeOff: ` + + + `, + + lock: ` + + + `, + + unlock: ` + + + `, + + shield: ` + + `, + + key: ` + + `, + + flag: ` + + + `, + + bookmark: ` + + `, + + tag: ` + + + `, + + gift: ` + + + + + + `, + + award: ` + + + `, + + target: ` + + + + `, + + crosshair: ` + + + + + + `, + + move: ` + + + + + + + `, + + maximize: ` + + `, + + minimize: ` + + `, + + copy: ` + + + `, + + cut: ` + + + + + + `, + + paste: ` + + + `, + + rotateCw: ` + + + `, + + rotateCcw: ` + + + `, + + zoomIn: ` + + + + + `, + + zoomOut: ` + + + + `, + + crop: ` + + + `, + + sliders: ` + + + + + + + + + + `, + + toggleLeft: ` + + + `, + + toggleRight: ` + + + `, + + checkCircle: ` + + + `, + + xCircle: ` + + + + `, + + alertCircle: ` + + + + `, + + infoCircle: ` + + + + `, + + helpCircle: ` + + + + `, + + alertTriangle: ` + + + + `, + + checkSquare: ` + + + `, + + square: ` + + `, + + circle: ` + + `, + + triangle: ` + + `, + + hexagon: ` + + `, + + octagon: ` + + `, + + pentagon: ` + + `, + + diamond: ` + + `, +}; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..9fe789d --- /dev/null +++ b/src/index.js @@ -0,0 +1,264 @@ +/** + * MetonaToast - 轻量级Toast通知库 + * @module metona-toast + * @version 2.0.0 + * @author metona + * @description 轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。 + * @license MIT + */ + +import { meToast, Toast } from './core.js'; +import { animationUtils } from './animations.js'; +import { themeUtils } from './themes.js'; +import { i18nUtils } from './i18n.js'; +import { pluginUtils, presetPlugins } from './plugins.js'; +import { DEFAULTS } from './constants.js'; + +// 版本信息 +const VERSION = '2.0.0'; + +/** + * 主对象增强 + */ +const enhancedMeToast = { + ...meToast, + + version: VERSION, + + animations: animationUtils, + themes: themeUtils, + i18n: i18nUtils, + plugins: pluginUtils, + presetPlugins, + + /** + * 安装插件,并连接必要的生命周期钩子 + */ + use(plugin, options = {}) { + if (typeof plugin === 'string') { + const preset = presetPlugins[plugin]; + if (!preset) { + console.warn(`Preset plugin "${plugin}" not found`); + return this; + } + this.plugins.register(plugin, { ...preset, ...options }); + + // 连接插件钩子 + if (plugin === 'accessibility') { + Toast.on('afterShow', (toast) => preset.announce(toast)); + } + if (plugin === 'persistence') { + const saved = preset.install(); + if (saved) this.configure(saved); + Toast.on('afterClose', () => { preset.save(this.getConfig()); }); + } + } else if (plugin && typeof plugin === 'object') { + const name = plugin.name || 'custom'; + this.plugins.register(name, { ...plugin, ...options }); + } + + return this; + }, + + /** + * 初始化 + */ + init(options = {}) { + if (options.config) { + this.configure(options.config); + } + + if (options.theme) { + this.themes.switchTheme(options.theme); + } + + if (options.locale) { + this.i18n.switchLocale(options.locale); + } + + if (options.plugins && Array.isArray(options.plugins)) { + options.plugins.forEach((plugin) => { + this.use(plugin); + }); + } + + return this; + }, + + /** + * 销毁 + */ + destroy() { + this.dismiss(); + + if (this.plugins && typeof this.plugins.destroy === 'function') { + this.plugins.destroy(); + } + + if (this.themes) { + if (typeof this.themes.clearThemeListeners === 'function') { + this.themes.clearThemeListeners(); + } + if (typeof this.themes.unwatchSystemTheme === 'function') { + this.themes.unwatchSystemTheme(); + } + } + + if (this.i18n && typeof this.i18n.clearLocaleListeners === 'function') { + this.i18n.clearLocaleListeners(); + } + + if (this.animations && typeof this.animations.cancelAll === 'function') { + this.animations.cancelAll(); + } + + if (typeof document !== 'undefined') { + const containers = document.querySelectorAll('.met-container'); + containers.forEach((c) => c.parentNode && c.parentNode.removeChild(c)); + + const style = document.getElementById('metona-toast-styles'); + if (style) style.parentNode.removeChild(style); + } + + this._toasts.clear(); + }, + + /** + * 获取状态 + */ + getStatus() { + return { + version: VERSION, + toasts: this._toasts.size, + theme: this.themes?.getCurrentTheme?.() || 'auto', + locale: this.i18n?.getCurrentLocale?.() || 'zh-CN', + plugins: this.plugins?.getNames?.() || [], + animations: this.animations?.getActiveCount?.() || 0, + }; + }, + + /** + * 获取配置 + */ + getConfig() { + return { ...this._config }; + }, + + /** + * 更新配置 + */ + updateConfig(config) { + if (config && typeof config === 'object') { + this._config = { ...this._config, ...config }; + } + return this; + }, + + /** + * 重置配置 + */ + resetConfig() { + this._config = { ...DEFAULTS }; + return this; + }, + + /** + * 获取Toast列表 + */ + getToasts() { + return Array.from(this._toasts.values()); + }, + + /** + * 检查是否有Toast + */ + hasToasts() { + return this._toasts.size > 0; + }, + + /** + * 获取Toast + */ + getToast(id) { + if (!id) return null; + return this._toasts.get(id) || null; + }, + + /** + * 关闭所有Toast + */ + closeAll() { + this._toasts.forEach((t) => t.close()); + }, + + /** + * 清除所有Toast + */ + clearAll() { + this._toasts.forEach((t) => t.close()); + }, + + /** + * 暂停所有Toast + */ + pauseAll() { + this._toasts.forEach((t) => t._pause()); + }, + + /** + * 恢复所有Toast + */ + resumeAll() { + this._toasts.forEach((t) => t._resume()); + }, + + /** + * 更新所有Toast + */ + updateAll(partial) { + if (partial && typeof partial === 'object') { + this._toasts.forEach((t) => t.update(partial)); + } + }, + + /** + * 查找Toast + */ + findToasts(predicate) { + if (typeof predicate !== 'function') return []; + return Array.from(this._toasts.values()).filter(predicate); + }, + + /** + * 按类型查找Toast + */ + findByType(type) { + return this.findToasts((t) => t.type === type); + }, + + /** + * 按位置查找Toast + */ + findByPosition(position) { + return this.findToasts((t) => t.config.position === position); + }, + +}; +// 初始化主题和国际化 +if (typeof themeUtils.initTheme === 'function') { + themeUtils.initTheme(); +} +if (typeof i18nUtils.initI18n === 'function') { + i18nUtils.initI18n(); +} + +// 浏览器环境全局注册 +if (typeof window !== 'undefined') { + window.MeToast = enhancedMeToast; + window.Met = enhancedMeToast; + window.metonaToast = enhancedMeToast; +} + +// 导出 +export default enhancedMeToast; +export { enhancedMeToast as meToast, enhancedMeToast as Met, enhancedMeToast as MeToast, Toast, VERSION }; diff --git a/src/locales.js b/src/locales.js new file mode 100644 index 0000000..12134ce --- /dev/null +++ b/src/locales.js @@ -0,0 +1,752 @@ +/** + * MetonaToast Locales — 国际化翻译数据 + * @module locales + * @version 2.0.0 + * @description 内置 zh-CN / en-US 完整翻译 + */ + +export const LOCALES = { + 'zh-CN': { + close: '关闭', + loading: '加载中...', + success: '操作成功', + error: '操作失败', + warning: '警告', + info: '信息', + confirm: '确认', + cancel: '取消', + yes: '是', + no: '否', + ok: '确定', + retry: '重试', + undo: '撤销', + redo: '重做', + save: '保存', + delete: '删除', + edit: '编辑', + add: '添加', + remove: '移除', + search: '搜索', + filter: '筛选', + sort: '排序', + refresh: '刷新', + sync: '同步', + upload: '上传', + download: '下载', + share: '分享', + copy: '复制', + cut: '剪切', + paste: '粘贴', + print: '打印', + export: '导出', + import: '导入', + settings: '设置', + help: '帮助', + about: '关于', + version: '版本', + language: '语言', + theme: '主题', + dark: '暗色', + light: '亮色', + auto: '自动', + notifications: '通知', + enable: '启用', + disable: '禁用', + on: '开启', + off: '关闭', + max: '最大', + min: '最小', + expand: '展开', + collapse: '折叠', + fullscreen: '全屏', + exitFullscreen: '退出全屏', + zoomIn: '放大', + zoomOut: '缩小', + reset: '重置', + apply: '应用', + submit: '提交', + send: '发送', + receive: '接收', + connect: '连接', + disconnect: '断开', + start: '开始', + stop: '停止', + pause: '暂停', + resume: '继续', + next: '下一个', + previous: '上一个', + first: '第一个', + last: '最后一个', + back: '返回', + forward: '前进', + home: '首页', + menu: '菜单', + more: '更多', + less: '更少', + show: '显示', + hide: '隐藏', + visible: '可见', + hidden: '隐藏', + enabled: '已启用', + disabled: '已禁用', + active: '活跃', + inactive: '非活跃', + online: '在线', + offline: '离线', + connected: '已连接', + disconnected: '已断开', + loading: '加载中', + loaded: '已加载', + saving: '保存中', + saved: '已保存', + deleting: '删除中', + deleted: '已删除', + uploading: '上传中', + uploaded: '已上传', + downloading: '下载中', + downloaded: '已下载', + processing: '处理中', + processed: '已处理', + syncing: '同步中', + synced: '已同步', + sending: '发送中', + sent: '已发送', + receiving: '接收中', + received: '已接收', + connecting: '连接中', + error: '错误', + warning: '警告', + info: '信息', + success: '成功', + question: '问题', + help: '帮助', + feedback: '反馈', + report: '报告', + bug: '错误', + feature: '功能', + improvement: '改进', + suggestion: '建议', + request: '请求', + response: '响应', + status: '状态', + progress: '进度', + complete: '完成', + incomplete: '未完成', + pending: '待处理', + processing: '处理中', + failed: '失败', + cancelled: '已取消', + timeout: '超时', + expired: '已过期', + invalid: '无效', + valid: '有效', + required: '必填', + optional: '可选', + enabled: '启用', + disabled: '禁用', + allowed: '允许', + denied: '拒绝', + approved: '已批准', + rejected: '已拒绝', + accepted: '已接受', + declined: '已拒绝', + confirmed: '已确认', + unconfirmed: '未确认', + verified: '已验证', + unverified: '未验证', + authenticated: '已认证', + unauthenticated: '未认证', + authorized: '已授权', + unauthorized: '未授权', + public: '公开', + private: '私有', + protected: '受保护', + internal: '内部', + external: '外部', + local: '本地', + remote: '远程', + global: '全局', + system: '系统', + user: '用户', + admin: '管理员', + moderator: '版主', + guest: '访客', + member: '成员', + owner: '所有者', + creator: '创建者', + editor: '编辑者', + viewer: '查看者', + subscriber: '订阅者', + follower: '关注者', + following: '关注中', + friend: '朋友', + contact: '联系人', + group: '群组', + team: '团队', + organization: '组织', + company: '公司', + department: '部门', + project: '项目', + task: '任务', + issue: '问题', + ticket: '工单', + request: '请求', + response: '响应', + message: '消息', + notification: '通知', + alert: '警报', + reminder: '提醒', + event: '事件', + activity: '活动', + log: '日志', + report: '报告', + analytics: '分析', + statistics: '统计', + metrics: '指标', + performance: '性能', + security: '安全', + privacy: '隐私', + compliance: '合规', + policy: '政策', + terms: '条款', + conditions: '条件', + agreement: '协议', + contract: '合同', + license: '许可证', + copyright: '版权', + trademark: '商标', + patent: '专利', + tradeSecret: '商业秘密', + confidential: '机密', + sensitive: '敏感', + critical: '关键', + important: '重要', + urgent: '紧急', + high: '高', + medium: '中', + low: '低', + none: '无', + all: '全部', + any: '任何', + some: '一些', + each: '每个', + every: '每个', + both: '两者', + neither: '两者都不', + either: '任一', + other: '其他', + another: '另一个', + this: '这个', + that: '那个', + these: '这些', + those: '那些', + here: '这里', + there: '那里', + where: '哪里', + when: '何时', + why: '为什么', + how: '如何', + what: '什么', + who: '谁', + which: '哪个', + whose: '谁的', + whom: '谁', + myself: '我自己', + yourself: '你自己', + himself: '他自己', + herself: '她自己', + itself: '它自己', + ourselves: '我们自己', + yourselves: '你们自己', + themselves: '他们自己', + mine: '我的', + yours: '你的', + his: '他的', + hers: '她的', + its: '它的', + ours: '我们的', + yours: '你们的', + theirs: '他们的', + me: '我', + you: '你', + him: '他', + her: '她', + it: '它', + us: '我们', + them: '他们', + my: '我的', + your: '你的', + his: '他的', + her: '她的', + its: '它的', + our: '我们的', + your: '你们的', + their: '他们的', + i: '我', + you: '你', + he: '他', + she: '她', + it: '它', + we: '我们', + they: '他们', + am: '是', + is: '是', + are: '是', + was: '是', + were: '是', + be: '是', + been: '是', + being: '是', + have: '有', + has: '有', + had: '有', + having: '有', + do: '做', + does: '做', + did: '做', + doing: '做', + will: '会', + would: '会', + shall: '将', + should: '应该', + may: '可以', + might: '可能', + can: '能', + could: '能', + must: '必须', + need: '需要', + dare: '敢', + ought: '应该', + used: '过去常常', + to: '到', + of: '的', + in: '在', + for: '为了', + on: '在', + with: '和', + at: '在', + by: '通过', + from: '从', + into: '进入', + during: '在...期间', + before: '在...之前', + after: '在...之后', + above: '在...上面', + below: '在...下面', + between: '在...之间', + under: '在...下面', + over: '在...上面', + across: '穿过', + through: '通过', + into: '进入', + towards: '朝向', + upon: '在...上面', + about: '关于', + against: '反对', + among: '在...之中', + along: '沿着', + around: '周围', + beyond: '超出', + but: '但是', + despite: '尽管', + except: '除了', + inside: '里面', + outside: '外面', + since: '自从', + until: '直到', + unless: '除非', + whether: '是否', + while: '当...时候', + although: '虽然', + because: '因为', + if: '如果', + once: '一旦', + since: '自从', + so: '所以', + that: '那个', + though: '虽然', + till: '直到', + unless: '除非', + until: '直到', + when: '当...时候', + whenever: '每当', + where: '哪里', + wherever: '无论哪里', + whereas: '然而', + wherever: '无论哪里', + while: '当...时候', + why: '为什么', + }, + + 'en-US': { + close: 'Close', + loading: 'Loading...', + success: 'Success', + error: 'Error', + warning: 'Warning', + info: 'Info', + confirm: 'Confirm', + cancel: 'Cancel', + yes: 'Yes', + no: 'No', + ok: 'OK', + retry: 'Retry', + undo: 'Undo', + redo: 'Redo', + save: 'Save', + delete: 'Delete', + edit: 'Edit', + add: 'Add', + remove: 'Remove', + search: 'Search', + filter: 'Filter', + sort: 'Sort', + refresh: 'Refresh', + sync: 'Sync', + upload: 'Upload', + download: 'Download', + share: 'Share', + copy: 'Copy', + cut: 'Cut', + paste: 'Paste', + print: 'Print', + export: 'Export', + import: 'Import', + settings: 'Settings', + help: 'Help', + about: 'About', + version: 'Version', + language: 'Language', + theme: 'Theme', + dark: 'Dark', + light: 'Light', + auto: 'Auto', + notifications: 'Notifications', + enable: 'Enable', + disable: 'Disable', + on: 'On', + off: 'Off', + max: 'Max', + min: 'Min', + expand: 'Expand', + collapse: 'Collapse', + fullscreen: 'Fullscreen', + exitFullscreen: 'Exit Fullscreen', + zoomIn: 'Zoom In', + zoomOut: 'Zoom Out', + reset: 'Reset', + apply: 'Apply', + submit: 'Submit', + send: 'Send', + receive: 'Receive', + connect: 'Connect', + disconnect: 'Disconnect', + start: 'Start', + stop: 'Stop', + pause: 'Pause', + resume: 'Resume', + next: 'Next', + previous: 'Previous', + first: 'First', + last: 'Last', + back: 'Back', + forward: 'Forward', + home: 'Home', + menu: 'Menu', + more: 'More', + less: 'Less', + show: 'Show', + hide: 'Hide', + visible: 'Visible', + hidden: 'Hidden', + enabled: 'Enabled', + disabled: 'Disabled', + active: 'Active', + inactive: 'Inactive', + online: 'Online', + offline: 'Offline', + connected: 'Connected', + disconnected: 'Disconnected', + loading: 'Loading', + loaded: 'Loaded', + saving: 'Saving', + saved: 'Saved', + deleting: 'Deleting', + deleted: 'Deleted', + uploading: 'Uploading', + uploaded: 'Uploaded', + downloading: 'Downloading', + downloaded: 'Downloaded', + processing: 'Processing', + processed: 'Processed', + syncing: 'Syncing', + synced: 'Synced', + sending: 'Sending', + sent: 'Sent', + receiving: 'Receiving', + received: 'Received', + connecting: 'Connecting', + error: 'Error', + warning: 'Warning', + info: 'Info', + success: 'Success', + question: 'Question', + help: 'Help', + feedback: 'Feedback', + report: 'Report', + bug: 'Bug', + feature: 'Feature', + improvement: 'Improvement', + suggestion: 'Suggestion', + request: 'Request', + response: 'Response', + status: 'Status', + progress: 'Progress', + complete: 'Complete', + incomplete: 'Incomplete', + pending: 'Pending', + processing: 'Processing', + failed: 'Failed', + cancelled: 'Cancelled', + timeout: 'Timeout', + expired: 'Expired', + invalid: 'Invalid', + valid: 'Valid', + required: 'Required', + optional: 'Optional', + enabled: 'Enabled', + disabled: 'Disabled', + allowed: 'Allowed', + denied: 'Denied', + approved: 'Approved', + rejected: 'Rejected', + accepted: 'Accepted', + declined: 'Declined', + confirmed: 'Confirmed', + unconfirmed: 'Unconfirmed', + verified: 'Verified', + unverified: 'Unverified', + authenticated: 'Authenticated', + unauthenticated: 'Unauthenticated', + authorized: 'Authorized', + unauthorized: 'Unauthorized', + public: 'Public', + private: 'Private', + protected: 'Protected', + internal: 'Internal', + external: 'External', + local: 'Local', + remote: 'Remote', + global: 'Global', + system: 'System', + user: 'User', + admin: 'Admin', + moderator: 'Moderator', + guest: 'Guest', + member: 'Member', + owner: 'Owner', + creator: 'Creator', + editor: 'Editor', + viewer: 'Viewer', + subscriber: 'Subscriber', + follower: 'Follower', + following: 'Following', + friend: 'Friend', + contact: 'Contact', + group: 'Group', + team: 'Team', + organization: 'Organization', + company: 'Company', + department: 'Department', + project: 'Project', + task: 'Task', + issue: 'Issue', + ticket: 'Ticket', + request: 'Request', + response: 'Response', + message: 'Message', + notification: 'Notification', + alert: 'Alert', + reminder: 'Reminder', + event: 'Event', + activity: 'Activity', + log: 'Log', + report: 'Report', + analytics: 'Analytics', + statistics: 'Statistics', + metrics: 'Metrics', + performance: 'Performance', + security: 'Security', + privacy: 'Privacy', + compliance: 'Compliance', + policy: 'Policy', + terms: 'Terms', + conditions: 'Conditions', + agreement: 'Agreement', + contract: 'Contract', + license: 'License', + copyright: 'Copyright', + trademark: 'Trademark', + patent: 'Patent', + tradeSecret: 'Trade Secret', + confidential: 'Confidential', + sensitive: 'Sensitive', + critical: 'Critical', + important: 'Important', + urgent: 'Urgent', + high: 'High', + medium: 'Medium', + low: 'Low', + none: 'None', + all: 'All', + any: 'Any', + some: 'Some', + each: 'Each', + every: 'Every', + both: 'Both', + neither: 'Neither', + either: 'Either', + other: 'Other', + another: 'Another', + this: 'This', + that: 'That', + these: 'These', + those: 'Those', + here: 'Here', + there: 'There', + where: 'Where', + when: 'When', + why: 'Why', + how: 'How', + what: 'What', + who: 'Who', + which: 'Which', + whose: 'Whose', + whom: 'Whom', + myself: 'Myself', + yourself: 'Yourself', + himself: 'Himself', + herself: 'Herself', + itself: 'Itself', + ourselves: 'Ourselves', + yourselves: 'Yourselves', + themselves: 'Themselves', + mine: 'Mine', + yours: 'Yours', + his: 'His', + hers: 'Hers', + its: 'Its', + ours: 'Ours', + yours: 'Yours', + theirs: 'Theirs', + me: 'Me', + you: 'You', + him: 'Him', + her: 'Her', + it: 'It', + us: 'Us', + them: 'Them', + my: 'My', + your: 'Your', + his: 'His', + her: 'Her', + its: 'Its', + our: 'Our', + your: 'Your', + their: 'Their', + i: 'I', + you: 'You', + he: 'He', + she: 'She', + it: 'It', + we: 'We', + they: 'They', + am: 'Am', + is: 'Is', + are: 'Are', + was: 'Was', + were: 'Were', + be: 'Be', + been: 'Been', + being: 'Being', + have: 'Have', + has: 'Has', + had: 'Had', + having: 'Having', + do: 'Do', + does: 'Does', + did: 'Did', + doing: 'Doing', + will: 'Will', + would: 'Would', + shall: 'Shall', + should: 'Should', + may: 'May', + might: 'Might', + can: 'Can', + could: 'Could', + must: 'Must', + need: 'Need', + dare: 'Dare', + ought: 'Ought', + used: 'Used', + to: 'To', + of: 'Of', + in: 'In', + for: 'For', + on: 'On', + with: 'With', + at: 'At', + by: 'By', + from: 'From', + into: 'Into', + during: 'During', + before: 'Before', + after: 'After', + above: 'Above', + below: 'Below', + between: 'Between', + under: 'Under', + over: 'Over', + across: 'Across', + through: 'Through', + into: 'Into', + towards: 'Towards', + upon: 'Upon', + about: 'About', + against: 'Against', + among: 'Among', + along: 'Along', + around: 'Around', + beyond: 'Beyond', + but: 'But', + despite: 'Despite', + except: 'Except', + inside: 'Inside', + outside: 'Outside', + since: 'Since', + until: 'Until', + unless: 'Unless', + whether: 'Whether', + while: 'While', + although: 'Although', + because: 'Because', + if: 'If', + once: 'Once', + since: 'Since', + so: 'So', + that: 'That', + though: 'Though', + till: 'Till', + unless: 'Unless', + until: 'Until', + when: 'When', + whenever: 'Whenever', + where: 'Where', + wherever: 'Wherever', + whereas: 'Whereas', + wherever: 'Wherever', + while: 'While', + why: 'Why', + }, +}; diff --git a/src/plugins.js b/src/plugins.js new file mode 100644 index 0000000..2575b64 --- /dev/null +++ b/src/plugins.js @@ -0,0 +1,204 @@ +/** + * MetonaToast Plugins - 插件系统 + * @module plugins + * @version 2.0.0 + * @description 插件管理器 + 3 款预设插件 (keyboard / persistence / accessibility) + */ + +/** + * 插件管理器 + */ +class PluginManager { + constructor() { + this.plugins = new Map(); + this.initialized = false; + } + + register(name, plugin) { + if (this.plugins.has(name)) { + console.warn(`Plugin "${name}" is already registered`); + return this; + } + if (!plugin || typeof plugin !== 'object' || (!plugin.name && !plugin.version)) { + console.error(`Invalid plugin "${name}"`); + return this; + } + + this.plugins.set(name, { name, ...plugin, installed: false, enabled: true }); + + if (plugin.install) { + try { plugin.install(this); this.plugins.get(name).installed = true; } + catch (e) { console.error(`Failed to install plugin "${name}":`, e); } + } + return this; + } + + unregister(name) { + const plugin = this.plugins.get(name); + if (!plugin) return this; + if (plugin.uninstall) { + try { plugin.uninstall(this); } catch (e) { console.error(`Failed to uninstall plugin "${name}":`, e); } + } + this.plugins.delete(name); + return this; + } + + get(name) { return this.plugins.get(name) || null; } + has(name) { return this.plugins.has(name); } + getAll() { return Array.from(this.plugins.values()); } + getNames() { return Array.from(this.plugins.keys()); } + + enable(name) { + const p = this.plugins.get(name); + if (p) p.enabled = true; + return this; + } + disable(name) { + const p = this.plugins.get(name); + if (p) p.enabled = false; + return this; + } + isEnabled(name) { + const p = this.plugins.get(name); + return p ? p.enabled : false; + } + + destroy() { + this.plugins.forEach((p, name) => { + if (p.destroy) { try { p.destroy(this); } catch (e) {} } + }); + this.plugins.clear(); + } +} + +/** + * 预设插件 + */ +const presetPlugins = { + + /** + * 键盘快捷键插件 — ESC 关闭所有 Toast + */ + keyboard: { + name: 'keyboard', + version: '1.0.0', + description: 'ESC 关闭所有 Toast', + + _handler: null, + + install() { + if (typeof document === 'undefined') return; + this._handler = (e) => { + if (e.key === 'Escape') { + // 点击所有关闭按钮 + document.querySelectorAll('.met-toast .met-close').forEach(btn => { + try { btn.click(); } catch (_) {} + }); + } + }; + document.addEventListener('keydown', this._handler); + }, + + uninstall() { + if (this._handler && typeof document !== 'undefined') { + document.removeEventListener('keydown', this._handler); + this._handler = null; + } + }, + }, + + /** + * 持久化插件 — 自动保存/加载配置到 localStorage + */ + persistence: { + name: 'persistence', + version: '1.0.0', + description: '自动持久化配置到 localStorage', + storageKey: 'metona-toast-config', + + install() { + // 加载已保存的配置 + if (typeof localStorage !== 'undefined') { + try { + const saved = localStorage.getItem(this.storageKey); + return saved ? JSON.parse(saved) : null; + } catch (_) { return null; } + } + return null; + }, + + save(config) { + if (typeof localStorage !== 'undefined') { + try { localStorage.setItem(this.storageKey, JSON.stringify(config)); } catch (_) {} + } + }, + + uninstall() { + if (typeof localStorage !== 'undefined') { + try { localStorage.removeItem(this.storageKey); } catch (_) {} + } + }, + }, + + /** + * 无障碍插件 — 屏幕阅读器公告 + */ + accessibility: { + name: 'accessibility', + version: '1.0.0', + description: '通过屏幕阅读器朗读 Toast 内容', + + announce(toast) { + if (typeof document === 'undefined') return; + const el = document.createElement('div'); + el.setAttribute('aria-live', 'assertive'); + el.setAttribute('aria-atomic', 'true'); + el.style.cssText = 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;'; + const typeNames = { success:'成功', error:'错误', warning:'警告', info:'信息', loading:'加载中', default:'通知' }; + el.textContent = `${typeNames[toast.type] || '通知'}: ${toast.title || ''} ${toast.message || ''}`; + document.body.appendChild(el); + setTimeout(() => { if (el.parentNode) el.parentNode.removeChild(el); }, 3000); + }, + }, +}; + +/** + * 插件工具 + */ +const pluginUtils = { + createManager() { return new PluginManager(); }, + register(name, plugin) { return defaultPluginManager.register(name, plugin); }, + unregister(name) { return defaultPluginManager.unregister(name); }, + get(name) { return defaultPluginManager.get(name); }, + has(name) { return defaultPluginManager.has(name); }, + getAll() { return defaultPluginManager.getAll(); }, + getNames() { return defaultPluginManager.getNames(); }, + enable(name) { return defaultPluginManager.enable(name); }, + disable(name) { return defaultPluginManager.disable(name); }, + isEnabled(name) { return defaultPluginManager.isEnabled(name); }, + getPreset(name) { return presetPlugins[name] || null; }, + getAllPresets() { return { ...presetPlugins }; }, + + createPlugin(config) { + return { + name: config.name || 'custom', + version: config.version || '1.0.0', + description: config.description || '', + hooks: config.hooks || {}, + install: config.install || null, + uninstall: config.uninstall || null, + ...config, + }; + }, + + validatePlugin(plugin) { + const errors = []; + if (!plugin || typeof plugin !== 'object') errors.push('Plugin must be an object'); + if (!plugin.name && !plugin.version) errors.push('Plugin must have a name or version'); + return { valid: errors.length === 0, errors }; + }, +}; + +const defaultPluginManager = new PluginManager(); + +export { presetPlugins, pluginUtils, defaultPluginManager, PluginManager }; diff --git a/src/styles.js b/src/styles.js new file mode 100644 index 0000000..e60f108 --- /dev/null +++ b/src/styles.js @@ -0,0 +1,1848 @@ +/** + * MetonaToast Styles - 样式管理 + * @module styles + * @version 2.0.0 + * @description 样式注入、更新和主题管理 + */ + +import { THEMES } from './constants.js'; + +// 样式缓存 +let injectedStyles = null; +let styleElement = null; + +/** + * 生成CSS样式 + * @param {Object} theme - 主题配置 + * @returns {string} CSS字符串 + */ +const generateCSS = (theme) => { + return ` + /* MetonaToast 基础样式 */ + .met-container { + pointer-events: none; + display: flex; + flex-direction: column; + gap: 12px; + box-sizing: border-box; + padding: 24px; + max-width: 100vw; + position: fixed; + z-index: 9999; + } + + /* 位置样式 — 顶部位置用 column-reverse,新 toast 出现在最上方 */ + .met-container.top-left { + top: 0; + left: 0; + align-items: flex-start; + flex-direction: column-reverse; + } + + .met-container.top-center { + top: 0; + left: 0; + right: 0; + align-items: center; + flex-direction: column-reverse; + } + + .met-container.top-right { + top: 0; + right: 0; + align-items: flex-end; + flex-direction: column-reverse; + } + + .met-container.bottom-left { + bottom: 0; + left: 0; + align-items: flex-start; + flex-direction: column-reverse; + } + + .met-container.bottom-center { + bottom: 0; + left: 0; + right: 0; + align-items: center; + flex-direction: column-reverse; + } + + .met-container.bottom-right { + bottom: 0; + right: 0; + align-items: flex-end; + flex-direction: column-reverse; + } + + /* Toast基础样式 */ + .met-toast { + position: relative; + display: flex; + align-items: flex-start; + gap: 12px; + padding: 14px 16px; + border-radius: 12px; + box-sizing: border-box; + backdrop-filter: blur(14px) saturate(180%); + -webkit-backdrop-filter: blur(14px) saturate(180%); + font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + user-select: none; + -webkit-user-select: none; + transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), + box-shadow 0.25s ease, + opacity 0.25s ease; + will-change: transform, opacity; + flex-shrink: 0; + pointer-events: auto; + min-width: 240px; + max-width: calc(100vw - 48px); + width: 360px; + border: 1px solid var(--met-border, rgba(0,0,0,0.06)); + background: var(--met-bg, rgba(255,255,255,0.96)); + color: var(--met-text, #1f2937); + box-shadow: var(--met-shadow, 0 10px 36px -10px rgba(0,0,0,0.18), 0 4px 14px -4px rgba(0,0,0,0.08)); + } + + /* 悬停效果 */ + .met-toast:hover { + box-shadow: var(--met-hover-shadow, 0 14px 48px -10px rgba(0,0,0,0.22), 0 6px 18px -4px rgba(0,0,0,0.10)) !important; + } + + /* 可点击状态 */ + .met-toast.met-clickable { + cursor: pointer; + } + + /* 图标样式 */ + .met-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + margin-top: 1px; + } + + /* 内容样式 */ + .met-content { + flex: 1; + min-width: 0; + word-wrap: break-word; + overflow-wrap: break-word; + } + + /* 标题样式 */ + .met-title { + font-weight: 600; + font-size: 14px; + letter-spacing: 0.1px; + } + + /* 消息样式 */ + .met-message { + font-size: 13px; + opacity: 0.85; + margin-top: 2px; + } + + /* 关闭按钮样式 */ + .met-close { + flex-shrink: 0; + background: transparent; + border: 0; + padding: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + transition: background 0.2s, color 0.2s; + line-height: 0; + color: inherit; + opacity: 0.5; + } + + .met-close:hover { + opacity: 1; + background: var(--met-close-hover-bg, rgba(0,0,0,0.06)); + } + + /* 进度条样式 - 水平 */ + .met-progress { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 3px; + overflow: hidden; + background: var(--met-progress-bg, rgba(0,0,0,0.06)); + border-radius: 0 0 12px 12px; + } + + /* 进度条样式 - 垂直 */ + .met-progress-v { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 3px; + overflow: hidden; + background: var(--met-progress-bg, rgba(0,0,0,0.06)); + border-radius: 12px 0 0 12px; + } + + /* 进度条指示器 - 水平 */ + .met-bar { + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + transform-origin: left; + transform: scaleX(1); + } + + /* 进度条指示器 - 垂直 */ + .met-bar-v { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 100%; + transform-origin: bottom; + transform: scaleY(1); + } + + /* 侧边指示器 */ + .met-side { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 4px; + border-radius: 12px 0 0 12px; + } + + /* 加载动画 */ + .met-spin { + animation: met-rot 1s linear infinite; + transform-origin: 50% 50%; + } + + /* 离开状态 */ + .met-toast.met-leaving { + pointer-events: none; + z-index: 1; + } + + /* 动画关键帧 */ + @keyframes met-rot { + to { + transform: rotate(360deg); + } + } + + /* === 进入动画:初始隐藏态 === */ + .met-anim-slide.met-toast, + .met-anim-fade.met-toast, + .met-anim-scale.met-toast, + .met-anim-bounce.met-toast, + .met-anim-flip.met-toast, + .met-anim-rotate.met-toast, + .met-anim-zoom.met-toast, + .met-anim-slideUp.met-toast, + .met-anim-slideDown.met-toast, + .met-anim-slideLeft.met-toast, + .met-anim-slideRight.met-toast { + opacity: 0; + } + + /* === 进入动画:@keyframes 定义 === */ + @keyframes met-slide-in { + 0% { transform: translateX(80px); opacity: 0; } + 65% { transform: translateX(-6px); opacity: 1; } + 100% { transform: translateX(0); opacity: 1; } + } + @keyframes met-fade-in { + 0% { opacity: 0; filter: blur(3px); } + 100% { opacity: 1; filter: blur(0); } + } + @keyframes met-scale-in { + 0% { transform: scale(0.55); opacity: 0; } + 65% { transform: scale(1.07); opacity: 1; } + 100% { transform: scale(1); opacity: 1; } + } + @keyframes met-bounce-in { + 0% { transform: translateY(-80px); opacity: 0; animation-timing-function: ease-in; } + 45% { transform: translateY(14px); opacity: 1; animation-timing-function: ease-out; } + 65% { transform: translateY(-12px); animation-timing-function: ease-in; } + 82% { transform: translateY(4px); animation-timing-function: ease-out; } + 100% { transform: translateY(0); opacity: 1; } + } + @keyframes met-flip-in { + 0% { transform: perspective(500px) rotateX(-90deg); opacity: 0; } + 60% { transform: perspective(500px) rotateX(8deg); opacity: 1; } + 85% { transform: perspective(500px) rotateX(-2deg); } + 100% { transform: perspective(500px) rotateX(0); opacity: 1; } + } + @keyframes met-rotate-in { + 0% { transform: rotate(-25deg) scale(0.6); opacity: 0; } + 60% { transform: rotate(4deg) scale(1.05); opacity: 1; } + 85% { transform: rotate(-1deg) scale(0.98); } + 100% { transform: rotate(0) scale(1); opacity: 1; } + } + @keyframes met-zoom-in { + 0% { transform: scale(0.1); opacity: 0; } + 50% { transform: scale(1.12); opacity: 1; } + 75% { transform: scale(0.94); } + 100% { transform: scale(1); opacity: 1; } + } + @keyframes met-slideUp-in { + 0% { transform: translateY(60px); opacity: 0; } + 70% { transform: translateY(-6px); opacity: 1; } + 100% { transform: translateY(0); opacity: 1; } + } + @keyframes met-slideDown-in { + 0% { transform: translateY(-60px); opacity: 0; } + 70% { transform: translateY(6px); opacity: 1; } + 100% { transform: translateY(0); opacity: 1; } + } + @keyframes met-slideLeft-in { + 0% { transform: translateX(-90px); opacity: 0; } + 65% { transform: translateX(6px); opacity: 1; } + 100% { transform: translateX(0); opacity: 1; } + } + @keyframes met-slideRight-in { + 0% { transform: translateX(90px); opacity: 0; } + 65% { transform: translateX(-6px); opacity: 1; } + 100% { transform: translateX(0); opacity: 1; } + } + + /* === 进入动画:绑定到 .met-show === */ + .met-anim-slide.met-toast.met-show { animation: met-slide-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-fade.met-toast.met-show { animation: met-fade-in 0.50s ease forwards; } + .met-anim-scale.met-toast.met-show { animation: met-scale-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; } + .met-anim-bounce.met-toast.met-show { animation: met-bounce-in 0.65s ease forwards; } + .met-anim-flip.met-toast.met-show { animation: met-flip-in 0.50s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-rotate.met-toast.met-show { animation: met-rotate-in 0.50s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-zoom.met-toast.met-show { animation: met-zoom-in 0.50s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; } + .met-anim-slideUp.met-toast.met-show { animation: met-slideUp-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-slideDown.met-toast.met-show { animation: met-slideDown-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-slideLeft.met-toast.met-show { animation: met-slideLeft-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + .met-anim-slideRight.met-toast.met-show { animation: met-slideRight-in 0.40s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } + + /* 响应式设计 */ + @media (prefers-reduced-motion: reduce) { + .met-toast { + transition: opacity 0.15s !important; + } + + .met-toast.met-show { + animation: none !important; + opacity: 1 !important; + } + + .met-spin { + animation-duration: 2.5s !important; + } + } + + @media (max-width: 480px) { + .met-container { + padding: 12px !important; + } + + .met-toast { + width: 100% !important; + min-width: 0 !important; + } + } + + /* 暗色主题特定样式 */ + .met-toast.met-theme-dark { + background: rgba(28, 32, 40, 0.94); + color: #e6e8eb; + border-color: rgba(255, 255, 255, 0.08); + box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.6), + 0 4px 14px -4px rgba(0, 0, 0, 0.4); + } + + .met-toast.met-theme-dark:hover { + box-shadow: 0 14px 48px -8px rgba(0, 0, 0, 0.6), + 0 6px 18px -4px rgba(0, 0, 0, 0.4) !important; + } + + .met-toast.met-theme-dark .met-close:hover { + background: rgba(255, 255, 255, 0.08); + } + + .met-toast.met-theme-dark .met-progress, + .met-toast.met-theme-dark .met-progress-v { + background: rgba(255, 255, 255, 0.08); + } + + /* 亮色主题特定样式 */ + .met-toast.met-theme-light { + background: rgba(255, 255, 255, 0.96); + color: #1f2937; + border-color: rgba(0, 0, 0, 0.06); + box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.18), + 0 4px 14px -4px rgba(0, 0, 0, 0.08); + } + + .met-toast.met-theme-light:hover { + box-shadow: 0 14px 48px -10px rgba(0, 0, 0, 0.22), + 0 6px 18px -4px rgba(0, 0, 0, 0.10) !important; + } + + .met-toast.met-theme-light .met-close:hover { + background: rgba(0, 0, 0, 0.06); + } + + .met-toast.met-theme-light .met-progress, + .met-toast.met-theme-light .met-progress-v { + background: rgba(0, 0, 0, 0.06); + } + + /* 自定义主题支持 */ + .met-toast[data-theme] { + --met-bg: var(--met-theme-bg); + --met-text: var(--met-theme-text); + --met-border: var(--met-theme-border); + --met-shadow: var(--met-theme-shadow); + } + + /* 动画性能优化 */ + .met-toast { + backface-visibility: hidden; + -webkit-backface-visibility: hidden; + perspective: 1000; + } + + /* 滚动条样式 */ + .met-container::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + .met-container::-webkit-scrollbar-track { + background: transparent; + } + + .met-container::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.2); + border-radius: 3px; + } + + .met-container::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.3); + } + + /* 打印样式 */ + @media print { + .met-container { + display: none !important; + } + } + + /* 高对比度模式 */ + @media (forced-colors: active) { + .met-toast { + border: 2px solid ButtonText; + } + + .met-close { + border: 1px solid ButtonText; + } + } + + /* 焦点样式 */ + .met-toast:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; + } + + .met-close:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; + } + + /* 禁用状态 */ + .met-toast:disabled, + .met-toast[disabled] { + opacity: 0.5; + cursor: not-allowed; + } + + /* 加载状态 */ + .met-toast.met-loading { + cursor: wait; + } + + /* 成功状态 */ + .met-toast.met-success { + border-left: 4px solid #10b981; + } + + /* 错误状态 */ + .met-toast.met-error { + border-left: 4px solid #ef4444; + } + + /* 警告状态 */ + .met-toast.met-warning { + border-left: 4px solid #f59e0b; + } + + /* 信息状态 */ + .met-toast.met-info { + border-left: 4px solid #3b82f6; + } + + /* 加载状态 */ + .met-toast.met-loading { + border-left: 4px solid #6366f1; + } + + /* 进度条动画 */ + .met-bar, + .met-bar-v { + transition: transform 0.1s linear; + } + + /* 容器动画 */ + .met-container { + transition: all 0.3s ease; + } + + /* Toast进入动画 */ + .met-toast.met-enter { + animation: met-enter 0.3s ease forwards; + } + + /* Toast离开动画 */ + .met-toast.met-leave { + animation: met-leave 0.3s ease forwards; + } + + @keyframes met-enter { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + @keyframes met-leave { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(-20px); + } + } + + /* 响应式字体大小 */ + @media (max-width: 768px) { + .met-toast { + font-size: 13px; + } + + .met-title { + font-size: 13px; + } + + .met-message { + font-size: 12px; + } + } + + @media (max-width: 480px) { + .met-toast { + font-size: 12px; + padding: 12px 14px; + } + + .met-title { + font-size: 12px; + } + + .met-message { + font-size: 11px; + } + } + + /* 无障碍支持 */ + .met-toast[role="alert"] { + /* 警告类型Toast的特殊样式 */ + } + + .met-toast[role="status"] { + /* 状态类型Toast的特殊样式 */ + } + + /* 高对比度模式增强 */ + @media (prefers-contrast: high) { + .met-toast { + border-width: 2px; + } + + .met-close { + border: 1px solid currentColor; + } + } + + /* 暗色模式自动检测 */ + @media (prefers-color-scheme: dark) { + .met-theme-auto .met-toast { + background: rgba(28, 32, 40, 0.94); + color: #e6e8eb; + border-color: rgba(255, 255, 255, 0.08); + box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.6), + 0 4px 14px -4px rgba(0, 0, 0, 0.4); + } + + .met-theme-auto .met-toast:hover { + box-shadow: 0 14px 48px -8px rgba(0, 0, 0, 0.6), + 0 6px 18px -4px rgba(0, 0, 0, 0.4) !important; + } + + .met-theme-auto .met-close:hover { + background: rgba(255, 255, 255, 0.08); + } + + .met-theme-auto .met-progress, + .met-theme-auto .met-progress-v { + background: rgba(255, 255, 255, 0.08); + } + } + + /* 亮色模式自动检测 */ + @media (prefers-color-scheme: light) { + .met-theme-auto .met-toast { + background: rgba(255, 255, 255, 0.96); + color: #1f2937; + border-color: rgba(0, 0, 0, 0.06); + box-shadow: 0 10px 36px -10px rgba(0, 0, 0, 0.18), + 0 4px 14px -4px rgba(0, 0, 0, 0.08); + } + + .met-theme-auto .met-toast:hover { + box-shadow: 0 14px 48px -10px rgba(0, 0, 0, 0.22), + 0 6px 18px -4px rgba(0, 0, 0, 0.10) !important; + } + + .met-theme-auto .met-close:hover { + background: rgba(0, 0, 0, 0.06); + } + + .met-theme-auto .met-progress, + .met-theme-auto .met-progress-v { + background: rgba(0, 0, 0, 0.06); + } + } + + /* 动画性能优化 */ + .met-toast { + transform: translateZ(0); + -webkit-transform: translateZ(0); + } + + /* 触摸设备优化 */ + @media (hover: none) { + .met-toast:hover { + box-shadow: inherit; + } + } + + /* 打印时隐藏 */ + @media print { + .met-toast { + display: none !important; + } + } + + /* 滚动时固定位置 */ + .met-container { + position: fixed; + z-index: 9999; + } + + /* 全屏模式 */ + :fullscreen .met-container { + z-index: 2147483647; + } + + /* 画中画模式 */ + :picture-in-picture .met-container { + z-index: 2147483647; + } + + /* 安全区域适配 */ + @supports (padding: max(0px)) { + .met-container { + padding: max(24px, env(safe-area-inset-top)) + max(24px, env(safe-area-inset-right)) + max(24px, env(safe-area-inset-bottom)) + max(24px, env(safe-area-inset-left)); + } + } + + /* 暗色模式安全区域 */ + @media (prefers-color-scheme: dark) { + @supports (padding: max(0px)) { + .met-container { + padding: max(24px, env(safe-area-inset-top)) + max(24px, env(safe-area-inset-right)) + max(24px, env(safe-area-inset-bottom)) + max(24px, env(safe-area-inset-left)); + } + } + } + + /* 高分辨率屏幕优化 */ + @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .met-toast { + border-width: 0.5px; + } + } + + /* 触摸设备优化 */ + @media (hover: none) and (pointer: coarse) { + .met-toast { + min-height: 48px; + } + + .met-close { + min-width: 48px; + min-height: 48px; + } + } + + /* 键盘导航优化 */ + .met-toast:focus { + outline: 2px solid #3b82f6; + outline-offset: 2px; + } + + .met-toast:focus:not(:focus-visible) { + outline: none; + } + + .met-toast:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; + } + + /* 减少动画模式 */ + @media (prefers-reduced-motion: reduce) { + .met-toast { + transition: opacity 0.15s ease !important; + animation: none !important; + } + + .met-bar, + .met-bar-v { + transition: none !important; + } + + .met-container { + transition: none !important; + } + } + + /* 高对比度模式 */ + @media (prefers-contrast: high) { + .met-toast { + border-width: 3px; + border-style: solid; + } + + .met-close { + border: 2px solid currentColor; + border-radius: 4px; + } + + .met-progress, + .met-progress-v { + height: 4px; + } + + .met-bar, + .met-bar-v { + height: 100%; + } + } + + /* 低分辨率屏幕优化 */ + @media (max-resolution: 1dppx) { + .met-toast { + border-width: 1px; + } + } + + /* 触摸设备优化 */ + @media (hover: none) and (pointer: coarse) { + .met-toast { + min-height: 52px; + padding: 16px 18px; + } + + .met-close { + min-width: 52px; + min-height: 52px; + padding: 8px; + } + + .met-icon { + width: 28px; + height: 28px; + } + } + + /* 大屏幕优化 */ + @media (min-width: 1200px) { + .met-toast { + width: 400px; + } + } + + /* 超大屏幕优化 */ + @media (min-width: 1920px) { + .met-toast { + width: 440px; + } + } + + /* 小屏幕优化 */ + @media (max-width: 320px) { + .met-toast { + width: 100%; + min-width: 0; + padding: 12px 14px; + } + + .met-container { + padding: 8px; + } + } + + /* 横屏优化 */ + @media (orientation: landscape) and (max-height: 500px) { + .met-container { + padding: 12px 24px; + } + + .met-toast { + min-height: 44px; + padding: 10px 14px; + } + } + + /* 竖屏优化 */ + @media (orientation: portrait) and (max-width: 500px) { + .met-container { + padding: 12px; + } + + .met-toast { + width: 100%; + min-width: 0; + } + } + + /* 无障碍支持 */ + .met-toast[aria-live="assertive"] { + /* 紧急通知样式 */ + } + + .met-toast[aria-live="polite"] { + /* 普通通知样式 */ + } + + /* 焦点陷阱 */ + .met-toast:focus-within { + /* 包含焦点元素的Toast样式 */ + } + + /* 加载状态 */ + .met-toast[aria-busy="true"] { + cursor: wait; + } + + /* 禁用状态 */ + .met-toast[aria-disabled="true"] { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; + } + + /* 隐藏状态 */ + .met-toast[aria-hidden="true"] { + display: none; + } + + /* 展开状态 */ + .met-toast[aria-expanded="true"] { + /* 展开状态样式 */ + } + + /* 选中状态 */ + .met-toast[aria-selected="true"] { + /* 选中状态样式 */ + } + + /* 按下状态 */ + .met-toast:active { + transform: scale(0.98); + } + + /* 加载状态动画 */ + .met-toast.met-loading::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.1), + transparent + ); + animation: met-loading 1.5s infinite; + } + + @keyframes met-loading { + 0% { + transform: translateX(-100%); + } + 100% { + transform: translateX(100%); + } + } + + /* 成功状态动画 */ + .met-toast.met-success::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: #10b981; + border-radius: 12px 0 0 12px; + animation: met-success 0.3s ease; + } + + @keyframes met-success { + from { + transform: scaleY(0); + } + to { + transform: scaleY(1); + } + } + + /* 错误状态动画 */ + .met-toast.met-error::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: #ef4444; + border-radius: 12px 0 0 12px; + animation: met-error 0.3s ease; + } + + @keyframes met-error { + from { + transform: scaleY(0); + } + to { + transform: scaleY(1); + } + } + + /* 警告状态动画 */ + .met-toast.met-warning::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: #f59e0b; + border-radius: 12px 0 0 12px; + animation: met-warning 0.3s ease; + } + + @keyframes met-warning { + from { + transform: scaleY(0); + } + to { + transform: scaleY(1); + } + } + + /* 信息状态动画 */ + .met-toast.met-info::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: #3b82f6; + border-radius: 12px 0 0 12px; + animation: met-info 0.3s ease; + } + + @keyframes met-info { + from { + transform: scaleY(0); + } + to { + transform: scaleY(1); + } + } + + /* 加载状态动画 */ + .met-toast.met-loading::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: #6366f1; + border-radius: 12px 0 0 12px; + animation: met-loading-bar 1s infinite; + } + + @keyframes met-loading-bar { + 0% { + transform: scaleY(0); + transform-origin: top; + } + 50% { + transform: scaleY(1); + transform-origin: top; + } + 51% { + transform-origin: bottom; + } + 100% { + transform: scaleY(0); + transform-origin: bottom; + } + } + + /* 进度条脉冲动画 */ + .met-bar, + .met-bar-v { + animation: met-pulse 2s infinite; + } + + @keyframes met-pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.8; + } + } + + /* Toast堆叠效果 */ + .met-toast + .met-toast { + margin-top: 8px; + } + + /* Toast分组 */ + .met-toast-group { + display: flex; + flex-direction: column; + gap: 8px; + } + + /* Toast头部 */ + .met-toast-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + } + + /* Toast底部 */ + .met-toast-footer { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + margin-top: 12px; + } + + /* Toast操作按钮 */ + .met-toast-action { + background: transparent; + border: 1px solid currentColor; + padding: 6px 12px; + border-radius: 6px; + cursor: pointer; + font-size: 12px; + opacity: 0.7; + transition: opacity 0.2s; + } + + .met-toast-action:hover { + opacity: 1; + } + + /* Toast进度文本 */ + .met-toast-progress-text { + font-size: 12px; + opacity: 0.7; + margin-left: 8px; + } + + /* Toast时间戳 */ + .met-toast-timestamp { + font-size: 11px; + opacity: 0.5; + margin-left: auto; + } + + /* Toast头像 */ + .met-toast-avatar { + width: 32px; + height: 32px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; + } + + /* Toast图片 */ + .met-toast-image { + max-width: 100%; + max-height: 200px; + border-radius: 8px; + margin-top: 8px; + object-fit: cover; + } + + /* Toast视频 */ + .met-toast-video { + max-width: 100%; + max-height: 200px; + border-radius: 8px; + margin-top: 8px; + } + + /* Toast音频 */ + .met-toast-audio { + width: 100%; + margin-top: 8px; + } + + /* Toast代码块 */ + .met-toast-code { + background: rgba(0, 0, 0, 0.05); + padding: 8px 12px; + border-radius: 6px; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 12px; + margin-top: 8px; + overflow-x: auto; + } + + .met-theme-dark .met-toast-code { + background: rgba(255, 255, 255, 0.05); + } + + /* Toast引用 */ + .met-toast-quote { + border-left: 3px solid currentColor; + padding-left: 12px; + margin-top: 8px; + opacity: 0.8; + } + + /* Toast列表 */ + .met-toast-list { + margin: 8px 0 0 0; + padding-left: 20px; + } + + .met-toast-list li { + margin-bottom: 4px; + } + + /* Toast表格 */ + .met-toast-table { + width: 100%; + border-collapse: collapse; + margin-top: 8px; + font-size: 12px; + } + + .met-toast-table th, + .met-toast-table td { + border: 1px solid rgba(0, 0, 0, 0.1); + padding: 6px 8px; + text-align: left; + } + + .met-theme-dark .met-toast-table th, + .met-theme-dark .met-toast-table td { + border-color: rgba(255, 255, 255, 0.1); + } + + .met-toast-table th { + background: rgba(0, 0, 0, 0.05); + font-weight: 600; + } + + .met-theme-dark .met-toast-table th { + background: rgba(255, 255, 255, 0.05); + } + + /* Toast分割线 */ + .met-toast-divider { + height: 1px; + background: rgba(0, 0, 0, 0.1); + margin: 12px 0; + } + + .met-theme-dark .met-toast-divider { + background: rgba(255, 255, 255, 0.1); + } + + /* Toast标签 */ + .met-toast-tag { + display: inline-block; + background: rgba(0, 0, 0, 0.05); + padding: 2px 8px; + border-radius: 4px; + font-size: 11px; + margin-right: 4px; + margin-bottom: 4px; + } + + .met-theme-dark .met-toast-tag { + background: rgba(255, 255, 255, 0.05); + } + + /* Toast徽章 */ + .met-toast-badge { + display: inline-flex; + align-items: center; + justify-content: center; + background: #3b82f6; + color: white; + padding: 2px 8px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; + min-width: 20px; + height: 20px; + } + + /* Toast进度环 */ + .met-toast-progress-ring { + width: 40px; + height: 40px; + transform: rotate(-90deg); + } + + .met-toast-progress-ring circle { + fill: none; + stroke-width: 3; + stroke-linecap: round; + } + + .met-toast-progress-ring .met-progress-ring-bg { + stroke: rgba(0, 0, 0, 0.1); + } + + .met-theme-dark .met-toast-progress-ring .met-progress-ring-bg { + stroke: rgba(255, 255, 255, 0.1); + } + + .met-toast-progress-ring .met-progress-ring-fill { + stroke: #3b82f6; + stroke-dasharray: 100; + stroke-dashoffset: 100; + transition: stroke-dashoffset 0.3s ease; + } + + /* Toast滑块 */ + .met-toast-slider { + width: 100%; + height: 4px; + background: rgba(0, 0, 0, 0.1); + border-radius: 2px; + margin-top: 8px; + position: relative; + } + + .met-theme-dark .met-toast-slider { + background: rgba(255, 255, 255, 0.1); + } + + .met-toast-slider-fill { + position: absolute; + left: 0; + top: 0; + height: 100%; + background: #3b82f6; + border-radius: 2px; + transition: width 0.3s ease; + } + + /* Toast开关 */ + .met-toast-switch { + position: relative; + display: inline-block; + width: 36px; + height: 20px; + margin-top: 8px; + } + + .met-toast-switch input { + opacity: 0; + width: 0; + height: 0; + } + + .met-toast-switch-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.1); + border-radius: 20px; + transition: 0.3s; + } + + .met-theme-dark .met-toast-switch-slider { + background: rgba(255, 255, 255, 0.1); + } + + .met-toast-switch-slider:before { + content: ''; + position: absolute; + height: 16px; + width: 16px; + left: 2px; + bottom: 2px; + background: white; + border-radius: 50%; + transition: 0.3s; + } + + .met-toast-switch input:checked + .met-toast-switch-slider { + background: #3b82f6; + } + + .met-toast-switch input:checked + .met-toast-switch-slider:before { + transform: translateX(16px); + } + + /* Toast复选框 */ + .met-toast-checkbox { + display: flex; + align-items: center; + gap: 8px; + margin-top: 8px; + cursor: pointer; + } + + .met-toast-checkbox input { + width: 16px; + height: 16px; + cursor: pointer; + } + + /* Toast单选框 */ + .met-toast-radio { + display: flex; + align-items: center; + gap: 8px; + margin-top: 8px; + cursor: pointer; + } + + .met-toast-radio input { + width: 16px; + height: 16px; + cursor: pointer; + } + + /* Toast输入框 */ + .met-toast-input { + width: 100%; + padding: 8px 12px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 6px; + font-size: 13px; + margin-top: 8px; + background: transparent; + color: inherit; + } + + .met-theme-dark .met-toast-input { + border-color: rgba(255, 255, 255, 0.1); + } + + .met-toast-input:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + } + + /* Toast文本域 */ + .met-toast-textarea { + width: 100%; + padding: 8px 12px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 6px; + font-size: 13px; + margin-top: 8px; + background: transparent; + color: inherit; + resize: vertical; + min-height: 80px; + } + + .met-theme-dark .met-toast-textarea { + border-color: rgba(255, 255, 255, 0.1); + } + + .met-toast-textarea:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + } + + /* Toast选择框 */ + .met-toast-select { + width: 100%; + padding: 8px 12px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 6px; + font-size: 13px; + margin-top: 8px; + background: transparent; + color: inherit; + cursor: pointer; + } + + .met-theme-dark .met-toast-select { + border-color: rgba(255, 255, 255, 0.1); + } + + .met-toast-select:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + } + + /* Toast下拉菜单 */ + .met-toast-dropdown { + position: relative; + display: inline-block; + } + + .met-toast-dropdown-content { + display: none; + position: absolute; + background: ${theme.bg}; + min-width: 160px; + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); + border-radius: 8px; + z-index: 1; + padding: 8px 0; + margin-top: 4px; + } + + .met-theme-dark .met-toast-dropdown-content { + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); + } + + .met-toast-dropdown:hover .met-toast-dropdown-content { + display: block; + } + + .met-toast-dropdown-item { + padding: 8px 16px; + cursor: pointer; + font-size: 13px; + } + + .met-toast-dropdown-item:hover { + background: rgba(0, 0, 0, 0.05); + } + + .met-theme-dark .met-toast-dropdown-item:hover { + background: rgba(255, 255, 255, 0.05); + } + + /* Toast工具提示 */ + .met-toast-tooltip { + position: relative; + display: inline-block; + } + + .met-toast-tooltip .met-toast-tooltip-text { + visibility: hidden; + width: 120px; + background: ${theme.bg}; + color: ${theme.text}; + text-align: center; + border-radius: 6px; + padding: 6px 8px; + position: absolute; + z-index: 1; + bottom: 125%; + left: 50%; + margin-left: -60px; + opacity: 0; + transition: opacity 0.3s; + font-size: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + } + + .met-theme-dark .met-toast-tooltip .met-toast-tooltip-text { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + } + + .met-toast-tooltip:hover .met-toast-tooltip-text { + visibility: visible; + opacity: 1; + } + + /* Toast弹出框 */ + .met-toast-popover { + position: relative; + display: inline-block; + } + + .met-toast-popover .met-toast-popover-content { + visibility: hidden; + background: ${theme.bg}; + color: ${theme.text}; + border-radius: 8px; + padding: 12px 16px; + position: absolute; + z-index: 1; + bottom: 125%; + left: 50%; + transform: translateX(-50%); + opacity: 0; + transition: opacity 0.3s; + min-width: 200px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); + } + + .met-theme-dark .met-toast-popover .met-toast-popover-content { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); + } + + .met-toast-popover:hover .met-toast-popover-content { + visibility: visible; + opacity: 1; + } + + /* Toast模态框 */ + .met-toast-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; + } + + .met-toast-modal-content { + background: ${theme.bg}; + color: ${theme.text}; + border-radius: 12px; + padding: 24px; + max-width: 500px; + width: 90%; + max-height: 80vh; + overflow-y: auto; + } + + /* Toast抽屉 */ + .met-toast-drawer { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 10000; + } + + .met-toast-drawer-content { + position: absolute; + top: 0; + right: 0; + width: 300px; + height: 100%; + background: ${theme.bg}; + color: ${theme.text}; + padding: 24px; + transform: translateX(100%); + transition: transform 0.3s ease; + } + + .met-toast-drawer.open .met-toast-drawer-content { + transform: translateX(0); + } + + /* Toast通知栏 */ + .met-toast-notification-bar { + position: fixed; + top: 0; + left: 0; + right: 0; + background: ${theme.bg}; + color: ${theme.text}; + padding: 12px 24px; + display: flex; + align-items: center; + justify-content: space-between; + z-index: 9999; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + } + + /* Toast状态栏 */ + .met-toast-status-bar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: ${theme.bg}; + color: ${theme.text}; + padding: 8px 24px; + display: flex; + align-items: center; + justify-content: space-between; + z-index: 9999; + font-size: 12px; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); + } + `; +}; + +/** + * 注入样式 + * @param {Object} theme - 主题配置 + */ +export const injectStyles = (theme = THEMES.light) => { + // 检查是否在浏览器环境 + if (typeof document === 'undefined') return; + + // 检查是否已注入 + if (styleElement && document.getElementById('metona-toast-styles')) { + return; + } + + // 生成CSS + const css = generateCSS(theme); + + // 创建样式元素 + styleElement = document.createElement('style'); + styleElement.id = 'metona-toast-styles'; + styleElement.textContent = css.replace(/\s+/g, ' '); + + // 添加到文档头 + document.head.appendChild(styleElement); + + // 缓存样式 + injectedStyles = css; +}; + +/** + * 更新样式 + * @param {Object} theme - 新主题配置 + */ +export const updateStyles = (theme) => { + if (!styleElement) { + injectStyles(theme); + return; + } + + const css = generateCSS(theme); + styleElement.textContent = css.replace(/\s+/g, ' '); + injectedStyles = css; +}; + +/** + * 移除样式 + */ +export const removeStyles = () => { + if (styleElement && styleElement.parentNode) { + styleElement.parentNode.removeChild(styleElement); + } + + styleElement = null; + injectedStyles = null; +}; + +/** + * 获取当前样式 + * @returns {string|null} 当前CSS字符串 + */ +export const getStyles = () => { + return injectedStyles; +}; + +/** + * 检查样式是否已注入 + * @returns {boolean} 是否已注入 + */ +export const isStylesInjected = () => { + return !!styleElement && !!document.getElementById('metona-toast-styles'); +}; + +/** + * 重置样式 + */ +export const resetStyles = () => { + removeStyles(); + injectStyles(); +}; + +/** + * 添加自定义CSS + * @param {string} css - CSS字符串 + */ +export const addCustomCSS = (css) => { + if (!styleElement) { + injectStyles(); + } + + const customStyle = document.createElement('style'); + customStyle.id = 'metona-toast-custom-styles'; + customStyle.textContent = css; + document.head.appendChild(customStyle); +}; + +/** + * 移除自定义CSS + */ +export const removeCustomCSS = () => { + const customStyle = document.getElementById('metona-toast-custom-styles'); + if (customStyle && customStyle.parentNode) { + customStyle.parentNode.removeChild(customStyle); + } +}; + +/** + * 生成主题变量 + * @param {Object} theme - 主题配置 + * @returns {string} CSS变量字符串 + */ +export const generateThemeVariables = (theme) => { + return ` + :root { + --met-theme-bg: ${theme.bg}; + --met-theme-text: ${theme.text}; + --met-theme-border: ${theme.border}; + --met-theme-shadow: ${theme.shadow}; + --met-theme-hover-shadow: ${theme.hoverShadow}; + --met-theme-progress-bg: ${theme.progressBg}; + --met-theme-close-hover-bg: ${theme.closeHoverBg}; + } + `; +}; + +/** + * 应用主题变量 + * @param {Object} theme - 主题配置 + */ +export const applyThemeVariables = (theme) => { + const css = generateThemeVariables(theme); + addCustomCSS(css); +}; + +/** + * 清除主题变量 + */ +export const clearThemeVariables = () => { + removeCustomCSS(); +}; + +/** + * 获取系统主题 + * @returns {string} 系统主题 + */ +export const getSystemTheme = () => { + if (typeof window === 'undefined') return 'light'; + + return window.matchMedia && + window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'dark' + : 'light'; +}; + +/** + * 监听系统主题变化 + * @param {Function} callback - 回调函数 + * @returns {Function} 取消监听函数 + */ +export const watchSystemTheme = (callback) => { + if (typeof window === 'undefined' || !window.matchMedia) { + return () => {}; + } + + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + + const handler = (e) => { + callback(e.matches ? 'dark' : 'light'); + }; + + mediaQuery.addEventListener('change', handler); + + return () => { + mediaQuery.removeEventListener('change', handler); + }; +}; + +/** + * 自动应用系统主题 + * @returns {Function} 取消监听函数 + */ +export const autoApplySystemTheme = () => { + const applyTheme = (theme) => { + updateStyles(THEMES[theme]); + applyThemeVariables(THEMES[theme]); + }; + + // 应用当前系统主题 + applyTheme(getSystemTheme()); + + // 监听系统主题变化 + return watchSystemTheme(applyTheme); +}; diff --git a/src/themes.js b/src/themes.js new file mode 100644 index 0000000..164b0fd --- /dev/null +++ b/src/themes.js @@ -0,0 +1,722 @@ +/** + * MetonaToast Themes - 主题管理 + * @module themes + * @version 2.0.0 + * @description 主题系统、自定义主题和主题切换 + */ + +import { THEMES } from './constants.js'; +import { prefersDark } from './utils.js'; + +// 当前主题状态 +let currentTheme = 'auto'; +let themeListeners = new Set(); +let systemThemeMediaQuery = null; +let systemThemeListener = null; + +/** + * 获取系统主题 + * @returns {string} 系统主题 ('light' 或 'dark') + */ +export const getSystemTheme = () => { + if (typeof window === 'undefined') return 'light'; + return prefersDark() ? 'dark' : 'light'; +}; + +/** + * 获取主题(别名) + * @param {string} theme - 主题名称 + * @returns {string} 解析后的主题 + */ +export const getTheme = (theme) => { + return resolveTheme(theme); +}; + +/** + * 解析主题 + * @param {string} theme - 主题名称 + * @returns {string} 解析后的主题 + */ +export const resolveTheme = (theme) => { + if (theme === 'auto') { + // 优先使用用户设置的全局主题,否则使用系统主题 + if (currentTheme && currentTheme !== 'auto') { + return currentTheme; + } + return getSystemTheme(); + } + return theme; +}; + +/** + * 获取主题配置 + * @param {string} theme - 主题名称 + * @returns {Object} 主题配置 + */ +export const getThemeConfig = (theme) => { + const resolved = resolveTheme(theme); + return THEMES[resolved] || THEMES.light; +}; + +/** + * 应用主题 + * @param {string} theme - 主题名称 + */ +export const applyTheme = (theme) => { + currentTheme = theme; + const resolved = resolveTheme(theme); + + // 应用主题到文档 + if (typeof document !== 'undefined') { + document.documentElement.setAttribute('data-met-theme', resolved); + document.documentElement.classList.remove('met-theme-light', 'met-theme-dark', 'met-theme-auto'); + document.documentElement.classList.add(`met-theme-${resolved}`); + + // 设置CSS变量 + const config = getThemeConfig(theme); + setThemeVariables(config); + } + + // 通知监听器 + notifyThemeListeners(theme, resolved); +}; + +/** + * 设置主题CSS变量 + * @param {Object} config - 主题配置 + */ +export const setThemeVariables = (config) => { + if (typeof document === 'undefined') return; + + const root = document.documentElement; + root.style.setProperty('--met-bg', config.bg); + root.style.setProperty('--met-text', config.text); + root.style.setProperty('--met-border', config.border); + root.style.setProperty('--met-shadow', config.shadow); + root.style.setProperty('--met-hover-shadow', config.hoverShadow); + root.style.setProperty('--met-progress-bg', config.progressBg); + root.style.setProperty('--met-close-hover-bg', config.closeHoverBg); + + // 设置颜色变量 + root.style.setProperty('--met-success', '#10b981'); + root.style.setProperty('--met-error', '#ef4444'); + root.style.setProperty('--met-warning', '#f59e0b'); + root.style.setProperty('--met-info', '#3b82f6'); + root.style.setProperty('--met-loading', '#6366f1'); +}; + +/** + * 清除主题CSS变量 + */ +export const clearThemeVariables = () => { + if (typeof document === 'undefined') return; + + const root = document.documentElement; + const variables = [ + '--met-bg', + '--met-text', + '--met-border', + '--met-shadow', + '--met-hover-shadow', + '--met-progress-bg', + '--met-close-hover-bg', + '--met-success', + '--met-error', + '--met-warning', + '--met-info', + '--met-loading', + ]; + + variables.forEach((variable) => { + root.style.removeProperty(variable); + }); +}; + +/** + * 获取当前主题 + * @returns {string} 当前主题 + */ +export const getCurrentTheme = () => { + return currentTheme; +}; + +/** + * 获取解析后的主题 + * @returns {string} 解析后的主题 + */ +export const getResolvedTheme = () => { + return resolveTheme(currentTheme); +}; + +/** + * 切换主题 + * @param {string} theme - 新主题 + */ +export const switchTheme = (theme) => { + applyTheme(theme); + saveTheme(theme); +}; + +/** + * 切换亮色/暗色主题 + */ +export const toggleTheme = () => { + const resolved = getResolvedTheme(); + const newTheme = resolved === 'dark' ? 'light' : 'dark'; + switchTheme(newTheme); +}; + +/** + * 重置为自动主题 + */ +export const resetToAuto = () => { + switchTheme('auto'); +}; + +/** + * 保存主题到本地存储 + * @param {string} theme - 主题名称 + */ +export const saveTheme = (theme) => { + if (typeof localStorage !== 'undefined') { + try { + localStorage.setItem('metona-toast-theme', theme); + } catch (e) { + console.warn('Failed to save theme:', e); + } + } +}; + +/** + * 从本地存储加载主题 + * @returns {string} 主题名称 + */ +export const loadTheme = () => { + if (typeof localStorage !== 'undefined') { + try { + return localStorage.getItem('metona-toast-theme') || 'auto'; + } catch (e) { + console.warn('Failed to load theme:', e); + } + } + return 'auto'; +}; + +/** + * 初始化主题系统 + */ +export const initTheme = () => { + // 加载保存的主题 + const savedTheme = loadTheme(); + applyTheme(savedTheme); + + // 监听系统主题变化 + watchSystemTheme(); +}; + +/** + * 监听系统主题变化 + */ +export const watchSystemTheme = () => { + if (typeof window === 'undefined' || !window.matchMedia) return; + + // 移除旧的监听器 + if (systemThemeMediaQuery && systemThemeListener) { + systemThemeMediaQuery.removeEventListener('change', systemThemeListener); + } + + // 创建新的监听器 + systemThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + systemThemeListener = (e) => { + if (currentTheme === 'auto') { + applyTheme('auto'); + } + }; + + systemThemeMediaQuery.addEventListener('change', systemThemeListener); +}; + +/** + * 停止监听系统主题变化 + */ +export const unwatchSystemTheme = () => { + if (systemThemeMediaQuery && systemThemeListener) { + systemThemeMediaQuery.removeEventListener('change', systemThemeListener); + systemThemeMediaQuery = null; + systemThemeListener = null; + } +}; + +/** + * 添加主题监听器 + * @param {Function} listener - 监听器函数 + * @returns {Function} 移除监听器函数 + */ +export const addThemeListener = (listener) => { + themeListeners.add(listener); + + return () => { + themeListeners.delete(listener); + }; +}; + +/** + * 移除主题监听器 + * @param {Function} listener - 监听器函数 + */ +export const removeThemeListener = (listener) => { + themeListeners.delete(listener); +}; + +/** + * 通知主题监听器 + * @param {string} theme - 主题名称 + * @param {string} resolved - 解析后的主题 + */ +const notifyThemeListeners = (theme, resolved) => { + themeListeners.forEach((listener) => { + try { + listener(theme, resolved); + } catch (e) { + console.error('Theme listener error:', e); + } + }); +}; + +/** + * 清除所有主题监听器 + */ +export const clearThemeListeners = () => { + themeListeners.clear(); +}; + +/** + * 注册自定义主题 + * @param {string} name - 主题名称 + * @param {Object} config - 主题配置 + */ +export const registerTheme = (name, config) => { + THEMES[name] = { + bg: config.bg || THEMES.light.bg, + text: config.text || THEMES.light.text, + border: config.border || THEMES.light.border, + shadow: config.shadow || THEMES.light.shadow, + hoverShadow: config.hoverShadow || THEMES.light.hoverShadow, + progressBg: config.progressBg || THEMES.light.progressBg, + closeHoverBg: config.closeHoverBg || THEMES.light.closeHoverBg, + }; +}; + +/** + * 注销自定义主题 + * @param {string} name - 主题名称 + */ +export const unregisterTheme = (name) => { + if (name === 'light' || name === 'dark' || name === 'auto') { + console.warn('Cannot unregister built-in theme:', name); + return; + } + + delete THEMES[name]; +}; + +/** + * 获取所有主题 + * @returns {Object} 主题映射 + */ +export const getAllThemes = () => { + return { ...THEMES }; +}; + +/** + * 获取主题名称列表 + * @returns {Array} 主题名称数组 + */ +export const getThemeNames = () => { + return Object.keys(THEMES); +}; + +/** + * 检查主题是否存在 + * @param {string} name - 主题名称 + * @returns {boolean} 是否存在 + */ +export const hasTheme = (name) => { + return name in THEMES; +}; + +/** + * 获取主题预览 + * @param {string} theme - 主题名称 + * @returns {Object} 主题预览 + */ +export const getThemePreview = (theme) => { + const config = getThemeConfig(theme); + const resolved = resolveTheme(theme); + + return { + name: theme, + resolved, + colors: { + background: config.bg, + text: config.text, + border: config.border, + }, + isDark: resolved === 'dark', + isLight: resolved === 'light', + isAuto: theme === 'auto', + }; +}; + +/** + * 生成主题CSS + * @param {string} theme - 主题名称 + * @returns {string} CSS字符串 + */ +export const generateThemeCSS = (theme) => { + const config = getThemeConfig(theme); + const resolved = resolveTheme(theme); + + return ` + .met-theme-${resolved} { + --met-bg: ${config.bg}; + --met-text: ${config.text}; + --met-border: ${config.border}; + --met-shadow: ${config.shadow}; + --met-hover-shadow: ${config.hoverShadow}; + --met-progress-bg: ${config.progressBg}; + --met-close-hover-bg: ${config.closeHoverBg}; + } + `; +}; + +/** + * 应用主题CSS + * @param {string} theme - 主题名称 + */ +export const applyThemeCSS = (theme) => { + if (typeof document === 'undefined') return; + + const css = generateThemeCSS(theme); + const styleId = 'metona-toast-theme-css'; + + // 移除旧样式 + const oldStyle = document.getElementById(styleId); + if (oldStyle) { + oldStyle.remove(); + } + + // 添加新样式 + const style = document.createElement('style'); + style.id = styleId; + style.textContent = css; + document.head.appendChild(style); +}; + +/** + * 移除主题CSS + */ +export const removeThemeCSS = () => { + if (typeof document === 'undefined') return; + + const styleId = 'metona-toast-theme-css'; + const style = document.getElementById(styleId); + if (style) { + style.remove(); + } +}; + +/** + * 主题工具 + */ +export const themeUtils = { + /** + * 获取系统主题 + * @returns {string} 系统主题 + */ + getSystemTheme() { + return getSystemTheme(); + }, + + /** + * 解析主题 + * @param {string} theme - 主题名称 + * @returns {string} 解析后的主题 + */ + resolveTheme(theme) { + return resolveTheme(theme); + }, + + /** + * 获取主题配置 + * @param {string} theme - 主题名称 + * @returns {Object} 主题配置 + */ + getThemeConfig(theme) { + return getThemeConfig(theme); + }, + + /** + * 应用主题 + * @param {string} theme - 主题名称 + */ + applyTheme(theme) { + applyTheme(theme); + }, + + /** + * 获取当前主题 + * @returns {string} 当前主题 + */ + getCurrentTheme() { + return getCurrentTheme(); + }, + + /** + * 获取解析后的主题 + * @returns {string} 解析后的主题 + */ + getResolvedTheme() { + return getResolvedTheme(); + }, + + /** + * 切换主题 + * @param {string} theme - 新主题 + */ + switchTheme(theme) { + switchTheme(theme); + }, + + /** + * 切换亮色/暗色主题 + */ + toggleTheme() { + toggleTheme(); + }, + + /** + * 重置为自动主题 + */ + resetToAuto() { + resetToAuto(); + }, + + /** + * 初始化主题系统 + */ + initTheme() { + initTheme(); + }, + + /** + * 监听系统主题变化 + */ + watchSystemTheme() { + watchSystemTheme(); + }, + + /** + * 停止监听系统主题变化 + */ + unwatchSystemTheme() { + unwatchSystemTheme(); + }, + + /** + * 添加主题监听器 + * @param {Function} listener - 监听器函数 + * @returns {Function} 移除监听器函数 + */ + addThemeListener(listener) { + return addThemeListener(listener); + }, + + /** + * 移除主题监听器 + * @param {Function} listener - 监听器函数 + */ + removeThemeListener(listener) { + removeThemeListener(listener); + }, + + /** + * 清除所有主题监听器 + */ + clearThemeListeners() { + clearThemeListeners(); + }, + + /** + * 注册自定义主题 + * @param {string} name - 主题名称 + * @param {Object} config - 主题配置 + */ + registerTheme(name, config) { + registerTheme(name, config); + }, + + /** + * 注销自定义主题 + * @param {string} name - 主题名称 + */ + unregisterTheme(name) { + unregisterTheme(name); + }, + + /** + * 获取所有主题 + * @returns {Object} 主题映射 + */ + getAllThemes() { + return getAllThemes(); + }, + + /** + * 获取主题名称列表 + * @returns {Array} 主题名称数组 + */ + getThemeNames() { + return getThemeNames(); + }, + + /** + * 检查主题是否存在 + * @param {string} name - 主题名称 + * @returns {boolean} 是否存在 + */ + hasTheme(name) { + return hasTheme(name); + }, + + /** + * 获取主题预览 + * @param {string} theme - 主题名称 + * @returns {Object} 主题预览 + */ + getThemePreview(theme) { + return getThemePreview(theme); + }, + + /** + * 生成主题CSS + * @param {string} theme - 主题名称 + * @returns {string} CSS字符串 + */ + generateThemeCSS(theme) { + return generateThemeCSS(theme); + }, + + /** + * 应用主题CSS + * @param {string} theme - 主题名称 + */ + applyThemeCSS(theme) { + applyThemeCSS(theme); + }, + + /** + * 移除主题CSS + */ + removeThemeCSS() { + removeThemeCSS(); + }, + + /** + * 保存主题 + * @param {string} theme - 主题名称 + */ + saveTheme(theme) { + saveTheme(theme); + }, + + /** + * 加载主题 + * @returns {string} 主题名称 + */ + loadTheme() { + return loadTheme(); + }, +}; + +/** + * 预设主题 + */ +export const presetThemes = { + /** + * 浅色主题 + */ + light: { + name: '浅色', + description: '明亮清晰的主题', + config: THEMES.light, + }, + + /** + * 深色主题 + */ + dark: { + name: '深色', + description: '护眼舒适的暗色主题', + config: THEMES.dark, + }, + + /** + * 自动主题 + */ + auto: { + name: '自动', + description: '跟随系统主题设置', + config: 'auto', + }, + + warm: { + name: '暖色', + description: '温馨舒适的暖色主题', + config: THEMES.warm, + }, +}; + +// 注册预设主题 +Object.entries(presetThemes).forEach(([name, theme]) => { + if (name !== 'auto' && theme.config !== 'auto') { + THEMES[name] = theme.config; + } +}); + +/** + * 创建主题管理器 + * @returns {Object} 主题管理器 + */ +export const createThemeManager = () => { + return { + getSystemTheme, + resolveTheme, + getThemeConfig, + applyTheme, + getCurrentTheme, + getResolvedTheme, + switchTheme, + toggleTheme, + resetToAuto, + initTheme, + watchSystemTheme, + unwatchSystemTheme, + addThemeListener, + removeThemeListener, + clearThemeListeners, + registerTheme, + unregisterTheme, + getAllThemes, + getThemeNames, + hasTheme, + getThemePreview, + generateThemeCSS, + applyThemeCSS, + removeThemeCSS, + saveTheme, + loadTheme, + }; +}; + +export { themeUtils as default }; diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..fa4e9dd --- /dev/null +++ b/src/utils.js @@ -0,0 +1,1062 @@ +/** + * MetonaToast Utils - 工具函数 + * @module utils + * @version 2.0.0 + * @description 通用工具函数集合 + */ + +/** + * 生成唯一ID + * @returns {string} 唯一ID + */ +export const generateId = () => { + return 'met-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 8); +}; + +/** + * HTML转义 + * @param {string} s - 输入字符串 + * @returns {string} 转义后的字符串 + */ +export const escapeHTML = (s) => { + if (typeof document === 'undefined') { + // Node.js环境 + return String(s == null ? '' : s) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + const div = document.createElement('div'); + div.textContent = String(s == null ? '' : s); + return div.innerHTML; +}; + +/** + * 事件绑定 + * @param {HTMLElement} el - 元素 + * @param {string} evt - 事件名 + * @param {Function} handler - 事件处理函数 + * @param {Object} opts - 选项 + * @returns {Function} 清理函数 + */ +export const on = (el, evt, handler, opts) => { + el.addEventListener(evt, handler, opts); + return () => el.removeEventListener(evt, handler, opts); +}; + +/** + * 检测暗色模式偏好 + * @returns {boolean} 是否偏好暗色模式 + */ +export const prefersDark = () => { + return typeof window !== 'undefined' && + window.matchMedia && + window.matchMedia('(prefers-color-scheme: dark)').matches; +}; + +/** + * 防抖函数 + * @param {Function} func - 要防抖的函数 + * @param {number} wait - 等待时间(毫秒) + * @param {boolean} immediate - 是否立即执行 + * @returns {Function} 防抖后的函数 + */ +export const debounce = (func, wait, immediate = false) => { + let timeout; + return function executedFunction(...args) { + const context = this; + const later = () => { + timeout = null; + if (!immediate) func.apply(context, args); + }; + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +}; + +/** + * 节流函数 + * @param {Function} func - 要节流的函数 + * @param {number} limit - 限制时间(毫秒) + * @returns {Function} 节流后的函数 + */ +export const throttle = (func, limit) => { + let inThrottle; + return function executedFunction(...args) { + const context = this; + if (!inThrottle) { + func.apply(context, args); + inThrottle = true; + setTimeout(() => inThrottle = false, limit); + } + }; +}; + +/** + * 深度合并对象 + * @param {Object} target - 目标对象 + * @param {Object} source - 源对象 + * @returns {Object} 合并后的对象 + */ +export const deepMerge = (target, source) => { + const output = { ...target }; + + Object.keys(source).forEach(key => { + if (source[key] instanceof Object && key in target && target[key] instanceof Object) { + output[key] = deepMerge(target[key], source[key]); + } else { + output[key] = source[key]; + } + }); + + return output; +}; + +/** + * 检查是否为浏览器环境 + * @returns {boolean} 是否为浏览器环境 + */ +export const isBrowser = () => { + return typeof window !== 'undefined' && typeof document !== 'undefined'; +}; + +/** + * 安全获取嵌套对象属性 + * @param {Object} obj - 对象 + * @param {string} path - 属性路径 + * @param {*} defaultValue - 默认值 + * @returns {*} 属性值 + */ +export const getNestedValue = (obj, path, defaultValue = undefined) => { + const keys = path.split('.'); + let result = obj; + + for (const key of keys) { + result = result?.[key]; + if (result === undefined) return defaultValue; + } + + return result; +}; + +/** + * 格式化文件大小 + * @param {number} bytes - 字节数 + * @param {number} decimals - 小数位数 + * @returns {string} 格式化后的字符串 + */ +export const formatFileSize = (bytes, decimals = 2) => { + if (bytes === 0) return '0 Bytes'; + + const k = 1024; + const dm = decimals < 0 ? 0 : decimals; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; +}; + +/** + * 格式化日期 + * @param {Date|string|number} date - 日期 + * @param {string} format - 格式 + * @returns {string} 格式化后的日期字符串 + */ +export const formatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => { + const d = new Date(date); + + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hours = String(d.getHours()).padStart(2, '0'); + const minutes = String(d.getMinutes()).padStart(2, '0'); + const seconds = String(d.getSeconds()).padStart(2, '0'); + + return format + .replace('YYYY', year) + .replace('MM', month) + .replace('DD', day) + .replace('HH', hours) + .replace('mm', minutes) + .replace('ss', seconds); +}; + +/** + * 生成随机数 + * @param {number} min - 最小值 + * @param {number} max - 最大值 + * @returns {number} 随机数 + */ +export const random = (min, max) => { + return Math.floor(Math.random() * (max - min + 1)) + min; +}; + +/** + * 检查元素是否在视口中 + * @param {HTMLElement} el - 元素 + * @returns {boolean} 是否在视口中 + */ +export const isInViewport = (el) => { + const rect = el.getBoundingClientRect(); + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); +}; + +/** + * 平滑滚动到元素 + * @param {HTMLElement} el - 元素 + * @param {Object} options - 选项 + */ +export const scrollToElement = (el, options = {}) => { + const defaultOptions = { + behavior: 'smooth', + block: 'start', + inline: 'nearest', + }; + + el.scrollIntoView({ ...defaultOptions, ...options }); +}; + +/** + * 复制文本到剪贴板 + * @param {string} text - 文本 + * @returns {Promise} 是否成功 + */ +export const copyToClipboard = async (text) => { + try { + if (navigator.clipboard) { + await navigator.clipboard.writeText(text); + return true; + } + + // 降级方案 + const textarea = document.createElement('textarea'); + textarea.value = text; + textarea.style.position = 'fixed'; + textarea.style.opacity = '0'; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand('copy'); + document.body.removeChild(textarea); + + return true; + } catch (err) { + console.error('Failed to copy text: ', err); + return false; + } +}; + +/** + * 检测设备类型 + * @returns {string} 设备类型 + */ +export const getDeviceType = () => { + const ua = navigator.userAgent; + + if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) { + return 'tablet'; + } + + if (/Mobile|Android|iP(hone|od)|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/.test(ua)) { + return 'mobile'; + } + + return 'desktop'; +}; + +/** + * 检测浏览器 + * @returns {Object} 浏览器信息 + */ +export const getBrowserInfo = () => { + const ua = navigator.userAgent; + let browser = 'unknown'; + let version = 'unknown'; + + if (ua.includes('Firefox/')) { + browser = 'Firefox'; + version = ua.split('Firefox/')[1]; + } else if (ua.includes('Edg/')) { + browser = 'Edge'; + version = ua.split('Edg/')[1]; + } else if (ua.includes('Chrome/')) { + browser = 'Chrome'; + version = ua.split('Chrome/')[1]; + } else if (ua.includes('Safari/')) { + browser = 'Safari'; + version = ua.split('Version/')[1]; + } + + return { browser, version }; +}; + +/** + * 检测操作系统 + * @returns {string} 操作系统 + */ +export const getOS = () => { + const ua = navigator.userAgent; + + if (ua.includes('Win')) return 'Windows'; + if (ua.includes('Mac')) return 'MacOS'; + if (ua.includes('Linux')) return 'Linux'; + if (ua.includes('Android')) return 'Android'; + if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'; + + return 'Unknown'; +}; + +/** + * 检测网络状态 + * @returns {Object} 网络信息 + */ +export const getNetworkInfo = () => { + if (!navigator.connection) { + return { online: navigator.onLine, type: 'unknown', speed: 'unknown' }; + } + + const connection = navigator.connection; + + return { + online: navigator.onLine, + type: connection.effectiveType || 'unknown', + speed: connection.downlink || 'unknown', + rtt: connection.rtt || 'unknown', + }; +}; + +/** + * 存储数据到localStorage + * @param {string} key - 键 + * @param {*} value - 值 + * @param {number} expiry - 过期时间(毫秒) + */ +export const setStorage = (key, value, expiry = null) => { + const item = { + value, + timestamp: Date.now(), + expiry: expiry ? Date.now() + expiry : null, + }; + + localStorage.setItem(key, JSON.stringify(item)); +}; + +/** + * 从localStorage获取数据 + * @param {string} key - 键 + * @param {*} defaultValue - 默认值 + * @returns {*} 值 + */ +export const getStorage = (key, defaultValue = null) => { + const itemStr = localStorage.getItem(key); + + if (!itemStr) return defaultValue; + + try { + const item = JSON.parse(itemStr); + + // 检查是否过期 + if (item.expiry && Date.now() > item.expiry) { + localStorage.removeItem(key); + return defaultValue; + } + + return item.value; + } catch (err) { + console.error('Error parsing storage item:', err); + return defaultValue; + } +}; + +/** + * 从localStorage删除数据 + * @param {string} key - 键 + */ +export const removeStorage = (key) => { + localStorage.removeItem(key); +}; + +/** + * 清空localStorage + */ +export const clearStorage = () => { + localStorage.clear(); +}; + +/** + * 生成UUID + * @returns {string} UUID + */ +export const generateUUID = () => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); +}; + +/** + * 检查是否支持某个CSS属性 + * @param {string} property - CSS属性 + * @returns {boolean} 是否支持 + */ +export const supportsCSSProperty = (property) => { + return typeof document !== 'undefined' && + property in document.documentElement.style; +}; + +/** + * 检查是否支持某个JavaScript API + * @param {string} api - API名称 + * @returns {boolean} 是否支持 + */ +export const supportsAPI = (api) => { + return api in window || api in navigator; +}; + +/** + * 获取URL参数 + * @param {string} name - 参数名 + * @returns {string|null} 参数值 + */ +export const getURLParam = (name) => { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(name); +}; + +/** + * 设置URL参数 + * @param {string} name - 参数名 + * @param {string} value - 参数值 + */ +export const setURLParam = (name, value) => { + const url = new URL(window.location); + url.searchParams.set(name, value); + window.history.pushState({}, '', url); +}; + +/** + * 删除URL参数 + * @param {string} name - 参数名 + */ +export const removeURLParam = (name) => { + const url = new URL(window.location); + url.searchParams.delete(name); + window.history.pushState({}, '', url); +}; + +/** + * 格式化数字 + * @param {number} number - 数字 + * @param {number} decimals - 小数位数 + * @param {string} decimalSeparator - 小数分隔符 + * @param {string} thousandsSeparator - 千位分隔符 + * @returns {string} 格式化后的字符串 + */ +export const formatNumber = (number, decimals = 0, decimalSeparator = '.', thousandsSeparator = ',') => { + const fixed = number.toFixed(decimals); + const [intPart, decPart] = fixed.split('.'); + + const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator); + + return decimals > 0 ? `${formattedInt}${decimalSeparator}${decPart}` : formattedInt; +}; + +/** + * 格式化货币 + * @param {number} amount - 金额 + * @param {string} currency - 货币代码 + * @param {string} locale - 地区 + * @returns {string} 格式化后的字符串 + */ +export const formatCurrency = (amount, currency = 'USD', locale = 'en-US') => { + return new Intl.NumberFormat(locale, { + style: 'currency', + currency, + }).format(amount); +}; + +/** + * 格式化百分比 + * @param {number} value - 值 + * @param {number} decimals - 小数位数 + * @param {string} locale - 地区 + * @returns {string} 格式化后的字符串 + */ +export const formatPercent = (value, decimals = 2, locale = 'en-US') => { + return new Intl.NumberFormat(locale, { + style: 'percent', + minimumFractionDigits: decimals, + maximumFractionDigits: decimals, + }).format(value / 100); +}; + +/** + * 检查是否为空值 + * @param {*} value - 值 + * @returns {boolean} 是否为空 + */ +export const isEmpty = (value) => { + if (value === null || value === undefined) return true; + if (typeof value === 'string') return value.trim().length === 0; + if (Array.isArray(value)) return value.length === 0; + if (typeof value === 'object') return Object.keys(value).length === 0; + return false; +}; + +/** + * 深拷贝对象 + * @param {*} obj - 对象 + * @returns {*} 拷贝后的对象 + */ +export const deepClone = (obj) => { + if (obj === null || typeof obj !== 'object') return obj; + if (obj instanceof Date) return new Date(obj.getTime()); + if (obj instanceof RegExp) return new RegExp(obj); + if (obj instanceof Map) return new Map([...obj].map(([k, v]) => [k, deepClone(v)])); + if (obj instanceof Set) return new Set([...obj].map(item => deepClone(item))); + + const cloned = Array.isArray(obj) ? [] : {}; + + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + cloned[key] = deepClone(obj[key]); + } + } + + return cloned; +}; + +/** + * 比较两个对象是否相等 + * @param {*} obj1 - 对象1 + * @param {*} obj2 - 对象2 + * @returns {boolean} 是否相等 + */ +export const isEqual = (obj1, obj2) => { + if (obj1 === obj2) return true; + if (obj1 === null || obj2 === null) return false; + if (typeof obj1 !== typeof obj2) return false; + + if (typeof obj1 !== 'object') return obj1 === obj2; + + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + + if (keys1.length !== keys2.length) return false; + + for (const key of keys1) { + if (!keys2.includes(key)) return false; + if (!isEqual(obj1[key], obj2[key])) return false; + } + + return true; +}; + +/** + * 验证邮箱格式 + * @param {string} email - 邮箱 + * @returns {boolean} 是否有效 + */ +export const isValidEmail = (email) => { + const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return re.test(email); +}; + +/** + * 验证URL格式 + * @param {string} url - URL + * @returns {boolean} 是否有效 + */ +export const isValidURL = (url) => { + try { + new URL(url); + return true; + } catch { + return false; + } +}; + +/** + * 验证手机号格式 + * @param {string} phone - 手机号 + * @returns {boolean} 是否有效 + */ +export const isValidPhone = (phone) => { + const re = /^1[3-9]\d{9}$/; + return re.test(phone); +}; + +/** + * 验证身份证号格式 + * @param {string} idCard - 身份证号 + * @returns {boolean} 是否有效 + */ +export const isValidIDCard = (idCard) => { + const re = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/; + return re.test(idCard); +}; + +/** + * 生成随机颜色 + * @returns {string} 颜色值 + */ +export const randomColor = () => { + return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'); +}; + +/** + * 颜色转RGBA + * @param {string} color - 颜色值 + * @param {number} alpha - 透明度 + * @returns {string} RGBA颜色值 + */ +export const colorToRGBA = (color, alpha = 1) => { + const hex = color.replace('#', ''); + const r = parseInt(hex.substring(0, 2), 16); + const g = parseInt(hex.substring(2, 4), 16); + const b = parseInt(hex.substring(4, 6), 16); + + return `rgba(${r}, ${g}, ${b}, ${alpha})`; +}; + +/** + * 获取颜色亮度 + * @param {string} color - 颜色值 + * @returns {number} 亮度值(0-255) + */ +export const getColorBrightness = (color) => { + const hex = color.replace('#', ''); + const r = parseInt(hex.substring(0, 2), 16); + const g = parseInt(hex.substring(2, 4), 16); + const b = parseInt(hex.substring(4, 6), 16); + + return (r * 299 + g * 587 + b * 114) / 1000; +}; + +/** + * 判断是否为浅色 + * @param {string} color - 颜色值 + * @returns {boolean} 是否为浅色 + */ +export const isLightColor = (color) => { + return getColorBrightness(color) > 128; +}; + +/** + * 获取对比色 + * @param {string} color - 颜色值 + * @returns {string} 对比色 + */ +export const getContrastColor = (color) => { + return isLightColor(color) ? '#000000' : '#FFFFFF'; +}; + +/** + * 生成渐变色 + * @param {string} color1 - 起始颜色 + * @param {string} color2 - 结束颜色 + * @param {number} steps - 步数 + * @returns {Array} 颜色数组 + */ +export const generateGradient = (color1, color2, steps = 10) => { + const hex = (color) => { + const c = color.replace('#', ''); + return [ + parseInt(c.substring(0, 2), 16), + parseInt(c.substring(2, 4), 16), + parseInt(c.substring(4, 6), 16), + ]; + }; + + const [r1, g1, b1] = hex(color1); + const [r2, g2, b2] = hex(color2); + + const gradient = []; + + for (let i = 0; i < steps; i++) { + const r = Math.round(r1 + (r2 - r1) * (i / (steps - 1))); + const g = Math.round(g1 + (g2 - g1) * (i / (steps - 1))); + const b = Math.round(b1 + (b2 - b1) * (i / (steps - 1))); + + gradient.push(`#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`); + } + + return gradient; +}; + +/** + * 获取字符长度(支持中文) + * @param {string} str - 字符串 + * @returns {number} 长度 + */ +export const getStringLength = (str) => { + let length = 0; + for (let i = 0; i < str.length; i++) { + const code = str.charCodeAt(i); + if (code > 0 && code <= 128) { + length += 1; + } else { + length += 2; + } + } + return length; +}; + +/** + * 截取字符串(支持中文) + * @param {string} str - 字符串 + * @param {number} length - 长度 + * @param {string} suffix - 后缀 + * @returns {string} 截取后的字符串 + */ +export const truncateString = (str, length, suffix = '...') => { + let currentLength = 0; + let result = ''; + + for (let i = 0; i < str.length; i++) { + const char = str[i]; + const code = str.charCodeAt(i); + + if (code > 0 && code <= 128) { + currentLength += 1; + } else { + currentLength += 2; + } + + if (currentLength > length) { + return result + suffix; + } + + result += char; + } + + return result; +}; + +/** + * 驼峰转换 + * @param {string} str - 字符串 + * @returns {string} 驼峰格式字符串 + */ +export const toCamelCase = (str) => { + return str + .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : '')) + .replace(/^[A-Z]/, (c) => c.toLowerCase()); +}; + +/** + * 短横线转换 + * @param {string} str - 字符串 + * @returns {string} 短横线格式字符串 + */ +export const toKebabCase = (str) => { + return str + .replace(/([a-z])([A-Z])/g, '$1-$2') + .replace(/[\s_]+/g, '-') + .toLowerCase(); +}; + +/** + * 下划线转换 + * @param {string} str - 字符串 + * @returns {string} 下划线格式字符串 + */ +export const toSnakeCase = (str) => { + return str + .replace(/([a-z])([A-Z])/g, '$1_$2') + .replace(/[\s\-]+/g, '_') + .toLowerCase(); +}; + +/** + * 首字母大写 + * @param {string} str - 字符串 + * @returns {string} 首字母大写字符串 + */ +export const capitalize = (str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}; + +/** + * 每个单词首字母大写 + * @param {string} str - 字符串 + * @returns {string} 每个单词首字母大写字符串 + */ +export const capitalizeWords = (str) => { + return str.replace(/\b\w/g, (char) => char.toUpperCase()); +}; + +/** + * 移除HTML标签 + * @param {string} html - HTML字符串 + * @returns {string} 纯文本 + */ +export const stripHTML = (html) => { + const tmp = document.createElement('div'); + tmp.innerHTML = html; + return tmp.textContent || tmp.innerText || ''; +}; + +/** + * 转义正则表达式 + * @param {string} str - 字符串 + * @returns {string} 转义后的字符串 + */ +export const escapeRegExp = (str) => { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +}; + +/** + * 生成随机字符串 + * @param {number} length - 长度 + * @param {string} chars - 字符集 + * @returns {string} 随机字符串 + */ +export const randomString = (length = 8, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') => { + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; +}; + +/** + * 延迟执行 + * @param {number} ms - 毫秒数 + * @returns {Promise} Promise对象 + */ +export const sleep = (ms) => { + return new Promise(resolve => setTimeout(resolve, ms)); +}; + +/** + * 重试函数 + * @param {Function} fn - 函数 + * @param {number} maxAttempts - 最大尝试次数 + * @param {number} delay - 延迟时间 + * @returns {Promise} Promise对象 + */ +export const retry = async (fn, maxAttempts = 3, delay = 1000) => { + let lastError; + + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + try { + return await fn(); + } catch (err) { + lastError = err; + if (attempt < maxAttempts) { + await sleep(delay * attempt); + } + } + } + + throw lastError; +}; + +/** + * 超时控制 + * @param {Promise} promise - Promise对象 + * @param {number} ms - 毫秒数 + * @returns {Promise} Promise对象 + */ +export const timeout = (promise, ms) => { + return Promise.race([ + promise, + new Promise((_, reject) => { + setTimeout(() => reject(new Error('Timeout')), ms); + }), + ]); +}; + +/** + * 并发控制 + * @param {Array} tasks - 任务数组 + * @param {number} concurrency - 并发数 + * @returns {Promise} Promise对象 + */ +export const parallel = async (tasks, concurrency = 5) => { + const results = []; + const executing = new Set(); + + for (const [index, task] of tasks.entries()) { + const p = Promise.resolve().then(() => task()); + results.push(p); + executing.add(p); + + const clean = () => executing.delete(p); + p.then(clean, clean); + + if (executing.size >= concurrency) { + await Promise.race(executing); + } + } + + return Promise.all(results); +}; + +/** + * 序列执行 + * @param {Array} tasks - 任务数组 + * @returns {Promise} Promise对象 + */ +export const sequence = async (tasks) => { + const results = []; + + for (const task of tasks) { + results.push(await task()); + } + + return results; +}; + +/** + * 缓存函数 + * @param {Function} fn - 函数 + * @param {number} maxSize - 最大缓存数 + * @returns {Function} 缓存后的函数 + */ +export const memoize = (fn, maxSize = 100) => { + const cache = new Map(); + + return (...args) => { + const key = JSON.stringify(args); + + if (cache.has(key)) { + return cache.get(key); + } + + const result = fn(...args); + + if (cache.size >= maxSize) { + const firstKey = cache.keys().next().value; + cache.delete(firstKey); + } + + cache.set(key, result); + + return result; + }; +}; + +/** + * 单例模式 + * @param {Function} fn - 函数 + * @returns {Function} 单例函数 + */ +export const singleton = (fn) => { + let instance; + + return (...args) => { + if (!instance) { + instance = fn(...args); + } + return instance; + }; +}; + +/** + * 观察者模式 + * @returns {Object} 观察者对象 + */ +export const createObserver = () => { + const listeners = new Map(); + + return { + on(event, callback) { + if (!listeners.has(event)) { + listeners.set(event, new Set()); + } + listeners.get(event).add(callback); + + return () => this.off(event, callback); + }, + + off(event, callback) { + if (listeners.has(event)) { + listeners.get(event).delete(callback); + } + }, + + emit(event, ...args) { + if (listeners.has(event)) { + listeners.get(event).forEach(callback => callback(...args)); + } + }, + + once(event, callback) { + const wrapper = (...args) => { + callback(...args); + this.off(event, wrapper); + }; + this.on(event, wrapper); + }, + + clear() { + listeners.clear(); + }, + }; +}; + +/** + * 状态机 + * @param {Object} config - 配置 + * @returns {Object} 状态机对象 + */ +export const createStateMachine = (config) => { + let currentState = config.initial; + const listeners = new Map(); + + return { + get state() { + return currentState; + }, + + transition(event) { + const transitions = config.transitions[currentState]; + if (!transitions || !transitions[event]) { + throw new Error(`Invalid transition: ${event} from ${currentState}`); + } + + const nextState = transitions[event]; + const prevState = currentState; + currentState = nextState; + + if (listeners.has(nextState)) { + listeners.get(nextState).forEach(callback => callback(prevState, nextState)); + } + + return nextState; + }, + + on(state, callback) { + if (!listeners.has(state)) { + listeners.set(state, new Set()); + } + listeners.get(state).add(callback); + + return () => this.off(state, callback); + }, + + off(state, callback) { + if (listeners.has(state)) { + listeners.get(state).delete(callback); + } + }, + + can(event) { + const transitions = config.transitions[currentState]; + return transitions && transitions[event] !== undefined; + }, + }; +}; diff --git a/tests/index.test.js b/tests/index.test.js new file mode 100644 index 0000000..136d66d --- /dev/null +++ b/tests/index.test.js @@ -0,0 +1,1933 @@ +/** + * MetonaToast 单元测试 + * @module tests + * @version 2.0.0 + */ + +import MeToast, { Toast, VERSION } from '../src/index.js'; + +// 模拟DOM环境 +const mockDocument = { + createElement: jest.fn(() => ({ + className: '', + style: {}, + setAttribute: jest.fn(), + appendChild: jest.fn(), + querySelector: jest.fn(), + querySelectorAll: jest.fn(() => []), + execCommand: jest.fn(() => true), + classList: { + add: jest.fn(), + remove: jest.fn(), + contains: jest.fn(), + }, + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + setPointerCapture: jest.fn(), + releasePointerCapture: jest.fn(), + animate: jest.fn(() => ({ + onfinish: null, + oncancel: null, + cancel: jest.fn(), + pause: jest.fn(), + play: jest.fn(), + })), + innerHTML: '', + textContent: '', + dataset: {}, + parentNode: { + removeChild: jest.fn(), + }, + })), + getElementById: jest.fn(), + querySelector: jest.fn(), + querySelectorAll: jest.fn(() => []), + head: { + appendChild: jest.fn(), + }, + body: { + appendChild: jest.fn(), + }, + readyState: 'complete', + addEventListener: jest.fn(), + execCommand: jest.fn(() => true), +}; + +const mockWindow = { + matchMedia: jest.fn(() => ({ + matches: false, + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })), + requestAnimationFrame: jest.fn((cb) => setTimeout(cb, 0)), + cancelAnimationFrame: jest.fn(), + getComputedStyle: jest.fn(() => ({})), + innerWidth: 1024, + innerHeight: 768, + navigator: { + language: 'zh-CN', + clipboard: { + writeText: jest.fn(), + }, + connection: { + effectiveType: '4g', + downlink: 10, + rtt: 50, + }, + onLine: true, + }, + location: { + search: '', + href: 'http://localhost', + }, + history: { + pushState: jest.fn(), + }, + localStorage: { + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), + clear: jest.fn(), + }, + Audio: jest.fn(() => ({ + play: jest.fn(), + volume: 0, + })), +}; + +// 设置全局变量 +global.document = mockDocument; +global.window = mockWindow; +global.navigator = mockWindow.navigator; +global.localStorage = mockWindow.localStorage; +global.requestAnimationFrame = mockWindow.requestAnimationFrame; +global.cancelAnimationFrame = mockWindow.cancelAnimationFrame; +global.matchMedia = mockWindow.matchMedia; +global.getComputedStyle = mockWindow.getComputedStyle; +global.Audio = mockWindow.Audio; + +// 测试套件 +describe('MetonaToast', () => { + beforeEach(() => { + // 清除所有模拟调用 + jest.clearAllMocks(); + + // 重置Toast状态 + MeToast._toasts.clear(); + }); + + describe('版本信息', () => { + test('应该有正确的版本号', () => { + expect(VERSION).toBe('2.0.0'); + expect(MeToast.version).toBe('2.0.0'); + }); + }); + + describe('基础功能', () => { + test('应该能够显示成功Toast', () => { + const toast = MeToast.success('成功消息'); + expect(toast).toBeDefined(); + expect(toast.id).toBeDefined(); + expect(toast.type).toBe('success'); + expect(toast.message).toBe('成功消息'); + }); + + test('应该能够显示错误Toast', () => { + const toast = MeToast.error('错误消息'); + expect(toast).toBeDefined(); + expect(toast.type).toBe('error'); + expect(toast.message).toBe('错误消息'); + }); + + test('应该能够显示警告Toast', () => { + const toast = MeToast.warning('警告消息'); + expect(toast).toBeDefined(); + expect(toast.type).toBe('warning'); + expect(toast.message).toBe('警告消息'); + }); + + test('应该能够显示信息Toast', () => { + const toast = MeToast.info('信息消息'); + expect(toast).toBeDefined(); + expect(toast.type).toBe('info'); + expect(toast.message).toBe('信息消息'); + }); + + test('应该能够显示默认Toast', () => { + const toast = MeToast.show('默认消息'); + expect(toast).toBeDefined(); + expect(toast.type).toBe('default'); + expect(toast.message).toBe('默认消息'); + }); + + test('应该能够显示带标题的Toast', () => { + const toast = MeToast.success({ + title: '成功', + message: '操作成功', + }); + expect(toast.title).toBe('成功'); + expect(toast.message).toBe('操作成功'); + }); + + test('应该能够显示加载Toast', () => { + const loading = MeToast.loading('加载中...'); + expect(loading).toBeDefined(); + expect(loading.id).toBeDefined(); + expect(loading.success).toBeInstanceOf(Function); + expect(loading.error).toBeInstanceOf(Function); + expect(loading.info).toBeInstanceOf(Function); + expect(loading.warning).toBeInstanceOf(Function); + expect(loading.update).toBeInstanceOf(Function); + expect(loading.dismiss).toBeInstanceOf(Function); + }); + }); + + describe('Toast管理', () => { + test('应该能够获取所有Toast', () => { + MeToast.success('消息1'); + MeToast.error('消息2'); + + const toasts = MeToast.getToasts(); + expect(toasts).toHaveLength(2); + }); + + test('应该能够获取Toast数量', () => { + MeToast.success('消息1'); + MeToast.error('消息2'); + MeToast.warning('消息3'); + + expect(MeToast.count()).toBe(3); + }); + + test('应该能够检查是否有Toast', () => { + expect(MeToast.hasToasts()).toBe(false); + + MeToast.success('消息'); + + expect(MeToast.hasToasts()).toBe(true); + }); + + test('应该能够查找Toast', () => { + const toast = MeToast.success('消息'); + const found = MeToast.find(toast.id); + + expect(found).toBeDefined(); + expect(found.id).toBe(toast.id); + }); + + test('应该能够关闭Toast', () => { + const toast = MeToast.success('消息'); + toast.close(); + + // 等待关闭动画 + setTimeout(() => { + expect(MeToast.count()).toBe(0); + }, 300); + }); + + test('应该能够关闭所有Toast', () => { + MeToast.success('消息1'); + MeToast.error('消息2'); + MeToast.warning('消息3'); + + MeToast.dismiss(); + + // 等待关闭动画 + setTimeout(() => { + expect(MeToast.count()).toBe(0); + }, 300); + }); + + test('应该能够清除所有Toast', () => { + MeToast.success('消息1'); + MeToast.error('消息2'); + + MeToast.clear(); + + // 等待关闭动画 + setTimeout(() => { + expect(MeToast.count()).toBe(0); + }, 300); + }); + }); + + describe('配置管理', () => { + test('应该能够配置全局选项', () => { + MeToast.configure({ + position: 'bottom-center', + duration: 5000, + theme: 'dark', + }); + + const config = MeToast.getConfig(); + expect(config.position).toBe('bottom-center'); + expect(config.duration).toBe(5000); + expect(config.theme).toBe('dark'); + }); + + test('应该能够重置配置', () => { + MeToast.configure({ + position: 'bottom-center', + duration: 5000, + }); + + MeToast.resetConfig(); + + const config = MeToast.getConfig(); + expect(config.position).toBe('top-right'); + expect(config.duration).toBe(4000); + }); + + test('应该能够更新配置', () => { + MeToast.updateConfig({ + position: 'top-left', + }); + + const config = MeToast.getConfig(); + expect(config.position).toBe('top-left'); + }); + }); + + describe('主题系统', () => { + test('应该能够获取当前主题', () => { + const theme = MeToast.themes.getCurrentTheme(); + expect(theme).toBeDefined(); + }); + + test('应该能够切换主题', () => { + MeToast.themes.switchTheme('dark'); + expect(MeToast.themes.getCurrentTheme()).toBe('dark'); + + MeToast.themes.switchTheme('light'); + expect(MeToast.themes.getCurrentTheme()).toBe('light'); + }); + + test('应该能够获取主题配置', () => { + const config = MeToast.themes.getThemeConfig('light'); + expect(config).toBeDefined(); + expect(config.bg).toBeDefined(); + expect(config.text).toBeDefined(); + expect(config.border).toBeDefined(); + }); + + test('应该能够获取所有主题', () => { + const themes = MeToast.themes.getAllThemes(); + expect(themes).toBeDefined(); + expect(themes.light).toBeDefined(); + expect(themes.dark).toBeDefined(); + }); + + test('应该能够注册自定义主题', () => { + MeToast.themes.registerTheme('custom', { + bg: 'rgba(255, 255, 255, 0.96)', + text: '#1f2937', + border: 'rgba(0, 0, 0, 0.06)', + shadow: '0 10px 36px -10px rgba(0, 0, 0, 0.18)', + hoverShadow: '0 14px 48px -10px rgba(0, 0, 0, 0.22)', + progressBg: 'rgba(0, 0, 0, 0.06)', + closeHoverBg: 'rgba(0, 0, 0, 0.06)', + }); + + expect(MeToast.themes.hasTheme('custom')).toBe(true); + }); + }); + + describe('国际化系统', () => { + test('应该能够获取当前语言', () => { + const locale = MeToast.i18n.getCurrentLocale(); + expect(locale).toBeDefined(); + }); + + test('应该能够切换语言', () => { + MeToast.i18n.switchLocale('en-US'); + expect(MeToast.i18n.getCurrentLocale()).toBe('en-US'); + + MeToast.i18n.switchLocale('zh-CN'); + expect(MeToast.i18n.getCurrentLocale()).toBe('zh-CN'); + }); + + test('应该能够获取翻译', () => { + const text = MeToast.i18n.t('success'); + expect(text).toBeDefined(); + }); + + test('应该能够检查翻译是否存在', () => { + expect(MeToast.i18n.hasTranslation('success')).toBe(true); + expect(MeToast.i18n.hasTranslation('nonexistent')).toBe(false); + }); + + test('应该能够获取支持的语言列表', () => { + const locales = MeToast.i18n.getSupportedLocales(); + expect(locales).toContain('zh-CN'); + expect(locales).toContain('en-US'); + }); + + test('应该能够获取语言名称', () => { + const name = MeToast.i18n.getLocaleName('zh-CN'); + expect(name).toBe('简体中文'); + }); + + test('应该能够格式化数字', () => { + const formatted = MeToast.i18n.formatNumber(1234567.89); + expect(formatted).toBeDefined(); + }); + + test('应该能够格式化货币', () => { + const formatted = MeToast.i18n.formatCurrency(99.99, 'USD'); + expect(formatted).toBeDefined(); + }); + + test('应该能够格式化日期', () => { + const formatted = MeToast.i18n.formatDate(new Date()); + expect(formatted).toBeDefined(); + }); + }); + + describe('插件系统', () => { + test('应该能够注册插件', () => { + const plugin = { + name: 'test-plugin', + version: '1.0.0', + install: jest.fn(), + }; + + MeToast.plugins.register('test', plugin); + expect(MeToast.plugins.has('test')).toBe(true); + }); + + test('应该能够获取插件', () => { + const plugin = { + name: 'test-plugin', + version: '1.0.0', + }; + + MeToast.plugins.register('test', plugin); + const retrieved = MeToast.plugins.get('test'); + expect(retrieved).toBeDefined(); + expect(retrieved.name).toBe('test-plugin'); + }); + + test('应该能够注销插件', () => { + const plugin = { + name: 'test-plugin', + version: '1.0.0', + uninstall: jest.fn(), + }; + + MeToast.plugins.register('test', plugin); + MeToast.plugins.unregister('test'); + expect(MeToast.plugins.has('test')).toBe(false); + }); + + test('应该能够启用/禁用插件', () => { + const plugin = { + name: 'test-plugin', + version: '1.0.0', + }; + + MeToast.plugins.register('test', plugin); + + MeToast.plugins.disable('test'); + expect(MeToast.plugins.isEnabled('test')).toBe(false); + + MeToast.plugins.enable('test'); + expect(MeToast.plugins.isEnabled('test')).toBe(true); + }); + + test('应该能够获取所有插件', () => { + // 清理前面测试遗留的插件 + ['test', 'test-plugin', 'custom'].forEach(n => { + if (MeToast.plugins.has(n)) MeToast.plugins.unregister(n); + }); + MeToast.plugins.register('test1', { name: 'test1' }); + MeToast.plugins.register('test2', { name: 'test2' }); + + const plugins = MeToast.plugins.getAll(); + expect(plugins).toHaveLength(2); + }); + + test('应该能够获取插件名称', () => { + MeToast.plugins.register('test1', { name: 'test1' }); + MeToast.plugins.register('test2', { name: 'test2' }); + + const names = MeToast.plugins.getNames(); + expect(names).toContain('test1'); + expect(names).toContain('test2'); + }); + + test('应该能够使用预设插件', () => { + MeToast.use('keyboard'); + expect(MeToast.plugins.has('keyboard')).toBe(true); + }); + }); + + describe('动画系统', () => { + test('应该能够获取所有动画名称', () => { + const names = MeToast.animations.getAnimationNames(); + expect(names).toContain('slide'); + expect(names).toContain('fade'); + expect(names).toContain('scale'); + expect(names).toContain('bounce'); + }); + + test('应该能够获取动画配置', () => { + const config = MeToast.animations.get('slide'); + expect(config).toBeDefined(); + expect(config.enter).toBeDefined(); + expect(config.leave).toBeDefined(); + expect(config.duration).toBeDefined(); + expect(config.easing).toBeDefined(); + }); + + test('应该能够注册自定义动画', () => { + MeToast.animations.register('custom', { + enter: { + transform: 'scale(0)', + opacity: 0, + }, + leave: { + transform: 'scale(1)', + opacity: 1, + }, + duration: 500, + }); + + expect(MeToast.animations.get('custom')).toBeDefined(); + }); + + test('应该能够注销动画', () => { + MeToast.animations.register('custom', { + enter: {}, + leave: {}, + }); + + MeToast.animations.unregister('custom'); + expect(MeToast.animations.get('custom')).toBeNull(); + }); + }); + + describe('Promise支持', () => { + test('应该能够使用Promise风格', async () => { + const promise = Promise.resolve('success'); + + await MeToast.promise(promise, { + loading: '加载中...', + success: '成功', + error: '失败', + }); + + // 验证Toast被创建 + expect(MeToast.count()).toBeGreaterThan(0); + }); + + test('应该能够处理Promise拒绝', async () => { + const promise = Promise.reject(new Error('error')); + + try { + await MeToast.promise(promise, { + loading: '加载中...', + success: '成功', + error: '失败', + }); + } catch (error) { + expect(error).toBeDefined(); + } + }); + }); + + describe('Toast实例', () => { + test('应该能够更新Toast', () => { + const toast = MeToast.success('原始消息'); + + toast.update({ + title: '新标题', + message: '新消息', + type: 'info', + }); + + expect(toast.title).toBe('新标题'); + expect(toast.message).toBe('新消息'); + expect(toast.type).toBe('info'); + }); + + test('应该能够暂停和恢复Toast', () => { + const toast = MeToast.success({ + message: '消息', + duration: 5000, + }); + + toast._pause(); + expect(toast.paused).toBe(true); + + toast._resume(); + expect(toast.paused).toBe(false); + }); + + test('应该能够获取Toast配置', () => { + const toast = MeToast.success({ + message: '消息', + position: 'bottom-center', + duration: 5000, + }); + + expect(toast.config.position).toBe('bottom-center'); + expect(toast.config.duration).toBe(5000); + }); + }); + + describe('状态信息', () => { + test('应该能够获取状态信息', () => { + MeToast.success('消息'); + + const status = MeToast.getStatus(); + expect(status.version).toBe('2.0.0'); + expect(status.toasts).toBeGreaterThanOrEqual(0); + expect(status.theme).toBeDefined(); + expect(status.locale).toBeDefined(); + expect(status.plugins).toBeInstanceOf(Array); + expect(status.animations).toBeGreaterThanOrEqual(0); + }); + }); + + describe('销毁功能', () => { + test('应该能够销毁所有Toast', () => { + MeToast.success('消息1'); + MeToast.error('消息2'); + + MeToast.destroy(); + + // 等待销毁完成 + setTimeout(() => { + expect(MeToast.count()).toBe(0); + }, 300); + }); + }); +}); + +describe('Toast类', () => { + test('应该能够创建Toast实例', () => { + const toast = new Toast({ + type: 'success', + title: '成功', + message: '操作成功', + }); + + expect(toast).toBeDefined(); + expect(toast.type).toBe('success'); + expect(toast.title).toBe('成功'); + expect(toast.message).toBe('操作成功'); + }); + + test('应该能够生成唯一ID', () => { + const toast1 = new Toast({ message: '消息1' }); + const toast2 = new Toast({ message: '消息2' }); + + expect(toast1.id).not.toBe(toast2.id); + }); + + test('应该能够设置默认配置', () => { + const toast = new Toast({ message: '消息' }); + + expect(toast.config).toBeDefined(); + expect(toast.config.position).toBe('top-right'); + expect(toast.config.duration).toBe(4000); + expect(toast.config.max).toBe(6); + }); + + test('应该能够合并配置', () => { + const toast = new Toast({ + message: '消息', + position: 'bottom-center', + duration: 5000, + }); + + expect(toast.config.position).toBe('bottom-center'); + expect(toast.config.duration).toBe(5000); + }); + + test('应该能够设置类型', () => { + const types = ['success', 'error', 'warning', 'info', 'loading', 'default']; + + types.forEach((type) => { + const toast = new Toast({ type, message: '消息' }); + expect(toast.type).toBe(type); + }); + }); + + test('应该能够设置标题', () => { + const toast = new Toast({ + title: '标题', + message: '消息', + }); + + expect(toast.title).toBe('标题'); + }); + + test('应该能够设置消息', () => { + const toast = new Toast({ + message: '消息内容', + }); + + expect(toast.message).toBe('消息内容'); + }); + + test('应该能够设置HTML内容', () => { + const toast = new Toast({ + html: '加粗', + }); + + expect(toast.html).toBe('加粗'); + }); + + test('应该能够设置自定义图标', () => { + const toast = new Toast({ + iconHTML: '...', + }); + + expect(toast.iconHTML).toBe('...'); + }); + + test('应该能够更新Toast', () => { + const toast = new Toast({ message: '原始消息' }); + + toast.update({ + title: '新标题', + message: '新消息', + type: 'success', + }); + + expect(toast.title).toBe('新标题'); + expect(toast.message).toBe('新消息'); + expect(toast.type).toBe('success'); + }); + + test('应该能够关闭Toast', (done) => { + const toast = new Toast({ message: '消息' }); + + toast.close(); + + expect(toast.closing).toBe(true); + // _destroy 在 300ms setTimeout 中异步调用 + setTimeout(() => { + expect(toast.el).toBeNull(); + done(); + }, 350); + }); + + test('应该能够暂停计时', () => { + const toast = new Toast({ + message: '消息', + duration: 5000, + }); + + toast._pause(); + + expect(toast.paused).toBe(true); + }); + + test('应该能够恢复计时', () => { + const toast = new Toast({ + message: '消息', + duration: 5000, + }); + + toast._pause(); + toast._resume(); + + expect(toast.paused).toBe(false); + }); + + test('应该能够获取配色方案', () => { + const toast = new Toast({ type: 'success' }); + const palette = toast._palette(); + + expect(palette).toBeDefined(); + expect(palette.theme).toBeDefined(); + expect(palette.c).toBeDefined(); + expect(palette.t).toBeDefined(); + }); +}); + +describe('工具函数', () => { + test('应该能够生成唯一ID', () => { + const { generateId } = require('../src/utils.js'); + + const id1 = generateId(); + const id2 = generateId(); + + expect(id1).not.toBe(id2); + expect(id1).toMatch(/^met-/); + }); + + test('应该能够转义HTML', () => { + const { escapeHTML } = require('../src/utils.js'); + + const escaped = escapeHTML(''); + expect(escaped).not.toContain('