히스토리 패널 UI 작업 완료
- T-008 태스크 완료: 히스토리 패널 UI 마크업 구현 (슬라이드 인) - 히스토리, UNDO, 전송하기 버튼을 세로로 균등 간격 배치 - Tailwind CSS v3/v4 버전 충돌 문제 해결 - v4 패키지 완전 제거 (@tailwindcss/postcss 등) - PostCSS 설정을 v3 방식으로 수정 - CSS 파일에서 수동 클래스 정의 제거 - Vite 캐시 완전 삭제로 설정 변경 반영 - 히스토리 패널 기능 개선 - 우측 슬라이드 인 애니메이션 - 파일 업로드 시에만 표시 - 상태별 아이콘과 시간순 로그 리스트 - 재적용 및 전체 삭제 기능 - 새로운 rule 파일 생성: tailwind-css-management.mdc
This commit is contained in:
5
.cursor/rules/tailwind-css-management.mdc
Normal file
5
.cursor/rules/tailwind-css-management.mdc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
description:
|
||||||
|
globs:
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
411
package-lock.json
generated
411
package-lock.json
generated
@@ -9,7 +9,6 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.10",
|
|
||||||
"@univerjs/core": "^0.8.2",
|
"@univerjs/core": "^0.8.2",
|
||||||
"@univerjs/design": "^0.8.2",
|
"@univerjs/design": "^0.8.2",
|
||||||
"@univerjs/docs": "^0.8.2",
|
"@univerjs/docs": "^0.8.2",
|
||||||
@@ -79,6 +78,7 @@
|
|||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||||
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||||
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
@@ -1185,18 +1186,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@isaacs/fs-minipass": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"minipass": "^7.0.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jest/diff-sequences": {
|
"node_modules/@jest/diff-sequences": {
|
||||||
"version": "30.0.1",
|
"version": "30.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
|
||||||
@@ -1467,6 +1456,7 @@
|
|||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||||
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
|
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/set-array": "^1.2.1",
|
"@jridgewell/set-array": "^1.2.1",
|
||||||
@@ -1481,6 +1471,7 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@@ -1490,6 +1481,7 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@@ -1499,12 +1491,14 @@
|
|||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.25",
|
"version": "0.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
@@ -2758,279 +2752,6 @@
|
|||||||
"@sinonjs/commons": "^3.0.0"
|
"@sinonjs/commons": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/node": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@ampproject/remapping": "^2.3.0",
|
|
||||||
"enhanced-resolve": "^5.18.1",
|
|
||||||
"jiti": "^2.4.2",
|
|
||||||
"lightningcss": "1.30.1",
|
|
||||||
"magic-string": "^0.30.17",
|
|
||||||
"source-map-js": "^1.2.1",
|
|
||||||
"tailwindcss": "4.1.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/node/node_modules/tailwindcss": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"detect-libc": "^2.0.4",
|
|
||||||
"tar": "^7.4.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@tailwindcss/oxide-android-arm64": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-darwin-x64": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.10",
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==",
|
|
||||||
"bundleDependencies": [
|
|
||||||
"@napi-rs/wasm-runtime",
|
|
||||||
"@emnapi/core",
|
|
||||||
"@emnapi/runtime",
|
|
||||||
"@tybys/wasm-util",
|
|
||||||
"@emnapi/wasi-threads",
|
|
||||||
"tslib"
|
|
||||||
],
|
|
||||||
"cpu": [
|
|
||||||
"wasm32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/core": "^1.4.3",
|
|
||||||
"@emnapi/runtime": "^1.4.3",
|
|
||||||
"@emnapi/wasi-threads": "^1.0.2",
|
|
||||||
"@napi-rs/wasm-runtime": "^0.2.10",
|
|
||||||
"@tybys/wasm-util": "^0.9.0",
|
|
||||||
"tslib": "^2.8.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@alloc/quick-lru": "^5.2.0",
|
|
||||||
"@tailwindcss/node": "4.1.10",
|
|
||||||
"@tailwindcss/oxide": "4.1.10",
|
|
||||||
"postcss": "^8.4.41",
|
|
||||||
"tailwindcss": "4.1.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/tailwindcss": {
|
|
||||||
"version": "4.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz",
|
|
||||||
"integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@testing-library/dom": {
|
"node_modules/@testing-library/dom": {
|
||||||
"version": "10.4.0",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
|
||||||
@@ -7765,15 +7486,6 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chownr": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
|
||||||
"license": "BlueOak-1.0.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ci-info": {
|
"node_modules/ci-info": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz",
|
||||||
@@ -8205,7 +7917,10 @@
|
|||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||||
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -8341,19 +8056,6 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
|
||||||
"version": "5.18.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
|
|
||||||
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"graceful-fs": "^4.2.4",
|
|
||||||
"tapable": "^2.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/entities": {
|
"node_modules/entities": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||||
@@ -9984,7 +9686,10 @@
|
|||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
||||||
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"jiti": "lib/jiti-cli.mjs"
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
}
|
}
|
||||||
@@ -10175,7 +9880,10 @@
|
|||||||
"version": "1.30.1",
|
"version": "1.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||||
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-libc": "^2.0.3"
|
"detect-libc": "^2.0.3"
|
||||||
},
|
},
|
||||||
@@ -10206,11 +9914,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10226,11 +9936,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10246,11 +9958,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10266,11 +9980,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10286,11 +10002,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10306,11 +10024,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10326,11 +10046,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10346,11 +10068,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10366,11 +10090,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10386,11 +10112,13 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -10647,6 +10375,7 @@
|
|||||||
"version": "0.30.17",
|
"version": "0.30.17",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
||||||
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
|
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
@@ -10750,38 +10479,12 @@
|
|||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minizlib": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
|
||||||
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"minipass": "^7.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mkdirp": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"mkdirp": "dist/cjs/src/bin.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/monaco-editor": {
|
"node_modules/monaco-editor": {
|
||||||
"version": "0.52.2",
|
"version": "0.52.2",
|
||||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
|
||||||
@@ -11138,6 +10841,7 @@
|
|||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
@@ -11177,6 +10881,7 @@
|
|||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||||
|
"devOptional": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -12315,6 +12020,7 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -12672,32 +12378,6 @@
|
|||||||
"jiti": "bin/jiti.js"
|
"jiti": "bin/jiti.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
|
||||||
"version": "2.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
|
|
||||||
"integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tar": {
|
|
||||||
"version": "7.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
|
||||||
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"@isaacs/fs-minipass": "^4.0.0",
|
|
||||||
"chownr": "^3.0.0",
|
|
||||||
"minipass": "^7.1.2",
|
|
||||||
"minizlib": "^3.0.1",
|
|
||||||
"mkdirp": "^3.0.1",
|
|
||||||
"yallist": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tar-stream": {
|
"node_modules/tar-stream": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||||
@@ -12728,15 +12408,6 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tar/node_modules/yallist": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
|
||||||
"license": "BlueOak-1.0.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/thenify": {
|
"node_modules/thenify": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
"test:coverage": "vitest run --coverage"
|
"test:coverage": "vitest run --coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.10",
|
|
||||||
"@univerjs/core": "^0.8.2",
|
"@univerjs/core": "^0.8.2",
|
||||||
"@univerjs/design": "^0.8.2",
|
"@univerjs/design": "^0.8.2",
|
||||||
"@univerjs/docs": "^0.8.2",
|
"@univerjs/docs": "^0.8.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
'@tailwindcss/postcss': {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -15,10 +15,12 @@ import "@univerjs/presets/lib/styles/preset-sheets-core.css";
|
|||||||
import { cn } from "../../lib/utils";
|
import { cn } from "../../lib/utils";
|
||||||
import LuckyExcel from "@zwight/luckyexcel";
|
import LuckyExcel from "@zwight/luckyexcel";
|
||||||
import PromptInput from "./PromptInput";
|
import PromptInput from "./PromptInput";
|
||||||
|
import HistoryPanel from "../ui/historyPanel";
|
||||||
import { useAppStore } from "../../stores/useAppStore";
|
import { useAppStore } from "../../stores/useAppStore";
|
||||||
import { rangeToAddress } from "../../utils/cellUtils";
|
import { rangeToAddress } from "../../utils/cellUtils";
|
||||||
import { CellSelectionHandler } from "../../utils/cellSelectionHandler";
|
import { CellSelectionHandler } from "../../utils/cellSelectionHandler";
|
||||||
import { aiProcessor } from "../../utils/aiProcessor";
|
import { aiProcessor } from "../../utils/aiProcessor";
|
||||||
|
import type { HistoryEntry } from "../../types/ai";
|
||||||
|
|
||||||
// 전역 고유 키 생성
|
// 전역 고유 키 생성
|
||||||
const GLOBAL_UNIVER_KEY = "__GLOBAL_UNIVER_INSTANCE__";
|
const GLOBAL_UNIVER_KEY = "__GLOBAL_UNIVER_INSTANCE__";
|
||||||
@@ -337,6 +339,52 @@ const TestSheetViewer: React.FC = () => {
|
|||||||
// CellSelectionHandler 인스턴스 생성
|
// CellSelectionHandler 인스턴스 생성
|
||||||
const cellSelectionHandler = useRef(new CellSelectionHandler());
|
const cellSelectionHandler = useRef(new CellSelectionHandler());
|
||||||
|
|
||||||
|
// 히스토리 관련 상태 추가
|
||||||
|
const [isHistoryOpen, setIsHistoryOpen] = useState(false);
|
||||||
|
const [history, setHistory] = useState<HistoryEntry[]>([]);
|
||||||
|
|
||||||
|
// 히스토리 관련 핸들러
|
||||||
|
const handleHistoryToggle = () => {
|
||||||
|
console.log("🔄 히스토리 토글:", !isHistoryOpen);
|
||||||
|
setIsHistoryOpen(!isHistoryOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHistoryClear = () => {
|
||||||
|
if (window.confirm("모든 히스토리를 삭제하시겠습니까?")) {
|
||||||
|
setHistory([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHistoryReapply = (entry: HistoryEntry) => {
|
||||||
|
// 히스토리 항목 재적용 로직
|
||||||
|
setPrompt(entry.prompt);
|
||||||
|
console.log("🔄 히스토리 재적용:", entry);
|
||||||
|
// TODO: 실제 액션 재실행 로직 구현
|
||||||
|
};
|
||||||
|
|
||||||
|
// 새 히스토리 항목 추가 함수
|
||||||
|
const addHistoryEntry = (
|
||||||
|
prompt: string,
|
||||||
|
range: string,
|
||||||
|
sheetName: string,
|
||||||
|
actions: any[],
|
||||||
|
status: "success" | "error" | "pending",
|
||||||
|
error?: string,
|
||||||
|
) => {
|
||||||
|
const newEntry: HistoryEntry = {
|
||||||
|
id: `history-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
||||||
|
timestamp: new Date(),
|
||||||
|
prompt,
|
||||||
|
range,
|
||||||
|
sheetName,
|
||||||
|
actions,
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
|
||||||
|
setHistory((prev) => [newEntry, ...prev]); // 최신 항목을 맨 위에
|
||||||
|
};
|
||||||
|
|
||||||
// Univer 초기화 함수 (Presets 기반)
|
// Univer 초기화 함수 (Presets 기반)
|
||||||
const initializeUniver = useCallback(
|
const initializeUniver = useCallback(
|
||||||
async (workbookData?: any) => {
|
async (workbookData?: any) => {
|
||||||
@@ -718,7 +766,23 @@ const TestSheetViewer: React.FC = () => {
|
|||||||
<div style={{ height: "1rem" }} />
|
<div style={{ height: "1rem" }} />
|
||||||
|
|
||||||
{/* 프롬프트 입력창 - Univer 하단에 이어서 */}
|
{/* 프롬프트 입력창 - Univer 하단에 이어서 */}
|
||||||
<PromptInput value={prompt} onChange={(e) => setPrompt(e.target.value)} />
|
<PromptInput
|
||||||
|
value={prompt}
|
||||||
|
onChange={(e) => setPrompt(e.target.value)}
|
||||||
|
onHistoryToggle={handleHistoryToggle}
|
||||||
|
historyCount={history.length}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 히스토리 패널 - 파일이 업로드된 후에만 표시 */}
|
||||||
|
{!showUploadOverlay && (
|
||||||
|
<HistoryPanel
|
||||||
|
isOpen={isHistoryOpen}
|
||||||
|
onClose={() => setIsHistoryOpen(false)}
|
||||||
|
history={history}
|
||||||
|
onReapply={handleHistoryReapply}
|
||||||
|
onClear={handleHistoryClear}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 파일 업로드 오버레이 - 레이어 분리 */}
|
{/* 파일 업로드 오버레이 - 레이어 분리 */}
|
||||||
{showUploadOverlay && (
|
{showUploadOverlay && (
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ interface PromptInputProps {
|
|||||||
onExecute?: () => void;
|
onExecute?: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
|
onHistoryToggle?: () => void;
|
||||||
|
historyCount?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,6 +26,8 @@ const PromptInput: React.FC<PromptInputProps> = ({
|
|||||||
onExecute,
|
onExecute,
|
||||||
disabled = true,
|
disabled = true,
|
||||||
maxLength = 500,
|
maxLength = 500,
|
||||||
|
onHistoryToggle,
|
||||||
|
historyCount,
|
||||||
}) => {
|
}) => {
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
const [showCellInsertFeedback, setShowCellInsertFeedback] = useState(false);
|
const [showCellInsertFeedback, setShowCellInsertFeedback] = useState(false);
|
||||||
@@ -182,8 +186,42 @@ const PromptInput: React.FC<PromptInputProps> = ({
|
|||||||
rows={5}
|
rows={5}
|
||||||
/>
|
/>
|
||||||
<div style={{ width: "1rem" }} />
|
<div style={{ width: "1rem" }} />
|
||||||
|
|
||||||
|
{/* 버튼들을 세로로 배치 */}
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
{/* 히스토리 버튼 - 맨 위 */}
|
||||||
|
{onHistoryToggle && (
|
||||||
<button
|
<button
|
||||||
className="ml-2 px-6 py-2 rounded-lg text-white font-semibold text-base shadow transition disabled:opacity-60 disabled:cursor-not-allowed"
|
className="px-4 py-2 rounded-lg text-gray-600 border border-gray-300 hover:bg-gray-50 font-semibold text-base shadow transition disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-center gap-2"
|
||||||
|
onClick={onHistoryToggle}
|
||||||
|
disabled={isProcessing}
|
||||||
|
aria-label="작업 히스토리 보기"
|
||||||
|
>
|
||||||
|
📝
|
||||||
|
{historyCount !== undefined && historyCount > 0 && (
|
||||||
|
<span className="text-xs bg-blue-500 text-white rounded-full px-2 py-0.5 min-w-[20px] h-5 flex items-center justify-center">
|
||||||
|
{historyCount > 99 ? "99+" : historyCount}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* UNDO 버튼 - 중간 */}
|
||||||
|
<button
|
||||||
|
className="px-4 py-2 rounded-lg text-gray-600 border border-gray-300 hover:bg-gray-50 font-semibold text-base shadow transition disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-center gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
// TODO: UNDO 기능 구현
|
||||||
|
console.log("🔄 UNDO 버튼 클릭");
|
||||||
|
}}
|
||||||
|
disabled={isProcessing}
|
||||||
|
aria-label="실행 취소"
|
||||||
|
>
|
||||||
|
↶
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 전송하기 버튼 - 맨 아래 */}
|
||||||
|
<button
|
||||||
|
className="px-6 py-2 rounded-lg text-white font-semibold text-base shadow transition disabled:opacity-60 disabled:cursor-not-allowed"
|
||||||
style={{
|
style={{
|
||||||
background: isProcessing
|
background: isProcessing
|
||||||
? "#6b7280"
|
? "#6b7280"
|
||||||
@@ -195,6 +233,7 @@ const PromptInput: React.FC<PromptInputProps> = ({
|
|||||||
{isProcessing ? "처리 중..." : "전송하기"}
|
{isProcessing ? "처리 중..." : "전송하기"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="w-full max-w-3xl flex justify-between items-center mt-1 px-1">
|
<div className="w-full max-w-3xl flex justify-between items-center mt-1 px-1">
|
||||||
<span className="text-xs text-gray-500">
|
<span className="text-xs text-gray-500">
|
||||||
Press Enter to send, Shift+Enter for new line | 시트에서 셀 클릭하여
|
Press Enter to send, Shift+Enter for new line | 시트에서 셀 클릭하여
|
||||||
|
|||||||
287
src/components/ui/historyPanel.tsx
Normal file
287
src/components/ui/historyPanel.tsx
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "./card";
|
||||||
|
import { Button } from "./button";
|
||||||
|
import type { HistoryPanelProps, HistoryEntry } from "../../types/ai";
|
||||||
|
import { cn } from "../../lib/utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 히스토리 패널 컴포넌트
|
||||||
|
* 우측에서 슬라이드 인하는 방식으로 작동
|
||||||
|
*/
|
||||||
|
const HistoryPanel: React.FC<HistoryPanelProps> = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
history,
|
||||||
|
onReapply,
|
||||||
|
onClear,
|
||||||
|
}) => {
|
||||||
|
// 키보드 접근성: Escape 키로 패널 닫기
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (event.key === "Escape" && isOpen) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
|
// 포커스 트랩을 위해 패널에 포커스 설정
|
||||||
|
const panel = document.getElementById("history-panel");
|
||||||
|
if (panel) {
|
||||||
|
panel.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [isOpen, onClose]);
|
||||||
|
|
||||||
|
// 시간 포맷팅 함수
|
||||||
|
const formatTime = (date: Date): string => {
|
||||||
|
return new Intl.DateTimeFormat("ko-KR", {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
}).format(date);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 날짜 포맷팅 함수
|
||||||
|
const formatDate = (date: Date): string => {
|
||||||
|
const today = new Date();
|
||||||
|
const yesterday = new Date(today);
|
||||||
|
yesterday.setDate(yesterday.getDate() - 1);
|
||||||
|
|
||||||
|
if (date.toDateString() === today.toDateString()) {
|
||||||
|
return "오늘";
|
||||||
|
} else if (date.toDateString() === yesterday.toDateString()) {
|
||||||
|
return "어제";
|
||||||
|
} else {
|
||||||
|
return new Intl.DateTimeFormat("ko-KR", {
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
}).format(date);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 상태별 아이콘 및 색상
|
||||||
|
const getStatusIcon = (status: HistoryEntry["status"]) => {
|
||||||
|
switch (status) {
|
||||||
|
case "success":
|
||||||
|
return <span className="text-green-500">✅</span>;
|
||||||
|
case "error":
|
||||||
|
return <span className="text-red-500">❌</span>;
|
||||||
|
case "pending":
|
||||||
|
return <span className="text-yellow-500 animate-pulse">⏳</span>;
|
||||||
|
default:
|
||||||
|
return <span className="text-gray-400">❓</span>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 액션 요약 생성
|
||||||
|
const getActionSummary = (actions: HistoryEntry["actions"]): string => {
|
||||||
|
if (actions.length === 0) return "액션 없음";
|
||||||
|
|
||||||
|
const actionTypes = actions.map((action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case "formula":
|
||||||
|
return "수식";
|
||||||
|
case "style":
|
||||||
|
return "스타일";
|
||||||
|
case "chart":
|
||||||
|
return "차트";
|
||||||
|
default:
|
||||||
|
return "기타";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return `${actionTypes.join(", ")} (${actions.length}개)`;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* 백드롭 오버레이 */}
|
||||||
|
{isOpen && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 bg-black bg-opacity-60 z-40 transition-opacity duration-300"
|
||||||
|
onClick={onClose}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 히스토리 패널 */}
|
||||||
|
<div
|
||||||
|
id="history-panel"
|
||||||
|
className={cn(
|
||||||
|
"bg-white shadow-2xl z-50",
|
||||||
|
"transform transition-transform duration-300 ease-in-out",
|
||||||
|
"flex flex-col border-l border-gray-200",
|
||||||
|
isOpen ? "translate-x-0" : "translate-x-full",
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
top: 65,
|
||||||
|
right: 0,
|
||||||
|
height: "100vh",
|
||||||
|
width: "384px", // w-96 = 384px
|
||||||
|
backgroundColor: "#ffffff",
|
||||||
|
zIndex: 50,
|
||||||
|
}}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="history-panel-title"
|
||||||
|
aria-describedby="history-panel-description"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
{/* 헤더 */}
|
||||||
|
<div className="flex-shrink-0 border-b border-gray-200 p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h2
|
||||||
|
id="history-panel-title"
|
||||||
|
className="text-lg font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
📝 작업 히스토리
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
id="history-panel-description"
|
||||||
|
className="text-sm text-gray-500 mt-1"
|
||||||
|
>
|
||||||
|
AI 프롬프트 실행 기록 ({history.length}개)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 닫기 버튼 */}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={onClose}
|
||||||
|
aria-label="히스토리 패널 닫기"
|
||||||
|
className="text-gray-400 hover:text-gray-600"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 전체 삭제 버튼 */}
|
||||||
|
{history.length > 0 && onClear && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={onClear}
|
||||||
|
className="w-full text-red-600 border-red-200 hover:bg-red-50"
|
||||||
|
aria-label="모든 히스토리 삭제"
|
||||||
|
>
|
||||||
|
🗑️ 전체 삭제
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 히스토리 목록 */}
|
||||||
|
<div className="flex-1 overflow-y-auto">
|
||||||
|
{history.length === 0 ? (
|
||||||
|
// 빈 상태
|
||||||
|
<div className="flex flex-col items-center justify-center h-full text-gray-500">
|
||||||
|
<div className="text-4xl mb-4">📋</div>
|
||||||
|
<p className="text-center px-4">
|
||||||
|
아직 실행된 AI 프롬프트가 없습니다.
|
||||||
|
<br />
|
||||||
|
<span className="text-sm text-gray-400">
|
||||||
|
프롬프트를 입력하고 실행해보세요!
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
// 히스토리 항목들
|
||||||
|
<div className="p-4 space-y-3">
|
||||||
|
{history.map((entry, index) => (
|
||||||
|
<Card
|
||||||
|
key={entry.id}
|
||||||
|
className={cn(
|
||||||
|
"transition-all duration-200 hover:shadow-md",
|
||||||
|
entry.status === "error" && "border-red-200 bg-red-50",
|
||||||
|
entry.status === "success" &&
|
||||||
|
"border-green-200 bg-green-50",
|
||||||
|
entry.status === "pending" &&
|
||||||
|
"border-yellow-200 bg-yellow-50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
{getStatusIcon(entry.status)}
|
||||||
|
<div className="text-xs text-gray-500">
|
||||||
|
{formatDate(entry.timestamp)}{" "}
|
||||||
|
{formatTime(entry.timestamp)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-400">
|
||||||
|
#{history.length - index}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="pt-0">
|
||||||
|
{/* 프롬프트 */}
|
||||||
|
<div className="mb-3">
|
||||||
|
<p className="text-sm font-medium text-gray-900 mb-1">
|
||||||
|
프롬프트:
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-700 bg-gray-100 rounded-md p-2 break-words">
|
||||||
|
{entry.prompt}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 범위 및 시트 정보 */}
|
||||||
|
<div className="mb-3 text-xs text-gray-600">
|
||||||
|
<span className="font-medium">범위:</span> {entry.range} |
|
||||||
|
<span className="font-medium ml-1">시트:</span>{" "}
|
||||||
|
{entry.sheetName}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 액션 요약 */}
|
||||||
|
<div className="mb-3">
|
||||||
|
<p className="text-xs text-gray-600">
|
||||||
|
<span className="font-medium">실행된 액션:</span>{" "}
|
||||||
|
{getActionSummary(entry.actions)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 에러 메시지 */}
|
||||||
|
{entry.status === "error" && entry.error && (
|
||||||
|
<div className="mb-3 p-2 bg-red-100 border border-red-200 rounded-md">
|
||||||
|
<p className="text-xs text-red-700">
|
||||||
|
<span className="font-medium">오류:</span>{" "}
|
||||||
|
{entry.error}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 재적용 버튼 */}
|
||||||
|
{entry.status === "success" && onReapply && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => onReapply(entry)}
|
||||||
|
className="w-full text-blue-600 border-blue-200 hover:bg-blue-50"
|
||||||
|
aria-label={`프롬프트 재적용: ${entry.prompt.slice(0, 20)}...`}
|
||||||
|
>
|
||||||
|
🔄 다시 적용
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HistoryPanel;
|
||||||
148
src/index.css
148
src/index.css
@@ -11,109 +11,6 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
/* 필요한 색상 클래스들 추가 */
|
|
||||||
.text-gray-500 { color: #6b7280; }
|
|
||||||
.text-gray-600 { color: #4b5563; }
|
|
||||||
.text-gray-900 { color: #111827; }
|
|
||||||
.text-blue-600 { color: #2563eb; }
|
|
||||||
.text-blue-700 { color: #1d4ed8; }
|
|
||||||
.text-blue-800 { color: #1e40af; }
|
|
||||||
|
|
||||||
.bg-gray-50 { background-color: #f9fafb; }
|
|
||||||
.bg-blue-50 { background-color: #eff6ff; }
|
|
||||||
.bg-blue-100 { background-color: #dbeafe; }
|
|
||||||
.bg-blue-200 { background-color: #bfdbfe; }
|
|
||||||
|
|
||||||
.border-gray-300 { border-color: #d1d5db; }
|
|
||||||
.border-blue-200 { border-color: #bfdbfe; }
|
|
||||||
.border-blue-400 { border-color: #60a5fa; }
|
|
||||||
.border-blue-500 { border-color: #3b82f6; }
|
|
||||||
|
|
||||||
.hover\:border-blue-400:hover { border-color: #60a5fa; }
|
|
||||||
.hover\:bg-blue-50:hover { background-color: #eff6ff; }
|
|
||||||
|
|
||||||
.focus\:ring-blue-500:focus {
|
|
||||||
--tw-ring-color: #3b82f6;
|
|
||||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 추가 유틸리티 클래스들 */
|
|
||||||
.max-w-7xl { max-width: 80rem; }
|
|
||||||
.max-w-2xl { max-width: 42rem; }
|
|
||||||
.max-w-lg { max-width: 32rem; }
|
|
||||||
.max-w-md { max-width: 28rem; }
|
|
||||||
|
|
||||||
.h-16 { height: 4rem; }
|
|
||||||
.h-20 { height: 5rem; }
|
|
||||||
.h-24 { height: 6rem; }
|
|
||||||
.w-20 { width: 5rem; }
|
|
||||||
.w-24 { width: 6rem; }
|
|
||||||
|
|
||||||
.h-6 { height: 1.5rem; }
|
|
||||||
.w-6 { width: 1.5rem; }
|
|
||||||
.h-10 { height: 2.5rem; }
|
|
||||||
.w-10 { width: 2.5rem; }
|
|
||||||
.h-12 { height: 3rem; }
|
|
||||||
.w-12 { width: 3rem; }
|
|
||||||
|
|
||||||
.space-x-4 > :not([hidden]) ~ :not([hidden]) { margin-left: 1rem; }
|
|
||||||
.space-x-2 > :not([hidden]) ~ :not([hidden]) { margin-left: 0.5rem; }
|
|
||||||
.space-y-1 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.25rem; }
|
|
||||||
.space-y-2 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.5rem; }
|
|
||||||
.space-y-4 > :not([hidden]) ~ :not([hidden]) { margin-top: 1rem; }
|
|
||||||
|
|
||||||
.p-3 { padding: 0.75rem; }
|
|
||||||
.p-4 { padding: 1rem; }
|
|
||||||
.p-8 { padding: 2rem; }
|
|
||||||
.p-12 { padding: 3rem; }
|
|
||||||
.px-4 { padding-left: 1rem; padding-right: 1rem; }
|
|
||||||
.py-8 { padding-top: 2rem; padding-bottom: 2rem; }
|
|
||||||
|
|
||||||
.mb-2 { margin-bottom: 0.5rem; }
|
|
||||||
.mb-3 { margin-bottom: 0.75rem; }
|
|
||||||
.mb-4 { margin-bottom: 1rem; }
|
|
||||||
.mb-6 { margin-bottom: 1.5rem; }
|
|
||||||
.mb-8 { margin-bottom: 2rem; }
|
|
||||||
.mt-6 { margin-top: 1.5rem; }
|
|
||||||
|
|
||||||
.text-xs { font-size: 0.75rem; line-height: 1rem; }
|
|
||||||
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
|
|
||||||
.text-base { font-size: 1rem; line-height: 1.5rem; }
|
|
||||||
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
|
|
||||||
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
|
|
||||||
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
|
|
||||||
.text-4xl { font-size: 2.25rem; line-height: 2.5rem; }
|
|
||||||
.text-6xl { font-size: 3.75rem; line-height: 1; }
|
|
||||||
|
|
||||||
.font-medium { font-weight: 500; }
|
|
||||||
.font-semibold { font-weight: 600; }
|
|
||||||
.font-bold { font-weight: 700; }
|
|
||||||
|
|
||||||
.rounded-lg { border-radius: 0.5rem; }
|
|
||||||
.rounded-md { border-radius: 0.375rem; }
|
|
||||||
|
|
||||||
.shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }
|
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
|
||||||
.sm\:px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.md\:h-24 { height: 6rem; }
|
|
||||||
.md\:w-24 { width: 6rem; }
|
|
||||||
.md\:h-12 { height: 3rem; }
|
|
||||||
.md\:w-12 { width: 3rem; }
|
|
||||||
.md\:p-12 { padding: 3rem; }
|
|
||||||
.md\:text-base { font-size: 1rem; line-height: 1.5rem; }
|
|
||||||
.md\:text-lg { font-size: 1.125rem; line-height: 1.75rem; }
|
|
||||||
.md\:text-2xl { font-size: 1.5rem; line-height: 2rem; }
|
|
||||||
.md\:text-6xl { font-size: 3.75rem; line-height: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.lg\:px-8 { padding-left: 2rem; padding-right: 2rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 전역 스타일 */
|
/* 전역 스타일 */
|
||||||
html, body, #root {
|
html, body, #root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -199,61 +96,53 @@ html, body, #root {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0% {
|
0%, 100% {
|
||||||
transform: scale(1);
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.2);
|
opacity: .5;
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 에러 메시지 스타일 */
|
/* 에러 메시지 스타일 */
|
||||||
.error-message {
|
.error-message {
|
||||||
|
color: #dc2626;
|
||||||
background-color: #fef2f2;
|
background-color: #fef2f2;
|
||||||
border: 1px solid #fecaca;
|
border: 1px solid #fecaca;
|
||||||
color: #dc2626;
|
border-radius: 0.375rem;
|
||||||
padding: 12px;
|
padding: 0.75rem;
|
||||||
border-radius: 6px;
|
margin: 0.5rem 0;
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 성공 메시지 스타일 */
|
/* 성공 메시지 스타일 */
|
||||||
.success-message {
|
.success-message {
|
||||||
|
color: #059669;
|
||||||
background-color: #f0fdf4;
|
background-color: #f0fdf4;
|
||||||
border: 1px solid #bbf7d0;
|
border: 1px solid #bbf7d0;
|
||||||
color: #16a34a;
|
border-radius: 0.375rem;
|
||||||
padding: 12px;
|
padding: 0.75rem;
|
||||||
border-radius: 6px;
|
margin: 0.5rem 0;
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 정보 메시지 스타일 */
|
/* 정보 메시지 스타일 */
|
||||||
.info-message {
|
.info-message {
|
||||||
|
color: #2563eb;
|
||||||
background-color: #eff6ff;
|
background-color: #eff6ff;
|
||||||
border: 1px solid #bfdbfe;
|
border: 1px solid #bfdbfe;
|
||||||
color: #2563eb;
|
border-radius: 0.375rem;
|
||||||
padding: 12px;
|
padding: 0.75rem;
|
||||||
border-radius: 6px;
|
margin: 0.5rem 0;
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 반응형 디자인 */
|
/* 모바일 반응형 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.file-upload-area {
|
.file-upload-area {
|
||||||
padding: 15px;
|
padding: 16px;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.univer-container {
|
.univer-container {
|
||||||
min-height: 400px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +151,7 @@ html, body, #root {
|
|||||||
.file-upload-area {
|
.file-upload-area {
|
||||||
border-color: #374151;
|
border-color: #374151;
|
||||||
background-color: #1f2937;
|
background-color: #1f2937;
|
||||||
|
color: #f9fafb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-upload-area:hover {
|
.file-upload-area:hover {
|
||||||
|
|||||||
@@ -48,3 +48,23 @@ export interface AIHistory {
|
|||||||
success: boolean;
|
success: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 히스토리 관련 타입 추가
|
||||||
|
export interface HistoryEntry {
|
||||||
|
id: string;
|
||||||
|
timestamp: Date;
|
||||||
|
prompt: string;
|
||||||
|
range: string;
|
||||||
|
sheetName: string;
|
||||||
|
actions: AIAction[];
|
||||||
|
status: "success" | "error" | "pending";
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryPanelProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
history: HistoryEntry[];
|
||||||
|
onReapply?: (entry: HistoryEntry) => void;
|
||||||
|
onClear?: () => void;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user