-
+
+
+
+
+
+
+
+ 将文件拖到此处,或点击上传
+
+
{{ getUploadTip() }}
+
+
+
+
+
+
+
待上传文件:
+
+
+
+
{{ getFileTypeIcon(file) }}
+
+
+
+
{{ file.name }}
+
{{ formatFileSize(file.size) }}
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+ {{ uploading ? '上传中...' : '确定上传' }}
+
+
+
+
+
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadExample.vue b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadExample.vue
new file mode 100644
index 0000000..9a77b25
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadExample.vue
@@ -0,0 +1,312 @@
+
+
+
文件上传组件测试
+
+
+
+ 1. 封面模式测试
+
+
+
+
+
+
当前封面: {{ coverImage || '无' }}
+
说明: 点击上传封面图片,支持JPG、PNG、GIF格式,最大5MB
+
+
+
+
+
+
+ 2. 弹窗模式测试
+
+
+
+
已上传文件数: {{ dialogFileList.length }}
+
说明: 点击按钮打开弹窗,支持多文件上传,最多5个文件,每个文件最大10MB
+
+
已上传的文件:
+
+
+ {{ file.name }}
+ ({{ formatFileSize(file.size || 0) }})
+ {{ file.type }}
+
+
+
+
+
+
+
+
+
+ 3. 内容模式测试
+
+
+
+
已上传文件数: {{ contentFileList.length }}
+
说明: 直接在页面中显示上传区域,最多3个文件,每个文件最大20MB
+
+
已上传的文件:
+
+
+ {{ file.name }}
+ ({{ formatFileSize(file.size || 0) }})
+ {{ file.type }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue
deleted file mode 100644
index 5738760..0000000
--- a/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
- Shared Components Demo
-
- Home |
- FileUpload Demo
-
-
-
-
-
-
-
-
-
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/SharedLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/SharedLayout.vue
new file mode 100644
index 0000000..4da507c
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/layouts/SharedLayout.vue
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
diff --git a/urbanLifelineWeb/packages/shared/src/router/index.ts b/urbanLifelineWeb/packages/shared/src/router/index.ts
index 5e71969..f374239 100644
--- a/urbanLifelineWeb/packages/shared/src/router/index.ts
+++ b/urbanLifelineWeb/packages/shared/src/router/index.ts
@@ -15,8 +15,8 @@ interface RouteItem {
}
// 布局组件
-const DefaultLayout = defineAsyncComponent(
- () => import('../layouts/DefaultLayout.vue')
+const SharedLayout = defineAsyncComponent(
+ () => import('../layouts/SharedLayout.vue')
)
// 首页组件
@@ -46,7 +46,7 @@ const Home = {
const routes: RouteRecordRaw[] = [
{
path: '/',
- component: DefaultLayout,
+ component: SharedLayout,
children: [
{
path: '',
@@ -59,29 +59,33 @@ const routes: RouteRecordRaw[] = [
}
]
-// 自动导入所有以 Test.vue 结尾的组件
-const testComponents = import.meta.glob('../components/**/*Test.vue')
+// 自动导入所有以 Example.vue 结尾的组件
+const testComponents = import.meta.glob('../components/**/*Example.vue')
// 为每个测试组件创建路由
Object.entries(testComponents).forEach(([path, component]) => {
- // 从路径中提取路由路径
- // 例如: ../components/fileupload/FileUploadTest.vue -> /fileupload
- const routePath = path
- .replace('../components/', '/') // 移除相对路径
- .replace(/\/\w+Test\.vue$/, '') // 移除 Test.vue 部分
- .toLowerCase() // 统一小写
-
- const routeName = routePath.slice(1) || 'home'
+ // 保持完整的路径结构
+ // ../components/base/button/ButtonExample.vue -> /base/button
+ // ../components/fileupload/FileUploadExample.vue -> /fileupload
+ const pathSegments = path
+ .replace('../components/', '')
+ .replace(/Test\.vue$/, '')
+ .split('/')
+ .filter(Boolean)
+
+ const routePath = `/${pathSegments.join('/').toLowerCase()}`
+ const componentName = pathSegments[pathSegments.length - 1].toLowerCase()
+
const routeConfig: RouteRecordRaw = {
path: routePath,
- name: routeName,
- component: DefaultLayout,
+ name: componentName,
+ component: SharedLayout,
children: [
{
path: '',
- name: `${routeName}-content`,
+ name: `${componentName}-content`,
component: defineAsyncComponent(component as any),
- meta: { title: `${routeName} Demo` }
+ meta: { title: `${componentName.charAt(0).toUpperCase() + componentName.slice(1)} Demo` }
}
]
}
@@ -103,7 +107,7 @@ Object.entries(testComponents).forEach(([path, component]) => {
const props = homeRoute.props as { routes: RouteItem[] }
props.routes.push({
path: routePath,
- name: routeName
+ name: componentName
})
}
})
diff --git a/urbanLifelineWeb/packages/shared/src/types/file/file.ts b/urbanLifelineWeb/packages/shared/src/types/file/file.ts
index 1861585..bef198d 100644
--- a/urbanLifelineWeb/packages/shared/src/types/file/file.ts
+++ b/urbanLifelineWeb/packages/shared/src/types/file/file.ts
@@ -25,3 +25,17 @@ export interface TbSysFileDTO extends BaseDTO {
/** 文件状态 */
status?: string
}
+
+export interface FileUploadParam {
+ file: File;
+ module?: string;
+ optsn?: string;
+ uploader?: string;
+}
+
+export interface BatchFileUploadParam {
+ files: File[];
+ module?: string;
+ optsn?: string;
+ uploader?: string;
+}
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/utils/file.ts b/urbanLifelineWeb/packages/shared/src/utils/file.ts
new file mode 100644
index 0000000..b918556
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/utils/file.ts
@@ -0,0 +1,181 @@
+/**
+ * 文件处理相关工具函数
+ */
+
+/**
+ * 验证文件类型
+ */
+export const isValidFileType = (file: File, accept: string): boolean => {
+ if (!accept || accept === '*/*') return true
+
+ const acceptTypes = accept.split(',').map(t => t.trim())
+ return acceptTypes.some(type => {
+ if (type.startsWith('.')) {
+ return file.name.toLowerCase().endsWith(type.toLowerCase())
+ } else if (type.endsWith('/*')) {
+ return file.type.startsWith(type.replace('/*', ''))
+ } else {
+ return file.type === type
+ }
+ })
+}
+
+/**
+ * 判断是否为图片文件
+ */
+export const isImageFile = (file: File): boolean => {
+ return file.type.startsWith('image/')
+}
+
+/**
+ * 判断是否为文本文件
+ */
+export const isTextFile = (file: File): boolean => {
+ return file.type.startsWith('text/')
+}
+
+/**
+ * 获取文件预览URL
+ */
+export const getFilePreviewUrl = (file: File): string => {
+ return URL.createObjectURL(file)
+}
+
+/**
+ * 格式化文件大小
+ */
+export const formatFileSize = (bytes: number): string => {
+ if (bytes === 0) return '0 B'
+ const k = 1024
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
+}
+
+/**
+ * 获取文件类型图标
+ */
+export const getFileTypeIcon = (file: File): string => {
+ const extension = file.name.split('.').pop()?.toLowerCase()
+ const iconMap: Record
= {
+ // 文档类
+ 'pdf': '📄',
+ 'doc': '📝',
+ 'docx': '📝',
+ 'txt': '📄',
+ 'md': '📄',
+ 'rtf': '📄',
+
+ // 表格类
+ 'xls': '📊',
+ 'xlsx': '📊',
+ 'csv': '📊',
+
+ // 演示文稿
+ 'ppt': '📊',
+ 'pptx': '📊',
+
+ // 压缩包
+ 'zip': '📦',
+ 'rar': '📦',
+ '7z': '📦',
+ 'tar': '📦',
+ 'gz': '📦',
+
+ // 视频
+ 'mp4': '🎬',
+ 'avi': '🎬',
+ 'mov': '🎬',
+ 'wmv': '🎬',
+ 'flv': '🎬',
+ 'mkv': '🎬',
+
+ // 音频
+ 'mp3': '🎵',
+ 'wav': '🎵',
+ 'flac': '🎵',
+ 'aac': '🎵',
+
+ // 图片
+ 'jpg': '🖼️',
+ 'jpeg': '🖼️',
+ 'png': '🖼️',
+ 'gif': '🖼️',
+ 'bmp': '🖼️',
+ 'svg': '🖼️',
+ 'webp': '🖼️'
+ }
+ return iconMap[extension || ''] || '📄'
+}
+
+/**
+ * 验证文件大小
+ */
+export const validateFileSize = (file: File, maxSize: number): { valid: boolean; error?: string } => {
+ if (file.size > maxSize) {
+ const maxSizeMB = (maxSize / 1024 / 1024).toFixed(0)
+ return {
+ valid: false,
+ error: `文件 ${file.name} 大小超过 ${maxSizeMB}MB`
+ }
+ }
+ return { valid: true }
+}
+
+/**
+ * 验证文件类型
+ */
+export const validateFileType = (file: File, accept?: string): { valid: boolean; error?: string } => {
+ if (accept && !isValidFileType(file, accept)) {
+ return {
+ valid: false,
+ error: `文件 ${file.name} 类型不符合要求`
+ }
+ }
+ return { valid: true }
+}
+
+/**
+ * 检查文件是否重复
+ */
+export const checkFileDuplicate = (file: File, existingFiles: File[]): { valid: boolean; error?: string } => {
+ if (existingFiles.some(f => f.name === file.name && f.size === file.size)) {
+ return {
+ valid: false,
+ error: `文件 ${file.name} 已添加`
+ }
+ }
+ return { valid: true }
+}
+
+/**
+ * 综合验证文件
+ */
+export const validateFile = (
+ file: File,
+ options: {
+ maxSize?: number
+ accept?: string
+ existingFiles?: File[]
+ } = {}
+): { valid: boolean; error?: string } => {
+ const { maxSize, accept, existingFiles = [] } = options
+
+ // 检查文件大小
+ if (maxSize) {
+ const sizeResult = validateFileSize(file, maxSize)
+ if (!sizeResult.valid) return sizeResult
+ }
+
+ // 检查文件类型
+ if (accept) {
+ const typeResult = validateFileType(file, accept)
+ if (!typeResult.valid) return typeResult
+ }
+
+ // 检查是否重复
+ const duplicateResult = checkFileDuplicate(file, existingFiles)
+ if (!duplicateResult.valid) return duplicateResult
+
+ return { valid: true }
+}
diff --git a/urbanLifelineWeb/packages/shared/src/utils/index.ts b/urbanLifelineWeb/packages/shared/src/utils/index.ts
new file mode 100644
index 0000000..f74df63
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/utils/index.ts
@@ -0,0 +1,5 @@
+/**
+ * Utils 统一导出
+ */
+
+export * from './file'
diff --git a/urbanLifelineWeb/pnpm-lock.yaml b/urbanLifelineWeb/pnpm-lock.yaml
index ef1eaff..b72b5ef 100644
--- a/urbanLifelineWeb/pnpm-lock.yaml
+++ b/urbanLifelineWeb/pnpm-lock.yaml
@@ -11,9 +11,19 @@ devDependencies:
rimraf:
specifier: ^5.0.5
version: 5.0.10
+ sass:
+ specifier: ^1.94.2
+ version: 1.94.2
+ sass-embedded:
+ specifier: ^1.93.3
+ version: 1.93.3
packages:
+ /@bufbuild/protobuf@2.10.1:
+ resolution: {integrity: sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg==}
+ dev: true
+
/@isaacs/cliui@8.0.2:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -26,6 +36,155 @@ packages:
wrap-ansi-cjs: /wrap-ansi@7.0.0
dev: true
+ /@parcel/watcher-android-arm64@2.5.1:
+ resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-darwin-arm64@2.5.1:
+ resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-darwin-x64@2.5.1:
+ resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-freebsd-x64@2.5.1:
+ resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-arm-glibc@2.5.1:
+ resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-arm-musl@2.5.1:
+ resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-arm64-glibc@2.5.1:
+ resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-arm64-musl@2.5.1:
+ resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-x64-glibc@2.5.1:
+ resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-linux-x64-musl@2.5.1:
+ resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-win32-arm64@2.5.1:
+ resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-win32-ia32@2.5.1:
+ resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher-win32-x64@2.5.1:
+ resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@parcel/watcher@2.5.1:
+ resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
+ engines: {node: '>= 10.0.0'}
+ requiresBuild: true
+ dependencies:
+ detect-libc: 1.0.3
+ is-glob: 4.0.3
+ micromatch: 4.0.8
+ node-addon-api: 7.1.1
+ optionalDependencies:
+ '@parcel/watcher-android-arm64': 2.5.1
+ '@parcel/watcher-darwin-arm64': 2.5.1
+ '@parcel/watcher-darwin-x64': 2.5.1
+ '@parcel/watcher-freebsd-x64': 2.5.1
+ '@parcel/watcher-linux-arm-glibc': 2.5.1
+ '@parcel/watcher-linux-arm-musl': 2.5.1
+ '@parcel/watcher-linux-arm64-glibc': 2.5.1
+ '@parcel/watcher-linux-arm64-musl': 2.5.1
+ '@parcel/watcher-linux-x64-glibc': 2.5.1
+ '@parcel/watcher-linux-x64-musl': 2.5.1
+ '@parcel/watcher-win32-arm64': 2.5.1
+ '@parcel/watcher-win32-ia32': 2.5.1
+ '@parcel/watcher-win32-x64': 2.5.1
+ dev: true
+ optional: true
+
/@pkgjs/parseargs@0.11.0:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -65,6 +224,19 @@ packages:
balanced-match: 1.0.2
dev: true
+ /braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+ requiresBuild: true
+ dependencies:
+ fill-range: 7.1.1
+ dev: true
+ optional: true
+
+ /buffer-builder@0.2.0:
+ resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
+ dev: true
+
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@@ -73,6 +245,13 @@ packages:
supports-color: 7.2.0
dev: true
+ /chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
+ dependencies:
+ readdirp: 4.1.2
+ dev: true
+
/cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
@@ -93,6 +272,10 @@ packages:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
+ /colorjs.io@0.5.2:
+ resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
+ dev: true
+
/concurrently@9.2.1:
resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==}
engines: {node: '>=18'}
@@ -115,6 +298,14 @@ packages:
which: 2.0.2
dev: true
+ /detect-libc@1.0.3:
+ resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
+ engines: {node: '>=0.10'}
+ hasBin: true
+ requiresBuild: true
+ dev: true
+ optional: true
+
/eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true
@@ -132,6 +323,15 @@ packages:
engines: {node: '>=6'}
dev: true
+ /fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+ requiresBuild: true
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+ optional: true
+
/foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
@@ -162,11 +362,38 @@ packages:
engines: {node: '>=8'}
dev: true
+ /immutable@5.1.4:
+ resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==}
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
/is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
dev: true
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ requiresBuild: true
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+ optional: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
@@ -183,6 +410,16 @@ packages:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
dev: true
+ /micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+ requiresBuild: true
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+ dev: true
+ optional: true
+
/minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -195,6 +432,12 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
dev: true
+ /node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
/package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
dev: true
@@ -212,6 +455,18 @@ packages:
minipass: 7.1.2
dev: true
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+ dev: true
+
/require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -230,6 +485,236 @@ packages:
tslib: 2.8.1
dev: true
+ /sass-embedded-all-unknown@1.93.3:
+ resolution: {integrity: sha512-3okGgnE41eg+CPLtAPletu6nQ4N0ij7AeW+Sl5Km4j29XcmqZQeFwYjHe1AlKTEgLi/UAONk1O8i8/lupeKMbw==}
+ cpu: ['!arm', '!arm64', '!riscv64', '!x64']
+ requiresBuild: true
+ dependencies:
+ sass: 1.93.3
+ dev: true
+ optional: true
+
+ /sass-embedded-android-arm64@1.93.3:
+ resolution: {integrity: sha512-uqUl3Kt1IqdGVAcAdbmC+NwuUJy8tM+2ZnB7/zrt6WxWVShVCRdFnWR9LT8HJr7eJN7AU8kSXxaVX/gedanPsg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-android-arm@1.93.3:
+ resolution: {integrity: sha512-8xOw9bywfOD6Wv24BgCmgjkk6tMrsOTTHcb28KDxeJtFtoxiUyMbxo0vChpPAfp2Hyg2tFFKS60s0s4JYk+Raw==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-android-riscv64@1.93.3:
+ resolution: {integrity: sha512-2jNJDmo+3qLocjWqYbXiBDnfgwrUeZgZFHJIwAefU7Fn66Ot7rsXl+XPwlokaCbTpj7eMFIqsRAZ/uDueXNCJg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [riscv64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-android-x64@1.93.3:
+ resolution: {integrity: sha512-y0RoAU6ZenQFcjM9PjQd3cRqRTjqwSbtWLL/p68y2oFyh0QGN0+LQ826fc0ZvU/AbqCsAizkqjzOn6cRZJxTTQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-darwin-arm64@1.93.3:
+ resolution: {integrity: sha512-7zb/hpdMOdKteK17BOyyypemglVURd1Hdz6QGsggy60aUFfptTLQftLRg8r/xh1RbQAUKWFbYTNaM47J9yPxYg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-darwin-x64@1.93.3:
+ resolution: {integrity: sha512-Ek1Vp8ZDQEe327Lz0b7h3hjvWH3u9XjJiQzveq74RPpJQ2q6d9LfWpjiRRohM4qK6o4XOHw1X10OMWPXJtdtWg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-arm64@1.93.3:
+ resolution: {integrity: sha512-RBrHWgfd8Dd8w4fbmdRVXRrhh8oBAPyeWDTKAWw8ZEmuXfVl4ytjDuyxaVilh6rR1xTRTNpbaA/YWApBlLrrNw==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: glibc
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-arm@1.93.3:
+ resolution: {integrity: sha512-yeiv2y+dp8B4wNpd3+JsHYD0mvpXSfov7IGyQ1tMIR40qv+ROkRqYiqQvAOXf76Qwh4Y9OaYZtLpnsPjfeq6mA==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: glibc
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-musl-arm64@1.93.3:
+ resolution: {integrity: sha512-PS829l+eUng+9W4PFclXGb4uA2+965NHV3/Sa5U7qTywjeeUUYTZg70dJHSqvhrBEfCc2XJABeW3adLJbyQYkw==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: musl
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-musl-arm@1.93.3:
+ resolution: {integrity: sha512-fU0fwAwbp7sBE3h5DVU5UPzvaLg7a4yONfFWkkcCp6ZrOiPuGRHXXYriWQ0TUnWy4wE+svsVuWhwWgvlb/tkKg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: musl
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-musl-riscv64@1.93.3:
+ resolution: {integrity: sha512-cK1oBY+FWQquaIGEeQ5H74KTO8cWsSWwXb/WaildOO9U6wmUypTgUYKQ0o5o/29nZbWWlM1PHuwVYTSnT23Jjg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [riscv64]
+ os: [linux]
+ libc: musl
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-musl-x64@1.93.3:
+ resolution: {integrity: sha512-A7wkrsHu2/I4Zpa0NMuPGkWDVV7QGGytxGyUq3opSXgAexHo/vBPlGoDXoRlSdex0cV+aTMRPjoGIfdmNlHwyg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: musl
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-riscv64@1.93.3:
+ resolution: {integrity: sha512-vWkW1+HTF5qcaHa6hO80gx/QfB6GGjJUP0xLbnAoY4pwEnw5ulGv6RM8qYr8IDhWfVt/KH+lhJ2ZFxnJareisQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [riscv64]
+ os: [linux]
+ libc: glibc
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-linux-x64@1.93.3:
+ resolution: {integrity: sha512-k6uFxs+e5jSuk1Y0niCwuq42F9ZC5UEP7P+RIOurIm8w/5QFa0+YqeW+BPWEW5M1FqVOsNZH3qGn4ahqvAEjPA==}
+ engines: {node: '>=14.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: glibc
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-unknown-all@1.93.3:
+ resolution: {integrity: sha512-o5wj2rLpXH0C+GJKt/VpWp6AnMsCCbfFmnMAttcrsa+U3yrs/guhZ3x55KAqqUsE8F47e3frbsDL+1OuQM5DAA==}
+ os: ['!android', '!darwin', '!linux', '!win32']
+ requiresBuild: true
+ dependencies:
+ sass: 1.93.3
+ dev: true
+ optional: true
+
+ /sass-embedded-win32-arm64@1.93.3:
+ resolution: {integrity: sha512-0dOfT9moy9YmBolodwYYXtLwNr4jL4HQC9rBfv6mVrD7ud8ue2kDbn+GVzj1hEJxvEexVSmDCf7MHUTLcGs9xQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded-win32-x64@1.93.3:
+ resolution: {integrity: sha512-wHFVfxiS9hU/sNk7KReD+lJWRp3R0SLQEX4zfOnRP2zlvI2X4IQR5aZr9GNcuMP6TmNpX0nQPZTegS8+h9RrEg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /sass-embedded@1.93.3:
+ resolution: {integrity: sha512-+VUy01yfDqNmIVMd/LLKl2TTtY0ovZN0rTonh+FhKr65mFwIYgU9WzgIZKS7U9/SPCQvWTsTGx9jyt+qRm/XFw==}
+ engines: {node: '>=16.0.0'}
+ hasBin: true
+ dependencies:
+ '@bufbuild/protobuf': 2.10.1
+ buffer-builder: 0.2.0
+ colorjs.io: 0.5.2
+ immutable: 5.1.4
+ rxjs: 7.8.2
+ supports-color: 8.1.1
+ sync-child-process: 1.0.2
+ varint: 6.0.0
+ optionalDependencies:
+ sass-embedded-all-unknown: 1.93.3
+ sass-embedded-android-arm: 1.93.3
+ sass-embedded-android-arm64: 1.93.3
+ sass-embedded-android-riscv64: 1.93.3
+ sass-embedded-android-x64: 1.93.3
+ sass-embedded-darwin-arm64: 1.93.3
+ sass-embedded-darwin-x64: 1.93.3
+ sass-embedded-linux-arm: 1.93.3
+ sass-embedded-linux-arm64: 1.93.3
+ sass-embedded-linux-musl-arm: 1.93.3
+ sass-embedded-linux-musl-arm64: 1.93.3
+ sass-embedded-linux-musl-riscv64: 1.93.3
+ sass-embedded-linux-musl-x64: 1.93.3
+ sass-embedded-linux-riscv64: 1.93.3
+ sass-embedded-linux-x64: 1.93.3
+ sass-embedded-unknown-all: 1.93.3
+ sass-embedded-win32-arm64: 1.93.3
+ sass-embedded-win32-x64: 1.93.3
+ dev: true
+
+ /sass@1.93.3:
+ resolution: {integrity: sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ chokidar: 4.0.3
+ immutable: 5.1.4
+ source-map-js: 1.2.1
+ optionalDependencies:
+ '@parcel/watcher': 2.5.1
+ dev: true
+ optional: true
+
+ /sass@1.94.2:
+ resolution: {integrity: sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ chokidar: 4.0.3
+ immutable: 5.1.4
+ source-map-js: 1.2.1
+ optionalDependencies:
+ '@parcel/watcher': 2.5.1
+ dev: true
+
/shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -252,6 +737,11 @@ packages:
engines: {node: '>=14'}
dev: true
+ /source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -298,6 +788,27 @@ packages:
has-flag: 4.0.0
dev: true
+ /sync-child-process@1.0.2:
+ resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==}
+ engines: {node: '>=16.0.0'}
+ dependencies:
+ sync-message-port: 1.1.3
+ dev: true
+
+ /sync-message-port@1.1.3:
+ resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
+ engines: {node: '>=16.0.0'}
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ requiresBuild: true
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+ optional: true
+
/tree-kill@1.2.2:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
@@ -307,6 +818,10 @@ packages:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
dev: true
+ /varint@6.0.0:
+ resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
+ dev: true
+
/which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}