This commit is contained in:
Danilo Znamerovszkij
2025-09-27 15:31:19 +02:00
14 changed files with 1095 additions and 352 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
legacy-peer-deps=true

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
22.12.0

View File

@@ -39,92 +39,104 @@
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
/* background: #1b1b1b; */
background: linear-gradient(135deg, #1b1b1b 0%, #111111 100%);
"Helvetica Neue", Arial, sans-serif;
background: #1b1b1b;
overflow: hidden;
}
.app-container {
display: flex;
height: 100vh;
background: #1b1b1b;
}
.chart-container {
flex: 1;
position: relative;
width: 100%;
background: #1b1b1b;
}
#main {
width: 100%;
height: 100%;
background: transparent;
}
.nav-buttons {
position: fixed;
top: 20px;
left: 20px;
top: 24px;
left: 24px;
z-index: 1001;
display: flex;
gap: 10px;
gap: 12px;
flex-wrap: wrap;
align-items: flex-start;
}
.nav-buttons button {
background: rgba(252, 215, 113, 0.1);
border: 1px solid rgba(252, 215, 113, 0.3);
color: #fcd771;
padding: 8px 16px;
border-radius: 6px;
background: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.2);
color: #3b82f6;
padding: 10px 16px;
border-radius: 8px;
cursor: pointer;
font-size: 12px;
transition: all 0.3s ease;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
backdrop-filter: blur(10px);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.nav-buttons button:hover {
background: rgba(252, 215, 113, 0.2);
border-color: rgba(252, 215, 113, 0.5);
background: rgba(59, 130, 246, 0.15);
border-color: rgba(59, 130, 246, 0.3);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.nav-buttons button:focus {
outline: 2px solid rgba(59, 130, 246, 0.5);
outline-offset: 2px;
}
.search-container {
position: relative;
min-width: 300px;
min-width: 320px;
}
#theory-search {
width: 100%;
padding: 10px 16px;
background: rgba(252, 215, 113, 0.1);
border: 1px solid rgba(252, 215, 113, 0.3);
border-radius: 6px;
color: #fcd771;
padding: 12px 16px;
background: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.2);
border-radius: 8px;
color: #3b82f6;
font-size: 14px;
font-weight: 400;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
#theory-search::placeholder {
color: rgba(252, 215, 113, 0.6);
color: rgba(59, 130, 246, 0.6);
}
#theory-search:focus {
outline: none;
border-color: rgba(252, 215, 113, 0.5);
background: rgba(252, 215, 113, 0.15);
box-shadow: 0 0 0 2px rgba(252, 215, 113, 0.1);
border-color: rgba(59, 130, 246, 0.4);
background: rgba(59, 130, 246, 0.15);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.search-dropdown {
top: 100%;
left: 0;
right: 0;
background: rgba(3, 4, 94, 0.98);
border: 1px solid rgba(252, 215, 113, 0.3);
border-radius: 6px;
background: rgba(15, 23, 42, 0.95);
border: 1px solid rgba(59, 130, 246, 0.2);
border-radius: 8px;
margin-top: 4px;
max-height: 300px;
overflow-y: auto;
@@ -132,9 +144,9 @@
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s ease;
transition: all 0.2s ease;
backdrop-filter: blur(20px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.search-dropdown.visible {
@@ -146,7 +158,7 @@
.search-item {
padding: 12px 16px;
cursor: pointer;
border-bottom: 1px solid rgba(252, 215, 113, 0.1);
border-bottom: 1px solid rgba(59, 130, 246, 0.1);
transition: all 0.2s ease;
}
@@ -155,11 +167,11 @@
}
.search-item:hover {
background: rgba(252, 215, 113, 0.1);
background: rgba(59, 130, 246, 0.1);
}
.search-item-title {
color: #fcd771;
color: #f1f5f9;
font-size: 14px;
font-weight: 500;
margin-bottom: 4px;
@@ -167,9 +179,10 @@
}
.search-item-category {
color: rgba(252, 215, 113, 0.7);
color: #64748b;
font-size: 12px;
text-transform: capitalize;
font-weight: 400;
}
@media (max-width: 768px) {
@@ -183,6 +196,32 @@
left: 0;
justify-content: center;
margin-bottom: 20px;
padding: 16px;
}
.search-container {
min-width: 280px;
}
}
@media (max-width: 480px) {
.nav-buttons {
padding: 12px;
gap: 8px;
}
.nav-buttons button {
padding: 8px 12px;
font-size: 12px;
}
.search-container {
min-width: 240px;
}
#theory-search {
padding: 10px 12px;
font-size: 13px;
}
}
</style>

829
package-lock.json generated
View File

@@ -9,29 +9,386 @@
"version": "0.0.0",
"dependencies": {
"echarts": "^6.0.0",
"vite": "^5.4.0",
"vite-tsconfig-paths": "^5.1.4"
},
"devDependencies": {
"sass": "^1.91.0",
"typescript": "~5.8.3",
"vite": "^7.1.2"
"typescript": "~5.8.3"
},
"engines": {
"node": "22.x"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "4.6.1"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
"integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@parcel/watcher": {
@@ -92,6 +449,32 @@
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz",
"integrity": "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz",
"integrity": "sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz",
@@ -99,32 +482,239 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz",
"integrity": "sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz",
"integrity": "sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz",
"integrity": "sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz",
"integrity": "sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz",
"integrity": "sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz",
"integrity": "sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz",
"integrity": "sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz",
"integrity": "sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz",
"integrity": "sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz",
"integrity": "sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz",
"integrity": "sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz",
"integrity": "sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.1.tgz",
"integrity": "sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz",
"integrity": "sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz",
"integrity": "sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz",
"integrity": "sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz",
"integrity": "sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.3.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz",
"integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"undici-types": "~7.10.0"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
@@ -197,63 +787,41 @@
}
},
"node_modules/esbuild": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
"integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
"devOptional": true,
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.9",
"@esbuild/android-arm": "0.25.9",
"@esbuild/android-arm64": "0.25.9",
"@esbuild/android-x64": "0.25.9",
"@esbuild/darwin-arm64": "0.25.9",
"@esbuild/darwin-x64": "0.25.9",
"@esbuild/freebsd-arm64": "0.25.9",
"@esbuild/freebsd-x64": "0.25.9",
"@esbuild/linux-arm": "0.25.9",
"@esbuild/linux-arm64": "0.25.9",
"@esbuild/linux-ia32": "0.25.9",
"@esbuild/linux-loong64": "0.25.9",
"@esbuild/linux-mips64el": "0.25.9",
"@esbuild/linux-ppc64": "0.25.9",
"@esbuild/linux-riscv64": "0.25.9",
"@esbuild/linux-s390x": "0.25.9",
"@esbuild/linux-x64": "0.25.9",
"@esbuild/netbsd-arm64": "0.25.9",
"@esbuild/netbsd-x64": "0.25.9",
"@esbuild/openbsd-arm64": "0.25.9",
"@esbuild/openbsd-x64": "0.25.9",
"@esbuild/openharmony-arm64": "0.25.9",
"@esbuild/sunos-x64": "0.25.9",
"@esbuild/win32-arm64": "0.25.9",
"@esbuild/win32-ia32": "0.25.9",
"@esbuild/win32-x64": "0.25.9"
}
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
"@esbuild/aix-ppc64": "0.21.5",
"@esbuild/android-arm": "0.21.5",
"@esbuild/android-arm64": "0.21.5",
"@esbuild/android-x64": "0.21.5",
"@esbuild/darwin-arm64": "0.21.5",
"@esbuild/darwin-x64": "0.21.5",
"@esbuild/freebsd-arm64": "0.21.5",
"@esbuild/freebsd-x64": "0.21.5",
"@esbuild/linux-arm": "0.21.5",
"@esbuild/linux-arm64": "0.21.5",
"@esbuild/linux-ia32": "0.21.5",
"@esbuild/linux-loong64": "0.21.5",
"@esbuild/linux-mips64el": "0.21.5",
"@esbuild/linux-ppc64": "0.21.5",
"@esbuild/linux-riscv64": "0.21.5",
"@esbuild/linux-s390x": "0.21.5",
"@esbuild/linux-x64": "0.21.5",
"@esbuild/netbsd-x64": "0.21.5",
"@esbuild/openbsd-x64": "0.21.5",
"@esbuild/sunos-x64": "0.21.5",
"@esbuild/win32-arm64": "0.21.5",
"@esbuild/win32-ia32": "0.21.5",
"@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/fill-range": {
@@ -274,7 +842,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -373,7 +940,6 @@
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"devOptional": true,
"funding": [
{
"type": "github",
@@ -400,27 +966,12 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"devOptional": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -463,7 +1014,6 @@
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz",
"integrity": "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.8"
@@ -499,6 +1049,19 @@
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.49.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz",
"integrity": "sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/sass": {
"version": "1.91.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.91.0.tgz",
@@ -524,29 +1087,11 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"devOptional": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -591,7 +1136,7 @@
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"devOptional": true,
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -601,34 +1146,21 @@
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/vite": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz",
"integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==",
"devOptional": true,
"version": "5.4.20",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz",
"integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==",
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
"picomatch": "^4.0.3",
"postcss": "^8.5.6",
"rollup": "^4.43.0",
"tinyglobby": "^0.2.14"
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
"rollup": "^4.20.0"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
"node": "^18.0.0 || >=20.0.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
@@ -637,25 +1169,19 @@
"fsevents": "~2.3.3"
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
"@types/node": "^18.0.0 || >=20.0.0",
"less": "*",
"lightningcss": "^1.21.0",
"sass": "^1.70.0",
"sass-embedded": "^1.70.0",
"stylus": ">=0.54.8",
"sugarss": "^5.0.0",
"terser": "^5.16.0",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
"sass": "*",
"sass-embedded": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"jiti": {
"optional": true
},
"less": {
"optional": true
},
@@ -676,12 +1202,6 @@
},
"terser": {
"optional": true
},
"tsx": {
"optional": true
},
"yaml": {
"optional": true
}
}
},
@@ -704,21 +1224,6 @@
}
}
},
"node_modules/yaml": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"dev": true,
"license": "ISC",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
}
},
"node_modules/zrender": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz",

View File

@@ -3,19 +3,26 @@
"private": true,
"version": "0.0.0",
"type": "module",
"engines": {
"node": "22.x"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"type-check": "tsc --noEmit"
"type-check": "tsc --noEmit",
"vercel-build": "npm run build"
},
"devDependencies": {
"sass": "^1.91.0",
"typescript": "~5.8.3",
"vite": "^7.1.2"
"typescript": "~5.8.3"
},
"dependencies": {
"echarts": "^6.0.0",
"vite": "^5.4.0",
"vite-tsconfig-paths": "^5.1.4"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "4.6.1"
}
}

View File

@@ -13,7 +13,7 @@ export class ChartContainer {
this.container = element
}
init(renderer: 'canvas' | 'svg' = 'svg', theme?: string) {
init(renderer: 'canvas' | 'svg' = 'svg', theme: string = 'dark') {
this.chart = echarts.init(this.container, theme, {
renderer
})

View File

@@ -4,15 +4,11 @@
right: -400px;
width: 400px;
height: 100vh;
background: linear-gradient(
135deg,
rgba(3, 4, 94, 0.98) 0%,
rgba(30, 60, 114, 0.98) 100%
);
background: rgba(15, 23, 42, 0.95);
backdrop-filter: blur(20px);
border-left: 2px solid rgba(252, 215, 113, 0.4);
box-shadow: -10px 0 30px rgba(0, 0, 0, 0.4),
inset 0 0 50px rgba(252, 215, 113, 0.1);
border-left: 1px solid rgba(148, 163, 184, 0.2);
box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3),
inset 0 0 50px rgba(59, 130, 246, 0.05);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1000;
overflow-y: auto;
@@ -27,12 +23,12 @@
bottom: 0;
background: radial-gradient(
circle at 20% 50%,
rgba(252, 215, 113, 0.1) 0%,
rgba(59, 130, 246, 0.08) 0%,
transparent 50%
),
radial-gradient(
circle at 80% 20%,
rgba(46, 90, 91, 0.1) 0%,
rgba(16, 185, 129, 0.08) 0%,
transparent 50%
);
pointer-events: none;
@@ -41,83 +37,85 @@
&.visible {
right: 0;
transform: translateX(0);
box-shadow: -15px 0 40px rgba(0, 0, 0, 0.6),
inset 0 0 60px rgba(252, 215, 113, 0.15);
box-shadow: -15px 0 40px rgba(0, 0, 0, 0.4),
inset 0 0 60px rgba(59, 130, 246, 0.08);
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px 20px;
border-bottom: 1px solid rgba(252, 215, 113, 0.2);
background: linear-gradient(
135deg,
rgba(252, 215, 113, 0.1) 0%,
rgba(46, 90, 91, 0.1) 100%
);
padding: 20px 24px;
border-bottom: 1px solid rgba(148, 163, 184, 0.15);
background: rgba(59, 130, 246, 0.05);
position: relative;
z-index: 1;
h3 {
margin: 0;
color: #fcd771;
font-size: 16px;
color: #f1f5f9;
font-size: 18px;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
letter-spacing: 0.5px;
letter-spacing: -0.025em;
line-height: 1.2;
}
.close-btn {
background: rgba(252, 215, 113, 0.15);
border: 1px solid rgba(252, 215, 113, 0.4);
font-size: 18px;
color: #fcd771;
background: rgba(148, 163, 184, 0.1);
border: 1px solid rgba(148, 163, 184, 0.2);
font-size: 20px;
color: #94a3b8;
cursor: pointer;
padding: 0;
width: 36px;
height: 36px;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 8px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
backdrop-filter: blur(10px);
font-weight: 300;
font-weight: 400;
line-height: 1;
&:hover {
background: rgba(252, 215, 113, 0.25);
border-color: rgba(252, 215, 113, 0.6);
color: #fff;
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(252, 215, 113, 0.4);
background: rgba(239, 68, 68, 0.1);
border-color: rgba(239, 68, 68, 0.3);
color: #ef4444;
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.2);
}
&:focus {
outline: 2px solid rgba(59, 130, 246, 0.5);
outline-offset: 2px;
}
}
}
.panel-content {
padding: 20px;
padding: 24px;
position: relative;
z-index: 1;
#item-info {
.welcome-message {
text-align: center;
padding: 40px 20px;
padding: 48px 24px;
.mystic-icon {
font-size: 48px;
color: #fcd771;
margin-bottom: 16px;
font-size: 56px;
color: #3b82f6;
margin-bottom: 20px;
animation: pulse 2s ease-in-out infinite;
}
p {
color: rgba(252, 215, 113, 0.8);
font-size: 14px;
color: #94a3b8;
font-size: 16px;
line-height: 1.6;
margin: 0;
font-weight: 400;
}
}
@@ -125,87 +123,90 @@
animation: slideInUp 0.5s ease-out;
.item-header {
margin-bottom: 20px;
margin-bottom: 24px;
.item-heading {
margin: 0 0 8px 0;
color: #fcd771;
font-size: 18px;
color: #f1f5f9;
font-size: 20px;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
line-height: 1.3;
letter-spacing: -0.025em;
}
.item-category {
color: rgba(252, 215, 113, 0.7);
font-size: 12px;
color: #64748b;
font-size: 13px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
letter-spacing: 0.05em;
}
}
.item-description {
margin-bottom: 20px;
margin-bottom: 24px;
.item-text {
margin: 0;
color: rgba(255, 255, 255, 0.95);
line-height: 1.6;
font-size: 14px;
color: #e2e8f0;
line-height: 1.7;
font-size: 15px;
font-weight: 400;
}
}
.item-details {
margin-bottom: 20px;
margin-bottom: 24px;
h5 {
margin: 0 0 12px 0;
color: #fcd771;
color: #3b82f6;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
letter-spacing: 0.05em;
}
p {
margin: 0;
color: rgba(255, 255, 255, 0.9);
line-height: 1.6;
font-size: 13px;
color: #cbd5e1;
line-height: 1.7;
font-size: 14px;
font-weight: 400;
}
}
.item-tags {
h5 {
margin: 0 0 12px 0;
color: #fcd771;
color: #3b82f6;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
letter-spacing: 0.05em;
}
.tags-container {
display: flex;
flex-wrap: wrap;
gap: 6px;
gap: 8px;
.tag {
background: rgba(252, 215, 113, 0.1);
border: 1px solid rgba(252, 215, 113, 0.3);
color: #fcd771;
padding: 4px 8px;
border-radius: 12px;
font-size: 11px;
background: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.2);
color: #3b82f6;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
transition: all 0.3s ease;
transition: all 0.2s ease;
backdrop-filter: blur(10px);
&:hover {
background: rgba(252, 215, 113, 0.2);
border-color: rgba(252, 215, 113, 0.5);
background: rgba(59, 130, 246, 0.15);
border-color: rgba(59, 130, 246, 0.3);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2);
}
}
}
@@ -216,77 +217,79 @@
animation: slideInUp 0.5s ease-out;
.theory-header {
margin-bottom: 24px;
margin-bottom: 28px;
text-align: center;
.theory-title {
margin: 0 0 8px 0;
color: #fcd771;
font-size: 24px;
color: #f1f5f9;
font-size: 26px;
font-weight: 700;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
line-height: 1.2;
letter-spacing: -0.025em;
}
.theory-category {
color: rgba(252, 215, 113, 0.8);
color: #64748b;
font-size: 14px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
letter-spacing: 0.05em;
}
}
.theory-summary {
margin-bottom: 24px;
padding: 16px;
background: rgba(252, 215, 113, 0.05);
border-left: 3px solid rgba(252, 215, 113, 0.3);
margin-bottom: 28px;
padding: 20px;
background: rgba(59, 130, 246, 0.05);
border-left: 3px solid rgba(59, 130, 246, 0.3);
border-radius: 0 8px 8px 0;
.theory-summary-text {
margin: 0;
color: rgba(255, 255, 255, 0.95);
color: #e2e8f0;
line-height: 1.7;
font-size: 15px;
font-size: 16px;
font-style: italic;
font-weight: 400;
}
}
.theory-overview {
margin-bottom: 24px;
margin-bottom: 28px;
h3 {
margin: 0 0 16px 0;
color: #fcd771;
color: #3b82f6;
font-size: 16px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
border-bottom: 1px solid rgba(252, 215, 113, 0.2);
letter-spacing: 0.05em;
border-bottom: 1px solid rgba(59, 130, 246, 0.2);
padding-bottom: 8px;
}
.overview-grid {
display: flex;
flex-direction: column;
gap: 16px;
gap: 20px;
.overview-item {
h4 {
margin: 0 0 8px 0;
color: #fcd771;
font-size: 13px;
color: #3b82f6;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
letter-spacing: 0.05em;
}
p {
margin: 0;
color: rgba(255, 255, 255, 0.9);
line-height: 1.6;
font-size: 13px;
color: #cbd5e1;
line-height: 1.7;
font-size: 14px;
font-weight: 400;
}
}
}
@@ -295,32 +298,33 @@
.theory-components {
h3 {
margin: 0 0 16px 0;
color: #fcd771;
color: #3b82f6;
font-size: 16px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
border-bottom: 1px solid rgba(252, 215, 113, 0.2);
letter-spacing: 0.05em;
border-bottom: 1px solid rgba(59, 130, 246, 0.2);
padding-bottom: 8px;
}
.component-item {
margin-bottom: 16px;
margin-bottom: 20px;
h4 {
margin: 0 0 8px 0;
color: #fcd771;
font-size: 13px;
color: #3b82f6;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
letter-spacing: 0.05em;
}
p {
margin: 0;
color: rgba(255, 255, 255, 0.9);
line-height: 1.6;
font-size: 13px;
color: #cbd5e1;
line-height: 1.7;
font-size: 14px;
font-weight: 400;
}
}
}
@@ -329,25 +333,26 @@
.error-content {
animation: slideInUp 0.5s ease-out;
text-align: center;
padding: 40px 20px;
padding: 48px 24px;
.error-icon {
font-size: 48px;
margin-bottom: 16px;
font-size: 56px;
margin-bottom: 20px;
}
h3 {
margin: 0 0 12px 0;
color: #ff6b6b;
font-size: 18px;
color: #ef4444;
font-size: 20px;
font-weight: 600;
}
p {
margin: 0;
color: rgba(255, 255, 255, 0.8);
color: #94a3b8;
line-height: 1.6;
font-size: 14px;
font-size: 16px;
font-weight: 400;
}
}
}
@@ -390,8 +395,8 @@
// Responsive adjustments
@media (max-width: 1024px) {
.item-details-panel {
width: 350px;
right: -350px;
width: 380px;
right: -380px;
}
}
@@ -401,7 +406,29 @@
right: -100%;
.panel-header {
padding: 20px 16px;
padding: 16px 20px;
h3 {
font-size: 18px;
}
.close-btn {
width: 36px;
height: 36px;
font-size: 18px;
}
}
.panel-content {
padding: 20px;
}
}
}
@media (max-width: 480px) {
.item-details-panel {
.panel-header {
padding: 16px;
h3 {
font-size: 16px;
@@ -410,6 +437,20 @@
.panel-content {
padding: 16px;
#item-info {
.welcome-message {
padding: 32px 16px;
.mystic-icon {
font-size: 48px;
}
p {
font-size: 14px;
}
}
}
}
}
}

View File

@@ -116,15 +116,21 @@ export class ItemDetailsPanel {
private render() {
this.container.innerHTML = `
<div class="item-details-panel ${this.isVisible ? 'visible' : ''}">
<div class="item-details-panel ${this.isVisible ? 'visible' : ''}"
role="dialog"
aria-labelledby="item-title"
aria-hidden="${!this.isVisible}">
<div class="panel-header">
<h3 id="item-title">Item Details</h3>
<button class="close-btn" id="close-panel">×</button>
<button class="close-btn"
id="close-panel"
aria-label="Close panel"
title="Close panel">×</button>
</div>
<div class="panel-content">
<div id="item-info">
<div class="welcome-message">
<div class="mystic-icon">✦</div>
<div class="mystic-icon" aria-hidden="true">✦</div>
<p>Select an item from the chart to explore its mysteries</p>
</div>
</div>
@@ -143,12 +149,33 @@ export class ItemDetailsPanel {
// Call the close callback to update URL
this.onCloseCallback?.()
})
// Add keyboard support
closeBtn.addEventListener('keydown', (e) => {
const keyboardEvent = e as KeyboardEvent
if (keyboardEvent.key === 'Enter' || keyboardEvent.key === ' ') {
e.preventDefault()
this.hide()
this.onCloseCallback?.()
}
})
}
// Add escape key support
document.addEventListener('keydown', (e) => {
const keyboardEvent = e as KeyboardEvent
if (keyboardEvent.key === 'Escape' && this.isVisible) {
this.hide()
this.onCloseCallback?.()
}
})
}
public show(itemName: string) {
this.isVisible = true
this.container.querySelector('.item-details-panel')?.classList.add('visible')
const panel = this.container.querySelector('.item-details-panel')
panel?.classList.add('visible')
panel?.setAttribute('aria-hidden', 'false')
const itemData = this.itemData.get(itemName)
@@ -212,7 +239,9 @@ export class ItemDetailsPanel {
public showTheory(theoryData: TheoryData) {
this.isVisible = true
this.container.querySelector('.item-details-panel')?.classList.add('visible')
const panel = this.container.querySelector('.item-details-panel')
panel?.classList.add('visible')
panel?.setAttribute('aria-hidden', 'false')
// Update the title
const titleElement = this.container.querySelector('#item-title')
@@ -270,7 +299,9 @@ export class ItemDetailsPanel {
public showError(message: string) {
this.isVisible = true
this.container.querySelector('.item-details-panel')?.classList.add('visible')
const panel = this.container.querySelector('.item-details-panel')
panel?.classList.add('visible')
panel?.setAttribute('aria-hidden', 'false')
// Update the title
const titleElement = this.container.querySelector('#item-title')
@@ -293,7 +324,9 @@ export class ItemDetailsPanel {
public hide() {
this.isVisible = false
this.container.querySelector('.item-details-panel')?.classList.remove('visible')
const panel = this.container.querySelector('.item-details-panel')
panel?.classList.remove('visible')
panel?.setAttribute('aria-hidden', 'true')
}
public isPanelVisible(): boolean {

View File

@@ -1,7 +1,7 @@
export class SearchBar {
private container: HTMLElement
private input: HTMLInputElement
private dropdown: HTMLElement
private input!: HTMLInputElement
private dropdown!: HTMLElement
private router: any
private allTheories: Array<{category: string, theory: string, title: string}> = []
@@ -25,8 +25,16 @@ export class SearchBar {
id="theory-search"
placeholder="Search theories..."
autocomplete="off"
aria-label="Search theories"
aria-describedby="search-dropdown"
role="combobox"
aria-expanded="false"
aria-haspopup="listbox"
/>
<div class="search-dropdown" id="search-dropdown"></div>
<div class="search-dropdown"
id="search-dropdown"
role="listbox"
aria-label="Search results"></div>
</div>
`
@@ -53,6 +61,18 @@ export class SearchBar {
}, 200)
})
// Add keyboard navigation
this.input.addEventListener('keydown', (e) => {
const keyboardEvent = e as KeyboardEvent
if (keyboardEvent.key === 'ArrowDown') {
e.preventDefault()
this.focusFirstItem()
} else if (keyboardEvent.key === 'Escape') {
this.hideDropdown()
this.input.blur()
}
})
// Prevent dropdown from closing when clicking on it
this.dropdown.addEventListener('mousedown', (e) => {
e.preventDefault()
@@ -84,17 +104,23 @@ export class SearchBar {
this.dropdown.innerHTML = theoriesToShow
.slice(0, 8) // Limit to 8 results
.map(theory => `
<div class="search-item" data-category="${theory.category}" data-theory="${theory.theory}">
.map((theory) => `
<div class="search-item"
data-category="${theory.category}"
data-theory="${theory.theory}"
role="option"
tabindex="0"
aria-selected="false">
<div class="search-item-title">${theory.title}</div>
<div class="search-item-category">${theory.category}</div>
</div>
`).join('')
this.dropdown.classList.add('visible')
this.input.setAttribute('aria-expanded', 'true')
// Add click handlers to dropdown items
this.dropdown.querySelectorAll('.search-item').forEach(item => {
this.dropdown.querySelectorAll('.search-item').forEach((item, index) => {
item.addEventListener('click', () => {
const category = item.getAttribute('data-category')
const theory = item.getAttribute('data-theory')
@@ -104,10 +130,49 @@ export class SearchBar {
this.hideDropdown()
}
})
// Add keyboard navigation
item.addEventListener('keydown', (e) => {
const keyboardEvent = e as KeyboardEvent
if (keyboardEvent.key === 'Enter' || keyboardEvent.key === ' ') {
e.preventDefault()
const category = item.getAttribute('data-category')
const theory = item.getAttribute('data-theory')
if (category && theory) {
this.router.navigateToTheory(category, theory)
this.input.value = ''
this.hideDropdown()
}
} else if (keyboardEvent.key === 'ArrowDown') {
e.preventDefault()
const nextItem = this.dropdown.querySelectorAll('.search-item')[index + 1] as HTMLElement
if (nextItem) {
nextItem.focus()
}
} else if (keyboardEvent.key === 'ArrowUp') {
e.preventDefault()
if (index === 0) {
this.input.focus()
} else {
const prevItem = this.dropdown.querySelectorAll('.search-item')[index - 1] as HTMLElement
if (prevItem) {
prevItem.focus()
}
}
}
})
})
}
private hideDropdown() {
this.dropdown.classList.remove('visible')
this.input.setAttribute('aria-expanded', 'false')
}
private focusFirstItem() {
const firstItem = this.dropdown.querySelector('.search-item') as HTMLElement
if (firstItem) {
firstItem.focus()
}
}
}

View File

@@ -25,7 +25,7 @@ const itemDetailsPanel = chartExample.getItemDetailsPanel()
;(window as any).router = router
// Initialize search bar
const searchBar = new SearchBar('search-container', router)
new SearchBar('search-container', router)
// Set up close callback to navigate to home when panel is closed
itemDetailsPanel.setCloseCallback(() => {

View File

@@ -9,15 +9,15 @@ body {
width: 100%;
height: 100%;
overflow: hidden;
background: #1a1a1a;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, sans-serif;
background: #1b1b1b;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
color: #f1f5f9;
}
#main {
width: 100vw;
height: 100vh;
background: #1a1a1a;
background: transparent;
}
h1 {
@@ -55,32 +55,52 @@ h1 {
button {
border-radius: 8px;
border: 1px solid transparent;
border: 1px solid rgba(59, 130, 246, 0.2);
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
background-color: rgba(59, 130, 246, 0.1);
color: #3b82f6;
cursor: pointer;
transition: border-color 0.25s;
transition: all 0.2s ease;
backdrop-filter: blur(10px);
}
button:hover {
border-color: #646cff;
border-color: rgba(59, 130, 246, 0.4);
background-color: rgba(59, 130, 246, 0.15);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
outline: 2px solid rgba(59, 130, 246, 0.5);
outline-offset: 2px;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
color: #1e293b;
background: #f8fafc;
}
a:hover {
color: #747bff;
body {
background: #f8fafc;
color: #1e293b;
}
#main {
background: transparent;
}
button {
background-color: #f9f9f9;
background-color: rgba(59, 130, 246, 0.1);
color: #1d4ed8;
border-color: rgba(59, 130, 246, 0.3);
}
button:hover {
background-color: rgba(59, 130, 246, 0.15);
border-color: rgba(59, 130, 246, 0.5);
}
}

View File

@@ -1,9 +1,9 @@
{
"compilerOptions": {
"target": "ES2022",
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
@@ -15,8 +15,8 @@
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,

21
vercel.json Normal file
View File

@@ -0,0 +1,21 @@
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"rewrites": [
{
"source": "/(.*)",
"destination": "/index.html"
}
],
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}

View File

@@ -6,19 +6,29 @@ export default defineConfig({
tsconfigPaths()
],
server: {
port: 3000,
port: 8080,
open: true,
historyApiFallback: true
},
build: {
target: 'esnext',
target: 'es2020',
minify: 'esbuild',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
echarts: ['echarts']
}
}
}
},
chunkSizeWarningLimit: 1000,
outDir: 'dist',
emptyOutDir: true
},
optimizeDeps: {
include: ['echarts']
},
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
}
})