diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 0000000..529fba1 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,30 @@ +pkgbase = emerald-legacy-launcher + pkgdesc = FOSS, cross-platform launcher for Minecraft Legacy Console Edition + pkgver = 1.0.0 + pkgrel = 1 + url = https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher + arch = x86_64 + license = GPL-3.0 + makedepends = git + makedepends = openssl + makedepends = appmenu-gtk-module + makedepends = libappindicator-gtk3 + makedepends = librsvg + makedepends = cargo + makedepends = pnpm + makedepends = nodejs + depends = cairo + depends = desktop-file-utils + depends = gdk-pixbuf2 + depends = glib2 + depends = gtk3 + depends = hicolor-icon-theme + depends = libsoup + depends = pango + depends = webkit2gtk-4.1 + optdepends = discord: Discord RPC support + provides = emerald-legacy-launcher + source = emerald-legacy-launcher::git+https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher#branch=dev + sha256sums = SKIP + +pkgname = emerald-legacy-launcher diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..819e519 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,257 @@ +name: 'nightly' +on: + push: + branches: ["dev"] + +jobs: + nightly-tauri: + permissions: + contents: write + strategy: + fail-fast: false + matrix: + include: + - platform: 'macos-latest' + args: '--target aarch64-apple-darwin' + - platform: 'macos-latest' + args: '--target x86_64-apple-darwin' + - platform: 'ubuntu-22.04' + args: '' + - platform: 'windows-latest' + args: '' + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v4 + + - name: install dependencies (ubuntu only) + if: matrix.platform == 'ubuntu-22.04' + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libudev-dev + + - name: setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'pnpm' + + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: './src-tauri -> target' + + - name: install frontend dependencies + run: pnpm install + + - name: Build and create DMG for macOS + if: matrix.platform == 'macos-latest' + run: | + pnpm build + cd src-tauri + cargo build --release --target ${{ matrix.args }} + cd .. + + TARGET_ARCH=${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }} + + mkdir -p "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS" + mkdir -p "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Resources" + + cp "src-tauri/target/$TARGET_ARCH/release/emerald-legacy-launcher" "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS/" + + printf '\n\n\n\n CFBundleExecutable\n emerald-legacy-launcher\n CFBundleIdentifier\n com.emerald.legacy\n CFBundleName\n Emerald Legacy Launcher\n CFBundleVersion\n 1.0.0\n CFBundleShortVersionString\n 1.0.0\n CFBundlePackageType\n APPL\n NSHighResolutionCapable\n \n LSApplicationCategoryType\n public.app-category.games\n\n\n' > "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Info.plist" + + if [ -f "src-tauri/icons/icon.icns" ]; then + cp src-tauri/icons/icon.icns "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Resources/" + fi + + chmod +x "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS/emerald-legacy-launcher" + + cd "src-tauri/target/$TARGET_ARCH/release/bundle/macos" + hdiutil create -volname "Emerald Legacy Launcher" -srcfolder "Emerald Legacy Launcher.app" -ov -format UDZO "Emerald Legacy Launcher.dmg" + + mkdir -p "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/dmg/" + mv "Emerald Legacy Launcher.dmg" "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/dmg/" + + - name: Build with tauri-action for Windows and Linux + if: matrix.platform != 'macos-latest' + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tagName: nightly + releaseName: 'Emerald Nightly' + releaseBody: | + # Emerald Legacy Launcher (Nightly) + + ## 📥 What to download? + + ### 🐧 GNU/Linux + - **RHEL/Fedora**: `Emerald.Legacy.Launcher-*.rpm` + - **Debian/Ubuntu**: `Emerald.Legacy.Launcher-*.deb` + - **Universal**: `Emerald.Legacy.Launcher-*.AppImage` + - **Flatpak**: `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` + + ### 🍎 macOS + - **Intel Mac**: `Emerald.Legacy.Launcher_*.x64.dmg` + - **M-series Mac**: `Emerald.Legacy.Launcher_*.aarch64.dmg` + + ### 🪟 Windows + - **Setup Installer**: `Emerald.Legacy.Launcher-*.exe` + - **MSI Installer**: `Emerald.Legacy.Launcher-*.msi` + + --- + + ## ⚠️ Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + + ## 🍎 macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + releaseDraft: false + prerelease: true + args: ${{ matrix.args }} + + - name: Upload all artifacts to release + uses: softprops/action-gh-release@v2 + with: + files: | + src-tauri/target/release/bundle/deb/*.deb + src-tauri/target/release/bundle/appimage/*.AppImage + src-tauri/target/release/bundle/rpm/*.rpm + src-tauri/target/release/bundle/msi/*.msi + src-tauri/target/release/bundle/nsis/*.exe + tag_name: nightly + name: 'Emerald Nightly' + body: | + # Emerald Legacy Launcher (Nightly) + # What to download? + - `Emerald.Legacy.Launcher-*.rpm` for GNU/Linux (RHEL) + - `Emerald.Legacy.Launcher-*.deb` for GNU/Linux (Debian+Ubuntu) + - `Emerald.Legacy.Launcher-*.AppImage` for GNU/Linux (Universal) + - `Emerald Legacy Launcher*.dmg` for macOS (Intel + M-series) + - `Emerald.Legacy.Launcher-*.exe` for Windows (Setup) + - `Emerald.Legacy.Launcher-*.msi` for Windows (Setup) + - `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` for GNU/Linux (Flatpak) + --- + # Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + --- + # macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + draft: false + prerelease: true + + - name: Upload macOS DMGs to release + if: matrix.platform == 'macos-latest' + uses: softprops/action-gh-release@v2 + with: + files: src-tauri/target/release/bundle/dmg/*.dmg + tag_name: nightly + name: 'Emerald Nightly' + body: | + # Emerald Legacy Launcher (Nightly) + # What to download? + - `Emerald.Legacy.Launcher-*.rpm` for GNU/Linux (RHEL) + - `Emerald.Legacy.Launcher-*.deb` for GNU/Linux (Debian+Ubuntu) + - `Emerald.Legacy.Launcher-*.AppImage` for GNU/Linux (Universal) + - `Emerald Legacy Launcher*.dmg` for macOS (Intel + M-series) + - `Emerald.Legacy.Launcher-*.exe` for Windows (Setup) + - `Emerald.Legacy.Launcher-*.msi` for Windows (Setup) + - `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` for GNU/Linux (Flatpak) + --- + # Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + --- + # macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + draft: false + prerelease: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + nightly-flatpak: + runs-on: ubuntu-latest + permissions: + contents: write + needs: nightly-tauri + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: install dependencies + run: | + sudo apt-get update + sudo apt-get install -y flatpak flatpak-builder + + - name: setup flathub + run: | + sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + sudo flatpak install -y flathub org.gnome.Sdk//48 org.gnome.Platform//48 org.freedesktop.Sdk.Extension.node20//24.08 org.freedesktop.Sdk.Extension.rust-stable//24.08 + sudo flatpak update + + - name: setup flatpak + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak + manifest-path: flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml + cache-key: flatpak-builder-${{ github.sha }} + build-bundle: true + repository-url: https://flathub.org/repo/flathub.flatpakrepo + repository-name: flathub + + - name: Upload flatpak to release + uses: softprops/action-gh-release@v2 + with: + files: "*.flatpak" + tag_name: nightly + name: 'Emerald Nightly' + body: | + # Emerald Legacy Launcher (Nightly) + # What to download? + - `Emerald.Legacy.Launcher-*.rpm` for GNU/Linux (RHEL) + - `Emerald.Legacy.Launcher-*.deb` for GNU/Linux (Debian+Ubuntu) + - `Emerald.Legacy.Launcher-*.AppImage` for GNU/Linux (Universal) + - `Emerald Legacy Launcher*.dmg` for macOS (Intel + M-series) + - `Emerald.Legacy.Launcher-*.exe` for Windows (Setup) + - `Emerald.Legacy.Launcher-*.msi` for Windows (Setup) + - `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` for GNU/Linux (Flatpak) + --- + # Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + --- + # macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + draft: false + prerelease: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 09ae899..4333557 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,11 +24,19 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Extract version + id: get_version + shell: bash + run: | + VERSION=$(node -p "require('./package.json').version") + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "APP_VERSION=$VERSION" >> $GITHUB_ENV + - name: install dependencies (ubuntu only) if: matrix.platform == 'ubuntu-22.04' run: | sudo apt-get update - sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libudev-dev - name: setup pnpm uses: pnpm/action-setup@v4 @@ -52,13 +60,222 @@ jobs: - name: install frontend dependencies run: pnpm install - - uses: tauri-apps/tauri-action@v0 + - name: Build and create artifacts for macOS + if: matrix.platform == 'macos-latest' + run: | + # Build the app once + pnpm build + cd src-tauri + cargo build --release --target ${{ matrix.args }} + cd .. + + # Setup target architecture name + TARGET_ARCH=${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }} + + # Prepare paths for .app bundle + mkdir -p "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS" + mkdir -p "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Resources" + + cp "src-tauri/target/$TARGET_ARCH/release/emerald-legacy-launcher" "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS/" + + printf '\n\n\n\n CFBundleExecutable\n emerald-legacy-launcher\n CFBundleIdentifier\n com.emerald.legacy\n CFBundleName\n Emerald Legacy Launcher\n CFBundleVersion\n ${{ steps.get_version.outputs.VERSION }}\n CFBundleShortVersionString\n ${{ steps.get_version.outputs.VERSION }}\n CFBundlePackageType\n APPL\n NSHighResolutionCapable\n \n LSApplicationCategoryType\n public.app-category.games\n\n\n' > "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Info.plist" + + if [ -f "src-tauri/icons/icon.icns" ]; then + cp src-tauri/icons/icon.icns "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/Resources/" + fi + + chmod +x "src-tauri/target/$TARGET_ARCH/release/bundle/macos/Emerald Legacy Launcher.app/Contents/MacOS/emerald-legacy-launcher" + + # Create PKG (optional, using the built .app) + mkdir -p pkg_temp/scripts + cp scripts/postinstall.sh pkg_temp/scripts/ + + pkgbuild --root "src-tauri/target/$TARGET_ARCH/release/bundle/macos" \ + --install-location /Applications \ + --scripts pkg_temp/scripts \ + --identifier "com.emerald.legacy" \ + --version "${{ steps.get_version.outputs.VERSION }}" \ + "Emerald-Legacy-Launcher.pkg" + + # Create DMG + cd "src-tauri/target/$TARGET_ARCH/release/bundle/macos" + hdiutil create -volname "Emerald Legacy Launcher" -srcfolder "Emerald Legacy Launcher.app" -ov -format UDZO "Emerald Legacy Launcher.dmg" + + # Move artifacts to final locations + mkdir -p "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/dmg/" + mv "Emerald Legacy Launcher.dmg" "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/dmg/" + + mkdir -p "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/macos/" + mv "$GITHUB_WORKSPACE/Emerald-Legacy-Launcher.pkg" "$GITHUB_WORKSPACE/src-tauri/target/release/bundle/macos/" + + - name: Build with tauri-action for Windows and Linux + if: matrix.platform != 'macos-latest' + uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tagName: v__VERSION__ - releaseName: 'Emerald v__VERSION__' - releaseBody: '*pls edit me*' + tagName: v${{ steps.get_version.outputs.VERSION }} + releaseName: 'Emerald v${{ steps.get_version.outputs.VERSION }}' + releaseBody: | + # Emerald Legacy Launcher v${{ steps.get_version.outputs.VERSION }} + + ## 📥 What to download? + + ### 🐧 GNU/Linux + - **RHEL/Fedora**: `Emerald.Legacy.Launcher-*.rpm` + - **Debian/Ubuntu**: `Emerald.Legacy.Launcher-*.deb` + - **Universal**: `Emerald.Legacy.Launcher-*.AppImage` + - **Flatpak**: `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` + + ### 🍎 macOS + - **Intel Mac**: `Emerald.Legacy.Launcher_*.x64.dmg` + - **M-series Mac**: `Emerald.Legacy.Launcher_*.aarch64.dmg` + + ### 🪟 Windows + - **Setup Installer**: `Emerald.Legacy.Launcher-*.exe` + - **MSI Installer**: `Emerald.Legacy.Launcher-*.msi` + + --- + + ## ⚠️ Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + + ## 🍎 macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` releaseDraft: true prerelease: false args: ${{ matrix.args }} + + - name: Upload all artifacts to release + if: matrix.platform != 'macos-latest' + uses: softprops/action-gh-release@v2 + with: + files: | + src-tauri/target/release/bundle/deb/*.deb + src-tauri/target/release/bundle/appimage/*.AppImage + src-tauri/target/release/bundle/rpm/*.rpm + src-tauri/target/release/bundle/msi/*.msi + src-tauri/target/release/bundle/nsis/*.exe + tag_name: v${{ steps.get_version.outputs.VERSION }} + name: 'Emerald v${{ steps.get_version.outputs.VERSION }}' + body: | + # Emerald Legacy Launcher v${{ steps.get_version.outputs.VERSION }} + + ## 📥 What to download? + + ### 🐧 GNU/Linux + - **RHEL/Fedora**: `Emerald.Legacy.Launcher-*.rpm` + - **Debian/Ubuntu**: `Emerald.Legacy.Launcher-*.deb` + - **Universal**: `Emerald.Legacy.Launcher-*.AppImage` + - **Flatpak**: `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` + + ### 🍎 macOS + - **Intel Mac**: `Emerald.Legacy.Launcher_*.x64.dmg` + - **M-series Mac**: `Emerald.Legacy.Launcher_*.aarch64.dmg` + + ### 🪟 Windows + - **Setup Installer**: `Emerald.Legacy.Launcher-*.exe` + - **MSI Installer**: `Emerald.Legacy.Launcher-*.msi` + + --- + + ## ⚠️ Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + + ## 🍎 macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + draft: true + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload macOS DMGs to release + if: matrix.platform == 'macos-latest' + uses: softprops/action-gh-release@v2 + with: + files: | + src-tauri/target/release/bundle/dmg/*.dmg + src-tauri/target/release/bundle/macos/*.pkg + tag_name: v${{ steps.get_version.outputs.VERSION }} + name: 'Emerald v${{ steps.get_version.outputs.VERSION }}' + body: | + # Emerald Legacy Launcher v${{ steps.get_version.outputs.VERSION }} + + ## 📥 What to download? + + ### 🐧 GNU/Linux + - **RHEL/Fedora**: `Emerald.Legacy.Launcher-*.rpm` + - **Debian/Ubuntu**: `Emerald.Legacy.Launcher-*.deb` + - **Universal**: `Emerald.Legacy.Launcher-*.AppImage` + - **Flatpak**: `io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak` + + ### 🍎 macOS + - **Intel Mac**: `Emerald.Legacy.Launcher_*.x64.dmg` + - **M-series Mac**: `Emerald.Legacy.Launcher_*.aarch64.dmg` + + ### 🪟 Windows + - **Setup Installer**: `Emerald.Legacy.Launcher-*.exe` + - **MSI Installer**: `Emerald.Legacy.Launcher-*.msi` + + --- + + ## ⚠️ Windows SmartScreen + This software is completely safe. Because the launcher is unsigned, you will see a "Windows protected your PC" window. To proceed: + + 1. Click the **"More info"** link under the main text. + 2. Click the **"Run anyway"** button that appears. + + ## 🍎 macOS Installation + Download the DMG file, open it, and drag the app to Applications folder. + If you see "app damaged" error, right-click the app → Open → confirm Open. + Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + draft: true + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-flatpak: + runs-on: ubuntu-latest + permissions: + contents: write + needs: publish-tauri + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: install dependencies + run: | + sudo apt-get update + sudo apt-get install -y flatpak flatpak-builder + + - name: setup flathub + run: | + sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + sudo flatpak install -y flathub org.gnome.Sdk//48 org.gnome.Platform//48 org.freedesktop.Sdk.Extension.node20//24.08 org.freedesktop.Sdk.Extension.rust-stable//24.08 + sudo flatpak update + + - name: setup flatpak + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak + manifest-path: flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml + cache-key: flatpak-builder-${{ github.sha }} + build-bundle: true + repository-url: https://flathub.org/repo/flathub.flatpakrepo + repository-name: flathub + - uses: softprops/action-gh-release@v2 + with: + files: io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.flatpak + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 76efcdb..1e5bed2 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,8 @@ Thumbs.db # Log files *.log + +/build-flatpak +/.flatpak-builder +/*.flatpak +/emerald-repo diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ff13813 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "flatpak/shared-modules"] + path = flatpak/shared-modules + url = https://github.com/flathub/shared-modules.git diff --git a/BUILD.md b/BUILD.md index c5ada03..3e6c46d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -15,3 +15,21 @@ pnpm install # or npm pnpm tauri build # or npm ``` + +## macOS ARM Fix + +If you encounter "application is damaged" error on macOS ARM, the build process now includes automatic fixes. If manual intervention is needed: + +```sh +# Remove quarantine attributes +xattr -cr /path/to/Emerald\ Legacy\ Launcher.app + +# Apply ad-hoc signature +codesign --force --deep --sign - "/path/to/Emerald\ Legacy\ Launcher.app" +``` + +## Flatpak + +```sh +pnpm flatpak # or npm +``` \ No newline at end of file diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..42b3572 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,33 @@ +# Maintainer: NEOAPPS +# Maintainer: Santiago Fisela +pkgname=emerald-legacy-launcher +pkgver=1.0.0 +pkgrel=1 +pkgdesc="FOSS, cross-platform launcher for Minecraft Legacy Console Edition" +arch=('x86_64') +url="https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher" +license=('GPL-3.0') +depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk-4.1') +optdepends=('discord: Discord RPC support') +makedepends=('git' 'openssl' 'appmenu-gtk-module' 'libappindicator-gtk3' 'librsvg' 'cargo' 'pnpm' 'nodejs') +provides=('emerald-legacy-launcher') +source=("$pkgname::git+$url#branch=dev") +sha256sums=('SKIP') +pkgver() { + cd "$srcdir/$pkgname" + ( set -o pipefail + git describe --long --abbrev=7 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' || + printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)" + ) +} + +build() { + cd "$srcdir/$pkgname" + pnpm install + pnpm tauri build --bundles=deb +} + +package() { + cd "$srcdir/$pkgname" + cp -a src-tauri/target/release/bundle/deb/Emerald*_*_*/data/* "${pkgdir}" +} \ No newline at end of file diff --git a/README.md b/README.md index 3c99c5d..07c9aa9 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,326 @@ -
- -

Emerald Legacy Launcher

-

FOSS cross-platform launcher for Minecraft Legacy Console Edition

-
- -

- - Donate to the Project - - - Join the Community - -

- ---- - -> [!IMPORTANT] -> **Emerald Legacy Launcher is currently in Alpha.** -> Expect bugs, frequent updates, and features that are still being polished as we work toward a stable release. - ---- - -image - - -### PROJECT OVERVIEW -Emerald Legacy Launcher started as a solo project to create a better way to play Legacy Console Edition. Over time, other developers joined the effort, bringing expertise from various preservation projects into one place. - -**Our Philosophy:** For too long, the LCE scene has been fragmented across different, often resource-heavy launchers. Emerald was built to stop this fragmentation and centralize everything into a single, definitive hub. By avoiding bloated frameworks and utilizing a modern Rust/Tauri stack, we deliver a high-performance, cross-platform experience that uses only ~15MB of RAM, leaving all your PC's resources dedicated to the game itself. - ---- - -### CORE FEATURES - - - - - - - - - *Proudly developed by a passionate team from the LCE community.* - -
- EASY SETUP
- An automated installation process for TU19 and TU24, with more versions coming in future updates. -
- RUST BACKEND
- A memory-safe backend that handles all file operations and game execution with minimal overhead. -
- EASY CONFIGURATION
- An integrated settings menu to change your username and manage game parameters directly through the launcher. -
- TAURI FRONTEND
- A lightweight frontend that handles the user interface and configuration management via webview. -
- ---- - -### [DEVELOPMENT ROADMAP](https://github.com/orgs/Emerald-Legacy-Launcher/projects/2) -Click the heading above to track progress, view active tasks, and see upcoming launcher features. - ---- - -> ### ACKNOWLEDGMENTS -> * **The Emerald Team:** Technical development and maintenance. -> * **4J Studios & Mojang:** Original creators of Legacy Console Edition. -> * **smartcmd & The LCE Community:** Research and foundations for Legacy Console Edition on PC. -> * **Tauri & Rust:** Core technologies. - ---- - -***This project is licensed under the [GNU GPL v3 License](LICENSE)*** - \ No newline at end of file +
+ Emerald Legacy Launcher Logo +

Emerald Legacy Launcher

+

FOSS cross-platform launcher for Minecraft Legacy Console Edition

+ +

+ Version + License + Platforms +

+
+ +

+ + Donate to the Project + + + Join the Community + +

+ +--- + +> [!IMPORTANT] +> **Emerald Legacy Launcher is currently in Beta.** +> Expect minor bugs, frequent updates, and features that are still being polished as we work toward a stable release. + +--- + +## Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [Screenshots](#screenshots) +- [Installation](#installation) + - [Windows](#windows) + - [macOS](#macos) + - [Linux](#linux) +- [Game Versions & Partnerships](#game-versions--partnerships) +- [Building from Source](#building-from-source) +- [Development](#development) + - [Project Structure](#project-structure) + - [Tech Stack](#tech-stack) +- [Troubleshooting](#troubleshooting) +- [Roadmap](#roadmap) +- [Acknowledgments](#acknowledgments) +- [License](#license) + +--- + +## Overview + +Emerald Legacy Launcher is a **high-performance, open-source launcher** for Minecraft Legacy Console Edition (LCE). Built to centralize the fragmented LCE scene, it provides a lightweight, unified hub for playing your favorite console versions of Minecraft on PC. + +**Why Emerald?** Traditional launchers often rely on bloated frameworks, consuming excessive resources. Emerald utilizes a modern **Rust/Tauri** architecture, using only **~15MB of RAM** — leaving your PC's resources dedicated to the game itself. + +The project started as a solo effort and has grown into a collaborative community project, bringing together expertise from various LCE preservation initiatives. + +--- + +## Features + +### Core Features + +| Feature | Description | +|---------|-------------| +| **Automated Setup** | One-click installation for TU19, Legacy Evolved, Revelations, and 360Revived versions | +| **Cross-Platform** | Native support for Windows, macOS (Intel & Apple Silicon), and Linux | +| **Lightweight** | Very light RAM usage thanks to Rust backend and Tauri framework | +| **Easy Configuration** | Built-in settings for username, game parameters, and profiles | + +### Advanced Features + +| Feature | Description | +|---------|-------------| +| **3D Skin Viewer** | Interactive skin preview using Three.js with layer support | +| **Custom Skins** | Import and manage your own skins with local storage | +| **Controller Support** | Full gamepad navigation support (keyboard fallback included) | +| **Discord Rich Presence** | Show your current activity and game status on Discord | +| **Workshop and modloader** | *(Coming Soon)* Community content and mod browser | + +--- + +## Game Versions & Partnerships + +Emerald Legacy Launcher integrates multiple community-driven builds of Minecraft Legacy Console Edition. Each build brings unique features and improvements to the classic LCE experience. + +### Available Builds + +| Build | Developer | Platform | Description | +|-------|-----------|----------|-------------| +| **[Revelations](https://github.com/itsRevela/MinecraftConsoles)** | [@itsRevela](https://github.com/itsRevela) | GitHub | Enhanced LCE with uncapped FPS, graphics fixes, hardcore hearts, and dedicated server security. Features LAN multiplayer, split-screen, and keyboard & mouse support. | +| **[360 Revived](https://github.com/BluTac10/360Revived)** | [@BluTac10](https://github.com/BluTac10) | GitHub | PC port of Xbox 360 Edition TU19 with desktop optimizations. Features keyboard & mouse, fullscreen, LAN multiplayer, dedicated server, and split-screen support. | +| **[Legacy Evolved](https://codeberg.org/piebot/LegacyEvolved)** | [@piebot](https://codeberg.org/piebot) | Codeberg | Backports newer title updates to LCE TU19 base. Currently porting TU25 (~98% complete) and TU31 (~76% complete). | +| **[Title Update 19](https://github.com/smartcmd/MinecraftConsoles)** | [@smartcmd](https://github.com/smartcmd) | GitHub | Minecraft LCE v1.6.0560.0 with compilation fixes. Base version for modding with keyboard & mouse, fullscreen, LAN multiplayer, and dedicated server support. | + +### Coming Soon: Legacy Minecraft Restoration Project (LMRP) + +**LMRP** will be our **first major collaboration** to bring fully functional **online mini-games** back to Legacy Console Edition. This groundbreaking project aims to: + +- Restore classic LCE mini-games (Battle, Tumble, Glide) +- Preserve the authentic mini-game mechanics and maps + +Stay tuned for updates on this exciting partnership! :) + +--- + +## Screenshots + +Emerald Legacy Launcher Screenshot + +--- + +## Installation + +### Windows + +Download the latest release from [GitHub Releases](https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher/releases): + +| Format | Best For | +|--------|----------| +| `.exe` (NSIS) | Standard installation with uninstaller | +| `.msi` | Enterprise/IT deployment | + +**⚠️ Windows SmartScreen Warning:** +> Since the launcher is unsigned, Windows may show a "Windows protected your PC" warning. To proceed: +> 1. Click **"More info"** +> 2. Click **"Run anyway"** + +### macOS + +| Format | Architecture | +|--------|-------------| +| `.dmg` (x64) | Intel Macs | +| `.dmg` (aarch64) | Apple Silicon (M1/M2/M3) | + +**Installation Steps:** +1. Download the appropriate DMG for your Mac +2. Open the DMG and drag the app to Applications +3. If you see "app is damaged" error: + - Right-click the app → **Open** → confirm **Open** + - Or run: `xattr -cr "/Applications/Emerald Legacy Launcher.app"` + +### Linux + +Multiple distribution formats available: + +| Format | Distribution | +|--------|------------| +| `.deb` | Debian, Ubuntu, Linux Mint | +| `.rpm` | RHEL, Fedora, openSUSE | +| `.AppImage` | Universal (no installation required) | +| `Flatpak` | Universal with sandboxing | + +**Flatpak Installation:** +```bash +flatpak install emerald.flatpak +``` + +**Dependencies (if building from source):** +```bash +# Ubuntu/Debian +sudo apt install libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libudev-dev + +# Fedora +sudo dnf install webkit2gtk4.1-devel libappindicator-gtk3-devel librsvg2-devel patchelf systemd-devel +``` + +--- + +## Building from Source + +### Requirements + +- **Node.js** (LTS recommended) +- **Rust** (latest stable) +- **PNPM** (recommended) or NPM +- Platform-specific dependencies: + - Linux: `WebKit2GTK-4.1` + - macOS: WebKit (pre-installed) + - Windows: Edge WebView2 Runtime (usually pre-installed) + +### Build Steps + +```bash +# Clone the repository +git clone https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher.git +cd Emerald-Legacy-Launcher + +# Install dependencies +pnpm install + +# Development mode +pnpm tauri dev + +# Production build +pnpm tauri build +``` + +**Flatpak Build:** +```bash +pnpm flatpak +``` + +--- + +## Development + +### Project Structure + +``` +Emerald-Legacy-Launcher/ +├── src/ # React frontend +│ ├── components/ # UI components +│ ├── context/ # React context providers +│ ├── hooks/ # Custom React hooks +│ ├── pages/ # Page components +│ ├── services/ # API/services layer +│ └── css/ # Global styles +├── src-tauri/ # Rust backend +│ ├── src/ # Rust source code +│ ├── Cargo.toml # Rust dependencies +│ └── tauri.conf.json # Tauri configuration +├── public/ # Static assets +├── flatpak/ # Flatpak build config +└── scripts/ # Build scripts +``` + +### Tech Stack + +| Layer | Technology | Version | +|-------|-----------|---------| +| **Backend** | Rust | 2021 Edition | +| **Framework** | Tauri | v2 | +| **Frontend** | React | ^19.1.0 | +| **Language** | TypeScript | ~5.8.3 | +| **Styling** | TailwindCSS | v4 | +| **Animations** | Framer Motion | ^12.36.0 | +| **3D Rendering** | Three.js | ^0.183.2 | +| **Build Tool** | Vite | ^7.0.4 | + +### Key Dependencies + +**Rust Crates:** +- `tauri` — Cross-platform app framework +- `serde` — Serialization +- `reqwest` — HTTP client +- `tokio` — Async runtime +- `rfd` — Native file dialogs + +**Frontend Packages:** +- `@tauri-apps/api` — Tauri JS API +- `tauri-plugin-drpc` — Discord Rich Presence +- `tauri-plugin-gamepad-api` — Controller support + +--- + +## Troubleshooting + +### macOS "App is Damaged" Error + +```bash +# Remove quarantine attributes +xattr -cr /path/to/Emerald\ Legacy\ Launcher.app +``` + +### Linux WebView Issues + +Ensure WebKit2GTK-4.1 is installed: +```bash +# Check installation +pkg-config --modversion webkit2gtk-4.1 + +# Reinstall if needed +sudo apt install --reinstall libwebkit2gtk-4.1-0 +``` + +### Game Not Launching + +1. Verify game files are properly installed via the launcher +2. Check that Wine/Proton is installed (Linux only) +3. Check that Wine/GPTK3 are installed (macOS only) +4. Ensure your GPU drivers are up to date + +### Controller Not Detected + +- Connect controller before launching the launcher +- Xbox and PlayStation controllers are best supported + +--- + +## Roadmap + +Track our progress and upcoming features on the [Development Roadmap](https://github.com/orgs/Emerald-Legacy-Launcher/projects/2). + +**Planned Features:** +- [ ] Workshop content browser +- [ ] Additional TU versions support +- [ ] Enhanced mod support +- [ ] Cloud sync for settings/skins +- [ ] Auto-updater integration + +--- + +## Acknowledgments + +*Proudly developed by a passionate team from the LCE community.* + +- **The Emerald Team** — Technical development and maintenance +- **4J Studios & Mojang** — Original creators of Legacy Console Edition +- **smartcmd & The LCE Community** — Research and foundations for LCE on PC +- **Tauri & Rust Communities** — Core technologies and ecosystem + +--- + +## License + +This project is licensed under the **[GNU GPL v3 License](LICENSE)**. + +You are free to: +- **Use** — Use the launcher for any purpose +- **Study** — Access and study the source code +- **Share** — Redistribute copies +- **Improve** — Submit improvements and modifications + +See `LICENSE` file for full terms. diff --git a/assets/screenshots/main-window.png b/assets/screenshots/main-window.png new file mode 100644 index 0000000..6234411 Binary files /dev/null and b/assets/screenshots/main-window.png differ diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..dd3a7bb --- /dev/null +++ b/bun.lock @@ -0,0 +1,546 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "emerald-legacy-launcher", + "dependencies": { + "@tailwindcss/vite": "^4.2.1", + "@tauri-apps/api": "^2.10.1", + "@tauri-apps/plugin-opener": "^2.5.3", + "framer-motion": "^12.36.0", + "path": "^0.12.7", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.13.1", + "tauri-plugin-drpc": "^1.0.3", + "tauri-plugin-gamepad-api": "^0.0.5", + "three": "^0.183.2", + }, + "devDependencies": { + "@tauri-apps/cli": "^2.10.1", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@types/three": "^0.183.1", + "@vitejs/plugin-react": "^4.6.0", + "autoprefixer": "^10.4.27", + "postcss": "^8.5.8", + "tailwindcss": "^3.4.19", + "typescript": "~5.8.3", + "vite": "^7.0.4", + }, + }, + }, + "packages": { + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + + "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], + + "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], + + "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], + + "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], + + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], + + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], + + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], + + "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], + + "@dimforge/rapier3d-compat": ["@dimforge/rapier3d-compat@0.12.0", "", {}, "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="], + + "@tauri-apps/api": ["@tauri-apps/api@2.10.1", "", {}, "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw=="], + + "@tauri-apps/cli": ["@tauri-apps/cli@2.10.1", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.10.1", "@tauri-apps/cli-darwin-x64": "2.10.1", "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1", "@tauri-apps/cli-linux-arm64-gnu": "2.10.1", "@tauri-apps/cli-linux-arm64-musl": "2.10.1", "@tauri-apps/cli-linux-riscv64-gnu": "2.10.1", "@tauri-apps/cli-linux-x64-gnu": "2.10.1", "@tauri-apps/cli-linux-x64-musl": "2.10.1", "@tauri-apps/cli-win32-arm64-msvc": "2.10.1", "@tauri-apps/cli-win32-ia32-msvc": "2.10.1", "@tauri-apps/cli-win32-x64-msvc": "2.10.1" }, "bin": { "tauri": "tauri.js" } }, "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g=="], + + "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.10.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ=="], + + "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.10.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw=="], + + "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.10.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w=="], + + "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.10.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA=="], + + "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.10.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg=="], + + "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.10.1", "", { "os": "linux", "cpu": "none" }, "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw=="], + + "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.10.1", "", { "os": "linux", "cpu": "x64" }, "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw=="], + + "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.10.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ=="], + + "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.10.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg=="], + + "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.10.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw=="], + + "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.10.1", "", { "os": "win32", "cpu": "x64" }, "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg=="], + + "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ=="], + + "@tweenjs/tween.js": ["@tweenjs/tween.js@23.1.3", "", {}, "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="], + + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], + + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], + + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], + + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], + + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + + "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], + + "@types/three": ["@types/three@0.183.1", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": ">=0.5.17", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~1.0.1" } }, "sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw=="], + + "@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="], + + "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], + + "@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + + "autoprefixer": ["autoprefixer@10.4.27", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": "bin/autoprefixer" }, "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": "dist/cli.cjs" }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": "cli.js" }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], + + "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001778", "", {}, "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": "bin/cssesc" }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.313", "", {}, "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA=="], + + "enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="], + + "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": "bin/esbuild" }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], + + "framer-motion": ["framer-motion@12.36.0", "", { "dependencies": { "motion-dom": "^12.36.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "jiti": ["jiti@1.21.7", "", { "bin": "bin/jiti.js" }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], + + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "meshoptimizer": ["meshoptimizer@1.0.1", "", {}, "sha512-Vix+QlA1YYT3FwmBBZ+49cE5y/b+pRrcXKqGpS5ouh33d3lSp2PoTpCw19E0cKDFWalembrHnIaZetf27a+W2g=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "motion-dom": ["motion-dom@12.36.0", "", { "dependencies": { "motion-utils": "^12.36.0" } }, "sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA=="], + + "motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + + "path": ["path@0.12.7", "", { "dependencies": { "process": "^0.11.1", "util": "^0.10.3" } }, "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], + + "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], + + "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], + + "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="], + + "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], + + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], + + "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], + + "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + + "react-router": ["react-router@7.13.1", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA=="], + + "react-router-dom": ["react-router-dom@7.13.1", "", { "dependencies": { "react-router": "7.13.1" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw=="], + + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="], + + "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], + + "tauri-plugin-drpc": ["tauri-plugin-drpc@1.0.3", "", { "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-vl5dXhjKbl7+Nf9veW12usdmIUtZXwEf91SzxQPZlbRRJ/sjizbbQlnkUTtx6baJuGzz0KXXgP9xUhF39BdiXQ=="], + + "tauri-plugin-gamepad-api": ["tauri-plugin-gamepad-api@0.0.5", "", { "dependencies": { "@tauri-apps/api": "2.1.1", "tslib": "^2.1.0" } }, "sha512-WO0xwXmPr4PMe9HzljKUbTkGv7J6ur2Df/OuEPsxBeSA5QPffAJR3N32M4pM4yW72D9Vt19XplPnHHDVATVMSw=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "three": ["three@0.183.2", "", {}, "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + + "util": ["util@0.10.4", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "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" }, "optionalPeers": ["@types/node", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], + + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "@tailwindcss/node/tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], + + "@tailwindcss/vite/tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], + + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "tauri-plugin-gamepad-api/@tauri-apps/api": ["@tauri-apps/api@2.1.1", "", {}, "sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A=="], + } +} diff --git a/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop new file mode 100644 index 0000000..e013914 --- /dev/null +++ b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=Emerald Legacy Launcher +Comment=FOSS cross-platform launcher for Minecraft Legacy Console Edition +Exec=emerald-legacy-launcher +Icon=io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher +Type=Application +Categories=Game; \ No newline at end of file diff --git a/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.metainfo.xml b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.metainfo.xml new file mode 100644 index 0000000..5e9956a --- /dev/null +++ b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.metainfo.xml @@ -0,0 +1,24 @@ + + + io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher + CC0-1.0 + GPL-3.0-or-later + Emerald Legacy Launcher + A launcher for Minecraft Legacy Console Edition + +

FOSS cross-platform launcher for Minecraft Legacy Console Edition

+
+ io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop + https://github.com + Emerald Team + + + +

Latest stable release of the Emerald Legacy Launcher.

+
+
+
+ + emerald-legacy-launcher + +
diff --git a/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml new file mode 100644 index 0000000..10c2482 --- /dev/null +++ b/flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml @@ -0,0 +1,47 @@ +app-id: io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher +runtime: org.gnome.Platform +runtime-version: "48" +sdk: org.gnome.Sdk +sdk-extensions: + - org.freedesktop.Sdk.Extension.node20 + - org.freedesktop.Sdk.Extension.rust-stable +command: emerald-legacy-launcher +finish-args: + - --share=network + - --device=input + - --socket=x11 + - --socket=wayland + - --device=dri + - --filesystem=xdg-data + - --socket=pulseaudio + - --filesystem=xdg-run/pipewire-0 + +modules: + - shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json + - name: emerald-legacy-launcher + buildsystem: simple + build-options: + append-path: /usr/lib/sdk/node20/bin:/usr/lib/sdk/rust-stable/bin + build-args: + - --share=network + env: + PKG_CONFIG_PATH: /usr/lib/sdk/node20/lib/pkgconfig:/usr/lib/sdk/rust-stable/lib/pkgconfig + CARGO_HOME: /run/build/emerald-legacy-launcher/cargo + PNPM_HOME: /run/build/emerald-legacy-launcher/pnpm-home + build-commands: + - . /usr/lib/sdk/rust-stable/enable.sh + - mkdir -p /run/build/emerald-legacy-launcher/pnpm-bin + - curl -fSL https://github.com/pnpm/pnpm/releases/download/v10.32.1/pnpm-linux-x64 -o /run/build/emerald-legacy-launcher/pnpm-bin/pnpm # yes i hardcode URLs + - chmod +x /run/build/emerald-legacy-launcher/pnpm-bin/pnpm + - export PATH=/run/build/emerald-legacy-launcher/pnpm-bin:$PATH + - CI=true PATH=/run/build/emerald-legacy-launcher/pnpm-bin:$PATH /run/build/emerald-legacy-launcher/pnpm-bin/pnpm install + - CI=true PATH=/run/build/emerald-legacy-launcher/pnpm-bin:$PATH /run/build/emerald-legacy-launcher/pnpm-bin/pnpm tauri build --no-bundle + - install -Dm755 src-tauri/target/release/emerald-legacy-launcher /app/bin/emerald-legacy-launcher + - mkdir -p /app/share/emerald-legacy-launcher/ + - cp -r dist /app/share/emerald-legacy-launcher/ + - install -Dm644 flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop /app/share/applications/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.desktop + - install -Dm644 flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.metainfo.xml /app/share/metainfo/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.metainfo.xml + - install -Dm644 public/images/icon.png /app/share/icons/hicolor/512x512/apps/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.png + sources: + - type: dir + path: .. diff --git a/flatpak/shared-modules b/flatpak/shared-modules new file mode 160000 index 0000000..2f1fb18 --- /dev/null +++ b/flatpak/shared-modules @@ -0,0 +1 @@ +Subproject commit 2f1fb187252a619f4775e3126395584041b071fb diff --git a/index.html b/index.html index 2a62704..fe4ae1e 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,16 @@ - - - - - - Emerald Legacy - - -
- - - \ No newline at end of file + + + + + + + + + Emerald Legacy Launcher + + + +
+ + + diff --git a/package-lock.json b/package-lock.json index 3ad056f..5c4f5a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3565 +1,2908 @@ -{ - "name": "emerald-legacy-launcher", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "emerald-legacy-launcher", - "version": "0.1.0", - "dependencies": { - "@tailwindcss/vite": "^4.2.1", - "@tauri-apps/api": "^2.10.1", - "@tauri-apps/plugin-opener": "^2.5.3", - "react": "^19.1.0", - "react-dom": "^19.1.0" - }, - "devDependencies": { - "@tauri-apps/cli": "^2.10.1", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.6.0", - "autoprefixer": "^10.4.27", - "postcss": "^8.5.8", - "tailwindcss": "^3.4.19", - "typescript": "~5.8.3", - "vite": "^7.0.4" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@tailwindcss/node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", - "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.19.0", - "jiti": "^2.6.1", - "lightningcss": "1.31.1", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.2.1" - } - }, - "node_modules/@tailwindcss/node/node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", - "license": "MIT" - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", - "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-x64": "4.2.1", - "@tailwindcss/oxide-freebsd-x64": "4.2.1", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-x64-musl": "4.2.1", - "@tailwindcss/oxide-wasm32-wasi": "4.2.1", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", - "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", - "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", - "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", - "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", - "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", - "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", - "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", - "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", - "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", - "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", - "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.8.1", - "@emnapi/runtime": "^1.8.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.1", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", - "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", - "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz", - "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==", - "license": "MIT", - "dependencies": { - "@tailwindcss/node": "4.2.1", - "@tailwindcss/oxide": "4.2.1", - "tailwindcss": "4.2.1" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" - } - }, - "node_modules/@tailwindcss/vite/node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", - "license": "MIT" - }, - "node_modules/@tauri-apps/api": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", - "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==", - "license": "Apache-2.0 OR MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/tauri" - } - }, - "node_modules/@tauri-apps/cli": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.1.tgz", - "integrity": "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "bin": { - "tauri": "tauri.js" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/tauri" - }, - "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.10.1", - "@tauri-apps/cli-darwin-x64": "2.10.1", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1", - "@tauri-apps/cli-linux-arm64-gnu": "2.10.1", - "@tauri-apps/cli-linux-arm64-musl": "2.10.1", - "@tauri-apps/cli-linux-riscv64-gnu": "2.10.1", - "@tauri-apps/cli-linux-x64-gnu": "2.10.1", - "@tauri-apps/cli-linux-x64-musl": "2.10.1", - "@tauri-apps/cli-win32-arm64-msvc": "2.10.1", - "@tauri-apps/cli-win32-ia32-msvc": "2.10.1", - "@tauri-apps/cli-win32-x64-msvc": "2.10.1" - } - }, - "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.1.tgz", - "integrity": "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.1.tgz", - "integrity": "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.1.tgz", - "integrity": "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.1.tgz", - "integrity": "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.1.tgz", - "integrity": "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.1.tgz", - "integrity": "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.1.tgz", - "integrity": "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.1.tgz", - "integrity": "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.1.tgz", - "integrity": "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.1.tgz", - "integrity": "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.1.tgz", - "integrity": "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 OR MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/plugin-opener": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz", - "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==", - "license": "MIT OR Apache-2.0", - "dependencies": { - "@tauri-apps/api": "^2.8.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/autoprefixer": { - "version": "10.4.27", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", - "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001774", - "fraction.js": "^5.3.4", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001778", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001778.tgz", - "integrity": "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.313", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", - "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", - "dev": true, - "license": "ISC" - }, - "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lightningcss": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", - "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.31.1", - "lightningcss-darwin-arm64": "1.31.1", - "lightningcss-darwin-x64": "1.31.1", - "lightningcss-freebsd-x64": "1.31.1", - "lightningcss-linux-arm-gnueabihf": "1.31.1", - "lightningcss-linux-arm64-gnu": "1.31.1", - "lightningcss-linux-arm64-musl": "1.31.1", - "lightningcss-linux-x64-gnu": "1.31.1", - "lightningcss-linux-x64-musl": "1.31.1", - "lightningcss-win32-arm64-msvc": "1.31.1", - "lightningcss-win32-x64-msvc": "1.31.1" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", - "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", - "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", - "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", - "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", - "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", - "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", - "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", - "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", - "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", - "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", - "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", - "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map-js": { - "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==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sucrase": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", - "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "tinyglobby": "^0.2.11", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", - "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.7", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "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" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} +{ + "name": "emerald-legacy-launcher", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "emerald-legacy-launcher", + "version": "1.0.0", + "dependencies": { + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-opener": "^2", + "framer-motion": "^12.36.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "three": "^0.183.2" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.2.1", + "@tailwindcss/vite": "^4.2.1", + "@tauri-apps/cli": "^2", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@types/three": "^0.183.1", + "@vitejs/plugin-react": "^4.6.0", + "autoprefixer": "^10.4.27", + "postcss": "^8.5.8", + "tailwindcss": "^4.2.1", + "tauri-plugin-drpc": "^1.0.3", + "tauri-plugin-gamepad-api": "^0.0.5", + "typescript": "~5.8.3", + "vite": "^7.0.4" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@dimforge/rapier3d-compat": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", + "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.31.1", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-x64": "4.2.1", + "@tailwindcss/oxide-freebsd-x64": "4.2.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.1.tgz", + "integrity": "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "postcss": "^8.5.6", + "tailwindcss": "4.2.1" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz", + "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "tailwindcss": "4.2.1" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@tauri-apps/api": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", + "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==", + "license": "Apache-2.0 OR MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + } + }, + "node_modules/@tauri-apps/cli": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.1.tgz", + "integrity": "sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==", + "dev": true, + "license": "Apache-2.0 OR MIT", + "bin": { + "tauri": "tauri.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + }, + "optionalDependencies": { + "@tauri-apps/cli-darwin-arm64": "2.10.1", + "@tauri-apps/cli-darwin-x64": "2.10.1", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.1", + "@tauri-apps/cli-linux-arm64-gnu": "2.10.1", + "@tauri-apps/cli-linux-arm64-musl": "2.10.1", + "@tauri-apps/cli-linux-riscv64-gnu": "2.10.1", + "@tauri-apps/cli-linux-x64-gnu": "2.10.1", + "@tauri-apps/cli-linux-x64-musl": "2.10.1", + "@tauri-apps/cli-win32-arm64-msvc": "2.10.1", + "@tauri-apps/cli-win32-ia32-msvc": "2.10.1", + "@tauri-apps/cli-win32-x64-msvc": "2.10.1" + } + }, + "node_modules/@tauri-apps/cli-darwin-arm64": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.1.tgz", + "integrity": "sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-darwin-x64": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.1.tgz", + "integrity": "sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.1.tgz", + "integrity": "sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-gnu": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.1.tgz", + "integrity": "sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-musl": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.1.tgz", + "integrity": "sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.1.tgz", + "integrity": "sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-gnu": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.1.tgz", + "integrity": "sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-musl": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.1.tgz", + "integrity": "sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-arm64-msvc": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.1.tgz", + "integrity": "sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-ia32-msvc": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.1.tgz", + "integrity": "sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-x64-msvc": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.1.tgz", + "integrity": "sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/plugin-opener": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz", + "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.8.0" + } + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.183.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.183.1.tgz", + "integrity": "sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@dimforge/rapier3d-compat": "~0.12.0", + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": ">=0.5.17", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~1.0.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@webgpu/types": { + "version": "0.1.69", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz", + "integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", + "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001778", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001778.tgz", + "integrity": "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.313", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", + "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esbuild": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/framer-motion": { + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.36.0.tgz", + "integrity": "sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.36.0", + "motion-utils": "^12.36.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "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, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/meshoptimizer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.0.1.tgz", + "integrity": "sha512-Vix+QlA1YYT3FwmBBZ+49cE5y/b+pRrcXKqGpS5ouh33d3lSp2PoTpCw19E0cKDFWalembrHnIaZetf27a+W2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/motion-dom": { + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.36.0.tgz", + "integrity": "sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.36.0" + } + }, + "node_modules/motion-utils": { + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", + "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": 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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tauri-plugin-drpc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tauri-plugin-drpc/-/tauri-plugin-drpc-1.0.3.tgz", + "integrity": "sha512-vl5dXhjKbl7+Nf9veW12usdmIUtZXwEf91SzxQPZlbRRJ/sjizbbQlnkUTtx6baJuGzz0KXXgP9xUhF39BdiXQ==", + "dev": true, + "peerDependencies": { + "typescript": "^5.0.0" + } + }, + "node_modules/tauri-plugin-gamepad-api": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/tauri-plugin-gamepad-api/-/tauri-plugin-gamepad-api-0.0.5.tgz", + "integrity": "sha512-WO0xwXmPr4PMe9HzljKUbTkGv7J6ur2Df/OuEPsxBeSA5QPffAJR3N32M4pM4yW72D9Vt19XplPnHHDVATVMSw==", + "dev": true, + "dependencies": { + "@tauri-apps/api": "2.1.1", + "tslib": "^2.1.0" + } + }, + "node_modules/tauri-plugin-gamepad-api/node_modules/@tauri-apps/api": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.1.1.tgz", + "integrity": "sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A==", + "dev": true, + "license": "Apache-2.0 OR MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + } + }, + "node_modules/three": { + "version": "0.183.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.183.2.tgz", + "integrity": "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "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" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json index 3a343a2..ab6fc0c 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,39 @@ -{ - "name": "emerald-legacy-launcher", - "private": true, - "version": "0.2.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "tauri": "tauri" - }, - "dependencies": { - "@tailwindcss/vite": "^4.2.1", - "@tauri-apps/api": "^2.10.1", - "@tauri-apps/plugin-opener": "^2.5.3", - "react": "^19.1.0", - "react-dom": "^19.1.0" - }, - "devDependencies": { - "@tauri-apps/cli": "^2.10.1", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.6.0", - "autoprefixer": "^10.4.27", - "postcss": "^8.5.8", - "tailwindcss": "^3.4.19", - "typescript": "~5.8.3", - "vite": "^7.0.4" - } -} +{ + "name": "emerald-legacy-launcher", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "tauri": "tauri", + "tauri:build": "tauri build && pnpm run post-build:macos", + "post-build:macos": "sh src-tauri/scripts/post-build-macos.sh", + "flatpak": "flatpak-builder --user --install-deps-from=flathub --repo=emerald-repo --force-clean build-flatpak flatpak/io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher.yml && flatpak build-bundle emerald-repo emerald.flatpak io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher" + }, + "dependencies": { + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-opener": "^2", + "framer-motion": "^12.36.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "three": "^0.183.2" + }, + "devDependencies": { + "@types/three": "^0.183.1", + "@tailwindcss/postcss": "^4.2.1", + "@tailwindcss/vite": "^4.2.1", + "@tauri-apps/cli": "^2", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^4.6.0", + "autoprefixer": "^10.4.27", + "postcss": "^8.5.8", + "tailwindcss": "^4.2.1", + "typescript": "~5.8.3", + "vite": "^7.0.4", + "tauri-plugin-drpc": "^1.0.3", + "tauri-plugin-gamepad-api": "^0.0.5" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb9a0c5..4233947 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,24 +8,33 @@ importers: .: dependencies: - '@tailwindcss/vite': - specifier: ^4.2.1 - version: 4.2.1(vite@7.3.1(jiti@1.21.7)(lightningcss@1.31.1)) '@tauri-apps/api': - specifier: ^2.10.1 + specifier: ^2 version: 2.10.1 '@tauri-apps/plugin-opener': - specifier: ^2.5.3 + specifier: ^2 version: 2.5.3 + framer-motion: + specifier: ^12.36.0 + version: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: specifier: ^19.1.0 version: 19.2.4 react-dom: specifier: ^19.1.0 version: 19.2.4(react@19.2.4) + three: + specifier: ^0.183.2 + version: 0.183.2 devDependencies: + '@tailwindcss/postcss': + specifier: ^4.2.1 + version: 4.2.1 + '@tailwindcss/vite': + specifier: ^4.2.1 + version: 4.2.1(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) '@tauri-apps/cli': - specifier: ^2.10.1 + specifier: ^2 version: 2.10.1 '@types/react': specifier: ^19.1.8 @@ -33,9 +42,12 @@ importers: '@types/react-dom': specifier: ^19.1.6 version: 19.2.3(@types/react@19.2.14) + '@types/three': + specifier: ^0.183.1 + version: 0.183.1 '@vitejs/plugin-react': specifier: ^4.6.0 - version: 4.7.0(vite@7.3.1(jiti@1.21.7)(lightningcss@1.31.1)) + version: 4.7.0(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) autoprefixer: specifier: ^10.4.27 version: 10.4.27(postcss@8.5.8) @@ -43,14 +55,20 @@ importers: specifier: ^8.5.8 version: 8.5.8 tailwindcss: - specifier: ^3.4.19 - version: 3.4.19 + specifier: ^4.2.1 + version: 4.2.1 + tauri-plugin-drpc: + specifier: ^1.0.3 + version: 1.0.3(typescript@5.8.3) + tauri-plugin-gamepad-api: + specifier: ^0.0.5 + version: 0.0.5 typescript: specifier: ~5.8.3 version: 5.8.3 vite: specifier: ^7.0.4 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.31.1) + version: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) packages: @@ -108,12 +126,12 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} engines: {node: '>=6.0.0'} hasBin: true @@ -141,158 +159,161 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@esbuild/aix-ppc64@0.27.3': - resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + + '@esbuild/aix-ppc64@0.27.4': + resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.3': - resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + '@esbuild/android-arm64@0.27.4': + resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.3': - resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + '@esbuild/android-arm@0.27.4': + resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.3': - resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + '@esbuild/android-x64@0.27.4': + resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.3': - resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + '@esbuild/darwin-arm64@0.27.4': + resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.3': - resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + '@esbuild/darwin-x64@0.27.4': + resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.3': - resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + '@esbuild/freebsd-arm64@0.27.4': + resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': - resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + '@esbuild/freebsd-x64@0.27.4': + resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.3': - resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + '@esbuild/linux-arm64@0.27.4': + resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.3': - resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + '@esbuild/linux-arm@0.27.4': + resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.3': - resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + '@esbuild/linux-ia32@0.27.4': + resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.3': - resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + '@esbuild/linux-loong64@0.27.4': + resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.3': - resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + '@esbuild/linux-mips64el@0.27.4': + resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.3': - resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + '@esbuild/linux-ppc64@0.27.4': + resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.3': - resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + '@esbuild/linux-riscv64@0.27.4': + resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.3': - resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + '@esbuild/linux-s390x@0.27.4': + resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.3': - resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + '@esbuild/linux-x64@0.27.4': + resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.3': - resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + '@esbuild/netbsd-arm64@0.27.4': + resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': - resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + '@esbuild/netbsd-x64@0.27.4': + resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.3': - resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + '@esbuild/openbsd-arm64@0.27.4': + resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': - resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + '@esbuild/openbsd-x64@0.27.4': + resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.3': - resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + '@esbuild/openharmony-arm64@0.27.4': + resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.3': - resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + '@esbuild/sunos-x64@0.27.4': + resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.3': - resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + '@esbuild/win32-arm64@0.27.4': + resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.3': - resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + '@esbuild/win32-ia32@0.27.4': + resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.3': - resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + '@esbuild/win32-x64@0.27.4': + resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -313,18 +334,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} @@ -362,66 +371,79 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -491,24 +513,28 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.1': resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.1': resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.1': resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.1': resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} @@ -538,11 +564,17 @@ packages: resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} engines: {node: '>= 20'} + '@tailwindcss/postcss@4.2.1': + resolution: {integrity: sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==} + '@tailwindcss/vite@4.2.1': resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@tauri-apps/api@2.1.1': + resolution: {integrity: sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A==} + '@tauri-apps/api@2.10.1': resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==} @@ -569,30 +601,35 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.10.1': resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.10.1': resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.10.1': resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.10.1': resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} @@ -620,6 +657,9 @@ packages: '@tauri-apps/plugin-opener@2.5.3': resolution: {integrity: sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==} + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -643,21 +683,23 @@ packages: '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + + '@types/three@0.183.1': + resolution: {integrity: sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw==} + + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + '@vitejs/plugin-react@4.7.0': resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + '@webgpu/types@0.1.69': + resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==} autoprefixer@10.4.27: resolution: {integrity: sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==} @@ -666,47 +708,22 @@ packages: peerDependencies: postcss: ^8.1.0 - baseline-browser-mapping@2.10.0: - resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} + baseline-browser-mapping@2.10.8: + resolution: {integrity: sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==} engines: {node: '>=6.0.0'} hasBin: true - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - - caniuse-lite@1.0.30001778: - resolution: {integrity: sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} + caniuse-lite@1.0.30001780: + resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -723,21 +740,15 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - - dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - electron-to-chromium@1.5.313: resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==} - enhanced-resolve@5.20.0: - resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} + enhanced-resolve@5.20.1: + resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} engines: {node: '>=10.13.0'} - esbuild@0.27.3: - resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + esbuild@0.27.4: + resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} engines: {node: '>=18'} hasBin: true @@ -745,13 +756,6 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} - fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -761,64 +765,38 @@ packages: picomatch: optional: true - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + framer-motion@12.38.0: + resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - jiti@1.21.7: - resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} - hasBin: true - jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -871,24 +849,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.31.1: resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.31.1: resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.31.1: resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.31.1: resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} @@ -906,33 +888,24 @@ packages: resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} engines: {node: '>= 12.0.0'} - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + meshoptimizer@1.0.1: + resolution: {integrity: sha512-Vix+QlA1YYT3FwmBBZ+49cE5y/b+pRrcXKqGpS5ouh33d3lSp2PoTpCw19E0cKDFWalembrHnIaZetf27a+W2g==} - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + motion-dom@12.38.0: + resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==} + + motion-utils@12.36.0: + resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -941,80 +914,13 @@ packages: node-releases@2.0.36: resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - - postcss-import@15.1.0: - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - - postcss-js@4.1.0: - resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - - postcss-load-config@6.0.1: - resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} - engines: {node: '>= 18'} - peerDependencies: - jiti: '>=1.21.0' - postcss: '>=8.0.9' - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - jiti: - optional: true - postcss: - optional: true - tsx: - optional: true - yaml: - optional: true - - postcss-nested@6.2.0: - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -1022,9 +928,6 @@ packages: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - react-dom@19.2.4: resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} peerDependencies: @@ -1038,30 +941,11 @@ packages: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true - - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.59.0: resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -1073,20 +957,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - sucrase@3.35.1: - resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tailwindcss@3.4.19: - resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} - engines: {node: '>=14.0.0'} - hasBin: true - tailwindcss@4.2.1: resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} @@ -1094,23 +964,23 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} + tauri-plugin-drpc@1.0.3: + resolution: {integrity: sha512-vl5dXhjKbl7+Nf9veW12usdmIUtZXwEf91SzxQPZlbRRJ/sjizbbQlnkUTtx6baJuGzz0KXXgP9xUhF39BdiXQ==} + peerDependencies: + typescript: ^5.0.0 - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tauri-plugin-gamepad-api@0.0.5: + resolution: {integrity: sha512-WO0xwXmPr4PMe9HzljKUbTkGv7J6ur2Df/OuEPsxBeSA5QPffAJR3N32M4pM4yW72D9Vt19XplPnHHDVATVMSw==} + + three@0.183.2: + resolution: {integrity: sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==} tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} @@ -1123,9 +993,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1187,8 +1054,8 @@ snapshots: '@babel/generator': 7.29.1 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.0 + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 @@ -1203,7 +1070,7 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -1243,12 +1110,12 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.28.6': + '@babel/helpers@7.29.2': dependencies: '@babel/template': 7.28.6 '@babel/types': 7.29.0 - '@babel/parser@7.29.0': + '@babel/parser@7.29.2': dependencies: '@babel/types': 7.29.0 @@ -1265,7 +1132,7 @@ snapshots: '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 '@babel/traverse@7.29.0': @@ -1273,7 +1140,7 @@ snapshots: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/template': 7.28.6 '@babel/types': 7.29.0 debug: 4.4.3 @@ -1285,82 +1152,84 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@esbuild/aix-ppc64@0.27.3': + '@dimforge/rapier3d-compat@0.12.0': {} + + '@esbuild/aix-ppc64@0.27.4': optional: true - '@esbuild/android-arm64@0.27.3': + '@esbuild/android-arm64@0.27.4': optional: true - '@esbuild/android-arm@0.27.3': + '@esbuild/android-arm@0.27.4': optional: true - '@esbuild/android-x64@0.27.3': + '@esbuild/android-x64@0.27.4': optional: true - '@esbuild/darwin-arm64@0.27.3': + '@esbuild/darwin-arm64@0.27.4': optional: true - '@esbuild/darwin-x64@0.27.3': + '@esbuild/darwin-x64@0.27.4': optional: true - '@esbuild/freebsd-arm64@0.27.3': + '@esbuild/freebsd-arm64@0.27.4': optional: true - '@esbuild/freebsd-x64@0.27.3': + '@esbuild/freebsd-x64@0.27.4': optional: true - '@esbuild/linux-arm64@0.27.3': + '@esbuild/linux-arm64@0.27.4': optional: true - '@esbuild/linux-arm@0.27.3': + '@esbuild/linux-arm@0.27.4': optional: true - '@esbuild/linux-ia32@0.27.3': + '@esbuild/linux-ia32@0.27.4': optional: true - '@esbuild/linux-loong64@0.27.3': + '@esbuild/linux-loong64@0.27.4': optional: true - '@esbuild/linux-mips64el@0.27.3': + '@esbuild/linux-mips64el@0.27.4': optional: true - '@esbuild/linux-ppc64@0.27.3': + '@esbuild/linux-ppc64@0.27.4': optional: true - '@esbuild/linux-riscv64@0.27.3': + '@esbuild/linux-riscv64@0.27.4': optional: true - '@esbuild/linux-s390x@0.27.3': + '@esbuild/linux-s390x@0.27.4': optional: true - '@esbuild/linux-x64@0.27.3': + '@esbuild/linux-x64@0.27.4': optional: true - '@esbuild/netbsd-arm64@0.27.3': + '@esbuild/netbsd-arm64@0.27.4': optional: true - '@esbuild/netbsd-x64@0.27.3': + '@esbuild/netbsd-x64@0.27.4': optional: true - '@esbuild/openbsd-arm64@0.27.3': + '@esbuild/openbsd-arm64@0.27.4': optional: true - '@esbuild/openbsd-x64@0.27.3': + '@esbuild/openbsd-x64@0.27.4': optional: true - '@esbuild/openharmony-arm64@0.27.3': + '@esbuild/openharmony-arm64@0.27.4': optional: true - '@esbuild/sunos-x64@0.27.3': + '@esbuild/sunos-x64@0.27.4': optional: true - '@esbuild/win32-arm64@0.27.3': + '@esbuild/win32-arm64@0.27.4': optional: true - '@esbuild/win32-ia32@0.27.3': + '@esbuild/win32-ia32@0.27.4': optional: true - '@esbuild/win32-x64@0.27.3': + '@esbuild/win32-x64@0.27.4': optional: true '@jridgewell/gen-mapping@0.3.13': @@ -1382,18 +1251,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 - '@rolldown/pluginutils@1.0.0-beta.27': {} '@rollup/rollup-android-arm-eabi@4.59.0': @@ -1474,7 +1331,7 @@ snapshots: '@tailwindcss/node@4.2.1': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.0 + enhanced-resolve: 5.20.1 jiti: 2.6.1 lightningcss: 1.31.1 magic-string: 0.30.21 @@ -1532,12 +1389,22 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 - '@tailwindcss/vite@4.2.1(vite@7.3.1(jiti@1.21.7)(lightningcss@1.31.1))': + '@tailwindcss/postcss@4.2.1': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.2.1 + '@tailwindcss/oxide': 4.2.1 + postcss: 8.5.8 + tailwindcss: 4.2.1 + + '@tailwindcss/vite@4.2.1(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: '@tailwindcss/node': 4.2.1 '@tailwindcss/oxide': 4.2.1 tailwindcss: 4.2.1 - vite: 7.3.1(jiti@1.21.7)(lightningcss@1.31.1) + vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + + '@tauri-apps/api@2.1.1': {} '@tauri-apps/api@2.10.1': {} @@ -1592,9 +1459,11 @@ snapshots: dependencies: '@tauri-apps/api': 2.10.1 + '@tweenjs/tween.js@23.1.3': {} + '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 @@ -1606,7 +1475,7 @@ snapshots: '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': @@ -1623,7 +1492,21 @@ snapshots: dependencies: csstype: 3.2.3 - '@vitejs/plugin-react@4.7.0(vite@7.3.1(jiti@1.21.7)(lightningcss@1.31.1))': + '@types/stats.js@0.17.4': {} + + '@types/three@0.183.1': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + '@webgpu/types': 0.1.69 + fflate: 0.8.2 + meshoptimizer: 1.0.1 + + '@types/webxr@0.5.24': {} + + '@vitejs/plugin-react@4.7.0(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -1631,66 +1514,35 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.3.1(jiti@1.21.7)(lightningcss@1.31.1) + vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) transitivePeerDependencies: - supports-color - any-promise@1.3.0: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@5.0.2: {} + '@webgpu/types@0.1.69': {} autoprefixer@10.4.27(postcss@8.5.8): dependencies: browserslist: 4.28.1 - caniuse-lite: 1.0.30001778 + caniuse-lite: 1.0.30001780 fraction.js: 5.3.4 picocolors: 1.1.1 postcss: 8.5.8 postcss-value-parser: 4.2.0 - baseline-browser-mapping@2.10.0: {} - - binary-extensions@2.3.0: {} - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 + baseline-browser-mapping@2.10.8: {} browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.10.0 - caniuse-lite: 1.0.30001778 + baseline-browser-mapping: 2.10.8 + caniuse-lite: 1.0.30001780 electron-to-chromium: 1.5.313 node-releases: 2.0.36 update-browserslist-db: 1.2.3(browserslist@4.28.1) - camelcase-css@2.0.1: {} - - caniuse-lite@1.0.30001778: {} - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - commander@4.1.1: {} + caniuse-lite@1.0.30001780: {} convert-source-map@2.0.0: {} - cssesc@3.0.0: {} - csstype@3.2.3: {} debug@4.4.3: @@ -1699,109 +1551,68 @@ snapshots: detect-libc@2.1.2: {} - didyoumean@1.2.2: {} - - dlv@1.1.3: {} - electron-to-chromium@1.5.313: {} - enhanced-resolve@5.20.0: + enhanced-resolve@5.20.1: dependencies: graceful-fs: 4.2.11 tapable: 2.3.0 - esbuild@0.27.3: + esbuild@0.27.4: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.3 - '@esbuild/android-arm': 0.27.3 - '@esbuild/android-arm64': 0.27.3 - '@esbuild/android-x64': 0.27.3 - '@esbuild/darwin-arm64': 0.27.3 - '@esbuild/darwin-x64': 0.27.3 - '@esbuild/freebsd-arm64': 0.27.3 - '@esbuild/freebsd-x64': 0.27.3 - '@esbuild/linux-arm': 0.27.3 - '@esbuild/linux-arm64': 0.27.3 - '@esbuild/linux-ia32': 0.27.3 - '@esbuild/linux-loong64': 0.27.3 - '@esbuild/linux-mips64el': 0.27.3 - '@esbuild/linux-ppc64': 0.27.3 - '@esbuild/linux-riscv64': 0.27.3 - '@esbuild/linux-s390x': 0.27.3 - '@esbuild/linux-x64': 0.27.3 - '@esbuild/netbsd-arm64': 0.27.3 - '@esbuild/netbsd-x64': 0.27.3 - '@esbuild/openbsd-arm64': 0.27.3 - '@esbuild/openbsd-x64': 0.27.3 - '@esbuild/openharmony-arm64': 0.27.3 - '@esbuild/sunos-x64': 0.27.3 - '@esbuild/win32-arm64': 0.27.3 - '@esbuild/win32-ia32': 0.27.3 - '@esbuild/win32-x64': 0.27.3 + '@esbuild/aix-ppc64': 0.27.4 + '@esbuild/android-arm': 0.27.4 + '@esbuild/android-arm64': 0.27.4 + '@esbuild/android-x64': 0.27.4 + '@esbuild/darwin-arm64': 0.27.4 + '@esbuild/darwin-x64': 0.27.4 + '@esbuild/freebsd-arm64': 0.27.4 + '@esbuild/freebsd-x64': 0.27.4 + '@esbuild/linux-arm': 0.27.4 + '@esbuild/linux-arm64': 0.27.4 + '@esbuild/linux-ia32': 0.27.4 + '@esbuild/linux-loong64': 0.27.4 + '@esbuild/linux-mips64el': 0.27.4 + '@esbuild/linux-ppc64': 0.27.4 + '@esbuild/linux-riscv64': 0.27.4 + '@esbuild/linux-s390x': 0.27.4 + '@esbuild/linux-x64': 0.27.4 + '@esbuild/netbsd-arm64': 0.27.4 + '@esbuild/netbsd-x64': 0.27.4 + '@esbuild/openbsd-arm64': 0.27.4 + '@esbuild/openbsd-x64': 0.27.4 + '@esbuild/openharmony-arm64': 0.27.4 + '@esbuild/sunos-x64': 0.27.4 + '@esbuild/win32-arm64': 0.27.4 + '@esbuild/win32-ia32': 0.27.4 + '@esbuild/win32-x64': 0.27.4 escalade@3.2.0: {} - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fastq@1.20.1: - dependencies: - reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 + fflate@0.8.2: {} fraction.js@5.3.4: {} + framer-motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + motion-dom: 12.38.0 + motion-utils: 12.36.0 + tslib: 2.8.1 + optionalDependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - gensync@1.0.0-beta.2: {} - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - graceful-fs@4.2.11: {} - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - jiti@1.21.7: {} - jiti@2.6.1: {} js-tokens@4.0.0: {} @@ -1859,10 +1670,6 @@ snapshots: lightningcss-win32-arm64-msvc: 1.31.1 lightningcss-win32-x64-msvc: 1.31.1 - lilconfig@3.1.3: {} - - lines-and-columns@1.2.4: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -1871,72 +1678,24 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - merge2@1.4.1: {} + meshoptimizer@1.0.1: {} - micromatch@4.0.8: + motion-dom@12.38.0: dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + motion-utils: 12.36.0 + + motion-utils@12.36.0: {} ms@2.1.3: {} - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - nanoid@3.3.11: {} node-releases@2.0.36: {} - normalize-path@3.0.0: {} - - object-assign@4.1.1: {} - - object-hash@3.0.0: {} - - path-parse@1.0.7: {} - picocolors@1.1.1: {} - picomatch@2.3.1: {} - picomatch@4.0.3: {} - pify@2.3.0: {} - - pirates@4.0.7: {} - - postcss-import@15.1.0(postcss@8.5.8): - dependencies: - postcss: 8.5.8 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.11 - - postcss-js@4.1.0(postcss@8.5.8): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.8 - - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.8): - dependencies: - lilconfig: 3.1.3 - optionalDependencies: - jiti: 1.21.7 - postcss: 8.5.8 - - postcss-nested@6.2.0(postcss@8.5.8): - dependencies: - postcss: 8.5.8 - postcss-selector-parser: 6.1.2 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - postcss-value-parser@4.2.0: {} postcss@8.5.8: @@ -1945,8 +1704,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - queue-microtask@1.2.3: {} - react-dom@19.2.4(react@19.2.4): dependencies: react: 19.2.4 @@ -1956,22 +1713,6 @@ snapshots: react@19.2.4: {} - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.1.0: {} - rollup@4.59.0: dependencies: '@types/estree': 1.0.8 @@ -2003,78 +1744,33 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - scheduler@0.27.0: {} semver@6.3.1: {} source-map-js@1.2.1: {} - sucrase@3.35.1: - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - commander: 4.1.1 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.7 - tinyglobby: 0.2.15 - ts-interface-checker: 0.1.13 - - supports-preserve-symlinks-flag@1.0.0: {} - - tailwindcss@3.4.19: - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 3.1.3 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.8 - postcss-import: 15.1.0(postcss@8.5.8) - postcss-js: 4.1.0(postcss@8.5.8) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.8) - postcss-nested: 6.2.0(postcss@8.5.8) - postcss-selector-parser: 6.1.2 - resolve: 1.22.11 - sucrase: 3.35.1 - transitivePeerDependencies: - - tsx - - yaml - tailwindcss@4.2.1: {} tapable@2.3.0: {} - thenify-all@1.6.0: + tauri-plugin-drpc@1.0.3(typescript@5.8.3): dependencies: - thenify: 3.3.1 + typescript: 5.8.3 - thenify@3.3.1: + tauri-plugin-gamepad-api@0.0.5: dependencies: - any-promise: 1.3.0 + '@tauri-apps/api': 2.1.1 + tslib: 2.8.1 + + three@0.183.2: {} tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - ts-interface-checker@0.1.13: {} + tslib@2.8.1: {} typescript@5.8.3: {} @@ -2084,11 +1780,9 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - util-deprecate@1.0.2: {} - - vite@7.3.1(jiti@1.21.7)(lightningcss@1.31.1): + vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1): dependencies: - esbuild: 0.27.3 + esbuild: 0.27.4 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.8 @@ -2096,7 +1790,7 @@ snapshots: tinyglobby: 0.2.15 optionalDependencies: fsevents: 2.3.3 - jiti: 1.21.7 + jiti: 2.6.1 lightningcss: 1.31.1 yallist@3.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..efc037a --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +onlyBuiltDependencies: + - esbuild diff --git a/postcss.config.js b/postcss.config.js index 70d778e..47838e0 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,5 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, - } \ No newline at end of file +export default { + plugins: { + '@tailwindcss/postcss': {}, + }, +} \ No newline at end of file diff --git a/public/Skins/Journ3ym3n.png b/public/Skins/Journ3ym3n.png new file mode 100644 index 0000000..df703a8 Binary files /dev/null and b/public/Skins/Journ3ym3n.png differ diff --git a/public/Skins/JustNeki.png b/public/Skins/JustNeki.png new file mode 100644 index 0000000..6333e6b Binary files /dev/null and b/public/Skins/JustNeki.png differ diff --git a/public/Skins/KayJann.png b/public/Skins/KayJann.png new file mode 100644 index 0000000..bcc06c0 Binary files /dev/null and b/public/Skins/KayJann.png differ diff --git a/public/Skins/Leon.png b/public/Skins/Leon.png new file mode 100644 index 0000000..2f5fd0b Binary files /dev/null and b/public/Skins/Leon.png differ diff --git a/public/Skins/Peter.png b/public/Skins/Peter.png new file mode 100644 index 0000000..0e52cc7 Binary files /dev/null and b/public/Skins/Peter.png differ diff --git a/public/Skins/mr_anilex.png b/public/Skins/mr_anilex.png new file mode 100644 index 0000000..462221b Binary files /dev/null and b/public/Skins/mr_anilex.png differ diff --git a/public/Skins/neoapps.png b/public/Skins/neoapps.png new file mode 100644 index 0000000..485ab5b Binary files /dev/null and b/public/Skins/neoapps.png differ diff --git a/public/fonts/CHS/MSYH.ttf b/public/fonts/CHS/MSYH.ttf deleted file mode 100644 index 96d1db1..0000000 Binary files a/public/fonts/CHS/MSYH.ttf and /dev/null differ diff --git a/public/fonts/CHT/DFHeiMedium-B5.ttf b/public/fonts/CHT/DFHeiMedium-B5.ttf deleted file mode 100644 index f9fb489..0000000 Binary files a/public/fonts/CHT/DFHeiMedium-B5.ttf and /dev/null differ diff --git a/public/fonts/CHT/DFTT_R5.TTC b/public/fonts/CHT/DFTT_R5.TTC deleted file mode 100644 index 3483968..0000000 Binary files a/public/fonts/CHT/DFTT_R5.TTC and /dev/null differ diff --git a/public/fonts/JPN/DF-DotDotGothic16.ttf b/public/fonts/JPN/DF-DotDotGothic16.ttf deleted file mode 100644 index 1be2b4b..0000000 Binary files a/public/fonts/JPN/DF-DotDotGothic16.ttf and /dev/null differ diff --git a/public/fonts/JPN/DFGMaruGothic-Md.ttf b/public/fonts/JPN/DFGMaruGothic-Md.ttf deleted file mode 100644 index 4eb4eef..0000000 Binary files a/public/fonts/JPN/DFGMaruGothic-Md.ttf and /dev/null differ diff --git a/public/fonts/KOR/BOKMSD.ttf b/public/fonts/KOR/BOKMSD.ttf deleted file mode 100644 index 83fe869..0000000 Binary files a/public/fonts/KOR/BOKMSD.ttf and /dev/null differ diff --git a/public/fonts/KOR/candadite2.ttf b/public/fonts/KOR/candadite2.ttf deleted file mode 100644 index f2ba094..0000000 Binary files a/public/fonts/KOR/candadite2.ttf and /dev/null differ diff --git a/public/fonts/MinecraftTen.ttf b/public/fonts/MinecraftTen.ttf new file mode 100644 index 0000000..9a539dd Binary files /dev/null and b/public/fonts/MinecraftTen.ttf differ diff --git a/public/fonts/Mojang Font_11.ttf b/public/fonts/Mojang Font_11.ttf deleted file mode 100644 index 969cee5..0000000 Binary files a/public/fonts/Mojang Font_11.ttf and /dev/null differ diff --git a/public/fonts/Mojang Font_7.ttf b/public/fonts/Mojang Font_7.ttf deleted file mode 100644 index 727c5fb..0000000 Binary files a/public/fonts/Mojang Font_7.ttf and /dev/null differ diff --git a/public/fonts/Mojangles_11.abc b/public/fonts/Mojangles_11.abc deleted file mode 100644 index 016fdf9..0000000 Binary files a/public/fonts/Mojangles_11.abc and /dev/null differ diff --git a/public/fonts/Mojangles_7.abc b/public/fonts/Mojangles_7.abc deleted file mode 100644 index 6ce0667..0000000 Binary files a/public/fonts/Mojangles_7.abc and /dev/null differ diff --git a/public/fonts/RU/SpaceMace.ttf b/public/fonts/RU/SpaceMace.ttf deleted file mode 100644 index 70cd3f7..0000000 Binary files a/public/fonts/RU/SpaceMace.ttf and /dev/null differ diff --git a/public/images/Button_Background.png b/public/images/Button_Background.png new file mode 100644 index 0000000..28a3269 Binary files /dev/null and b/public/images/Button_Background.png differ diff --git a/public/images/Button_Background2.png b/public/images/Button_Background2.png new file mode 100644 index 0000000..2bfa4f4 Binary files /dev/null and b/public/images/Button_Background2.png differ diff --git a/public/images/Button_Square.png b/public/images/Button_Square.png new file mode 100644 index 0000000..0843391 Binary files /dev/null and b/public/images/Button_Square.png differ diff --git a/public/images/Button_Square_Highlighted.png b/public/images/Button_Square_Highlighted.png new file mode 100644 index 0000000..c3620fe Binary files /dev/null and b/public/images/Button_Square_Highlighted.png differ diff --git a/public/images/Change_Skin_Icon.png b/public/images/Change_Skin_Icon.png new file mode 100644 index 0000000..62d5012 Binary files /dev/null and b/public/images/Change_Skin_Icon.png differ diff --git a/public/images/Clock_Icon.png b/public/images/Clock_Icon.png new file mode 100644 index 0000000..07a6c38 Binary files /dev/null and b/public/images/Clock_Icon.png differ diff --git a/public/images/Day_Toggle.png b/public/images/Day_Toggle.png new file mode 100644 index 0000000..74f21c8 Binary files /dev/null and b/public/images/Day_Toggle.png differ diff --git a/public/images/Default.png b/public/images/Default.png new file mode 100644 index 0000000..8651456 Binary files /dev/null and b/public/images/Default.png differ diff --git a/public/images/Download_Background.png b/public/images/Download_Background.png new file mode 100644 index 0000000..23899aa Binary files /dev/null and b/public/images/Download_Background.png differ diff --git a/public/images/Download_Icon.png b/public/images/Download_Icon.png new file mode 100644 index 0000000..64f83d8 Binary files /dev/null and b/public/images/Download_Icon.png differ diff --git a/public/images/Folder_Icon.png b/public/images/Folder_Icon.png new file mode 100644 index 0000000..3a27cd1 Binary files /dev/null and b/public/images/Folder_Icon.png differ diff --git a/public/images/Hide_UI_Button.png b/public/images/Hide_UI_Button.png new file mode 100644 index 0000000..ab90844 Binary files /dev/null and b/public/images/Hide_UI_Button.png differ diff --git a/public/images/Layer_Icon.png b/public/images/Layer_Icon.png new file mode 100644 index 0000000..f963e12 Binary files /dev/null and b/public/images/Layer_Icon.png differ diff --git a/public/images/Night_Toggle.png b/public/images/Night_Toggle.png new file mode 100644 index 0000000..bac45d8 Binary files /dev/null and b/public/images/Night_Toggle.png differ diff --git a/public/images/Report_Button.png b/public/images/Report_Button.png new file mode 100644 index 0000000..9302d83 Binary files /dev/null and b/public/images/Report_Button.png differ diff --git a/public/images/Report_Button_Highlighted.png b/public/images/Report_Button_Highlighted.png new file mode 100644 index 0000000..09e9f7b Binary files /dev/null and b/public/images/Report_Button_Highlighted.png differ diff --git a/public/images/Screenshots_Icon.png b/public/images/Screenshots_Icon.png new file mode 100644 index 0000000..5b58c41 Binary files /dev/null and b/public/images/Screenshots_Icon.png differ diff --git a/public/images/Settings_Arrow_Down.png b/public/images/Settings_Arrow_Down.png new file mode 100644 index 0000000..b3470a4 Binary files /dev/null and b/public/images/Settings_Arrow_Down.png differ diff --git a/public/images/Settings_Arrow_Left.png b/public/images/Settings_Arrow_Left.png new file mode 100644 index 0000000..ce02668 Binary files /dev/null and b/public/images/Settings_Arrow_Left.png differ diff --git a/public/images/Settings_Arrow_Right.png b/public/images/Settings_Arrow_Right.png new file mode 100644 index 0000000..0884107 Binary files /dev/null and b/public/images/Settings_Arrow_Right.png differ diff --git a/public/images/Settings_Arrow_Up.png b/public/images/Settings_Arrow_Up.png new file mode 100644 index 0000000..d58d799 Binary files /dev/null and b/public/images/Settings_Arrow_Up.png differ diff --git a/public/images/SliderHandlerBackground.png b/public/images/SliderHandlerBackground.png new file mode 100644 index 0000000..9b113b6 Binary files /dev/null and b/public/images/SliderHandlerBackground.png differ diff --git a/public/images/Slider_Handle.png b/public/images/Slider_Handle.png new file mode 100644 index 0000000..acfd1fe Binary files /dev/null and b/public/images/Slider_Handle.png differ diff --git a/public/images/Toggle_Switch_Off.png b/public/images/Toggle_Switch_Off.png new file mode 100644 index 0000000..f47fc6f Binary files /dev/null and b/public/images/Toggle_Switch_Off.png differ diff --git a/public/images/Toggle_Switch_On.png b/public/images/Toggle_Switch_On.png new file mode 100644 index 0000000..64a7ea2 Binary files /dev/null and b/public/images/Toggle_Switch_On.png differ diff --git a/public/images/Trash_Bin_Icon.png b/public/images/Trash_Bin_Icon.png new file mode 100644 index 0000000..543d891 Binary files /dev/null and b/public/images/Trash_Bin_Icon.png differ diff --git a/public/images/Unhide_UI_Button.png b/public/images/Unhide_UI_Button.png new file mode 100644 index 0000000..b5f5f75 Binary files /dev/null and b/public/images/Unhide_UI_Button.png differ diff --git a/public/images/Update_Icon.png b/public/images/Update_Icon.png new file mode 100644 index 0000000..3874d32 Binary files /dev/null and b/public/images/Update_Icon.png differ diff --git a/public/images/backgroundframe.png b/public/images/backgroundframe.png new file mode 100644 index 0000000..ea42bf1 Binary files /dev/null and b/public/images/backgroundframe.png differ diff --git a/public/images/button_highlighted.png b/public/images/button_highlighted.png new file mode 100644 index 0000000..af20c13 Binary files /dev/null and b/public/images/button_highlighted.png differ diff --git a/public/images/dirt-background.png b/public/images/dirt-background.png deleted file mode 100644 index ba3e4dd..0000000 Binary files a/public/images/dirt-background.png and /dev/null differ diff --git a/public/images/discord.png b/public/images/discord.png new file mode 100644 index 0000000..98da78f Binary files /dev/null and b/public/images/discord.png differ diff --git a/public/images/frame_background.png b/public/images/frame_background.png new file mode 100644 index 0000000..d6dae3f Binary files /dev/null and b/public/images/frame_background.png differ diff --git a/public/images/github.png b/public/images/github.png new file mode 100644 index 0000000..4c7120b Binary files /dev/null and b/public/images/github.png differ diff --git a/public/images/icon.png b/public/images/icon.png new file mode 100644 index 0000000..fe90450 Binary files /dev/null and b/public/images/icon.png differ diff --git a/public/images/loading.gif b/public/images/loading.gif new file mode 100644 index 0000000..97d0368 Binary files /dev/null and b/public/images/loading.gif differ diff --git a/public/images/logo.png b/public/images/logo.png deleted file mode 100644 index e97e419..0000000 Binary files a/public/images/logo.png and /dev/null differ diff --git a/public/images/minecraft_title_360revived.png b/public/images/minecraft_title_360revived.png new file mode 100644 index 0000000..4689231 Binary files /dev/null and b/public/images/minecraft_title_360revived.png differ diff --git a/public/images/minecraft_title_LegacyEvolved.png b/public/images/minecraft_title_LegacyEvolved.png new file mode 100644 index 0000000..4293089 Binary files /dev/null and b/public/images/minecraft_title_LegacyEvolved.png differ diff --git a/public/images/minecraft_title_revelations.png b/public/images/minecraft_title_revelations.png new file mode 100644 index 0000000..aa9e0aa Binary files /dev/null and b/public/images/minecraft_title_revelations.png differ diff --git a/public/images/minecraft_title_tu19.png b/public/images/minecraft_title_tu19.png new file mode 100644 index 0000000..597f3a8 Binary files /dev/null and b/public/images/minecraft_title_tu19.png differ diff --git a/public/images/minecraft_title_tucustom.png b/public/images/minecraft_title_tucustom.png new file mode 100644 index 0000000..eb0e0c0 Binary files /dev/null and b/public/images/minecraft_title_tucustom.png differ diff --git a/public/images/sga_a.png b/public/images/sga_a.png new file mode 100644 index 0000000..cd8b055 Binary files /dev/null and b/public/images/sga_a.png differ diff --git a/public/images/sga_b.png b/public/images/sga_b.png new file mode 100644 index 0000000..71f8543 Binary files /dev/null and b/public/images/sga_b.png differ diff --git a/public/images/sga_c.png b/public/images/sga_c.png new file mode 100644 index 0000000..c1094d3 Binary files /dev/null and b/public/images/sga_c.png differ diff --git a/public/images/sga_d.png b/public/images/sga_d.png new file mode 100644 index 0000000..9979ab2 Binary files /dev/null and b/public/images/sga_d.png differ diff --git a/public/images/sga_e.png b/public/images/sga_e.png new file mode 100644 index 0000000..c3510c7 Binary files /dev/null and b/public/images/sga_e.png differ diff --git a/public/images/sga_f.png b/public/images/sga_f.png new file mode 100644 index 0000000..6841034 Binary files /dev/null and b/public/images/sga_f.png differ diff --git a/public/images/sga_g.png b/public/images/sga_g.png new file mode 100644 index 0000000..d05b34b Binary files /dev/null and b/public/images/sga_g.png differ diff --git a/public/images/sga_h.png b/public/images/sga_h.png new file mode 100644 index 0000000..bbd339e Binary files /dev/null and b/public/images/sga_h.png differ diff --git a/public/images/sga_i.png b/public/images/sga_i.png new file mode 100644 index 0000000..c656745 Binary files /dev/null and b/public/images/sga_i.png differ diff --git a/public/images/sga_j.png b/public/images/sga_j.png new file mode 100644 index 0000000..f2bc370 Binary files /dev/null and b/public/images/sga_j.png differ diff --git a/public/images/sga_k.png b/public/images/sga_k.png new file mode 100644 index 0000000..5c738c6 Binary files /dev/null and b/public/images/sga_k.png differ diff --git a/public/images/sga_l.png b/public/images/sga_l.png new file mode 100644 index 0000000..fa219dc Binary files /dev/null and b/public/images/sga_l.png differ diff --git a/public/images/sga_m.png b/public/images/sga_m.png new file mode 100644 index 0000000..80cda84 Binary files /dev/null and b/public/images/sga_m.png differ diff --git a/public/images/sga_n.png b/public/images/sga_n.png new file mode 100644 index 0000000..5c0bbe5 Binary files /dev/null and b/public/images/sga_n.png differ diff --git a/public/images/sga_o.png b/public/images/sga_o.png new file mode 100644 index 0000000..a631de0 Binary files /dev/null and b/public/images/sga_o.png differ diff --git a/public/images/sga_p.png b/public/images/sga_p.png new file mode 100644 index 0000000..e52122f Binary files /dev/null and b/public/images/sga_p.png differ diff --git a/public/images/sga_q.png b/public/images/sga_q.png new file mode 100644 index 0000000..b8e7cc0 Binary files /dev/null and b/public/images/sga_q.png differ diff --git a/public/images/sga_r.png b/public/images/sga_r.png new file mode 100644 index 0000000..7c18590 Binary files /dev/null and b/public/images/sga_r.png differ diff --git a/public/images/sga_s.png b/public/images/sga_s.png new file mode 100644 index 0000000..74c4462 Binary files /dev/null and b/public/images/sga_s.png differ diff --git a/public/images/sga_t.png b/public/images/sga_t.png new file mode 100644 index 0000000..ede2c95 Binary files /dev/null and b/public/images/sga_t.png differ diff --git a/public/images/sga_u.png b/public/images/sga_u.png new file mode 100644 index 0000000..3839424 Binary files /dev/null and b/public/images/sga_u.png differ diff --git a/public/images/sga_v.png b/public/images/sga_v.png new file mode 100644 index 0000000..a17fc83 Binary files /dev/null and b/public/images/sga_v.png differ diff --git a/public/images/sga_w.png b/public/images/sga_w.png new file mode 100644 index 0000000..0792fe1 Binary files /dev/null and b/public/images/sga_w.png differ diff --git a/public/images/sga_x.png b/public/images/sga_x.png new file mode 100644 index 0000000..44ec936 Binary files /dev/null and b/public/images/sga_x.png differ diff --git a/public/images/sga_y.png b/public/images/sga_y.png new file mode 100644 index 0000000..fbedc84 Binary files /dev/null and b/public/images/sga_y.png differ diff --git a/public/images/sga_z.png b/public/images/sga_z.png new file mode 100644 index 0000000..7eae86f Binary files /dev/null and b/public/images/sga_z.png differ diff --git a/public/music/music1.ogg b/public/music/Blind Spots.ogg similarity index 100% rename from public/music/music1.ogg rename to public/music/Blind Spots.ogg diff --git a/public/music/music4.ogg b/public/music/Key.ogg similarity index 100% rename from public/music/music4.ogg rename to public/music/Key.ogg diff --git a/public/music/music3.ogg b/public/music/Living Mice.ogg similarity index 100% rename from public/music/music3.ogg rename to public/music/Living Mice.ogg diff --git a/public/music/music5.ogg b/public/music/Oxygene.ogg similarity index 100% rename from public/music/music5.ogg rename to public/music/Oxygene.ogg diff --git a/public/music/music2.ogg b/public/music/Subwoofer Lullaby.ogg similarity index 100% rename from public/music/music2.ogg rename to public/music/Subwoofer Lullaby.ogg diff --git a/public/panorama/legacy_evolved_Panorama_Background_Day.png b/public/panorama/legacy_evolved_Panorama_Background_Day.png new file mode 100644 index 0000000..c680c09 Binary files /dev/null and b/public/panorama/legacy_evolved_Panorama_Background_Day.png differ diff --git a/public/panorama/legacy_evolved_Panorama_Background_Night.png b/public/panorama/legacy_evolved_Panorama_Background_Night.png new file mode 100644 index 0000000..b915b51 Binary files /dev/null and b/public/panorama/legacy_evolved_Panorama_Background_Night.png differ diff --git a/public/panorama/vanilla_tu19_Panorama_Background_Day.png b/public/panorama/vanilla_tu19_Panorama_Background_Day.png new file mode 100644 index 0000000..aa4a554 Binary files /dev/null and b/public/panorama/vanilla_tu19_Panorama_Background_Day.png differ diff --git a/public/panorama/vanilla_tu19_Panorama_Background_Night.png b/public/panorama/vanilla_tu19_Panorama_Background_Night.png new file mode 100644 index 0000000..ce9d7de Binary files /dev/null and b/public/panorama/vanilla_tu19_Panorama_Background_Night.png differ diff --git a/public/panorama/vanilla_tu24_Panorama_Background_Day.png b/public/panorama/vanilla_tu24_Panorama_Background_Day.png new file mode 100644 index 0000000..0fe098b Binary files /dev/null and b/public/panorama/vanilla_tu24_Panorama_Background_Day.png differ diff --git a/public/panorama/vanilla_tu24_Panorama_Background_Night.png b/public/panorama/vanilla_tu24_Panorama_Background_Night.png new file mode 100644 index 0000000..ab4fba2 Binary files /dev/null and b/public/panorama/vanilla_tu24_Panorama_Background_Night.png differ diff --git a/public/particles/sga_a.png b/public/particles/sga_a.png new file mode 100644 index 0000000..cd8b055 Binary files /dev/null and b/public/particles/sga_a.png differ diff --git a/public/particles/sga_b.png b/public/particles/sga_b.png new file mode 100644 index 0000000..71f8543 Binary files /dev/null and b/public/particles/sga_b.png differ diff --git a/public/particles/sga_c.png b/public/particles/sga_c.png new file mode 100644 index 0000000..c1094d3 Binary files /dev/null and b/public/particles/sga_c.png differ diff --git a/public/particles/sga_d.png b/public/particles/sga_d.png new file mode 100644 index 0000000..9979ab2 Binary files /dev/null and b/public/particles/sga_d.png differ diff --git a/public/particles/sga_e.png b/public/particles/sga_e.png new file mode 100644 index 0000000..c3510c7 Binary files /dev/null and b/public/particles/sga_e.png differ diff --git a/public/particles/sga_f.png b/public/particles/sga_f.png new file mode 100644 index 0000000..6841034 Binary files /dev/null and b/public/particles/sga_f.png differ diff --git a/public/particles/sga_g.png b/public/particles/sga_g.png new file mode 100644 index 0000000..d05b34b Binary files /dev/null and b/public/particles/sga_g.png differ diff --git a/public/particles/sga_h.png b/public/particles/sga_h.png new file mode 100644 index 0000000..bbd339e Binary files /dev/null and b/public/particles/sga_h.png differ diff --git a/public/particles/sga_i.png b/public/particles/sga_i.png new file mode 100644 index 0000000..c656745 Binary files /dev/null and b/public/particles/sga_i.png differ diff --git a/public/particles/sga_j.png b/public/particles/sga_j.png new file mode 100644 index 0000000..f2bc370 Binary files /dev/null and b/public/particles/sga_j.png differ diff --git a/public/particles/sga_k.png b/public/particles/sga_k.png new file mode 100644 index 0000000..5c738c6 Binary files /dev/null and b/public/particles/sga_k.png differ diff --git a/public/particles/sga_l.png b/public/particles/sga_l.png new file mode 100644 index 0000000..fa219dc Binary files /dev/null and b/public/particles/sga_l.png differ diff --git a/public/particles/sga_m.png b/public/particles/sga_m.png new file mode 100644 index 0000000..80cda84 Binary files /dev/null and b/public/particles/sga_m.png differ diff --git a/public/particles/sga_n.png b/public/particles/sga_n.png new file mode 100644 index 0000000..5c0bbe5 Binary files /dev/null and b/public/particles/sga_n.png differ diff --git a/public/particles/sga_o.png b/public/particles/sga_o.png new file mode 100644 index 0000000..a631de0 Binary files /dev/null and b/public/particles/sga_o.png differ diff --git a/public/particles/sga_p.png b/public/particles/sga_p.png new file mode 100644 index 0000000..e52122f Binary files /dev/null and b/public/particles/sga_p.png differ diff --git a/public/particles/sga_q.png b/public/particles/sga_q.png new file mode 100644 index 0000000..b8e7cc0 Binary files /dev/null and b/public/particles/sga_q.png differ diff --git a/public/particles/sga_r.png b/public/particles/sga_r.png new file mode 100644 index 0000000..7c18590 Binary files /dev/null and b/public/particles/sga_r.png differ diff --git a/public/particles/sga_s.png b/public/particles/sga_s.png new file mode 100644 index 0000000..74c4462 Binary files /dev/null and b/public/particles/sga_s.png differ diff --git a/public/particles/sga_t.png b/public/particles/sga_t.png new file mode 100644 index 0000000..ede2c95 Binary files /dev/null and b/public/particles/sga_t.png differ diff --git a/public/particles/sga_u.png b/public/particles/sga_u.png new file mode 100644 index 0000000..3839424 Binary files /dev/null and b/public/particles/sga_u.png differ diff --git a/public/particles/sga_v.png b/public/particles/sga_v.png new file mode 100644 index 0000000..a17fc83 Binary files /dev/null and b/public/particles/sga_v.png differ diff --git a/public/particles/sga_w.png b/public/particles/sga_w.png new file mode 100644 index 0000000..0792fe1 Binary files /dev/null and b/public/particles/sga_w.png differ diff --git a/public/particles/sga_x.png b/public/particles/sga_x.png new file mode 100644 index 0000000..44ec936 Binary files /dev/null and b/public/particles/sga_x.png differ diff --git a/public/particles/sga_y.png b/public/particles/sga_y.png new file mode 100644 index 0000000..fbedc84 Binary files /dev/null and b/public/particles/sga_y.png differ diff --git a/public/particles/sga_z.png b/public/particles/sga_z.png new file mode 100644 index 0000000..7eae86f Binary files /dev/null and b/public/particles/sga_z.png differ diff --git a/public/sounds/wood click.wav b/public/sounds/press.wav similarity index 100% rename from public/sounds/wood click.wav rename to public/sounds/press.wav diff --git a/public/sounds/pop.wav b/public/sounds/save_click.wav similarity index 100% rename from public/sounds/pop.wav rename to public/sounds/save_click.wav diff --git a/scripts/fix-macos-quarantine.sh b/scripts/fix-macos-quarantine.sh new file mode 100755 index 0000000..dccf22d --- /dev/null +++ b/scripts/fix-macos-quarantine.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Fix macOS quarantine issue for ARM builds fuck apple man +# This script removes quarantine attributes from the built app + +set -e + +APP_PATH="$1" +BUNDLE_ID="com.emerald.legacy" + +if [ -z "$APP_PATH" ]; then + echo "Usage: $0 " + exit 1 +fi + +if [ ! -d "$APP_PATH" ]; then + echo "Error: App bundle not found at $APP_PATH" + exit 1 +fi + +echo "Fixing macOS quarantine for: $APP_PATH" + +# Remove quarantine attributes +xattr -cr "$APP_PATH" + +# Add basic code signing (ad-hoc signature) +codesign --force --deep --sign - "$APP_PATH" 2>/dev/null || { + echo "Warning: Code signing failed, but quarantine removal should work" +} + +echo "✅ macOS quarantine fix completed" +echo "The app should now launch without 'damaged' error" diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh new file mode 100755 index 0000000..67d968d --- /dev/null +++ b/scripts/postinstall.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Post-install script for PKG installer +# Automatically removes quarantine attributes from the installed app + +APP_PATH="$2/Applications/Emerald Legacy Launcher.app" + +echo "Removing quarantine attributes from Emerald Legacy Launcher..." + +if [ -d "$APP_PATH" ]; then + xattr -cr "$APP_PATH" + echo "Quarantine attributes removed successfully." + exit 0 +else + echo "Warning: App not found at expected location: $APP_PATH" + exit 1 +fi diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore new file mode 100644 index 0000000..d8769d0 --- /dev/null +++ b/src-tauri/.gitignore @@ -0,0 +1,7 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Generated by Tauri +# will have schema files for capabilities auto-completion +/gen/schemas diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1b98f00..6a0552a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,23 +1,28 @@ [package] name = "emerald-legacy-launcher" -version = "0.1.0" -description = "A Tauri App" -authors = ["you"] +version = "1.0.0" +description = "A FOSS, cross-platform launcher for Minecraft Legacy Edition" +authors = ["Emerald Team"] edition = "2021" [lib] -name = "emerald_legacy_launcher_lib" +name = "emerald_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2", features = [] } +tauri = { version = "2", features = ["tray-icon", "image-png"] } tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" +tauri-plugin-gamepad = "0.0.5" +tauri-plugin-drpc = "*" reqwest = { version = "0.11", features = ["stream"] } tokio = { version = "1", features = ["full"] } -futures-util = "0.3" # +futures-util = "0.3" tokio-util = { version = "0.7.18", features = ["rt"] } +base64 = "0.21" +rfd = "0.15" +libc = "0.2" diff --git a/src-tauri/build.rs b/src-tauri/build.rs index d860e1e..158c051 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,3 +1,3 @@ -fn main() { - tauri_build::build() -} +fn main() { + tauri_build::build(); +} diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 49a9218..e8589d1 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -1,18 +1,26 @@ -{ - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Capability for the main window", - "windows": ["main"], - "permissions": [ - "core:default", - "opener:default", - { - "identifier": "opener:allow-open-url", - "allow": [ - { "url": "https://github.com/KayJannOnGit/*" }, - { "url": "https://discord.gg/*" }, - { "url": "https://reddit.com/*" } - ] - } - ] +{ + "identifier": "default", + "description": "Default permissions", + "windows": [ + "main" + ], + "permissions": [ + "core:default", + "core:window:allow-minimize", + "core:window:allow-maximize", + "core:window:allow-toggle-maximize", + "core:window:allow-close", + "core:window:allow-set-title", + "core:window:allow-start-dragging", + "core:window:allow-show", + "core:window:allow-hide", + "core:window:allow-unminimize", + "core:window:allow-set-focus", + "opener:default", + "gamepad:default", + "drpc:allow-is-running", + "drpc:default", + "core:event:allow-listen", + "core:app:default" + ] } \ No newline at end of file diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index 931df68..f546e57 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}}} \ No newline at end of file +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"drpc":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-spawn-thread","allow-destroy-thread","allow-set-activity","allow-is-running"]},"permissions":{"allow-clear-activity":{"identifier":"allow-clear-activity","description":"Enables the clear_activity command without any pre-configured scope.","commands":{"allow":["clear_activity"],"deny":[]}},"allow-destroy-thread":{"identifier":"allow-destroy-thread","description":"Enables the destroy_thread command without any pre-configured scope.","commands":{"allow":["destroy_thread"],"deny":[]}},"allow-is-running":{"identifier":"allow-is-running","description":"Enables the is_running command without any pre-configured scope.","commands":{"allow":["is_running"],"deny":[]}},"allow-set-activity":{"identifier":"allow-set-activity","description":"Enables the set_activity command without any pre-configured scope.","commands":{"allow":["set_activity"],"deny":[]}},"allow-spawn-thread":{"identifier":"allow-spawn-thread","description":"Enables the spawn_thread command without any pre-configured scope.","commands":{"allow":["spawn_thread"],"deny":[]}},"deny-clear-activity":{"identifier":"deny-clear-activity","description":"Denies the clear_activity command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_activity"]}},"deny-destroy-thread":{"identifier":"deny-destroy-thread","description":"Denies the destroy_thread command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy_thread"]}},"deny-is-running":{"identifier":"deny-is-running","description":"Denies the is_running command without any pre-configured scope.","commands":{"allow":[],"deny":["is_running"]}},"deny-set-activity":{"identifier":"deny-set-activity","description":"Denies the set_activity command without any pre-configured scope.","commands":{"allow":[],"deny":["set_activity"]}},"deny-spawn-thread":{"identifier":"deny-spawn-thread","description":"Denies the spawn_thread command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn_thread"]}}},"permission_sets":{},"global_scope_schema":null},"gamepad":{"default_permission":{"identifier":"default","description":"This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n","permissions":["allow-execute"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json index 46f4955..be9e6b7 100644 --- a/src-tauri/gen/schemas/capabilities.json +++ b/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:default","opener:default",{"identifier":"opener:allow-open-url","allow":[{"url":"https://github.com/KayJannOnGit/*"},{"url":"https://discord.gg/*"},{"url":"https://reddit.com/*"}]}]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Default permissions","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-minimize","core:window:allow-maximize","core:window:allow-toggle-maximize","core:window:allow-close","core:window:allow-set-title","core:window:allow-start-dragging","core:window:allow-show","core:window:allow-hide","core:window:allow-unminimize","core:window:allow-set-focus","opener:default","gamepad:default","drpc:allow-is-running","drpc:default","core:event:allow-listen","core:app:default"]}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 4917625..56eb6a8 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -2312,6 +2312,90 @@ "const": "core:window:deny-unminimize", "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, + { + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`", + "type": "string", + "const": "drpc:default", + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`" + }, + { + "description": "Enables the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-clear-activity", + "markdownDescription": "Enables the clear_activity command without any pre-configured scope." + }, + { + "description": "Enables the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-destroy-thread", + "markdownDescription": "Enables the destroy_thread command without any pre-configured scope." + }, + { + "description": "Enables the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-is-running", + "markdownDescription": "Enables the is_running command without any pre-configured scope." + }, + { + "description": "Enables the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-set-activity", + "markdownDescription": "Enables the set_activity command without any pre-configured scope." + }, + { + "description": "Enables the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-spawn-thread", + "markdownDescription": "Enables the spawn_thread command without any pre-configured scope." + }, + { + "description": "Denies the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-clear-activity", + "markdownDescription": "Denies the clear_activity command without any pre-configured scope." + }, + { + "description": "Denies the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-destroy-thread", + "markdownDescription": "Denies the destroy_thread command without any pre-configured scope." + }, + { + "description": "Denies the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-is-running", + "markdownDescription": "Denies the is_running command without any pre-configured scope." + }, + { + "description": "Denies the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-set-activity", + "markdownDescription": "Denies the set_activity command without any pre-configured scope." + }, + { + "description": "Denies the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-spawn-thread", + "markdownDescription": "Denies the spawn_thread command without any pre-configured scope." + }, + { + "description": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`", + "type": "string", + "const": "gamepad:default", + "markdownDescription": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`" + }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:allow-execute", + "markdownDescription": "Enables the execute command without any pre-configured scope." + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:deny-execute", + "markdownDescription": "Denies the execute command without any pre-configured scope." + }, { "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", "type": "string", diff --git a/src-tauri/gen/schemas/linux-schema.json b/src-tauri/gen/schemas/linux-schema.json index 4917625..56eb6a8 100644 --- a/src-tauri/gen/schemas/linux-schema.json +++ b/src-tauri/gen/schemas/linux-schema.json @@ -2312,6 +2312,90 @@ "const": "core:window:deny-unminimize", "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, + { + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`", + "type": "string", + "const": "drpc:default", + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`" + }, + { + "description": "Enables the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-clear-activity", + "markdownDescription": "Enables the clear_activity command without any pre-configured scope." + }, + { + "description": "Enables the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-destroy-thread", + "markdownDescription": "Enables the destroy_thread command without any pre-configured scope." + }, + { + "description": "Enables the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-is-running", + "markdownDescription": "Enables the is_running command without any pre-configured scope." + }, + { + "description": "Enables the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-set-activity", + "markdownDescription": "Enables the set_activity command without any pre-configured scope." + }, + { + "description": "Enables the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-spawn-thread", + "markdownDescription": "Enables the spawn_thread command without any pre-configured scope." + }, + { + "description": "Denies the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-clear-activity", + "markdownDescription": "Denies the clear_activity command without any pre-configured scope." + }, + { + "description": "Denies the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-destroy-thread", + "markdownDescription": "Denies the destroy_thread command without any pre-configured scope." + }, + { + "description": "Denies the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-is-running", + "markdownDescription": "Denies the is_running command without any pre-configured scope." + }, + { + "description": "Denies the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-set-activity", + "markdownDescription": "Denies the set_activity command without any pre-configured scope." + }, + { + "description": "Denies the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-spawn-thread", + "markdownDescription": "Denies the spawn_thread command without any pre-configured scope." + }, + { + "description": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`", + "type": "string", + "const": "gamepad:default", + "markdownDescription": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`" + }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:allow-execute", + "markdownDescription": "Enables the execute command without any pre-configured scope." + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:deny-execute", + "markdownDescription": "Denies the execute command without any pre-configured scope." + }, { "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", "type": "string", diff --git a/src-tauri/gen/schemas/macOS-schema.json b/src-tauri/gen/schemas/windows-schema.json similarity index 96% rename from src-tauri/gen/schemas/macOS-schema.json rename to src-tauri/gen/schemas/windows-schema.json index 4917625..56eb6a8 100644 --- a/src-tauri/gen/schemas/macOS-schema.json +++ b/src-tauri/gen/schemas/windows-schema.json @@ -2312,6 +2312,90 @@ "const": "core:window:deny-unminimize", "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, + { + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`", + "type": "string", + "const": "drpc:default", + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`" + }, + { + "description": "Enables the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-clear-activity", + "markdownDescription": "Enables the clear_activity command without any pre-configured scope." + }, + { + "description": "Enables the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-destroy-thread", + "markdownDescription": "Enables the destroy_thread command without any pre-configured scope." + }, + { + "description": "Enables the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-is-running", + "markdownDescription": "Enables the is_running command without any pre-configured scope." + }, + { + "description": "Enables the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-set-activity", + "markdownDescription": "Enables the set_activity command without any pre-configured scope." + }, + { + "description": "Enables the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:allow-spawn-thread", + "markdownDescription": "Enables the spawn_thread command without any pre-configured scope." + }, + { + "description": "Denies the clear_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-clear-activity", + "markdownDescription": "Denies the clear_activity command without any pre-configured scope." + }, + { + "description": "Denies the destroy_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-destroy-thread", + "markdownDescription": "Denies the destroy_thread command without any pre-configured scope." + }, + { + "description": "Denies the is_running command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-is-running", + "markdownDescription": "Denies the is_running command without any pre-configured scope." + }, + { + "description": "Denies the set_activity command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-set-activity", + "markdownDescription": "Denies the set_activity command without any pre-configured scope." + }, + { + "description": "Denies the spawn_thread command without any pre-configured scope.", + "type": "string", + "const": "drpc:deny-spawn-thread", + "markdownDescription": "Denies the spawn_thread command without any pre-configured scope." + }, + { + "description": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`", + "type": "string", + "const": "gamepad:default", + "markdownDescription": "This permission set configures which\ngampead features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all gamepads.\n\n\n#### This default permission set includes:\n\n- `allow-execute`" + }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:allow-execute", + "markdownDescription": "Enables the execute command without any pre-configured scope." + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "gamepad:deny-execute", + "markdownDescription": "Denies the execute command without any pre-configured scope." + }, { "description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`", "type": "string", diff --git a/src-tauri/resources/DLC/Emerald Skin Pack/Skins1.pck b/src-tauri/resources/DLC/Emerald Skin Pack/Skins1.pck new file mode 100644 index 0000000..b92e5ce Binary files /dev/null and b/src-tauri/resources/DLC/Emerald Skin Pack/Skins1.pck differ diff --git a/src-tauri/scripts/post-build-macos.sh b/src-tauri/scripts/post-build-macos.sh new file mode 100755 index 0000000..e1c5bb5 --- /dev/null +++ b/src-tauri/scripts/post-build-macos.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Post-build script for macOS to fix quarantine issues (thank u apple...) +# This script runs automatically after Tauri build on macOS + +set -e + +APP_NAME="Emerald Legacy Launcher" +BUNDLE_ID="com.emerald.legacy" +BASE_DIR="src-tauri/target" + +echo "Running macOS post-build fixes" + +# Find the correct target directory (handles both native and cross-compilation) +TARGET_DIR=$(find "$BASE_DIR" -path "*/release/bundle/macos" -type d | head -n 1) + +if [ -z "$TARGET_DIR" ]; then + echo "❌ No macOS bundle directory found in $BASE_DIR" + exit 1 +fi + +echo "Using target directory: $TARGET_DIR" + +APP_PATH=$(find "$TARGET_DIR" -name "*.app" -type d | head -n 1) + +if [ -z "$APP_PATH" ]; then + echo "❌ No .app bundle found in $TARGET_DIR" + exit 1 +fi + +echo "Found app: $APP_PATH" + +echo "Removing quarantine attributes..." +xattr -cr "$APP_PATH" + +echo "Applying ad-hoc signature..." +codesign --force --deep --sign - "$APP_PATH" 2>/dev/null || { + echo "⚠️ Code signing failed, but quarantine removal should work" +} + +echo "Verifying app signature..." +codesign -v "$APP_PATH" 2>/dev/null && echo "✅ App signature verified" || echo "⚠️ App signature verification failed" + +echo "✅ macOS post-build fixes completed!" +echo "The app should now launch without 'damaged' error on macOS ARM" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index be86b7b..d109708 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -2,7 +2,13 @@ use std::fs; use std::io::Write; use std::path::PathBuf; use std::process::Command; + +#[cfg(target_os = "macos")] +use std::process::Stdio; + use tauri::{AppHandle, Emitter, State, Manager}; +use tauri::menu::{Menu, MenuItem, MenuEvent}; +use tauri::tray::{TrayIcon, TrayIconBuilder, TrayIconEvent}; use futures_util::StreamExt; use std::sync::Arc; use tokio::sync::Mutex; @@ -10,14 +16,60 @@ use tokio_util::sync::CancellationToken; use tauri_plugin_opener::OpenerExt; use serde::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct McServer { + pub name: String, + pub ip: String, + pub port: u16, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct SkinLibraryItem { + pub id: String, + pub name: String, + pub skin_base64: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CustomEdition { + pub id: String, + pub name: String, + pub desc: String, + pub url: String, +} + #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct AppConfig { pub username: String, pub linux_runner: Option, + pub skin_base64: Option, + pub skin_library: Option>, + pub theme_style_id: Option, + pub theme_palette_id: Option, + pub apple_silicon_performance_boost: Option, + pub custom_editions: Option>, + pub profile: Option, + pub keep_launcher_open: Option, + pub enable_tray_icon: Option, + pub animations_enabled: Option, + pub vfx_enabled: Option, + pub rpc_enabled: Option, + pub music_vol: Option, + pub sfx_vol: Option, + pub legacy_mode: Option, } #[derive(Serialize, Deserialize, Clone, Debug)] +pub struct ThemePalette { + pub id: String, + pub name: String, + pub colors: serde_json::Value, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] pub struct Runner { pub id: String, pub name: String, @@ -26,6 +78,16 @@ pub struct Runner { } pub struct DownloadState { pub token: Arc>> } +pub struct GameState { pub child: Arc>> } + +#[derive(Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +#[cfg(target_os = "macos")] +struct MacosSetupProgressPayload { + stage: String, + message: String, + percent: Option, +} fn get_app_dir(app: &AppHandle) -> PathBuf { app.path().app_local_data_dir().unwrap_or_else(|_| { @@ -33,6 +95,66 @@ fn get_app_dir(app: &AppHandle) -> PathBuf { }) } +#[cfg(target_os = "macos")] +fn get_macos_runtime_dir(app: &AppHandle) -> PathBuf { + let home = app + .path() + .home_dir() + .ok() + .or_else(|| std::env::var("HOME").ok().map(PathBuf::from)) + .unwrap_or_else(|| PathBuf::from("/")); + home.join("Library") + .join("Application Support") + .join("com.emerald.legacy") + .join("runtime") +} + +#[cfg(target_os = "macos")] +fn emit_macos_setup_progress(window: &tauri::Window, stage: &str, message: String, percent: Option) { + let _ = window.emit( + "macos-setup-progress", + MacosSetupProgressPayload { + stage: stage.to_string(), + message, + percent, + }, + ); +} + +#[cfg(target_os = "macos")] +fn find_executable_recursive(root: &PathBuf, file_name: &str) -> Option { + let entries = fs::read_dir(root).ok()?; + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + if let Some(found) = find_executable_recursive(&path, file_name) { + return Some(found); + } + continue; + } + + if path.file_name().and_then(|n| n.to_str()) == Some(file_name) { + return Some(path); + } + } + None +} + +#[cfg(unix)] +fn unix_path_to_wine_z_path(unix_path: &PathBuf) -> String { + let p = unix_path.to_string_lossy(); + let mut out = String::with_capacity(p.len() + 3); + out.push_str("Z:"); + for ch in p.chars() { + if ch == '/' { + out.push('\\'); + } else { + out.push(ch); + } + } + out +} + fn get_config_path(app: &AppHandle) -> PathBuf { get_app_dir(app).join("emerald_legacy_config.json") } @@ -54,33 +176,114 @@ fn load_config(app: AppHandle) -> AppConfig { return config; } } - + let old_path = get_app_dir(&app).join("emerald_legacy_config.txt"); let username = fs::read_to_string(old_path).unwrap_or_else(|_| "Player".into()); - AppConfig { username, linux_runner: None } + AppConfig { + username, + linux_runner: None, + skin_base64: None, + skin_library: None, + theme_style_id: None, + theme_palette_id: None, + apple_silicon_performance_boost: None, + custom_editions: None, + profile: Some("legacy_evolved".into()), + keep_launcher_open: None, + enable_tray_icon: Some(true), + animations_enabled: Some(true), + vfx_enabled: Some(true), + rpc_enabled: Some(true), + music_vol: Some(50), + sfx_vol: Some(100), + legacy_mode: Some(false), + } } #[tauri::command] -fn get_available_runners() -> Vec { +fn get_external_palettes(app: AppHandle) -> Vec { + let themes_dir = get_app_dir(&app).join("themes"); + let _ = fs::create_dir_all(&themes_dir); + let mut palettes = Vec::new(); + + if let Ok(entries) = fs::read_dir(themes_dir) { + for entry in entries.flatten() { + let path = entry.path(); + if path.extension().and_then(|s| s.to_str()) == Some("json") { + if let Ok(content) = fs::read_to_string(&path) { + if let Ok(palette) = serde_json::from_str::(&content) { + palettes.push(palette); + } + } + } + } + } + palettes +} + +#[tauri::command] +fn import_theme(app: AppHandle) -> Result { + let file = rfd::FileDialog::new() + .add_filter("JSON Theme", &["json"]) + .set_title("Import Theme Palette") + .pick_file(); + + if let Some(src_path) = file { + let content = fs::read_to_string(&src_path).map_err(|e| e.to_string())?; + let palette: ThemePalette = serde_json::from_str(&content).map_err(|_| "Invalid theme JSON format".to_string())?; + + let themes_dir = get_app_dir(&app).join("themes"); + let _ = fs::create_dir_all(&themes_dir); + + let dest_path = themes_dir.join(format!("{}.json", palette.id)); + fs::write(dest_path, content).map_err(|e| e.to_string())?; + + Ok(palette.name) + } else { + Err("CANCELED".into()) + } +} + +#[tauri::command] +fn get_available_runners(app: AppHandle) -> Vec { let mut runners = Vec::new(); + let mut seen_paths: std::collections::HashSet = std::collections::HashSet::new(); #[cfg(target_os = "linux")] { if let Ok(output) = Command::new("which").arg("wine").output() { if output.status.success() { let path = String::from_utf8_lossy(&output.stdout).trim().to_string(); - runners.push(Runner { - id: "wine".to_string(), - name: "System Wine".to_string(), - path, - r#type: "wine".to_string(), - }); + if !seen_paths.contains(&path) { + seen_paths.insert(path.clone()); + runners.push(Runner { + id: "wine".to_string(), + name: "System Wine".to_string(), + path, + r#type: "wine".to_string(), + }); + } + } + } + + if let Ok(output) = Command::new("ls").arg("/usr/share/emerald-legacy-launcher/wine/bin/wine").output() { + if output.status.success() { + let path = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if !seen_paths.contains(&path) { + seen_paths.insert(path.clone()); + runners.push(Runner { + id: "flatpaksucks".to_string(), + name: "Default for Flatpak".to_string(), + path, + r#type: "wine".to_string(), + }); + } } } let home = std::env::var("HOME").unwrap_or_default(); let steam_paths = [ - format!("{}/.steam/steam/steamapps/common", home), + format!("{}/.local/share/Steam/compatibilitytools.d", home), format!("{}/.local/share/Steam/steamapps/common", home), ]; @@ -90,14 +293,54 @@ fn get_available_runners() -> Vec { let path = entry.path(); if path.is_dir() { let name = entry.file_name().to_string_lossy().to_string(); - if name.starts_with("Proton") { + if name.contains("Proton") { + let path_str = path.to_string_lossy().to_string(); + if !seen_paths.contains(&path_str) { + seen_paths.insert(path_str.clone()); + runners.push(Runner { + id: format!("proton_{}", name), + name: name, + path: path_str, + r#type: "proton".to_string(), + }); + } + } + } + } + } + } + + let runners_dir = get_app_dir(&app).join("runners"); + let _ = fs::create_dir_all(&runners_dir); + if let Ok(entries) = fs::read_dir(&runners_dir) { + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + let dir_name = entry.file_name().to_string_lossy().to_string(); + let wine_bin = path.join("bin").join("wine"); + let proton_bin = path.join("proton"); + if proton_bin.exists() { + let path_str = path.to_string_lossy().to_string(); + if !seen_paths.contains(&path_str) { + seen_paths.insert(path_str.clone()); runners.push(Runner { - id: format!("proton_{}", name), - name: name, - path: path.to_string_lossy().to_string(), + id: format!("downloaded_{}", dir_name), + name: format!("{} (downloaded)", dir_name), + path: path_str, r#type: "proton".to_string(), }); } + } else if wine_bin.exists() { + let path_str = wine_bin.to_string_lossy().to_string(); + if !seen_paths.contains(&path_str) { + seen_paths.insert(path_str.clone()); + runners.push(Runner { + id: format!("downloaded_{}", dir_name), + name: format!("{} (downloaded)", dir_name), + path: path_str, + r#type: "wine".to_string(), + }); + } } } } @@ -108,41 +351,360 @@ fn get_available_runners() -> Vec { } #[tauri::command] -#[allow(non_snake_case)] -fn check_game_installed(app: AppHandle, instanceId: String) -> bool { - get_app_dir(&app).join("instances").join(&instanceId).join("Minecraft.Client.exe").exists() +async fn download_runner(app: AppHandle, state: State<'_, DownloadState>, name: String, url: String) -> Result { + let runners_dir = get_app_dir(&app).join("runners"); + fs::create_dir_all(&runners_dir).map_err(|e| e.to_string())?; + + let runner_dir = runners_dir.join(&name); + if runner_dir.exists() { + let _ = fs::remove_dir_all(&runner_dir); + } + fs::create_dir_all(&runner_dir).map_err(|e| e.to_string())?; + + let token = CancellationToken::new(); + let child_token = token.clone(); + { + let mut lock = state.token.lock().await; + if let Some(old_token) = lock.take() { + old_token.cancel(); + } + *lock = Some(token); + } + + let tarball_path = runners_dir.join(format!("{}.tar.gz", name)); + let response = reqwest::get(&url).await.map_err(|e| e.to_string())?; + + if !response.status().is_success() { + return Err(format!("Download failed: {}", response.status())); + } + + let total_size = response.content_length().unwrap_or(0) as f64; + let mut file = fs::File::create(&tarball_path).map_err(|e| e.to_string())?; + let mut downloaded = 0.0; + let mut stream = response.bytes_stream(); + + while let Some(chunk) = stream.next().await { + if child_token.is_cancelled() { + drop(file); + let _ = fs::remove_file(&tarball_path); + let _ = fs::remove_dir_all(&runner_dir); + return Err("CANCELLED".into()); + } + let chunk = chunk.map_err(|e| e.to_string())?; + file.write_all(&chunk).map_err(|e| e.to_string())?; + downloaded += chunk.len() as f64; + if total_size > 0.0 { + let _ = app.emit("runner-download-progress", downloaded / total_size * 100.0); + } + } + + drop(file); + { *state.token.lock().await = None; } + + let status = Command::new("tar") + .args(["-zxf", tarball_path.to_str().unwrap(), "-C", runner_dir.to_str().unwrap(), "--strip-components=1"]) + .status() + .map_err(|e| e.to_string())?; + + let _ = fs::remove_file(&tarball_path); + + if !status.success() { + let _ = fs::remove_dir_all(&runner_dir); + return Err("Extraction failed".into()); + } + + Ok(name) } #[tauri::command] #[allow(non_snake_case)] -fn open_instance_folder(app: AppHandle, instanceId: String) { - let dir = get_app_dir(&app).join("instances").join(&instanceId); +fn check_game_installed(app: AppHandle, instance_id: String) -> bool { + get_app_dir(&app).join("instances").join(&instance_id).join("Minecraft.Client.exe").exists() +} + +#[tauri::command] +#[allow(non_snake_case)] +fn open_instance_folder(app: AppHandle, instance_id: String) { + let dir = get_app_dir(&app).join("instances").join(&instance_id); if dir.exists() { let _ = app.opener().open_path(dir.to_str().unwrap(), None::<&str>); } } +#[tauri::command] +#[allow(non_snake_case)] +fn delete_instance(app: AppHandle, instance_id: String) -> Result<(), String> { + let dir = get_app_dir(&app).join("instances").join(&instance_id); + if dir.exists() { + let _ = fs::remove_dir_all(dir); + } + Ok(()) +} + #[tauri::command] async fn cancel_download(state: State<'_, DownloadState>) -> Result<(), String> { if let Some(token) = state.token.lock().await.take() { token.cancel(); } Ok(()) } +#[tauri::command] +async fn setup_macos_runtime(window: tauri::Window, app: AppHandle) -> Result<(), String> { + #[cfg(not(target_os = "macos"))] + { + let _ = window; + let _ = app; + return Err("macOS runtime setup is only supported on macOS.".into()); + } + + #[cfg(target_os = "macos")] + { + #[derive(Deserialize)] + struct GithubAsset { + name: String, + browser_download_url: String, + } + + #[derive(Deserialize)] + struct GithubRelease { + tag_name: String, + assets: Vec, + } + + emit_macos_setup_progress(&window, "resolving", "Resolving macOS compatibility runtime…".into(), None); + + let client = reqwest::Client::new(); + let release_text = client + .get("https://api.github.com/repos/Gcenx/game-porting-toolkit/releases/latest") + .header("User-Agent", "Emerald-Legacy-Launcher") + .send() + .await + .map_err(|e| e.to_string())? + .error_for_status() + .map_err(|e| e.to_string())? + .text() + .await + .map_err(|e| e.to_string())?; + + let release: GithubRelease = serde_json::from_str(&release_text).map_err(|e| e.to_string())?; + let asset = release + .assets + .iter() + .find(|a| a.name.ends_with(".tar.xz") || a.name.ends_with(".tar.gz")) + .ok_or_else(|| "No compatible runtime asset found in latest release.".to_string())?; + + let runtime_dir = get_macos_runtime_dir(&app); + let toolkit_dir = runtime_dir.join("toolkit"); + let prefix_dir = runtime_dir.join("prefix"); + fs::create_dir_all(&runtime_dir).map_err(|e| e.to_string())?; + + if toolkit_dir.exists() { + let _ = fs::remove_dir_all(&toolkit_dir); + } + fs::create_dir_all(&toolkit_dir).map_err(|e| e.to_string())?; + + emit_macos_setup_progress( + &window, + "downloading", + format!("Downloading runtime ({})…", release.tag_name), + Some(0.0), + ); + + let archive_path = runtime_dir.join(format!("gptk_{}", asset.name)); + let response = client + .get(&asset.browser_download_url) + .header("User-Agent", "Emerald-Legacy-Launcher") + .send() + .await + .map_err(|e| e.to_string())? + .error_for_status() + .map_err(|e| e.to_string())?; + + let total_size = response.content_length().unwrap_or(0) as f64; + let mut file = fs::File::create(&archive_path).map_err(|e| e.to_string())?; + let mut downloaded = 0.0; + let mut last_percent_sent: i64 = -1; + let mut stream = response.bytes_stream(); + + while let Some(chunk) = stream.next().await { + let chunk = chunk.map_err(|e| e.to_string())?; + file.write_all(&chunk).map_err(|e| e.to_string())?; + downloaded += chunk.len() as f64; + + if total_size > 0.0 { + let percent = (downloaded / total_size * 100.0).clamp(0.0, 100.0); + let rounded = percent.floor() as i64; + if rounded != last_percent_sent { + last_percent_sent = rounded; + emit_macos_setup_progress( + &window, + "downloading", + format!("Downloading runtime… {}%", rounded), + Some(percent), + ); + } + } + } + drop(file); + + emit_macos_setup_progress(&window, "extracting", "Extracting runtime…".into(), None); + + let archive_metadata = fs::metadata(&archive_path).map_err(|e| format!("Cannot read archive: {}", e))?; + println!("Archive size: {} bytes", archive_metadata.len()); + + if archive_metadata.len() < 100_000_000 { + return Err(format!("Archive too small: {} bytes", archive_metadata.len())); + } + + let status = Command::new("tar") + .args([ + "-xf", + archive_path.to_str().ok_or_else(|| "Invalid archive path".to_string())?, + "-C", + toolkit_dir.to_str().ok_or_else(|| "Invalid toolkit path".to_string())?, + ]) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::piped()) + .status() + .map_err(|e| e.to_string())?; + + println!("Tar exit status: {:?}", status); + + let _ = fs::remove_file(&archive_path); + if !status.success() { + return Err(format!("Extraction failed with status: {:?}", status)); + } + + fs::create_dir_all(&prefix_dir).map_err(|e| e.to_string())?; + + let wine_binary = find_executable_recursive(&toolkit_dir, "wine64") + .or_else(|| find_executable_recursive(&toolkit_dir, "wine")) + .ok_or_else(|| "Unable to locate wine binary inside runtime.".to_string())?; + + let wine_bin_dir = wine_binary + .parent() + .map(|pp| pp.to_path_buf()) + .ok_or_else(|| "Unable to locate wine bin directory inside runtime.".to_string())?; + + emit_macos_setup_progress(&window, "initializing", "Initializing Wine prefix…".into(), None); + + let mut cmd = Command::new(&wine_binary); + cmd.arg("wineboot"); + cmd.arg("-u"); + cmd.env("WINEPREFIX", &prefix_dir); + cmd.env("WINEARCH", "win64"); + cmd.env("WINEDEBUG", "-all"); + cmd.env("WINEESYNC", "1"); + cmd.env("WINEDLLOVERRIDES", "winemenubuilder.exe=d;mscoree,mshtml="); + cmd.env("MTL_HUD_ENABLED", "0"); + cmd.env( + "PATH", + format!( + "{}:{}", + wine_bin_dir.to_string_lossy(), + std::env::var("PATH").unwrap_or_default() + ), + ); + cmd.stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + let status = cmd.status().map_err(|e| e.to_string())?; + if !status.success() { + return Err("Wine prefix initialization failed".into()); + } + + emit_macos_setup_progress(&window, "done", "Setup complete.".into(), Some(100.0)); + Ok(()) + } +} + +fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> std::io::Result<()> { + fs::create_dir_all(&dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} + #[tauri::command] #[allow(non_snake_case)] -async fn download_and_install(app: AppHandle, state: State<'_, DownloadState>, url: String, instanceId: String) -> Result { +async fn download_and_install(app: AppHandle, state: State<'_, DownloadState>, url: String, instance_id: String) -> Result { let root = get_app_dir(&app); - let instance_dir = root.join("instances").join(&instanceId); + let instance_dir = root.join("instances").join(&instance_id); let token = CancellationToken::new(); let child_token = token.clone(); - { *state.token.lock().await = Some(token); } - - if instance_dir.exists() { let _ = fs::remove_dir_all(&instance_dir); } - fs::create_dir_all(&instance_dir).map_err(|e| e.to_string())?; - - let zip_path = root.join(format!("temp_{}.zip", instanceId)); + { + let mut lock = state.token.lock().await; + if let Some(old_token) = lock.take() { + old_token.cancel(); + } + *lock = Some(token); + } + + if !instance_dir.exists() { + fs::create_dir_all(&instance_dir).map_err(|e| e.to_string())?; + } else { + if let Ok(entries) = fs::read_dir(&instance_dir) { + for entry in entries.flatten() { + let file_name = entry.file_name(); + let name_str = file_name.to_string_lossy(); + + let keep_list = ["Windows64", "Windows64Media", "uid.dat", "username.txt", "settings.dat", "servers.dat", "servers.txt", "server.properties", "Common", "options.txt", "servers.db"]; + if !keep_list.contains(&name_str.as_ref()) { + let path = entry.path(); + if path.is_dir() { + let _ = fs::remove_dir_all(path); + } else { + let _ = fs::remove_file(path); + } + } else if name_str == "Common" { + let common_dir = entry.path(); + if let Ok(common_entries) = fs::read_dir(&common_dir) { + for c_entry in common_entries.flatten() { + let c_name = c_entry.file_name(); + if c_name.to_string_lossy() != "res" { + let c_path = c_entry.path(); + if c_path.is_dir() { let _ = fs::remove_dir_all(c_path); } else { let _ = fs::remove_file(c_path); } + } else { + let res_dir = c_entry.path(); + if let Ok(res_entries) = fs::read_dir(&res_dir) { + for r_entry in res_entries.flatten() { + let r_name = r_entry.file_name(); + if r_name.to_string_lossy() != "mob" { + let r_path = r_entry.path(); + if r_path.is_dir() { let _ = fs::remove_dir_all(r_path); } else { let _ = fs::remove_file(r_path); } + } else { + let mob_dir = r_entry.path(); + if let Ok(mob_entries) = fs::read_dir(&mob_dir) { + for m_entry in mob_entries.flatten() { + let m_name = m_entry.file_name(); + if m_name.to_string_lossy() != "char.png" { + let m_path = m_entry.path(); + if m_path.is_dir() { let _ = fs::remove_dir_all(m_path); } else { let _ = fs::remove_file(m_path); } + } + } + } + } + } + } + } + } + } + } + } + } + } + + let zip_path = root.join(format!("temp_{}.zip", instance_id)); let response = reqwest::get(&url).await.map_err(|e| e.to_string())?; - + if !response.status().is_success() { return Err(format!("Download failed: {}", response.status())); } @@ -151,7 +713,7 @@ async fn download_and_install(app: AppHandle, state: State<'_, DownloadState>, u let mut file = fs::File::create(&zip_path).map_err(|e| e.to_string())?; let mut downloaded = 0.0; let mut stream = response.bytes_stream(); - + while let Some(chunk) = stream.next().await { if child_token.is_cancelled() { drop(file); let _ = fs::remove_file(&zip_path); @@ -162,58 +724,224 @@ async fn download_and_install(app: AppHandle, state: State<'_, DownloadState>, u downloaded += chunk.len() as f64; if total_size > 0.0 { let _ = app.emit("download-progress", downloaded / total_size * 100.0); } } - + drop(file); { *state.token.lock().await = None; } - + #[cfg(target_os = "linux")] - let status = Command::new("unzip") - .args(["-q", zip_path.to_str().unwrap(), "-d", instance_dir.to_str().unwrap()]) - .status() - .map_err(|e| e.to_string())?; + { + let unzip_check = Command::new("unzip").arg("-v").status(); + if unzip_check.is_err() || !unzip_check.unwrap().success() { + return Err("The 'unzip' command was not found. Please install it (e.g., 'sudo apt install unzip') to continue.".into()); + } - #[cfg(not(target_os = "linux"))] - let status = Command::new("tar") - .args(["-xf", zip_path.to_str().unwrap(), "-C", instance_dir.to_str().unwrap()]) - .status() - .map_err(|e| e.to_string())?; - - let _ = fs::remove_file(&zip_path); + let status = Command::new("unzip") + .args(["-o", "-q", zip_path.to_str().unwrap(), "-d", instance_dir.to_str().unwrap()]) + .status() + .map_err(|e| e.to_string())?; - if !status.success() { - return Err("Extraction failed".into()); + if !status.success() { + return Err("Extraction failed".into()); + } } + #[cfg(not(target_os = "linux"))] + { + let status = Command::new("tar") + .args(["-xf", zip_path.to_str().unwrap(), "-C", instance_dir.to_str().unwrap()]) + .status() + .map_err(|e| e.to_string())?; + + if !status.success() { + return Err("Extraction failed".into()); + } + } + + let _ = fs::remove_file(&zip_path); + if let Ok(entries) = fs::read_dir(&instance_dir) { - let entries_vec: Vec<_> = entries.flatten().collect(); - - if entries_vec.len() == 1 && entries_vec[0].path().is_dir() { - let inner_dir = entries_vec[0].path(); - - if let Ok(inner_entries) = fs::read_dir(&inner_dir) { - for inner_entry in inner_entries.flatten() { - let file_name = inner_entry.file_name(); - let dest_path = instance_dir.join(file_name); - let _ = fs::rename(inner_entry.path(), dest_path); + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + let check_exe = path.join("Minecraft.Client.exe"); + if check_exe.exists() { + let inner_dir = path; + if let Ok(inner_entries) = fs::read_dir(&inner_dir) { + for inner_entry in inner_entries.flatten() { + let file_name = inner_entry.file_name(); + let dest_path = instance_dir.join(file_name); + if fs::rename(inner_entry.path(), &dest_path).is_err() { + if inner_entry.path().is_dir() { + let _ = copy_dir_all(inner_entry.path(), &dest_path); + let _ = fs::remove_dir_all(inner_entry.path()); + } else { + let _ = fs::copy(inner_entry.path(), &dest_path); + let _ = fs::remove_file(inner_entry.path()); + } + } + } + } + let _ = fs::remove_dir_all(&inner_dir); + break; } } - let _ = fs::remove_dir(&inner_dir); + } + } + + Ok("Success".into()) +} + +fn ensure_server_list(instance_dir: &PathBuf, servers: Vec) { + let servers_db = instance_dir.join("servers.db"); + + let mut all_servers = Vec::new(); + + if let Ok(content) = fs::read(&servers_db) { + if content.len() >= 12 && &content[0..4] == b"MCSV" { + let count = u32::from_le_bytes(content[8..12].try_into().unwrap_or([0; 4])); + let mut pos = 12; + for _ in 0..count { + if pos + 2 > content.len() { break; } + let ip_len = u16::from_le_bytes(content[pos..pos+2].try_into().unwrap_or([0; 2])) as usize; + pos += 2; + if pos + ip_len > content.len() { break; } + let ip = String::from_utf8_lossy(&content[pos..pos+ip_len]).to_string(); + pos += ip_len; + if pos + 2 > content.len() { break; } + let port = u16::from_le_bytes(content[pos..pos+2].try_into().unwrap_or([0; 2])); + pos += 2; + if pos + 2 > content.len() { break; } + let name_len = u16::from_le_bytes(content[pos..pos+2].try_into().unwrap_or([0; 2])) as usize; + pos += 2; + if pos + name_len > content.len() { break; } + let name = String::from_utf8_lossy(&content[pos..pos+name_len]).to_string(); + pos += name_len; + + all_servers.push(McServer { name, ip, port }); + } + } + } + + for s in servers { + all_servers.push(s); + } + + let mut unique_servers = Vec::new(); + let mut seen: std::collections::HashSet<(String, u16)> = std::collections::HashSet::new(); + for s in all_servers { + let key = (s.ip.clone(), s.port); + if seen.insert(key) { + unique_servers.push(s); + } + } + + let mut file_content = Vec::new(); + file_content.extend_from_slice(b"MCSV"); + file_content.extend_from_slice(&1u32.to_le_bytes()); + file_content.extend_from_slice(&(unique_servers.len() as u32).to_le_bytes()); + for server in unique_servers { + let ip_bytes = server.ip.as_bytes(); + let name_bytes = server.name.as_bytes(); + file_content.extend_from_slice(&(ip_bytes.len() as u16).to_le_bytes()); + file_content.extend_from_slice(ip_bytes); + file_content.extend_from_slice(&server.port.to_le_bytes()); + file_content.extend_from_slice(&(name_bytes.len() as u16).to_le_bytes()); + file_content.extend_from_slice(name_bytes); + } + let _ = fs::create_dir_all(instance_dir); + let _ = fs::write(&servers_db, file_content); +} + +fn perform_dlc_sync(app: &AppHandle, instance_dir: &PathBuf) -> Result<(), String> { + let mut dlc_src = None; + let root = get_app_dir(app); + + use tauri::path::BaseDirectory; + if let Ok(p) = app.path().resolve("resources/DLC", BaseDirectory::Resource) { + if p.exists() { + dlc_src = Some(p); + } else { + if let Ok(p2) = app.path().resolve("DLC", BaseDirectory::Resource) { + if p2.exists() { dlc_src = Some(p2); } + } } } - Ok("Success".into()) + if dlc_src.is_none() { + let current = std::env::current_dir().unwrap_or_default(); + let p3 = current.join("src-tauri").join("resources").join("DLC"); + let p4 = current.join("resources").join("DLC"); + if p3.exists() { dlc_src = Some(p3); } + else if p4.exists() { dlc_src = Some(p4); } + } + + if dlc_src.is_none() { + let p5 = root.join("DLC"); + if p5.exists() { dlc_src = Some(p5); } + } + + match dlc_src { + Some(src) => { + let dlc_dest = instance_dir.join("Windows64Media").join("DLC"); + let _ = fs::create_dir_all(&dlc_dest); + + if let Ok(entries) = fs::read_dir(&src) { + for entry in entries.flatten() { + let name = entry.file_name(); + let dest_path = dlc_dest.join(&name); + + if !dest_path.exists() { + if let Err(e) = if entry.path().is_dir() { + copy_dir_all(entry.path(), &dest_path) + } else { + fs::copy(entry.path(), &dest_path).map(|_| ()) + } { + eprintln!("[DLC Sync] Failed to copy {:?} to {:?}: {}", entry.path(), dest_path, e); + } else { + println!("[DLC Sync] Copied to {:?}", dest_path); + } + } else { + println!("[DLC Sync] Skipping {:?}: Already exists in instance", name); + } + } + } + Ok(()) + }, + None => { + println!("[DLC Sync] Skipping sync: No DLC source found."); + Ok(()) + } + } +} + +#[tauri::command] +async fn sync_dlc(app: AppHandle, instance_id: String) -> Result<(), String> { + let root = get_app_dir(&app); + let instance_dir = root.join("instances").join(&instance_id); + perform_dlc_sync(&app, &instance_dir) } #[tauri::command] #[allow(non_snake_case)] -async fn launch_game(app: AppHandle, instanceId: String) -> Result<(), String> { +async fn launch_game(app: AppHandle, state: State<'_, GameState>, instance_id: String, servers: Vec) -> Result<(), String> { let root = get_app_dir(&app); - let instance_dir = root.join("instances").join(&instanceId); + let instance_dir = root.join("instances").join(&instance_id); let config = load_config(app.clone()); let username = config.username; - let _ = fs::write(instance_dir.join("username.txt"), &username); - + ensure_server_list(&instance_dir, servers); + if let Some(skin_data) = config.skin_base64 { + use base64::{Engine as _, engine::general_purpose}; + let base64_str = skin_data.split(',').nth(1).unwrap_or(&skin_data); + if let Ok(bytes) = general_purpose::STANDARD.decode(base64_str) { + let skin_dir = instance_dir.join("Common").join("res").join("mob"); + let _ = fs::create_dir_all(&skin_dir); + let _ = fs::write(skin_dir.join("char.png"), bytes); + } + } + + let _ = perform_dlc_sync(&app, &instance_dir)?; + let game_exe = instance_dir.join("Minecraft.Client.exe"); if !game_exe.exists() { return Err("Game executable not found in instance folder.".into()); @@ -222,26 +950,54 @@ async fn launch_game(app: AppHandle, instanceId: String) -> Result<(), String> { #[cfg(target_os = "linux")] { if let Some(runner_id) = config.linux_runner { - let runners = get_available_runners(); + let runners = get_available_runners(app.clone()); if let Some(runner) = runners.into_iter().find(|r| r.id == runner_id) { let mut cmd = if runner.r#type == "proton" { let proton_exe = PathBuf::from(&runner.path).join("proton"); - let mut c = Command::new(proton_exe); + let mut c = tokio::process::Command::new(proton_exe); let compat_data = instance_dir.join("proton_prefix"); fs::create_dir_all(&compat_data).map_err(|e| e.to_string())?; c.env("STEAM_COMPAT_CLIENT_INSTALL_PATH", ""); c.env("STEAM_COMPAT_DATA_PATH", compat_data.to_str().unwrap()); + c.env("SteamAppId", "480"); c.arg("run"); c } else { - Command::new(runner.path) + tokio::process::Command::new(runner.path) }; + #[cfg(unix)] + cmd.process_group(0); + cmd.arg(&game_exe) - .current_dir(&instance_dir) - .spawn() - .map_err(|e| e.to_string())?; - return Ok(()); + .current_dir(&instance_dir); + + let child = cmd.spawn().map_err(|e| e.to_string())?; + { + let mut lock = state.child.lock().await; + *lock = Some(child); + } + + let status = loop { + { + let mut lock = state.child.lock().await; + if let Some(ref mut c) = *lock { + if let Some(s) = c.try_wait().map_err(|e| e.to_string())? { + break s; + } + } else { + return Ok(()); + } + } + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + }; + + { + let mut lock = state.child.lock().await; + *lock = None; + } + + return if status.success() || status.code() == Some(253) || status.code() == Some(96) { Ok(()) } else { Err(format!("Game exited with status: {}", status)) }; } } Err("No Linux runner selected in settings.".into()) @@ -249,16 +1005,257 @@ async fn launch_game(app: AppHandle, instanceId: String) -> Result<(), String> { #[cfg(not(target_os = "linux"))] { - let _ = Command::new(&game_exe).spawn().map_err(|e| e.to_string())?; - Ok(()) + #[cfg(target_os = "macos")] + { + let runtime_dir = get_macos_runtime_dir(&app); + let toolkit_dir = runtime_dir.join("toolkit"); + let prefix_dir = runtime_dir.join("prefix"); + + if !toolkit_dir.exists() || !prefix_dir.exists() { + return Err("macOS Compatibility is not set up. Open Settings and run Setup macOS Compatibility.".into()); + } + + let gptk_no_hud = find_executable_recursive(&toolkit_dir, "gameportingtoolkit-no-hud") + .or_else(|| find_executable_recursive(&toolkit_dir, "gameportingtoolkit")); + + let wine_binary = find_executable_recursive(&toolkit_dir, "wine64") + .or_else(|| find_executable_recursive(&toolkit_dir, "wine")) + .ok_or_else(|| "Unable to locate wine binary inside runtime.".to_string())?; + + let wine_bin_dir = wine_binary + .parent() + .map(|pp| pp.to_path_buf()) + .ok_or_else(|| "Unable to locate wine bin directory inside runtime.".to_string())?; + + let mut cmd = if let Some(wrapper) = gptk_no_hud { + let win_path = unix_path_to_wine_z_path(&game_exe); + let mut c = tokio::process::Command::new(wrapper); + c.arg(&prefix_dir); + c.arg(win_path); + c + } else { + let mut c = tokio::process::Command::new(&wine_binary); + c.env("WINEPREFIX", &prefix_dir); + c.arg(&game_exe); + c + }; + + #[cfg(unix)] + cmd.process_group(0); + + cmd.current_dir(&instance_dir); + cmd.env("WINEPREFIX", &prefix_dir); + cmd.env("WINEDEBUG", "-all"); + let perf_boost = config.apple_silicon_performance_boost.unwrap_or(false); + if perf_boost { + #[cfg(target_arch = "aarch64")] + { + cmd.env("WINE_MSYNC", "1"); + cmd.env("MVK_ALLOW_METAL_FENCES", "1"); + } + #[cfg(not(target_arch = "aarch64"))] + { + cmd.env("WINEESYNC", "1"); + } + } else { + cmd.env("WINEESYNC", "1"); + } + cmd.env("WINEDLLOVERRIDES", "winemenubuilder.exe=d;mscoree,mshtml="); + cmd.env("MTL_HUD_ENABLED", "0"); + cmd.env("MVK_CONFIG_RESUME_LOST_DEVICE", "1"); + cmd.env( + "PATH", + format!( + "{}:{}", + wine_bin_dir.to_string_lossy(), + std::env::var("PATH").unwrap_or_default() + ), + ); + cmd.stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + let child = cmd.spawn().map_err(|e| e.to_string())?; + { + let mut lock = state.child.lock().await; + *lock = Some(child); + } + + let status = loop { + { + let mut lock = state.child.lock().await; + if let Some(ref mut c) = *lock { + if let Some(s) = c.try_wait().map_err(|e| e.to_string())? { + break s; + } + } else { + return Ok(()); + } + } + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + }; + + { + let mut lock = state.child.lock().await; + *lock = None; + } + + return if status.success() || status.code() == Some(253) || status.code() == Some(96) { Ok(()) } else { Err(format!("Game exited with status: {}", status)) }; + } + + #[cfg(all(not(target_os = "macos"), not(target_os = "linux")))] + { + let mut cmd = tokio::process::Command::new(&game_exe); + #[cfg(unix)] + cmd.process_group(0); + cmd.current_dir(&instance_dir); + let child = cmd.spawn().map_err(|e| e.to_string())?; + { + let mut lock = state.child.lock().await; + *lock = Some(child); + } + let status = loop { + { + let mut lock = state.child.lock().await; + if let Some(ref mut c) = *lock { + if let Some(s) = c.try_wait().map_err(|e| e.to_string())? { + break s; + } + } else { + return Ok(()); + } + } + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + }; + { + let mut lock = state.child.lock().await; + *lock = None; + } + return if status.success() || status.code() == Some(253) || status.code() == Some(96) { Ok(()) } else { Err(format!("Game exited with status: {}", status)) }; + } } } +#[cfg(unix)] +fn kill_process_tree(app: &AppHandle, instance_id: &str) { + let root = get_app_dir(&app); + let instance_dir = root.join("instances").join(instance_id); + let target = unix_path_to_wine_z_path(&instance_dir.join("Minecraft.Client.exe")); + let Ok(entries) = fs::read_dir("/proc") else { return }; + for entry in entries.flatten() { + let Ok(pid) = entry.file_name().to_string_lossy().parse::() else { continue }; + let cmdline = fs::read_to_string(format!("/proc/{}/cmdline", pid)) + .unwrap_or_default(); + if cmdline.contains(&*target) { + unsafe { libc::kill(pid as i32, libc::SIGKILL); } + } + } +} + +#[tauri::command] +async fn stop_game(#[allow(unused_variables)] app: AppHandle, #[allow(unused_variables)] instance_id: String, state: State<'_, GameState>) -> Result<(), String> { + let mut lock = state.child.lock().await; + if let Some(mut child) = lock.take() { + #[cfg(unix)] kill_process_tree(&app, &instance_id); + let _ = child.kill().await; + } + Ok(()) +} + +#[tauri::command] +fn update_tray_icon(app: AppHandle, visible: bool) { + if let Some(tray) = app.tray_by_id("main") { + let _ = tray.set_visible(visible); + } +} + +#[tauri::command] +async fn fetch_skin(username: String) -> Result<(String, String), String> { + let client = reqwest::Client::new(); + let mojang_url = format!("https://api.mojang.com/users/profiles/minecraft/{}", username); + let mojang_res = client.get(&mojang_url).send().await.map_err(|e| format!("Failed request to mojang: {}", e))?; + if !mojang_res.status().is_success() { + return Err("Player not found".to_string()); + } + let mojang_text = mojang_res.text().await.map_err(|e| format!("Failed to read mojang text: {}", e))?; + let mojang_data: serde_json::Value = serde_json::from_str(&mojang_text).map_err(|e| format!("Invalid Mojang JSON: {}", e))?; + let id = mojang_data.get("id").and_then(|v| v.as_str()).ok_or_else(|| "Invalid Moajng response format".to_string())?; + let name_exact = mojang_data.get("name").and_then(|v| v.as_str()).unwrap_or(&username).to_string(); + + let mc_api_url = format!("https://api.minecraftapi.net/v3/profile/{}", id); + let mc_api_res = client.get(&mc_api_url).send().await.map_err(|e| format!("Failed request to mc api: {}", e))?; + if !mc_api_res.status().is_success() { + return Err("Error fetching skin data".to_string()); + } + let mc_api_text = mc_api_res.text().await.map_err(|e| format!("Failed to read mc api text: {}", e))?; + let mc_api_data: serde_json::Value = serde_json::from_str(&mc_api_text).map_err(|e| format!("Invalid MC API JSON: {}", e))?; + let image_b64 = mc_api_data.get("skin") + .and_then(|s| s.get("image")) + .and_then(|v| v.as_str()) + .ok_or_else(|| "No skin found".to_string())?; + + Ok((image_b64.to_string(), name_exact)) +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .manage(DownloadState { token: Arc::new(Mutex::new(None)) }) + .manage(GameState { child: Arc::new(Mutex::new(None)) }) + .plugin(tauri_plugin_gamepad::init()) .plugin(tauri_plugin_opener::init()) - .invoke_handler(tauri::generate_handler![launch_game, check_game_installed, save_config, load_config, download_and_install, open_instance_folder, cancel_download, get_available_runners]) + .plugin(tauri_plugin_drpc::init()) + .invoke_handler(tauri::generate_handler![setup_macos_runtime, launch_game, stop_game, check_game_installed, save_config, load_config, download_and_install, open_instance_folder, cancel_download, get_available_runners, get_external_palettes, import_theme, download_runner, delete_instance, update_tray_icon, sync_dlc, fetch_skin]) + .setup(|app| { + let config = load_config(app.handle().clone()); + let visible = config.enable_tray_icon.unwrap_or(true); + + let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; + let show_i = MenuItem::with_id(app, "show", "Show", true, None::<&str>)?; + let menu = Menu::with_items(app, &[&show_i, &quit_i])?; + + let tray = TrayIconBuilder::with_id("main") + .icon(tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png")).unwrap()) + .tooltip("Emerald Legacy Launcher") + .menu(&menu) + .on_menu_event(|app: &AppHandle, event: MenuEvent| { + match event.id.as_ref() { + "quit" => { + app.exit(0); + } + "show" => { + if let Some(window) = app.get_webview_window("main") { + let _ = window.show(); + let _ = window.set_focus(); + } + } + _ => {} + } + }) + .on_tray_icon_event(|tray: &TrayIcon, event: TrayIconEvent| { + if let TrayIconEvent::Click { button: tauri::tray::MouseButton::Left, .. } = event { + let app = tray.app_handle(); + if let Some(window) = app.get_webview_window("main") { + let _ = window.show(); + let _ = window.set_focus(); + } + } + }) + .build(app)?; + + let _ = tray.set_visible(visible); + + Ok(()) + }) + .on_window_event(|window, event| { + if let tauri::WindowEvent::CloseRequested { api, .. } = event { + let config = load_config(window.app_handle().clone()); + if config.enable_tray_icon.unwrap_or(true) { + api.prevent_close(); + let _ = window.hide(); + } + } + }) .run(tauri::generate_context!()) - .expect("error"); -} \ No newline at end of file + .expect("error while running tauri application"); +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c4f36ee..0c9434c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,9 +1,90 @@ -// Prevents additional console window on Windows in release, DO NOT REMOVE!! -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] - -fn main() { - #[cfg(target_os = "linux")] - std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1"); - - emerald_legacy_launcher_lib::run() -} +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + #[cfg(target_os = "linux")] + { + use std::env; + use std::process::{Command, Stdio, exit}; + use std::io::{BufReader, BufRead}; + use std::thread; + + let stage = env::var("EMERALD_LAUNCH_STAGE").unwrap_or_else(|_| "0".to_string()); + + if stage == "0" { + let mut child = Command::new(env::current_exe().unwrap()) + .env("EMERALD_LAUNCH_STAGE", "1") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("failed to spawn child process"); + + let stdout = child.stdout.take().expect("failed to take stdout"); + let stderr = child.stderr.take().expect("failed to take stderr"); + let child_id = child.id(); + + fn check_line(l: &str) -> bool { + let low = l.to_lowercase(); + (low.contains("gbm") && low.contains("buffer")) || + (low.contains("dmabuf") && low.contains("renderer")) || + (low.contains("invalid argument") && low.contains("buffer")) || + (low.contains("wayland") && low.contains("protocol error")) + } + + let h1 = thread::spawn(move || { + let reader = BufReader::new(stdout); + for line in reader.lines() { + if let Ok(l) = line { + println!("{}", l); + if check_line(&l) { + eprintln!("!!! Emerald: Graphics error detected in stdout: {}", l); + #[cfg(unix)] + let _ = Command::new("kill").arg("-9").arg(child_id.to_string()).status(); + return true; + } + } + } + false + }); + + let h2 = thread::spawn(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + if let Ok(l) = line { + eprintln!("{}", l); + if check_line(&l) { + eprintln!("!!! Emerald: Graphics error detected in stderr: {}", l); + #[cfg(unix)] + let _ = Command::new("kill").arg("-9").arg(child_id.to_string()).status(); + return true; + } + } + } + false + }); + + let status = child.wait().expect("failed to wait on child process"); + + let found_error = h1.join().unwrap_or(false) || h2.join().unwrap_or(false); + + if found_error || !status.success() { + if found_error { + println!("Emerald: Automatic recovery triggered for graphics crash/invisible launch."); + } + + let mut retry_child = Command::new(env::current_exe().unwrap()) + .env("EMERALD_LAUNCH_STAGE", "2") + .env("WEBKIT_DISABLE_DMABUF_RENDERER", "1") + .env("WEBKIT_DISABLE_COMPOSITING_MODE", "1") + .spawn() + .expect("failed to spawn fallback child process"); + + let retry_status = retry_child.wait().expect("failed to wait on fallback child process"); + exit(retry_status.code().unwrap_or(1)); + } + exit(0); + } + } + + emerald_lib::run() +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4df7b95..b75ec38 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,44 +1,53 @@ -{ - "$schema": "https://schema.tauri.app/config/2", - "productName": "Emerald Legacy Launcher", - "version": "0.2.0", - "identifier": "com.emerald.legacy", - "build": { - "beforeDevCommand": "npm run dev", - "devUrl": "http://localhost:1420", - "beforeBuildCommand": "npm run build", - "frontendDist": "../dist" - }, - "app": { - "windows": [ - { - "title": "Emerald Legacy", - "width": 1000, - "height": 650, - "decorations": true, - "transparent": false, - "titleBarStyle": "Visible", - "devtools": true - } - ], - "security": { - "csp": null - } - }, - "bundle": { - "active": true, - "targets": "all", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ] - }, - "plugins": { - "shell": { - "open": true - } - } -} +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "Emerald Legacy Launcher", + "version": "1.0.0", + "identifier": "com.emerald.legacy", + "build": { + "beforeDevCommand": "npm run dev", + "devUrl": "http://localhost:1420", + "beforeBuildCommand": "npm run build", + "frontendDist": "../dist" + }, + "app": { + "windows": [ + { + "label": "main", + "title": "Emerald Legacy Launcher", + "width": 1280, + "height": 720, + "minWidth": 1280, + "minHeight": 720, + "decorations": false, + "transparent": true, + "resizable": true, + "center": true, + "visible": false + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "resources": [ + "resources/DLC" + ], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "signingIdentity": null, + "providerShortName": "Emerald" + } + } +} diff --git a/src/App.tsx b/src/App.tsx deleted file mode 100644 index a1df1ba..0000000 --- a/src/App.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { useState, useEffect } from "react"; -import { useAudio } from "./hooks/useAudio"; -import { useSettings } from "./hooks/useSettings"; -import { useGameInstances } from "./hooks/useGameInstances"; -import { useLauncher } from "./hooks/useLauncher"; -import { TauriService } from "./services/tauri"; -import { AppConfig, Runner, ReinstallModalData, McNotification } from "./types"; -import { Sidebar } from "./components/layout/Sidebar"; -import { HomeView } from "./components/views/HomeView"; -import { VersionsView } from "./components/views/VersionsView"; -import { SettingsView } from "./components/views/SettingsView"; -import { FirstRunView } from "./components/views/FirstRunView"; -import { ReinstallModal } from "./components/modals/ReinstallModal"; -import { Notification } from "./components/common/Notification"; -import "./index.css"; - -export default function App() { - const [username, setUsername] = useState(""); - const [activeTab, setActiveTab] = useState("home"); - const [isFirstRun, setIsFirstRun] = useState(true); - const [selectedInstance, setSelectedInstance] = useState("vanilla_tu19"); - const [reinstallModal, setReinstallModal] = useState(null); - const [mcNotif, setMcNotif] = useState(null); - const [availableRunners, setAvailableRunners] = useState([]); - const [selectedRunner, setSelectedRunner] = useState(""); - const [isLinux, setIsLinux] = useState(false); - - const { musicVol, setMusicVol, sfxVol, setSfxVol, isMuted, setIsMuted } = useSettings(); - const { musicRef, playRandomMusic, playSfx, ensureAudio } = useAudio(musicVol, sfxVol, isMuted); - const { installedStatus, installingInstance, downloadProgress, executeInstall, updateAllStatus } = useGameInstances(playSfx, setMcNotif); - const { isRunning, fadeAndLaunch } = useLauncher(selectedInstance, musicRef, isMuted, musicVol, playRandomMusic, playSfx); - - useEffect(() => { - TauriService.loadConfig().then((c) => { - const config = c as AppConfig; - if (config.username && config.username.trim() !== "") { - setUsername(config.username); - setIsFirstRun(false); - setTimeout(playRandomMusic, 1000); - } - if (config.linuxRunner) setSelectedRunner(config.linuxRunner); - }); - - const platform = window.navigator.platform.toLowerCase(); - if (platform.includes("linux")) { - setIsLinux(true); - TauriService.getAvailableRunners().then((runners) => { - setAvailableRunners(runners); - }); - } - }, []); - - if (isFirstRun) { - return ( - - ); - } - - return ( -
e.preventDefault()} - > -
- ); -} \ No newline at end of file diff --git a/src/assets/react.svg b/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx deleted file mode 100644 index e384bd3..0000000 --- a/src/components/Icons.tsx +++ /dev/null @@ -1,29 +0,0 @@ -export const Icons = { - Discord: () => ( - - - - ), - Github: () => ( - - - - ), - Reddit: () => ( - - - - ), - Volume: ({ level }: { level: number }) => ( - - - {level > 0 && } - {level > 0.5 && } - - ), - Linux: () => ( - - - - ), -}; diff --git a/src/components/common/AchievementToast.tsx b/src/components/common/AchievementToast.tsx new file mode 100644 index 0000000..91a77c8 --- /dev/null +++ b/src/components/common/AchievementToast.tsx @@ -0,0 +1,106 @@ +import { useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; + +interface AchievementToastProps { + message: string | null; + onClose: () => void; + onClick?: () => void; + title?: string; + variant?: "error" | "update"; +} + +export function AchievementToast({ + message, + onClose, + onClick, + title = "Error Get!", + variant = "error" +}: AchievementToastProps) { + useEffect(() => { + if (message) { + const timer = setTimeout(() => { + onClose(); + }, 8000); + return () => clearTimeout(timer); + } + }, [message, onClose]); + + const getIcon = () => { + if (variant === "update") { + return ( + + + + ); + } + return ( + + + + + ); + }; + + return ( + + {message && ( + { + onClick(); + onClose(); + } : undefined} + className={`fixed top-6 right-6 z-[9999] ${onClick ? "cursor-pointer" : ""}`} + > +
+
+ {getIcon()} +
+
+ + {title} + + + {message} + +
+
+
+ )} +
+ ); +} diff --git a/src/components/common/ClickParticles.tsx b/src/components/common/ClickParticles.tsx new file mode 100644 index 0000000..12c5052 --- /dev/null +++ b/src/components/common/ClickParticles.tsx @@ -0,0 +1,67 @@ +import React, { useEffect, useState } from "react"; + +const SGA_CHARS = "abcdefghijklmnopqrstuvwxyz".split(""); + +interface Particle { + id: number; + char: string; + x: number; + y: number; + vX: number; + vY: number; + rotation: number; +} + +export const ClickParticles: React.FC = React.memo(() => { + const [bursts, setBursts] = useState([]); + + useEffect(() => { + const handleClick = (e: MouseEvent) => { + const newParticles: Particle[] = []; + const particleCount = 8; + + for (let i = 0; i < particleCount; i++) { + newParticles.push({ + id: Date.now() + Math.random(), + char: SGA_CHARS[Math.floor(Math.random() * SGA_CHARS.length)], + x: e.clientX, + y: e.clientY, + vX: (Math.random() - 0.5) * 200, + vY: (Math.random() - 0.5) * 200, + rotation: Math.random() * 360, + }); + } + + setBursts((prev) => [...prev, ...newParticles]); + setTimeout(() => { + setBursts((prev) => prev.filter(p => !newParticles.find(np => np.id === p.id))); + }, 1000); + }; + + window.addEventListener("mousedown", handleClick); + return () => window.removeEventListener("mousedown", handleClick); + }, []); + + return ( +
+ {bursts.map((p) => ( + magic-particle + ))} +
+ ); +}); \ No newline at end of file diff --git a/src/components/common/Notification.tsx b/src/components/common/Notification.tsx deleted file mode 100644 index d47f06e..0000000 --- a/src/components/common/Notification.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -interface NotificationProps { - title: string; - message: string; -} - -export const Notification: React.FC = ({ title, message }) => { - return ( -
-
- ✓ -
-
- {title} - {message} -
-
- ); -}; diff --git a/src/components/common/PanoramaBackground.tsx b/src/components/common/PanoramaBackground.tsx new file mode 100644 index 0000000..0d990b3 --- /dev/null +++ b/src/components/common/PanoramaBackground.tsx @@ -0,0 +1,70 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { useUI } from '../../context/LauncherContext'; + +interface PanoramaProps { + profile: string; + isDay: boolean; +} + +const PanoramaBackground = React.memo(({ profile, isDay }: PanoramaProps) => { + const { isWindowVisible } = useUI(); + const PANORAMA_PROFILES = ['legacy_evolved', 'vanilla_tu19', 'vanilla_tu24']; + const profileId = PANORAMA_PROFILES.includes(profile) ? profile : 'legacy_evolved'; + const currentPanorama = `/panorama/${profileId}_Panorama_Background_${isDay ? 'Day' : 'Night'}.png`; + + const [bgWidth, setBgWidth] = useState(null); + const containerRef = useRef(null); + + useEffect(() => { + let active = true; + const updateWidth = () => { + if (!containerRef.current) return; + const img = new Image(); + img.src = currentPanorama; + img.onload = () => { + if (!active || !containerRef.current) return; + const height = containerRef.current.clientHeight; + const aspectRatio = img.naturalWidth / img.naturalHeight; + setBgWidth(Math.ceil(height * aspectRatio)); + }; + }; + + updateWidth(); + window.addEventListener('resize', updateWidth); + return () => { + active = false; + window.removeEventListener('resize', updateWidth); + }; + }, [currentPanorama]); + + return ( + <> + {bgWidth && ( + + )} + +
+ {isWindowVisible && ( +
+ )} +
+
+ + ); +}); + +export default PanoramaBackground; \ No newline at end of file diff --git a/src/components/common/SkinViewer.tsx b/src/components/common/SkinViewer.tsx new file mode 100644 index 0000000..9282773 --- /dev/null +++ b/src/components/common/SkinViewer.tsx @@ -0,0 +1,328 @@ +import { useEffect, useRef, useState, memo } from 'react'; +import { motion } from 'framer-motion'; +import * as THREE from 'three'; +import { useLocalStorage } from '../../hooks/useLocalStorage'; +import { useConfig } from '../../context/LauncherContext'; + +interface SkinViewerProps { + username: string; + setUsername: (name: string) => void; + playClickSound: () => void; + skinUrl: string; + setSkinUrl: (url: string) => void; + setActiveView: (view: string) => void; + isFocusedSection: boolean; + onNavigateRight: () => void; +} + +const SkinViewer = memo(function SkinViewer({ username, setUsername, playClickSound, skinUrl, setSkinUrl, setActiveView, isFocusedSection, onNavigateRight }: SkinViewerProps) { + const mountRef = useRef(null); + const containerRef = useRef(null); + const [focusIndex, setFocusIndex] = useState(0); + const { legacyMode } = useConfig(); + + const [showLayers, setShowLayers] = useLocalStorage('lce-show-layers', true); + const overlaysRef = useRef([]); + const requestRenderRef = useRef<(() => void) | null>(null); + + useEffect(() => { + if (!mountRef.current) return; + + const width = 260; + const height = 450; + + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera(35, width / height, 0.1, 1000); + camera.position.set(0, 0, 68); + + const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); + renderer.setSize(width, height); + renderer.setPixelRatio(window.devicePixelRatio); + mountRef.current.innerHTML = ""; + mountRef.current.appendChild(renderer.domElement); + + scene.add(new THREE.AmbientLight(0xffffff, 0.4)); + scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 0.6)); + const dl = new THREE.DirectionalLight(0xffffff, 0.8); + dl.position.set(10, 20, 10); + scene.add(dl); + + const playerGroup = new THREE.Group(); + playerGroup.position.y = -1.5; + scene.add(playerGroup); + + const textureLoader = new THREE.TextureLoader(); + textureLoader.load(skinUrl || "/images/Default.png", (texture) => { + texture.magFilter = THREE.NearestFilter; + texture.minFilter = THREE.NearestFilter; + texture.colorSpace = THREE.SRGBColorSpace; + + const img = texture.image; + const isLegacy = img.height === 32; + + const createFaceMaterial = (x: number, y: number, w: number, h: number, flipX = false, flipY = false) => { + const matTex = texture.clone(); + matTex.repeat.set((flipX ? -w : w) / 64, (flipY ? -h : h) / img.height); + matTex.offset.set((flipX ? (x + w) : x) / 64, 1 - (flipY ? y : (y + h)) / img.height); + matTex.needsUpdate = true; + return new THREE.MeshLambertMaterial({ map: matTex, transparent: true, alphaTest: 0.5, side: THREE.FrontSide }); + }; + + const createPart = (w: number, h: number, d: number, uv: any, overlayUv?: any, swapMats = false, isLegacyMirror = false) => { + const group = new THREE.Group(); + const geo = new THREE.BoxGeometry(w, h, d); + + const getMats = (uvSet: any) => { + const flipX = isLegacyMirror; + return [ + createFaceMaterial(swapMats ? uvSet.right[0] : uvSet.left[0], uvSet.left[1], uvSet.left[2], uvSet.left[3], flipX), // +x (L) + createFaceMaterial(swapMats ? uvSet.left[0] : uvSet.right[0], uvSet.right[1], uvSet.right[2], uvSet.right[3], flipX), // -x (R) + createFaceMaterial(uvSet.top[0], uvSet.top[1], uvSet.top[2], uvSet.top[3], flipX, true), // +y (T) + createFaceMaterial(uvSet.bottom[0], uvSet.bottom[1], uvSet.bottom[2], uvSet.bottom[3], flipX, true), // -y (B) + createFaceMaterial(uvSet.front[0], uvSet.front[1], uvSet.front[2], uvSet.front[3], flipX), // +z (F) + createFaceMaterial(uvSet.back[0], uvSet.back[1], uvSet.back[2], uvSet.back[3], !flipX) // -z (B) + ]; + }; + + const mesh = new THREE.Mesh(geo, getMats(uv)); + group.add(mesh); + + if (overlayUv) { + const oGeo = new THREE.BoxGeometry(w + 0.5, h + 0.5, d + 0.5); + const oMesh = new THREE.Mesh(oGeo, getMats(overlayUv)); + oMesh.visible = showLayers; + overlaysRef.current.push(oMesh); + group.add(oMesh); + } + return group; + }; + + const limbUv = (x: number, y: number, w = 4) => ({ + top: [x + 4, y, w, 4], bottom: [x + 4 + w, y, w, 4], + right: [x, y + 4, 4, 12], front: [x + 4, y + 4, w, 12], + left: [x + 4 + w, y + 4, 4, 12], back: [x + 8 + w, y + 4, w, 12] + }); + + const isSlim = !isLegacy && (() => { + const canvas = document.createElement('canvas'); + canvas.width = img.width; canvas.height = img.height; + const ctx = canvas.getContext('2d'); + if (!ctx) return false; + ctx.drawImage(img, 0, 0); + const data = ctx.getImageData(42, 48, 1, 1).data; + return data[3] === 0; + })(); + const armW = isSlim ? 3 : 4; + + const headUv = { top: [8, 0, 8, 8], bottom: [16, 0, 8, 8], right: [0, 8, 8, 8], left: [16, 8, 8, 8], front: [8, 8, 8, 8], back: [24, 8, 8, 8] }; + const hatUv = { top: [40, 0, 8, 8], bottom: [48, 0, 8, 8], right: [32, 8, 8, 8], left: [48, 8, 8, 8], front: [40, 8, 8, 8], back: [56, 8, 8, 8] }; + const head = createPart(8, 8, 8, headUv, hatUv); + head.position.y = 10; + playerGroup.add(head); + + const bodyUv = { top: [20, 16, 8, 4], bottom: [28, 16, 8, 4], right: [16, 20, 4, 12], left: [28, 20, 4, 12], front: [20, 20, 8, 12], back: [32, 20, 8, 12] }; + const jacketUv = { top: [20, 32, 8, 4], bottom: [28, 32, 8, 4], right: [16, 36, 4, 12], left: [28, 36, 4, 12], front: [20, 36, 8, 12], back: [32, 36, 8, 12] }; + playerGroup.add(createPart(8, 12, 4, bodyUv, isLegacy ? undefined : jacketUv)); + + const rightArm = createPart(armW, 12, 4, limbUv(40, 16, armW), isLegacy ? undefined : limbUv(40, 32, armW)); + rightArm.position.set(isSlim ? -5.5 : -6, 0, 0); + playerGroup.add(rightArm); + + const leftArm = createPart(armW, 12, 4, isLegacy ? limbUv(40, 16, armW) : limbUv(32, 48, armW), isLegacy ? undefined : limbUv(48, 48, armW), true, isLegacy); + leftArm.position.set(isSlim ? 5.5 : 6, 0, 0); + playerGroup.add(leftArm); + + const rightLeg = createPart(4, 12, 4, limbUv(0, 16), isLegacy ? undefined : limbUv(0, 32)); + rightLeg.position.set(-2, -12, 0); + playerGroup.add(rightLeg); + + const leftLeg = createPart(4, 12, 4, isLegacy ? limbUv(0, 16) : limbUv(16, 48), isLegacy ? undefined : limbUv(0, 48), true, isLegacy); + leftLeg.position.set(2, -12, 0); + playerGroup.add(leftLeg); + + playerGroup.rotation.y = -0.3; + requestRenderRef.current?.(); + }); + + let isDragging = false; + let previousMousePosition = { x: 0, y: 0 }; + + const onMouseDown = (e: MouseEvent) => { + isDragging = true; + previousMousePosition = { x: e.clientX, y: e.clientY }; + }; + const onMouseUp = () => { isDragging = false; }; + const onMouseMove = (e: MouseEvent) => { + if (isDragging) { + playerGroup.rotation.y += (e.clientX - previousMousePosition.x) * 0.01; + previousMousePosition = { x: e.clientX, y: e.clientY }; + requestRenderRef.current?.(); + } + }; + + renderer.domElement.addEventListener("mousedown", onMouseDown); + window.addEventListener("mousemove", onMouseMove); + window.addEventListener("mouseup", onMouseUp); + + requestRenderRef.current = () => renderer.render(scene, camera); + requestRenderRef.current(); + + return () => { + window.removeEventListener("mousemove", onMouseMove); + window.removeEventListener("mouseup", onMouseUp); + + scene.traverse((object) => { + if (object instanceof THREE.Mesh) { + if (object.geometry) object.geometry.dispose(); + if (object.material) { + if (Array.isArray(object.material)) { + object.material.forEach((mat) => { + if (mat.map) mat.map.dispose(); + mat.dispose(); + }); + } else { + if (object.material.map) object.material.map.dispose(); + object.material.dispose(); + } + } + } + }); + renderer.dispose(); + overlaysRef.current = []; + requestRenderRef.current = null; + }; + }, [skinUrl]); + + useEffect(() => { + overlaysRef.current.forEach(overlay => { + overlay.visible = showLayers; + }); + requestRenderRef.current?.(); + }, [showLayers]); + + useEffect(() => { + if (!isFocusedSection) { + setFocusIndex(legacyMode ? 1 : 0); + return; + } + + const handleKeyDown = (e: KeyboardEvent) => { + if (document.activeElement?.tagName === 'INPUT' && e.key !== 'ArrowDown' && e.key !== 'ArrowRight') return; + + if (e.key === 'ArrowRight') { + if (legacyMode) onNavigateRight(); + else if (focusIndex === 3) onNavigateRight(); + else if (focusIndex === 1 || focusIndex === 2) setFocusIndex(prev => prev + 1); + } else if (e.key === 'ArrowLeft') { + if (legacyMode) return; + if (focusIndex === 2 || focusIndex === 3) setFocusIndex(prev => prev - 1); + } else if (e.key === 'ArrowDown') { + if (legacyMode) { + return; + } else { + setFocusIndex(prev => (prev < 3 ? prev + 1 : prev)); + } + } else if (e.key === 'ArrowUp') { + if (legacyMode) { + return; + } else { + setFocusIndex(prev => (prev > 0 ? prev - 1 : prev)); + } + } else if (e.key === 'Enter') { + if (focusIndex === 0) { + (containerRef.current?.querySelector('input') as HTMLElement)?.focus(); + } else if (focusIndex === 1) { + playClickSound(); + setActiveView('skins'); + } else if (focusIndex === 2) { + playClickSound(); + setShowLayers(!showLayers); + } else if (focusIndex === 3) { + playClickSound(); + setSkinUrl('/images/Default.png'); + } + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [isFocusedSection, focusIndex, onNavigateRight, playClickSound, setActiveView, setShowLayers, showLayers, setSkinUrl, legacyMode]); + + useEffect(() => { + if (isFocusedSection) { + const el = containerRef.current?.querySelector(`[data-focus="${focusIndex}"]`) as HTMLElement; + if (el && document.activeElement?.tagName !== 'INPUT') el.focus(); + } + }, [isFocusedSection, focusIndex]); + + return ( + + {!legacyMode && ( +
+ setUsername(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === 'ArrowDown') { + e.currentTarget.blur(); + e.stopPropagation(); + } + }} + className="bg-transparent text-white focus:text-[#FFFF55] outline-none border-none text-center font-['Mojangles'] mc-text-shadow tracking-widest text-xl cursor-default" + /> +
+ )} + {!legacyMode && ( +
+
+
+ )} +
+ + {!legacyMode && ( + + )} + {!legacyMode && ( + + )} +
+ + ); +}); + +export default SkinViewer; \ No newline at end of file diff --git a/src/components/layout/AppHeader.tsx b/src/components/layout/AppHeader.tsx new file mode 100644 index 0000000..9e4e824 --- /dev/null +++ b/src/components/layout/AppHeader.tsx @@ -0,0 +1,99 @@ +import { getCurrentWindow } from "@tauri-apps/api/window"; +import { motion } from "framer-motion"; +import { memo } from "react"; + +const appWindow = getCurrentWindow(); + +interface AppHeaderProps { + playClickSound: () => void; + uiFade: any; +} + +export const AppHeader = memo(function AppHeader({ playClickSound, uiFade }: AppHeaderProps) { + return ( + +
+ Icon + + Emerald Legacy Launcher + +
+
+ + + +
+
+ ); +}); diff --git a/src/components/layout/DownloadOverlay.tsx b/src/components/layout/DownloadOverlay.tsx new file mode 100644 index 0000000..74acfa5 --- /dev/null +++ b/src/components/layout/DownloadOverlay.tsx @@ -0,0 +1,54 @@ +import { motion } from "framer-motion"; +import { memo } from "react"; + +interface DownloadOverlayProps { + downloadProgress: number | null; + downloadingId: string | null; + editions: any[]; +} + +export const DownloadOverlay = memo(function DownloadOverlay({ downloadProgress, downloadingId, editions }: DownloadOverlayProps) { + if (downloadProgress === null) return null; + + return ( + +
+ + Downloading + +
+ {editions.find((e) => e.id === downloadingId)?.name || "Game Files"} +
+
+ + {Math.floor(downloadProgress)}% + +
+
+
+
+ Loading +
+
+
+ + ); +}); diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx deleted file mode 100644 index d7b6ac0..0000000 --- a/src/components/layout/Sidebar.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { openUrl } from "@tauri-apps/plugin-opener"; -import { TauriService } from '../../services/tauri'; - -interface SidebarProps { - activeTab: string; - setActiveTab: (tab: string) => void; - playSfx: (name: string, multiplier?: number) => void; - updateAllStatus: () => void; - installingInstance: string | null; - downloadProgress: number; -} - -export const Sidebar: React.FC = ({ - activeTab, - setActiveTab, - playSfx, - updateAllStatus, - installingInstance, - downloadProgress, -}) => { - return ( - - ); -}; diff --git a/src/components/modals/CustomTUModal.tsx b/src/components/modals/CustomTUModal.tsx new file mode 100644 index 0000000..f9b8fdf --- /dev/null +++ b/src/components/modals/CustomTUModal.tsx @@ -0,0 +1,186 @@ +import { motion } from "framer-motion"; +import { useState, useEffect } from "react"; + +export default function CustomTUModal({ + isOpen, + onClose, + onImport, + playSfx, + editingEdition = null, +}: any) { + const [name, setName] = useState(""); + const [desc, setDesc] = useState(""); + const [url, setUrl] = useState(""); + const [error, setError] = useState(""); + const [focusIndex, setFocusIndex] = useState(0); + + useEffect(() => { + if (isOpen && editingEdition) { + setName(editingEdition.name); + setDesc(editingEdition.desc); + setUrl(editingEdition.url); + } else if (!isOpen) { + setName(""); + setDesc(""); + setUrl(""); + setError(""); + } + }, [editingEdition, isOpen]); + + useEffect(() => { + if (!isOpen) { + setFocusIndex(0); + return; + } + const handleKey = (e: KeyboardEvent) => { + if (e.key === "Escape") { + playSfx("close_click.wav"); + onClose(); + } else if (e.key === "Enter") { + if (focusIndex === 3) { + playSfx("close_click.wav"); + onClose(); + } else if (focusIndex === 4 || e.ctrlKey) { + playSfx("save_click.wav"); + handleImport(); + } + } else if (e.key === "ArrowDown" || e.key === "Tab") { + e.preventDefault(); + setFocusIndex((prev) => (prev + 1) % 5); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setFocusIndex((prev) => (prev - 1 + 5) % 5); + } + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, [isOpen, focusIndex, name, desc, url]); + + if (!isOpen) return null; + + const handleImport = () => { + if (!name || !url) { + setError("Name and URL are required"); + return; + } + if (!url.startsWith("http")) { + setError("Invalid URL"); + return; + } + setError(""); + onImport({ name, desc: desc || "Custom imported TU", url }); + onClose(); + setName(""); + setDesc(""); + setUrl(""); + }; + + return ( + +
+

+ {editingEdition ? "Edit Custom TU" : "Import Custom TU"} +

+ +
+
+ + setName(e.target.value)} + onFocus={() => setFocusIndex(0)} + placeholder="e.g. My Awesome Mod" + className={`w-full h-12 px-4 bg-black/40 border-2 text-white text-lg transition-colors outline-none font-['Mojangles'] ${focusIndex === 0 ? "border-[#FFFF55]" : "border-[#373737]"}`} + style={{ imageRendering: "pixelated" }} + /> +
+ +
+ + setDesc(e.target.value)} + onFocus={() => setFocusIndex(1)} + placeholder="A brief description..." + className={`w-full h-12 px-4 bg-black/40 border-2 text-white text-lg transition-colors outline-none font-['Mojangles'] ${focusIndex === 1 ? "border-[#FFFF55]" : "border-[#373737]"}`} + style={{ imageRendering: "pixelated" }} + /> +
+ +
+ + setUrl(e.target.value)} + onFocus={() => setFocusIndex(2)} + placeholder="https://example.com/mod.zip" + className={`w-full h-12 px-4 bg-black/40 border-2 text-white text-lg transition-colors outline-none font-['Mojangles'] ${focusIndex === 2 ? "border-[#FFFF55]" : "border-[#373737]"}`} + style={{ imageRendering: "pixelated" }} + /> +
+ + {error && ( +
+ {error} +
+ )} +
+ +
+ + +
+
+
+ ); +} diff --git a/src/components/modals/ReinstallModal.tsx b/src/components/modals/ReinstallModal.tsx deleted file mode 100644 index 732b85c..0000000 --- a/src/components/modals/ReinstallModal.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import { ReinstallModalData } from '../../types'; - -interface ReinstallModalProps { - data: ReinstallModalData; - onCancel: () => void; - onConfirm: (id: string, url: string) => void; - playSfx: (name: string, multiplier?: number) => void; -} - -export const ReinstallModal: React.FC = ({ - data, - onCancel, - onConfirm, - playSfx, -}) => { - return ( -
-
-

- Warning -

-

- Reinstalling will delete all data. Continue? -

-
- - -
-
-
- ); -}; diff --git a/src/components/modals/SpecialThanksModal.tsx b/src/components/modals/SpecialThanksModal.tsx new file mode 100644 index 0000000..18d543b --- /dev/null +++ b/src/components/modals/SpecialThanksModal.tsx @@ -0,0 +1,98 @@ +import { motion } from "framer-motion"; +import { useState, useEffect } from "react"; + +export default function SpecialThanksModal({ + isOpen, + onClose, + playSfx, +}: any) { + const [focusIndex, setFocusIndex] = useState(0); + + const contributors = [ + { name: "smartcmd & LCE Community", desc: "Research & Foundations" }, + { name: "Andi_pog & AFanFromWalmart", desc: "Project Testers" } + ]; + + useEffect(() => { + if (!isOpen) { + setFocusIndex(0); + return; + } + const handleKey = (e: KeyboardEvent) => { + if (e.key === "Escape") { + playSfx("close_click.wav"); + onClose(); + } else if (e.key === "ArrowDown" || e.key === "Tab") { + e.preventDefault(); + setFocusIndex((prev) => (prev + 1) % (contributors.length + 1)); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setFocusIndex((prev) => (prev - 1 + (contributors.length + 1)) % (contributors.length + 1)); + } else if (e.key === "Enter") { + if (focusIndex === contributors.length) { + playSfx("close_click.wav"); + onClose(); + } + } + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, [isOpen, focusIndex]); + + if (!isOpen) return null; + + return ( + +
+

+ Special Thanks +

+
+ {contributors.map((item, idx) => ( +
setFocusIndex(idx)} + className={`w-[90%] p-2 flex flex-col items-center justify-center mc-text-shadow transition-transform outline-none border-none bg-transparent ${focusIndex === idx ? "scale-105 text-[#FFFF55]" : "opacity-80 text-white"}`} + > + + {item.name} + + + {item.desc} + +
+ ))} +
+ +
+
+ ); +} diff --git a/src/components/modals/TeamModal.tsx b/src/components/modals/TeamModal.tsx new file mode 100644 index 0000000..c5bc74c --- /dev/null +++ b/src/components/modals/TeamModal.tsx @@ -0,0 +1,112 @@ +import { motion } from "framer-motion"; +import { useState, useEffect } from "react"; + +export default function TeamModal({ + isOpen, + onClose, + playClickSound, + playSfx, +}: any) { + const [focusIndex, setFocusIndex] = useState(0); + + const team = [ + { name: "Leon", url: "https://github.com/hornyalcoholic" }, + { name: "Criador_Mods", url: "https://github.com/CriadorMods" }, + { name: "journ3ym3m", url: "https://github.com/journ3ym3n" }, + { name: "KayJann", url: "https://github.com/KayJannOnGit" }, + { name: "neoapps", url: "https://github.com/neoapps-dev" }, + { name: "Santiago Fisela", url: "https://github.com/PinkLittleKitty" }, + ]; + + useEffect(() => { + if (!isOpen) { + setFocusIndex(0); + return; + } + const handleKey = (e: KeyboardEvent) => { + if (e.key === "Escape") { + playSfx("close_click.wav"); + onClose(); + } else if (e.key === "ArrowDown" || e.key === "Tab") { + e.preventDefault(); + setFocusIndex((prev) => (prev + 1) % (team.length + 1)); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setFocusIndex((prev) => (prev - 1 + (team.length + 1)) % (team.length + 1)); + } else if (e.key === "Enter") { + if (focusIndex === team.length) { + playSfx("close_click.wav"); + onClose(); + } else { + playClickSound(); + window.open(team[focusIndex].url, "_blank", "noopener,noreferrer"); + } + } + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, [isOpen, focusIndex]); + + if (!isOpen) return null; + + return ( + +
+

+ Emerald Team +

+ + +
+
+ ); +} diff --git a/src/components/views/FirstRunView.tsx b/src/components/views/FirstRunView.tsx deleted file mode 100644 index cdb9261..0000000 --- a/src/components/views/FirstRunView.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import { TauriService } from '../../services/tauri'; -import { Runner } from '../../types'; - -interface FirstRunViewProps { - username: string; - setUsername: (name: string) => void; - isLinux: boolean; - selectedRunner: string; - availableRunners: Runner[]; - setIsFirstRun: (val: boolean) => void; - playRandomMusic: () => void; - playSfx: (name: string, multiplier?: number) => void; - ensureAudio: () => void; -} - -export const FirstRunView: React.FC = ({ - username, - setUsername, - isLinux, - selectedRunner, - availableRunners, - setIsFirstRun, - playRandomMusic, - playSfx, - ensureAudio, -}) => { - return ( -
e.preventDefault()} - > - Menu Title -
-

Welcome to Emerald Legacy!

- setUsername(e.target.value)} - className="w-full bg-black border-4 border-emerald-900 p-4 text-3xl text-center mb-8 outline-none" - placeholder="Username..." - /> - -
-
- ); -}; diff --git a/src/components/views/HomeView.tsx b/src/components/views/HomeView.tsx index 102a3f4..f038a7e 100644 --- a/src/components/views/HomeView.tsx +++ b/src/components/views/HomeView.tsx @@ -1,79 +1,175 @@ -import React from 'react'; +import { useState, useEffect, useMemo, memo } from "react"; +import { motion } from "framer-motion"; +import { useUI, useConfig, useAudio, useGame } from "../../context/LauncherContext"; -interface HomeViewProps { - username: string; - selectedInstance: string; - setSelectedInstance: (id: string) => void; - installedStatus: Record; - isRunning: boolean; - installingInstance: string | null; - fadeAndLaunch: () => void; - playSfx: (name: string, multiplier?: number) => void; - setActiveTab: (tab: string) => void; -} +const HomeView = memo(function HomeView() { + const { setActiveView, setShowCredits, setShowSpecialThanks, focusSection, onNavigateToSkin } = useUI(); + const { profile, legacyMode } = useConfig(); + const { playClickSound, playSfx } = useAudio(); + const { handleLaunch, isGameRunning, editions, installs, toggleInstall, downloadProgress, downloadingId } = useGame(); -export const HomeView: React.FC = ({ - username, - selectedInstance, - setSelectedInstance, - installedStatus, - isRunning, - installingInstance, - fadeAndLaunch, - playSfx, - setActiveTab, -}) => { - const hasInstalledInstance = installedStatus.vanilla_tu19 || installedStatus.vanilla_tu24; + const isFocusedSection = focusSection === "menu"; + const selectedEdition = editions.find((e: any) => e.id === profile); + const selectedVersionName = selectedEdition?.name || "Game"; + const isInstalled = installs.includes(profile); + const isDownloading = downloadingId === profile; + const [menuFocus, setMenuFocus] = useState(null); + const buttons = useMemo( + () => [ + { + label: isDownloading + ? `Downloading... ${Math.floor(downloadProgress || 0)}%` + : isInstalled + ? `Play Game` + : `Download ${selectedVersionName}`, + action: isDownloading + ? () => {} + : isInstalled + ? handleLaunch + : () => toggleInstall(profile), + isDanger: false, + }, + { label: "Help & Options", action: () => setActiveView("settings") }, + { label: "Versions", action: () => setActiveView("versions") }, + { label: "Workshop", action: () => setActiveView("workshop") }, + { label: "Themes & Tools", action: () => setActiveView("themes") }, + ], + [ + isGameRunning, + isDownloading, + downloadProgress, + isInstalled, + selectedVersionName, + handleLaunch, + toggleInstall, + profile, + setActiveView, + ], + ); + + useEffect(() => { + if (!isFocusedSection) { + setMenuFocus(null); + return; + } + + const handleKeyDown = (e: KeyboardEvent) => { + if (document.activeElement?.tagName === "INPUT") return; + if (e.key === "ArrowDown") + setMenuFocus((prev) => + prev === null ? 0 : prev < buttons.length - 1 ? prev + 1 : prev, + ); + if (e.key === "ArrowUp") + setMenuFocus((prev) => + prev === null ? buttons.length - 1 : prev > 0 ? prev - 1 : prev, + ); + if (e.key === "ArrowLeft") onNavigateToSkin(); + if (e.key === "Enter" && menuFocus !== null) { + buttons[menuFocus].action(); + } + }; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [menuFocus, buttons, playClickSound, isFocusedSection, onNavigateToSkin]); return ( -
-
- Menu Title -
- Welcome, {username}! -
-
-
- {hasInstalledInstance ? ( - <> - - - - ) : ( -
-

Game not installed

- + ))} + {!legacyMode && ( + -
+
+ + +
+ )} + ); -}; +}); + +export default HomeView; diff --git a/src/components/views/SettingsView.tsx b/src/components/views/SettingsView.tsx index 4cc95d0..86e49cf 100644 --- a/src/components/views/SettingsView.tsx +++ b/src/components/views/SettingsView.tsx @@ -1,177 +1,572 @@ -import React from 'react'; -import { Icons } from '../Icons'; -import { TauriService } from '../../services/tauri'; -import { Runner } from '../../types'; -import { openUrl } from "@tauri-apps/plugin-opener"; +import { useState, useEffect, useRef, useMemo, memo } from "react"; +import { motion } from "framer-motion"; +import { TauriService, Runner } from "../../services/TauriService"; +import { usePlatform } from "../../hooks/usePlatform"; +import { useUI, useConfig, useAudio, useGame } from "../../context/LauncherContext"; -interface SettingsViewProps { - username: string; - setUsername: (name: string) => void; - isLinux: boolean; - selectedRunner: string; - setSelectedRunner: (runner: string) => void; - availableRunners: Runner[]; - musicVol: number; - setMusicVol: (vol: number) => void; - sfxVol: number; - setSfxVol: (vol: number) => void; - isMuted: boolean; - setIsMuted: (muted: boolean) => void; - playSfx: (name: string, multiplier?: number) => void; -} +const SettingsView = memo(function SettingsView() { + const { setActiveView } = useUI(); + const { vfxEnabled, setVfxEnabled, animationsEnabled, setAnimationsEnabled, musicVol: musicVolume, setMusicVol: setMusicVolume, sfxVol: sfxVolume, setSfxVol: setSfxVolume, layout, setLayout, linuxRunner, setLinuxRunner, perfBoost, setPerfBoost, rpcEnabled, setRpcEnabled, legacyMode, setLegacyMode, keepLauncherOpen, setKeepLauncherOpen, enableTrayIcon, setEnableTrayIcon } = useConfig(); + const { currentTrack, setCurrentTrack, tracks, playClickSound, playBackSound } = useAudio(); + const { isGameRunning, stopGame, isRunnerDownloading, runnerDownloadProgress, downloadRunner } = useGame(); + const { isLinux, isMac } = usePlatform(); + const [focusIndex, setFocusIndex] = useState(null); + const [currentSubMenu, setCurrentSubMenu] = useState<"main" | "audio" | "video" | "controls" | "launcher">("main"); + const [runners, setRunners] = useState([]); + const containerRef = useRef(null); -export const SettingsView: React.FC = ({ - username, - setUsername, - isLinux, - selectedRunner, - setSelectedRunner, - availableRunners, - musicVol, - setMusicVol, - sfxVol, - setSfxVol, - isMuted, - setIsMuted, - playSfx, -}) => { - return ( -
-

Settings

-
-
- -
- setUsername(e.target.value)} - className="flex-1 bg-black border-4 border-slate-700 p-4 text-3xl outline-none focus:border-emerald-500" - /> - -
-
+ const layouts = ["KBM", "PLAYSTATION", "XBOX"]; - {isLinux && ( -
- -
- - {availableRunners.length === 0 && ( -

- No Proton or Wine installations found. Please install Steam or Wine. -

- )} -
-
- )} + useEffect(() => { + TauriService.getAvailableRunners().then(setRunners); + }, [isRunnerDownloading]); -
- -
-
- - Music {Math.round(musicVol * 100)}% - - setMusicVol(parseFloat(e.target.value))} - className="mc-range" - /> -
-
- - SFX {Math.round(sfxVol * 100)}% - - setSfxVol(parseFloat(e.target.value))} - className="mc-range" - /> -
-
- -
+ const handleLayoutToggle = () => { + playClickSound(); + const currentIndex = layouts.indexOf(layout); + const nextIndex = (currentIndex + 1) % layouts.length; + setLayout(layouts[nextIndex]); + }; -
-

- About the project -

-

- I'm KayJann, and I absolutely love this project! It's my very first one, - and my goal is to create a central hub for the LCE community to bring us all together. -

-

Social Links

-
- - - -
+ const handleVfxToggle = () => { + playClickSound(); + setVfxEnabled(!vfxEnabled); + }; + + const handleAnimationsToggle = () => { + playClickSound(); + setAnimationsEnabled(!animationsEnabled); + }; + + const handlePerfToggle = () => { + playClickSound(); + setPerfBoost(!perfBoost); + }; + + const handleRpcToggle = () => { + playClickSound(); + setRpcEnabled(!rpcEnabled); + }; + + const handleLegacyToggle = () => { + playClickSound(); + setLegacyMode(!legacyMode); + }; + + const handleKeepOpenToggle = () => { + playClickSound(); + setKeepLauncherOpen(!keepLauncherOpen); + }; + + const handleTrayToggle = () => { + playClickSound(); + setEnableTrayIcon(!enableTrayIcon); + }; + + const handleRunnerToggle = () => { + playClickSound(); + if (runners.length === 0) return; + const currentIndex = runners.findIndex((r) => r.id === linuxRunner); + const nextIndex = (currentIndex + 1) % runners.length; + setLinuxRunner(runners[nextIndex].id); + }; + + const handleTrackToggle = () => { + playClickSound(); + setCurrentTrack((currentTrack + 1) % tracks.length); + }; + + const handleResetSetup = () => { + playClickSound(); + + // Create styled confirmation dialog + const dialog = document.createElement('div'); + dialog.className = 'fixed inset-0 bg-black/80 flex items-center justify-center z-50'; + dialog.innerHTML = ` +
+

Reset Setup

+

Are you sure you want to reset launcher setup?

+
+ +
-
+ `; + + document.body.appendChild(dialog); + + const handleYes = () => { + document.body.removeChild(dialog); + showSecondConfirmation(); + }; + + const handleNo = () => { + document.body.removeChild(dialog); + }; + + dialog.querySelector('#reset-yes')?.addEventListener('click', handleYes); + dialog.querySelector('#reset-no')?.addEventListener('click', handleNo); + + dialog.addEventListener('click', (e) => { + if (e.target === dialog) { + document.body.removeChild(dialog); + } + }); + }; + + const showSecondConfirmation = () => { + const dialog = document.createElement('div'); + dialog.className = 'fixed inset-0 bg-black/80 flex items-center justify-center z-50'; + dialog.innerHTML = ` +
+

CONFIRM RESET

+
+

⚠️ This will:

+
    +
  • Clear all launcher settings
  • +
  • Reset your username
  • +
  • Show setup screen again
  • +
  • Require reconfiguration
  • +
+

This action cannot be undone!

+
+
+ + +
+
+ `; + + document.body.appendChild(dialog); + + const handleFinalYes = () => { + document.body.removeChild(dialog); + performReset(); + }; + + const handleFinalNo = () => { + document.body.removeChild(dialog); + }; + + dialog.querySelector('#reset-final-yes')?.addEventListener('click', handleFinalYes); + dialog.querySelector('#reset-final-no')?.addEventListener('click', handleFinalNo); + + dialog.addEventListener('click', (e) => { + if (e.target === dialog) { + document.body.removeChild(dialog); + } + }); + }; + + const performReset = () => { + // Clear all localStorage data + localStorage.clear(); + + // Set setup as not completed + localStorage.setItem('lce-setup-completed', 'false'); + + // Force reload to show setup screen + window.location.reload(); + }; + + let trackName = "Unknown"; + if (tracks && tracks.length > 0) { + const fullPath = tracks[currentTrack]; + if (fullPath) { + trackName = fullPath + .split("/") + .pop() + ?.replace(".ogg", "") + .replace(".wav", "") || "Unknown"; + } + } + + const selectedRunnerName = + runners.find((r) => r.id === linuxRunner)?.name || "Native / Default"; + + type SettingsItem = + | { + id: string; + label: string; + type: "slider"; + value: number; + onChange: (val: any) => void; + } + | { + id: string; + label: string; + type: "button"; + onClick: () => void; + small?: boolean; + color?: string; + }; + + const settingsItems = useMemo(() => { + const items: SettingsItem[] = []; + + if (currentSubMenu === "main") { + items.push({ + id: "audio_menu", + label: "Audio", + type: "button", + onClick: () => { playClickSound(); setCurrentSubMenu("audio"); setFocusIndex(0); }, + }); + items.push({ + id: "video_menu", + label: "User Interface", + type: "button", + onClick: () => { playClickSound(); setCurrentSubMenu("video"); setFocusIndex(0); }, + }); + items.push({ + id: "controls_menu", + label: "Controls", + type: "button", + onClick: () => { playClickSound(); setCurrentSubMenu("controls"); setFocusIndex(0); }, + }); + items.push({ + id: "launcher_menu", + label: "Options", + type: "button", + onClick: () => { playClickSound(); setCurrentSubMenu("launcher"); setFocusIndex(0); }, + }); + } else if (currentSubMenu === "audio") { + items.push({ + id: "music", + label: `Music: ${musicVolume ?? 50}%`, + type: "slider", + value: musicVolume ?? 50, + onChange: setMusicVolume, + }); + items.push({ + id: "sfx", + label: `SFX: ${sfxVolume ?? 100}%`, + type: "slider", + value: sfxVolume ?? 100, + onChange: setSfxVolume, + }); + items.push({ + id: "track", + label: `${trackName} - C418`, + type: "button", + onClick: handleTrackToggle, + }); + } else if (currentSubMenu === "video") { + items.push({ + id: "vfx", + label: `VFX: ${vfxEnabled ? "ON" : "OFF"}`, + type: "button", + onClick: handleVfxToggle, + }); + items.push({ + id: "animations", + label: `Animations: ${animationsEnabled ? "ON" : "OFF"}`, + type: "button", + onClick: handleAnimationsToggle, + }); + if (isMac) { + items.push({ + id: "perf", + label: `M1/M2 Boost: ${perfBoost ? "Enabled" : "Disabled"}`, + type: "button", + onClick: handlePerfToggle, + }); + } + } else if (currentSubMenu === "controls") { + items.push({ + id: "layout", + label: `Layout: ${layout}`, + type: "button", + onClick: handleLayoutToggle, + }); + } else if (currentSubMenu === "launcher") { + items.push({ + id: "rpc", + label: `Discord RPC: ${rpcEnabled ? "ON" : "OFF"}`, + type: "button", + onClick: handleRpcToggle, + }); + items.push({ + id: "legacy", + label: `Legacy Mode: ${legacyMode ? "ON" : "OFF"}`, + type: "button", + onClick: handleLegacyToggle, + }); + items.push({ + id: "keep_open", + label: `Keep Launcher Open: ${keepLauncherOpen ? "ON" : "OFF"}`, + type: "button", + onClick: handleKeepOpenToggle, + }); + items.push({ + id: "tray_icon", + label: `Tray Icon: ${enableTrayIcon ? "ON" : "OFF"}`, + type: "button", + onClick: handleTrayToggle, + }); + + if (isLinux) { + items.push({ + id: "runner", + label: `Runner: ${selectedRunnerName}`, + type: "button", + onClick: handleRunnerToggle, + }); + + if (runners.length === 0 || runners.every(r => r.type !== 'proton')) { + items.push({ + id: "download_runner", + label: isRunnerDownloading + ? `Downloading Runner... ${Math.floor(runnerDownloadProgress || 0)}%` + : "Download GE-Proton (Recommended)", + type: "button", + onClick: () => { + if (!isRunnerDownloading) { + downloadRunner("GE-Proton9-25", "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-25/GE-Proton9-25.tar.gz"); + } + }, + small: true, + }); + } + } + + items.push({ + id: "reset_setup", + label: "Reset Setup", + type: "button", + onClick: handleResetSetup, + color: "orange", + small: true, + }); + } + + if (isGameRunning) { + items.push({ + id: "stop", + label: "STOP GAME", + type: "button", + onClick: stopGame, + color: "red", + }); + } + + items.push({ + id: "back", + label: currentSubMenu === "main" ? "Done" : "Back", + type: "button", + onClick: () => { + playBackSound(); + if (currentSubMenu === "main") { + setActiveView("main"); + } else { + setCurrentSubMenu("main"); + setFocusIndex(0); + } + }, + }); + + return items; + }, [ + currentSubMenu, + musicVolume, + sfxVolume, + trackName, + vfxEnabled, + rpcEnabled, + legacyMode, + animationsEnabled, + keepLauncherOpen, + enableTrayIcon, + layout, + isLinux, + selectedRunnerName, + isRunnerDownloading, + runnerDownloadProgress, + isMac, + perfBoost, + isGameRunning, + handleTrackToggle, + handleVfxToggle, + handleRpcToggle, + handleLegacyToggle, + handleAnimationsToggle, + handleKeepOpenToggle, + handleTrayToggle, + handleLayoutToggle, + handleRunnerToggle, + handlePerfToggle, + handleResetSetup, + stopGame, + downloadRunner, + playClickSound, + playBackSound, + setActiveView, + runners, + ]); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "Escape" || e.key === "Backspace") { + playBackSound(); + if (currentSubMenu !== "main") { + setCurrentSubMenu("main"); + setFocusIndex(0); + } else { + setActiveView("main"); + } + return; + } + + const itemCount = settingsItems.length; + + if (e.key === "ArrowDown") { + setFocusIndex((prev) => + prev === null || prev >= itemCount - 1 ? 0 : prev + 1, + ); + } else if (e.key === "ArrowUp") { + setFocusIndex((prev) => + prev === null || prev <= 0 ? itemCount - 1 : prev - 1, + ); + } else if (e.key === "ArrowRight" || e.key === "ArrowLeft") { + if (focusIndex === null) return; + const item = settingsItems[focusIndex]; + if (item.type === "slider") { + const delta = e.key === "ArrowRight" ? 5 : -5; + item.onChange((v: number) => Math.max(0, Math.min(100, v + delta))); + } + } else if (e.key === "Enter" && focusIndex !== null) { + const item = settingsItems[focusIndex]; + if (item.type === "button") { + item.onClick(); + } + } + }; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [focusIndex, settingsItems, playBackSound, setActiveView, currentSubMenu]); + + useEffect(() => { + if (focusIndex !== null) { + const el = containerRef.current?.querySelector( + `[data-index="${focusIndex}"]`, + ) as HTMLElement; + if (el) el.focus(); + } + }, [focusIndex]); + + const getItemStyle = (index: number) => ({ + backgroundImage: + focusIndex === index + ? "url('/images/button_highlighted.png')" + : "url('/images/Button_Background.png')", + backgroundSize: "100% 100%", + imageRendering: "pixelated" as const, + }); + + const getSliderStyle = (index: number) => ({ + backgroundImage: "url('/images/Button_Background2.png')", + backgroundSize: "100% 100%", + imageRendering: "pixelated" as const, + color: focusIndex === index ? "#FFFF55" : "white", + }); + + return ( + +

+ {currentSubMenu === "main" ? "Settings" : currentSubMenu === "audio" ? "Audio" : currentSubMenu === "video" ? "User Interface" : currentSubMenu === "controls" ? "Controls" : "Options"} +

+ +
+ {settingsItems.map((item, index) => { + if (item.id === "back") return null; + + if (item.type === "slider") { + return ( +
setFocusIndex(index)} + className="relative w-[360px] h-10 flex items-center justify-center cursor-pointer transition-all outline-none border-none hover:text-[#FFFF55] shrink-0" + style={getSliderStyle(index)} + > + + {item.label} + +
+ item.onChange(parseInt(e.target.value))} + onMouseUp={playClickSound} + className="mc-slider-custom w-[calc(100%+16px)] h-full opacity-100 cursor-pointer z-20 outline-none m-0" + /> +
+
+ ); + } + + const isRed = (item as any).color === "red"; + const isSmall = (item as any).small; + + return ( + + ); + })} +
+ + {(() => { + const backIndex = settingsItems.findIndex((i) => i.id === "back"); + const backItem = settingsItems[backIndex]; + if (!backItem || backItem.type !== "button") return null; + + return ( + + ); + })()} +
); -}; +}); + +export default SettingsView; diff --git a/src/components/views/SetupView.tsx b/src/components/views/SetupView.tsx new file mode 100644 index 0000000..8e3a201 --- /dev/null +++ b/src/components/views/SetupView.tsx @@ -0,0 +1,626 @@ +import { useState, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { TauriService, Runner } from "../../services/TauriService"; +import { usePlatform } from "../../hooks/usePlatform"; +import { useConfig, useAudio, useGame } from "../../context/LauncherContext"; + +interface SetupViewProps { + onComplete: () => void; +} + +const SetupView: React.FC = ({ onComplete }) => { + const { isLinux, isMac } = usePlatform(); + const { + username, setUsername, + setHasCompletedSetup, + profile, + setEnableTrayIcon: setConfigTray, + setVfxEnabled: setConfigVfx, + setRpcEnabled: setConfigRpc, + setKeepLauncherOpen: setConfigKeepOpen, + setLinuxRunner, + linuxRunner: configLinuxRunner, + vfxEnabled: configVfx, + enableTrayIcon: configTray, + rpcEnabled: configRpc, + keepLauncherOpen: configKeepOpen + } = useConfig(); + const { playClickSound, playSfx } = useAudio(); + + const { editions } = useGame(); + const titleImage = editions.find(e => e.id === profile)?.titleImage || "/images/MenuTitle.png"; + + const [currentStep, setCurrentStep] = useState(0); + const [focusIndex, setFocusIndex] = useState(0); + const [tempUsername, setTempUsername] = useState(username); + const [runners, setRunners] = useState([]); + const [selectedRunner, setSelectedRunner] = useState(""); + const [isSettingUpRuntime, setIsSettingUpRuntime] = useState(false); + const [setupProgress, setSetupProgress] = useState<{ stage: string; message: string; percent?: number } | null>(null); + const [runtimeAlreadyInstalled, setRuntimeAlreadyInstalled] = useState(false); + + const [enableTrayIcon, setEnableTrayIcon] = useState(configTray); + const [enableVfx, setEnableVfx] = useState(configVfx); + const [enableDiscordRPC, setEnableDiscordRPC] = useState(configRpc); + const [keepLauncherOpen, setKeepLauncherOpen] = useState(configKeepOpen); + + const totalSteps = isLinux ? 4 : 4; + + useEffect(() => { + if (isLinux || isMac) { + TauriService.getAvailableRunners().then(availableRunners => { + setRunners(availableRunners); + if (configLinuxRunner && availableRunners.find(r => r.id === configLinuxRunner)) { + setSelectedRunner(configLinuxRunner); + } + }); + } + + if (isMac) { + checkMacOSRuntime(); + + const unlisten = TauriService.onMacosProgress((progress) => { + console.log("[macOS Setup Progress]", progress); + setSetupProgress(progress); + }); + + return () => { + unlisten.then(f => f?.()); + }; + } + }, [isLinux, isMac]); + + const checkMacOSRuntime = async () => { + try { + const localStorageInstalled = localStorage.getItem('lce-macos-runtime-installed') === 'true'; + + if (localStorageInstalled) { + console.log("[macOS Runtime] Using cached installation status"); + try { + const runtimeCheck = await TauriService.checkMacOSRuntimeInstalledFast(); + if (runtimeCheck) { + setRuntimeAlreadyInstalled(true); + return; + } else { + console.log("[macOS Runtime] Cache was wrong, clearing"); + localStorage.removeItem('lce-macos-runtime-installed'); + setRuntimeAlreadyInstalled(false); + return; + } + } catch (error) { + console.log("[macOS Runtime] Fast check failed, using cache"); + setRuntimeAlreadyInstalled(true); + return; + } + } else { + console.log("[macOS Runtime] No installation detected"); + setRuntimeAlreadyInstalled(false); + } + } catch (error) { + console.error("[macOS Runtime] Error checking:", error); + setRuntimeAlreadyInstalled(false); + } + }; + + const handleRunnerSelect = (runnerId: string) => { + playClickSound(); + setSelectedRunner(runnerId); + }; + + const handleNext = async () => { + playClickSound(); + + if (currentStep === 0) { + setUsername(tempUsername); + setCurrentStep(1); + setFocusIndex(0); + } else if (currentStep === 1) { + if (isLinux && selectedRunner) { + setLinuxRunner(selectedRunner); + } + setCurrentStep(2); + setFocusIndex(0); + } else if (currentStep === 2) { + setConfigTray(enableTrayIcon); + setConfigVfx(enableVfx); + setConfigRpc(enableDiscordRPC); + setConfigKeepOpen(keepLauncherOpen); + + setCurrentStep(3); + setFocusIndex(0); + } else if (currentStep === 3) { + playSfx("levelup.ogg"); + setHasCompletedSetup(true); + onComplete(); + } + }; + + const handleBack = () => { + playClickSound(); + if (currentStep > 0) { + setCurrentStep(currentStep - 1); + setFocusIndex(0); + } + }; + + useEffect(() => { + const handleKey = (e: KeyboardEvent) => { + // Elements count per step + let count = 0; + if (currentStep === 0) count = 2; // Input, Next + else if (currentStep === 1) { + if (isLinux) count = runners.length + 2; // Runners, Back, Next + else if (isMac) count = 3; // Install, Back, Next + else count = 2; // Back, Next + } else if (currentStep === 2) count = 6; // 4 Toggles, Back, Next + else if (currentStep === 3) count = 2; // Back, Finish + + if (e.key === "ArrowDown" || e.key === "Tab") { + e.preventDefault(); + setFocusIndex((prev) => (prev + 1) % count); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setFocusIndex((prev) => (prev - 1 + count) % count); + } else if (e.key === "Enter") { + // Handle enter based on focusIndex and step + if (currentStep === 0) { + if (focusIndex === 0) handleNext(); // For input field + else if (focusIndex === 1) handleNext(); // Next button + } else if (currentStep === 1) { + if (isLinux) { + if (focusIndex < runners.length) handleRunnerSelect(runners[focusIndex].id); + else if (focusIndex === runners.length) handleBack(); + else if (focusIndex === runners.length + 1) handleNext(); + } else if (isMac) { + if (focusIndex === 0) handleMacosSetup(); + else if (focusIndex === 1) handleBack(); + else if (focusIndex === 2) handleNext(); + } else { + if (focusIndex === 0) handleBack(); + else if (focusIndex === 1) handleNext(); + } + } else if (currentStep === 2) { + if (focusIndex === 0) { setEnableTrayIcon(!enableTrayIcon); playClickSound(); } + else if (focusIndex === 1) { setEnableVfx(!enableVfx); playClickSound(); } + else if (focusIndex === 2) { setEnableDiscordRPC(!enableDiscordRPC); playClickSound(); } + else if (focusIndex === 3) { setKeepLauncherOpen(!keepLauncherOpen); playClickSound(); } + else if (focusIndex === 4) handleBack(); + else if (focusIndex === 5) handleNext(); + } else if (currentStep === 3) { + if (focusIndex === 0) handleBack(); + else if (focusIndex === 1) handleNext(); + } + } + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, [currentStep, focusIndex, runners, enableTrayIcon, enableVfx, enableDiscordRPC, keepLauncherOpen, isLinux, isMac, tempUsername]); + + const handleMacosSetup = async () => { + playClickSound(); + setIsSettingUpRuntime(true); + setSetupProgress({ stage: "preparing", message: "Preparing macOS runtime setup...", percent: 0 }); + + try { + console.log("[macOS Setup] Starting runtime installation..."); + await TauriService.setupMacosRuntime(); + console.log("[macOS Setup] Runtime installation completed successfully!"); + setSetupProgress({ stage: "completed", message: "Setup completed successfully!", percent: 100 }); + + localStorage.setItem('lce-macos-runtime-installed', 'true'); + setRuntimeAlreadyInstalled(true); + + setTimeout(() => { + setCurrentStep(2); + setIsSettingUpRuntime(false); + setSetupProgress(null); + }, 2000); + } catch (e) { + console.error("[macOS Setup] Error:", e); + setSetupProgress({ stage: "error", message: `Setup failed: ${e}`, percent: 0 }); + setIsSettingUpRuntime(false); + } + }; + + const canProceed = () => { + if (currentStep === 0) { + return tempUsername.trim().length > 0; + } + if (currentStep === 1 && isMac) { + return runtimeAlreadyInstalled; + } + return true; + }; + + return ( +
+
+
+ Emerald Legacy +
+ + + +
+
+
+ {Array.from({ length: totalSteps }, (_, i) => ( + + ))} +
+ + + + {currentStep === 0 && ( +
+

+ Welcome to Emerald Legacy +

+

Let's configure your launcher

+ +
+ +
+
+ )} + + {currentStep === 1 && isMac && ( +
+

+ macOS Compatibility +

+

+ {runtimeAlreadyInstalled + ? "Emerald Legacy compatibility runtime is already installed" + : "Emerald Legacy needs compatibility runtime for macOS" + } +

+ + {setupProgress && ( +
+

{setupProgress.stage.toUpperCase()}

+

{setupProgress.message}

+ {setupProgress.percent !== undefined && ( +
+
+
+ )} +
+ )} + +
+
+

+ {runtimeAlreadyInstalled ? "✓ Runtime Detected" : "⚠ Runtime Not Detected"} +

+

+ {runtimeAlreadyInstalled + ? "The compatibility runtime is properly installed and ready to use." + : "You must install the compatibility runtime before proceeding to the next step." + } +

+
+ + + + {!runtimeAlreadyInstalled && ( +

+ ⚠ Installation required before proceeding to next step +

+ )} +
+
+ )} + + {currentStep === 1 && isLinux && ( +
+

+ Linux Compatibility +

+

Choose your preferred compatibility layer

+ + {runners.length === 0 ? ( +
+

No compatible runners found. Please install Wine or Proton.

+
+ ) : ( +
+ {runners.map((runner, idx) => ( + + ))} +
+ )} + +

You can change this later in settings

+
+ )} + + {currentStep === 1 && !isMac && !isLinux && ( +
+

+ Windows Setup +

+

Everything is ready to go!

+
✓ Native compatibility
+ +
+

✓ Windows Native Support

+

Emerald Legacy runs natively on Windows without additional requirements.

+
+
+ )} + + {currentStep === 2 && ( +
+

+ Customize Your Experience +

+

Choose your preferred launcher settings

+ +
+
+
+
+

System Tray Icon

+

Keep launcher accessible in system tray

+
+ +
+
+ +
+
+
+

Visual Effects

+

Click particles and animations

+
+ +
+
+ +
+
+
+

Discord Rich Presence

+

Show your Emerald Legacy status on Discord

+
+ +
+
+ +
+
+
+

Keep Launcher Open

+

Keep launcher running after game launch

+
+ +
+
+
+ +

You can change these later in settings

+
+ )} + + {currentStep === 3 && ( +
+

+ Setup Complete! +

+ +
+
+

Username: {tempUsername}

+ {isMac && ( +

+ Runtime: Ready +

+ )} + {isLinux && selectedRunner && ( +

+ Runner: {runners.find(r => r.id === selectedRunner)?.name} +

+ )} +
+

Customization:

+
+ {enableTrayIcon && Tray Icon} + {enableVfx && Visual Effects} + {enableDiscordRPC && Discord RPC} + {keepLauncherOpen && Keep Open} +
+
+
+
+ +

Emerald Legacy is now configured and ready to use!

+
+ )} + + +
+ +
+ {currentStep > 0 && ( + + )} + + +
+
+ + +
+
+ ); +}; + +export default SetupView; diff --git a/src/components/views/SkinsView.tsx b/src/components/views/SkinsView.tsx new file mode 100644 index 0000000..3057285 --- /dev/null +++ b/src/components/views/SkinsView.tsx @@ -0,0 +1,404 @@ +import { useState, useEffect, useRef, memo } from 'react'; +import { motion } from 'framer-motion'; +import { useLocalStorage } from '../../hooks/useLocalStorage'; +import { TauriService } from '../../services/TauriService'; +import { useUI, useAudio, useSkin, useConfig } from '../../context/LauncherContext'; + +interface SavedSkin { + id: string; + name: string; + url: string; +} + +const DEFAULT_SKINS: SavedSkin[] = [ + { id: 'default', name: 'Default Steve', url: '/images/Default.png' }, + { id: 'journ3ym3n', name: 'Journ3ym3n', url: '/Skins/Journ3ym3n.png' }, + { id: 'justneki', name: 'JustNeki', url: '/Skins/JustNeki.png' }, + { id: 'kayjann', name: 'KayJann', url: '/Skins/KayJann.png' }, + { id: 'leon', name: 'Leon', url: '/Skins/Leon.png' }, + { id: 'mr_anilex', name: 'mr_anilex', url: '/Skins/mr_anilex.png' }, + { id: 'neoapps', name: 'neoapps', url: '/Skins/neoapps.png' }, + { id: 'peter', name: 'Peter', url: '/Skins/Peter.png' }, +]; + +const SkinsView = memo(function SkinsView() { + const { setActiveView } = useUI(); + const { playClickSound, playBackSound } = useAudio(); + const { skinUrl, setSkinUrl } = useSkin(); + + const [focusIndex, setFocusIndex] = useState(null); + const containerRef = useRef(null); + const fileInputRef = useRef(null); + + const [storedSkins, setStoredSkins] = useLocalStorage('lce-custom-skins', []); + const savedSkins = [...DEFAULT_SKINS, ...storedSkins.filter(s => !DEFAULT_SKINS.some(d => d.id === s.id))]; + + const TOP_BUTTONS_COUNT = 3; // Import, Delete, Folder + const SKINS_START_INDEX = TOP_BUTTONS_COUNT; + const BACK_BUTTON_INDEX = SKINS_START_INDEX + savedSkins.length; + const ITEM_COUNT = BACK_BUTTON_INDEX + 1; + + const setSavedSkins = (newSkins: SavedSkin[] | ((val: SavedSkin[]) => SavedSkin[])) => { + const updatedSkins = typeof newSkins === 'function' ? newSkins(savedSkins) : newSkins; + const customOnes = updatedSkins.filter(s => !DEFAULT_SKINS.some(d => d.id === s.id)); + setStoredSkins(customOnes); + }; + + const [activeSkinId, setActiveSkinId] = useState(null); + + const [showImportModal, setShowImportModal] = useState(false); + const [modalFocusIndex, setModalFocusIndex] = useState(0); + const [importMode, setImportMode] = useState<'file' | 'username' | null>(null); + const [importUsername, setImportUsername] = useState(''); + const [isImporting, setIsImporting] = useState(false); + const [importError, setImportError] = useState(''); + + const processSkinImage = (url: string, defaultName: string) => { + const img = new Image(); + img.crossOrigin = "Anonymous"; + img.onload = () => { + const cvs = document.createElement("canvas"); + cvs.width = 64; + cvs.height = 32; + const ctx = cvs.getContext("2d"); + if (ctx) { + ctx.drawImage(img, 0, 0, 64, 32, 0, 0, 64, 32); + const base64String = cvs.toDataURL("image/png"); + const newId = Date.now().toString(); + const newSkin = { id: newId, name: defaultName, url: base64String }; + setSavedSkins(prev => [...prev, newSkin]); + setSkinUrl(base64String); + setActiveSkinId(newId); + } + }; + img.src = url; + }; + + const handleFetchUsername = async () => { + if (!importUsername.trim()) return; + playClickSound(); + setIsImporting(true); + setImportError(''); + try { + const [base64Raw, exactName] = await TauriService.fetchSkin(importUsername.trim()); + const skinBase64 = `data:image/png;base64,${base64Raw}`; + processSkinImage(skinBase64, exactName.substring(0, 16)); + + setShowImportModal(false); + setImportMode(null); + setImportUsername(''); + } catch (e: any) { + setImportError(typeof e === 'string' ? e : (e.message || 'Failed to fetch skin')); + } finally { + setIsImporting(false); + } + }; + + useEffect(() => { + if (!activeSkinId) { + const match = savedSkins.find(s => s.url === skinUrl); + if (match) setActiveSkinId(match.id); + } + }, [activeSkinId, savedSkins, skinUrl]); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (showImportModal) { + if (e.key === 'Escape') { + playBackSound(); + if (importMode) { + setImportMode(null); + setImportUsername(''); + setImportError(''); + setModalFocusIndex(0); + } else { + setShowImportModal(false); + setModalFocusIndex(0); + } + } else if (e.key === 'ArrowDown' || e.key === 'Tab') { + e.preventDefault(); + setModalFocusIndex(prev => (prev + 1) % 3); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + setModalFocusIndex(prev => (prev - 1 + 3) % 3); + } else if (e.key === 'Enter') { + if (!importMode) { + if (modalFocusIndex === 0) { playClickSound(); fileInputRef.current?.click(); } + else if (modalFocusIndex === 1) { playClickSound(); setImportMode('username'); setModalFocusIndex(0); } + else if (modalFocusIndex === 2) { + playBackSound(); + setShowImportModal(false); + setModalFocusIndex(0); + } + } else { + if (modalFocusIndex === 0 || modalFocusIndex === 1) handleFetchUsername(); + else if (modalFocusIndex === 2) { + playBackSound(); + setImportMode(null); + setImportUsername(''); + setImportError(''); + setModalFocusIndex(0); + } + } + } + return; + } + if (document.activeElement?.tagName === 'INPUT') return; + if (e.key === 'Escape') { + playBackSound(); + setActiveView('main'); + return; + } + + if (e.key === 'ArrowRight') { + setFocusIndex(prev => (prev === null || prev >= ITEM_COUNT - 1) ? 0 : prev + 1); + } else if (e.key === 'ArrowLeft') { + setFocusIndex(prev => (prev === null || prev <= 0) ? ITEM_COUNT - 1 : prev - 1); + } else if (e.key === 'ArrowDown') { + if (focusIndex === null || focusIndex < TOP_BUTTONS_COUNT) { + setFocusIndex(SKINS_START_INDEX); + } else if (focusIndex < BACK_BUTTON_INDEX) { + const next = focusIndex + 4; + setFocusIndex(next >= BACK_BUTTON_INDEX ? BACK_BUTTON_INDEX : next); + } + } else if (e.key === 'ArrowUp') { + if (focusIndex === null) { + setFocusIndex(0); + } else if (focusIndex === BACK_BUTTON_INDEX) { + setFocusIndex(SKINS_START_INDEX + savedSkins.length - 1); + } else if (focusIndex >= SKINS_START_INDEX) { + const next = focusIndex - 4; + setFocusIndex(next < SKINS_START_INDEX ? 0 : next); + } + } else if (e.key === 'Enter' && focusIndex !== null) { + if (focusIndex === 0) handleImportClick(); + else if (focusIndex === 1) handleDeleteActive(); + else if (focusIndex === 2) { playClickSound(); TauriService.openInstanceFolder('Skins').catch(() => { }); } + else if (focusIndex < BACK_BUTTON_INDEX) { + handleSkinSelect(savedSkins[focusIndex - SKINS_START_INDEX]); + } else { + playBackSound(); + setActiveView('main'); + } + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [focusIndex, savedSkins.length, playBackSound, setActiveView, playClickSound, showImportModal, importMode, modalFocusIndex, importUsername]); + + useEffect(() => { + if (focusIndex !== null) { + const el = containerRef.current?.querySelector(`[data-index="${focusIndex}"]`) as HTMLElement; + if (el) el.focus(); + } + }, [focusIndex]); + + const handleImportClick = () => { + playClickSound(); + setShowImportModal(true); + setModalFocusIndex(0); + }; + + const handleFileChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + if (file.type !== 'image/png') return; + + const defaultName = file.name.replace('.png', '').substring(0, 16); + const reader = new FileReader(); + reader.onload = (event) => { + const url = event.target?.result as string; + processSkinImage(url, defaultName); + }; + reader.readAsDataURL(file); + e.target.value = ''; + setShowImportModal(false); + setImportMode(null); + }; + + const handleSkinSelect = (skin: SavedSkin) => { + playClickSound(); + setActiveSkinId(skin.id); + setSkinUrl(skin.url); + }; + + const isDefaultSkin = (id: string | null) => DEFAULT_SKINS.some(d => d.id === id); + + const handleDeleteActive = () => { + if (!activeSkinId || isDefaultSkin(activeSkinId)) return; + playClickSound(); + const updatedSkins = savedSkins.filter(s => s.id !== activeSkinId); + setSavedSkins(updatedSkins); + setSkinUrl('/images/Default.png'); + setActiveSkinId('default'); + }; + + const handleNameChange = (id: string, newName: string) => { + const updatedSkins = savedSkins.map(s => s.id === id ? { ...s, name: newName } : s); + setSavedSkins(updatedSkins); + }; + + const isActiveDefault = isDefaultSkin(activeSkinId) || (!activeSkinId && skinUrl === '/images/Default.png'); + + return ( + +

Skin Library

+ +
+ +
+
+ + + +
+ +
+
+ +
+ + +
+ +
+ {savedSkins.map((skin, i) => { + const idx = SKINS_START_INDEX + i; + const isActive = activeSkinId ? activeSkinId === skin.id : skinUrl === skin.url; + const isFocused = focusIndex === idx; + return ( +
setFocusIndex(idx)} className="flex flex-col items-center gap-1 w-32 outline-none"> +
+ {isActive && Active} +
+
handleSkinSelect(skin)} + className={`w-16 h-16 bg-black/40 border-2 shadow-inner relative cursor-pointer overflow-hidden transition-colors outline-none ${(isActive || isFocused) ? 'border-[#FFFF55]' : 'border-[#373737] hover:border-[#A0A0A0]'}`} + > + {skin.name} +
+ handleNameChange(skin.id, e.target.value)} + className={`bg-transparent text-center outline-none border-none text-base mc-text-shadow w-full truncate transition-colors ${(isActive || isFocused) ? 'text-[#FFFF55]' : 'text-white'} ${isDefaultSkin(skin.id) ? 'pointer-events-none' : ''}`} + onClick={(e) => e.stopPropagation()} spellCheck={false} + readOnly={isDefaultSkin(skin.id)} + /> +
+ ); + })} +
+
+ + + + {showImportModal && ( +
+
+

Import Skin

+ + {!importMode ? ( +
+ + +
+ ) : ( +
+ setImportUsername(e.target.value)} + onFocus={() => setModalFocusIndex(0)} + autoFocus + spellCheck={false} + className={`w-full h-12 bg-black/50 border-2 text-white px-4 text-xl outline-none transition-colors ${modalFocusIndex === 0 ? 'border-[#FFFF55]' : 'border-[#373737]'}`} + /> + + {importError && {importError}} + + +
+ )} + + +
+
+ )} +
+ ); +}); + +export default SkinsView; diff --git a/src/components/views/ThemesView.tsx b/src/components/views/ThemesView.tsx new file mode 100644 index 0000000..993c78a --- /dev/null +++ b/src/components/views/ThemesView.tsx @@ -0,0 +1,157 @@ +import { useState, useEffect, useRef, memo } from "react"; +import { motion } from "framer-motion"; +import { TauriService, ThemePalette } from "../../services/TauriService"; +import { useUI, useConfig, useAudio } from "../../context/LauncherContext"; + +const ThemesView = memo(function ThemesView() { + const { setActiveView } = useUI(); + const { theme: currentTheme, setTheme } = useConfig(); + const { playClickSound, playBackSound } = useAudio(); + + const [focusIndex, setFocusIndex] = useState(null); + const [externalPalettes, setExternalPalettes] = useState([]); + const containerRef = useRef(null); + + const baseThemes = ["Default", "Modern"]; + + useEffect(() => { + TauriService.getExternalPalettes().then(setExternalPalettes); + }, []); + + const totalPalettes = [...baseThemes, ...externalPalettes.map((p) => p.name)]; + const ITEM_COUNT = 3; // Theme Cycle, Import Theme, Back + + const handleImport = async () => { + playClickSound(); + try { + const result = await TauriService.importTheme(); + if (result === "success") { + const updated = await TauriService.getExternalPalettes(); + setExternalPalettes(updated); + } + } catch (e) { + console.error(e); + } + }; + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "Escape" || e.key === "Backspace") { + playBackSound(); + setActiveView("main"); + return; + } + + if (e.key === "ArrowDown") { + setFocusIndex((prev) => + prev === null || prev >= ITEM_COUNT - 1 ? 0 : prev + 1, + ); + } else if (e.key === "ArrowUp") { + setFocusIndex((prev) => + prev === null || prev <= 0 ? ITEM_COUNT - 1 : prev - 1, + ); + } else if (e.key === "Enter" && focusIndex !== null) { + if (focusIndex === 0) { + playClickSound(); + const currentIndex = totalPalettes.indexOf(currentTheme); + const nextIndex = (currentIndex + 1) % totalPalettes.length; + setTheme(totalPalettes[nextIndex]); + } else if (focusIndex === 1) { + handleImport(); + } else { + playBackSound(); + setActiveView("main"); + } + } + }; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [ + focusIndex, + currentTheme, + playClickSound, + playBackSound, + setActiveView, + setTheme, + totalPalettes, + ]); + + useEffect(() => { + if (focusIndex !== null) { + const el = containerRef.current?.querySelector( + `[data-index="${focusIndex}"]`, + ) as HTMLElement; + if (el) el.focus(); + } + }, [focusIndex]); + + const getItemStyle = (index: number) => ({ + backgroundImage: + focusIndex === index + ? "url('/images/button_highlighted.png')" + : "url('/images/Button_Background.png')", + backgroundSize: "100% 100%", + imageRendering: "pixelated" as const, + }); + + return ( + +

+ Themes & Styles +

+ +
+ + + +
+ + +
+ ); +}); + +export default ThemesView; diff --git a/src/components/views/VersionsView.tsx b/src/components/views/VersionsView.tsx index c2eca9e..140d0b3 100644 --- a/src/components/views/VersionsView.tsx +++ b/src/components/views/VersionsView.tsx @@ -1,96 +1,594 @@ -import React from 'react'; -import { TauriService } from '../../services/tauri'; -import { ReinstallModalData } from '../../types'; +import { useState, useEffect, useRef, memo } from "react"; +import { motion } from "framer-motion"; +import { TauriService } from "../../services/TauriService"; +import CustomTUModal from "../modals/CustomTUModal"; +import { useUI, useConfig, useAudio, useGame } from "../../context/LauncherContext"; -interface VersionsViewProps { - installedStatus: Record; - installingInstance: string | null; - executeInstall: (id: string, url: string) => void; - setReinstallModal: (data: ReinstallModalData | null) => void; - playSfx: (name: string, multiplier?: number) => void; -} +const VersionsView = memo(function VersionsView() { + const { setActiveView } = useUI(); + const { profile: selectedProfile, setProfile: setSelectedProfile } = useConfig(); + const { playClickSound, playBackSound, playSfx } = useAudio(); + const { editions, installs: installedVersions, toggleInstall, handleUninstall: onUninstall, deleteCustomEdition: onDeleteEdition, addCustomEdition: onAddEdition, updateCustomEdition: onUpdateEdition, downloadingId } = useGame(); -export const VersionsView: React.FC = ({ - installedStatus, - installingInstance, - executeInstall, - setReinstallModal, - playSfx, -}) => { - const versions = [ - { - id: "vanilla_tu19", - name: "Vanilla Nightly (TU19)", - desc: "Leaked 4J Studios build.", - url: "https://huggingface.co/datasets/KayJann/emerald-legacy-assets/resolve/main/emerald_tu19_vanilla.zip" - }, - { - id: "vanilla_tu24", - name: "Vanilla TU24", - desc: "Horses and Wither update.", - url: "https://huggingface.co/datasets/KayJann/emerald-legacy-assets/resolve/main/emerald_tu24_vanilla.zip" - } - ]; + const [focusRow, setFocusRow] = useState(0); + const [focusCol, setFocusCol] = useState(0); + const [isImportModalOpen, setIsImportModalOpen] = useState(false); + const [editingEdition, setEditingEdition] = useState(null); + const containerRef = useRef(null); + + const ITEM_COUNT = editions.length + 2; + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (document.activeElement?.tagName === "INPUT") return; + if (e.key === "Escape" || e.key === "Backspace") { + playBackSound(); + setActiveView("main"); + return; + } + + if (e.key === "ArrowDown") { + setFocusRow((prev) => (prev >= ITEM_COUNT - 1 ? 0 : prev + 1)); + setFocusCol(0); + } else if (e.key === "ArrowUp") { + setFocusRow((prev) => (prev <= 0 ? ITEM_COUNT - 1 : prev - 1)); + setFocusCol(0); + } else if (e.key === "ArrowRight") { + if (focusRow < editions.length) { + const edition = editions[focusRow]; + const isInstalled = installedVersions.includes(edition.id); + const isCustom = edition.id.startsWith("custom_"); + const hasCredits = !isCustom && edition.credits; + + let maxCol = 1; + if (isInstalled) maxCol = 3; + if (isCustom) maxCol = isInstalled ? 5 : 3; + if (hasCredits) maxCol = Math.max(maxCol, 0); // credits button is at col -1 + + setFocusCol((prev) => (prev < maxCol ? prev + 1 : prev)); + } + } else if (e.key === "ArrowLeft") { + if (focusRow < editions.length) { + const edition = editions[focusRow]; + const isCustom = edition.id.startsWith("custom_"); + const hasCredits = !isCustom && edition.credits; + + if (hasCredits && focusCol > -1) { + setFocusCol(-1); + } else if (focusCol > 0) { + setFocusCol((prev) => prev - 1); + } + } else { + setFocusCol((prev) => (prev > 0 ? prev - 1 : prev)); + } + } else if (e.key === "Enter") { + if (focusRow < editions.length) { + const edition = editions[focusRow]; + const isInstalled = installedVersions.includes(edition.id); + const isCustom = edition.id.startsWith("custom_"); + + if (focusCol === -1) { + // Credits button + if (edition.credits) { + playClickSound(); + window.open(edition.credits.url, '_blank'); + } + } else if (focusCol === 1) { + if (!downloadingId) { + playClickSound(); + toggleInstall(edition.id); + } + } else if (focusCol === 2) { + if (isInstalled) { + playClickSound(); + TauriService.openInstanceFolder(edition.id); + } else if (isCustom) { + playClickSound(); + setEditingEdition(edition); + setIsImportModalOpen(true); + } + } else if (focusCol === 3) { + if (isInstalled) { + playBackSound(); + onUninstall(edition.id); + } else if (isCustom) { + playBackSound(); + onDeleteEdition(edition.id); + } + } else if (focusCol === 4) { + if (isCustom) { + playClickSound(); + setEditingEdition(edition); + setIsImportModalOpen(true); + } + } else if (focusCol === 5) { + if (isCustom) { + playBackSound(); + onDeleteEdition(edition.id); + } + } + } else if (focusRow === editions.length) { + playClickSound(); + setIsImportModalOpen(true); + } else { + playBackSound(); + setActiveView("main"); + } + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [editions, focusRow, focusCol, downloadingId, installedVersions, onUninstall, onDeleteEdition, ITEM_COUNT]); + + useEffect(() => { + const el = containerRef.current?.querySelector( + `[data-row="${focusRow}"][data-col="${focusCol}"]`, + ) as HTMLElement; + if (el) el.focus(); + }, [focusRow, focusCol]); return ( -
-

Instances

-
- {versions.map(v => ( -
-
-

{v.name}

-

{v.desc}

-
-
- {installedStatus[v.id] ? ( - <> - - - - ) : ( - - )} -
-
- ))} + +

+ Versions +

- {['TU75', 'TU9', 'Modded Pack'].map(v => ( -
-
-

Vanilla {v}

-

Legacy version.

-
- SOON +
+
+
+ {editions.map((edition: any, i: number) => { + const isInstalled = installedVersions.includes(edition.id); + const isSelected = selectedProfile === edition.id; + const isRowFocused = focusRow === i; + const isCustom = edition.id.startsWith("custom_"); + const isPlaceholder = edition.id === "lmrp_placeholder"; + + return ( +
{ + if (!isPlaceholder) { + setFocusRow(i); + setFocusCol(0); + } + }} + onClick={() => { + if (!isPlaceholder && isInstalled) { + playClickSound(); + setSelectedProfile(edition.id); + } + }} + style={{ + backdropFilter: 'blur(4px)', + cursor: isPlaceholder ? 'not-allowed' : isInstalled ? 'pointer' : 'default', + imageRendering: 'pixelated', + borderRadius: '0' + }} + > +
+
+ + {edition.name} + + {isCustom && ( + + Custom + + )} + {edition.id === "revelations_edition" && ( + <> + + New + + + Recommended + + + )} + {edition.id === "360revived" && ( + + New + + )} + {edition.id === "lmrp_placeholder" && ( + + Coming Soon + + )} + {!isCustom && edition.credits && ( + + by {edition.credits.developer} + + )} +
+
+ {edition.desc} +
+
+ + {!isPlaceholder && ( +
+ {!isCustom && edition.credits && ( + + )} + + {!isInstalled ? ( + + ) : ( + <> + + + + )} + {isCustom && ( + <> + + + + )} +
+ )} +
+ ); + })}
- ))} +
-
+ +
+ + + +
+ + { + setIsImportModalOpen(false); + setEditingEdition(null); + }} + onImport={(ed: any) => { + if (editingEdition) { + onUpdateEdition(editingEdition.id, ed); + } else { + const id = onAddEdition(ed); + setSelectedProfile(id); + } + }} + playSfx={playSfx} + editingEdition={editingEdition} + /> +
); -}; +}); + +export default VersionsView; diff --git a/src/components/views/WorkshopView.tsx b/src/components/views/WorkshopView.tsx new file mode 100644 index 0000000..d6b4944 --- /dev/null +++ b/src/components/views/WorkshopView.tsx @@ -0,0 +1,47 @@ +import { useState, useEffect, memo } from 'react'; +import { motion } from 'framer-motion'; +import { useUI, useAudio, useConfig } from '../../context/LauncherContext'; + +const WorkshopView = memo(function WorkshopView() { + const { setActiveView } = useUI(); + const { playBackSound } = useAudio(); + const [backHover, setBackHover] = useState(false); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape' || e.key === 'Backspace') { + playBackSound(); + setActiveView('main'); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [playBackSound, setActiveView]); + + return ( + +

Workshop

+ +
+ Workshop support coming soon... +
+ + +
+ ); +}); + +export default WorkshopView; \ No newline at end of file diff --git a/src/context/LauncherContext.tsx b/src/context/LauncherContext.tsx new file mode 100644 index 0000000..da712a0 --- /dev/null +++ b/src/context/LauncherContext.tsx @@ -0,0 +1,201 @@ +import React, { createContext, useContext, useState, useEffect, useMemo, useCallback } from "react"; +import { useAppConfig } from "../hooks/useAppConfig"; +import { TauriService } from "../services/TauriService"; +import { useAudioController } from "../hooks/useAudioController"; +import { useGameManager } from "../hooks/useGameManager"; +import { useSkinSync } from "../hooks/useSkinSync"; +import { useDiscordRPC } from "../hooks/useDiscordRPC"; +import { useGamepad } from "../hooks/useGamepad"; +import { useUpdateCheck } from "../hooks/useUpdateCheck"; + +interface UIContextType { + activeView: string; + setActiveView: (view: string) => void; + showIntro: boolean; + setShowIntro: (show: boolean) => void; + logoAnimDone: boolean; + setLogoAnimDone: (done: boolean) => void; + isUiHidden: boolean; + setIsUiHidden: (hidden: boolean) => void; + isWindowVisible: boolean; + showCredits: boolean; + setShowCredits: (show: boolean) => void; + showSpecialThanks: boolean; + setShowSpecialThanks: (show: boolean) => void; + focusSection: "menu" | "skin"; + setFocusSection: (section: "menu" | "skin") => void; + onNavigateToSkin: () => void; + onNavigateToMenu: () => void; + connected: boolean; + updateMessage: string | null; + clearUpdateMessage: () => void; +} +const UIContext = createContext(undefined); + +export const ConfigContext = createContext | undefined>(undefined); +export const AudioContext = createContext | undefined>(undefined); +export const GameContext = createContext | undefined>(undefined); +export const SkinContext = createContext | undefined>(undefined); + +export function LauncherProvider({ children }: { children: React.ReactNode }) { + const [showIntro, setShowIntro] = useState(true); + const [logoAnimDone, setLogoAnimDone] = useState(false); + const [activeView, setActiveView] = useState("main"); + const [isUiHidden, setIsUiHidden] = useState(false); + const [isWindowVisible, setIsWindowVisible] = useState(true); + const [showCredits, setShowCredits] = useState(false); + const [showSpecialThanks, setShowSpecialThanks] = useState(false); + const [focusSection, setFocusSection] = useState<"menu" | "skin">("menu"); + + const { updateMessage, clearUpdateMessage } = useUpdateCheck(); + + const configRaw = useAppConfig(); + const skinSync = useSkinSync(); + const gameRaw = useGameManager({ + profile: configRaw.profile, + setProfile: configRaw.setProfile, + customEditions: configRaw.customEditions, + setCustomEditions: configRaw.setCustomEditions, + keepLauncherOpen: configRaw.keepLauncherOpen, + }); + const audioRaw = useAudioController({ + musicVol: configRaw.musicVol, + sfxVol: configRaw.sfxVol, + showIntro, + isGameRunning: gameRaw.isGameRunning, + isWindowVisible, + }); + + const config = useMemo(() => configRaw, [ + configRaw.username, configRaw.theme, configRaw.layout, configRaw.vfxEnabled, + configRaw.rpcEnabled, configRaw.musicVol, configRaw.sfxVol, configRaw.isDayTime, + configRaw.profile, configRaw.linuxRunner, configRaw.perfBoost, configRaw.customEditions, + configRaw.legacyMode, configRaw.keepLauncherOpen, configRaw.enableTrayIcon, + configRaw.animationsEnabled, configRaw.saveConfig, configRaw.setUsername, configRaw.setTheme, + configRaw.setLayout, configRaw.setVfxEnabled, configRaw.setAnimationsEnabled, + configRaw.setRpcEnabled, configRaw.setMusicVol, configRaw.setSfxVol, configRaw.setIsDayTime, + configRaw.setProfile, configRaw.setLinuxRunner, configRaw.setPerfBoost, configRaw.setCustomEditions, + configRaw.isLoaded, configRaw.hasCompletedSetup, configRaw.setHasCompletedSetup + ]); + + const game = useMemo(() => gameRaw, [ + gameRaw.installs, gameRaw.isGameRunning, gameRaw.downloadProgress, + gameRaw.downloadingId, gameRaw.editions, gameRaw.isRunnerDownloading, + gameRaw.runnerDownloadProgress, gameRaw.error, gameRaw.updateCustomEdition, configRaw.profile, + gameRaw.handleLaunch, gameRaw.stopGame, gameRaw.toggleInstall, gameRaw.handleUninstall, + gameRaw.addCustomEdition, gameRaw.deleteCustomEdition, gameRaw.downloadRunner, gameRaw.checkInstalls + ]); + + const audio = useMemo(() => audioRaw, [ + audioRaw.currentTrack, audioRaw.splashIndex, audioRaw.tracks, audioRaw.splashes + ]); + + useDiscordRPC({ + rpcEnabled: config.rpcEnabled, + showIntro, + username: config.username, + profile: config.profile, + activeView, + isGameRunning: game.isGameRunning, + downloadProgress: game.downloadProgress, + downloadingId: game.downloadingId, + editions: game.editions, + isWindowVisible, + }); + + const { connected } = useGamepad({ playSfx: audio.playSfx, isWindowVisible }); + + const onNavigateToSkin = useCallback(() => setFocusSection("skin"), []); + const onNavigateToMenu = useCallback(() => setFocusSection("menu"), []); + + useEffect(() => { + if (activeView === "main") { + audioRaw.setSplashIndex(-1); + } + }, [activeView]); + + useEffect(() => { + if (config.isLoaded && config.profile) { + TauriService.syncDlc(config.profile).catch(console.error); + } + }, [config.profile, config.isLoaded]); + + useEffect(() => { + if (config.isLoaded) { + config.saveConfig(skinSync.skinBase64); + } + }, [ + config.username, skinSync.skinBase64, config.theme, config.linuxRunner, + config.perfBoost, config.customEditions, config.profile, config.keepLauncherOpen, + config.enableTrayIcon, config.vfxEnabled, config.animationsEnabled, + config.rpcEnabled, config.musicVol, config.sfxVol, config.legacyMode, config.isLoaded + ]); + + useEffect(() => { + const setupVisibilityDetection = async () => { + try { + const { listen } = await import("@tauri-apps/api/event"); + + const unlistenClose = await listen("tauri://close-requested", () => { + console.log("Window close requested - hiding music"); + setIsWindowVisible(false); + }); + + const unlistenShow = await listen("tauri://window-shown", () => { + console.log("Window shown - resuming music"); + setIsWindowVisible(true); + }); + + const unlistenFocus = await listen("tauri://focus", () => { + console.log("Window focused - resuming music"); + setIsWindowVisible(true); + }); + + const unlistenBlur = await listen("tauri://blur", () => { + console.log("Window blurred - checking visibility"); + }); + + return () => { + unlistenClose(); + unlistenShow(); + unlistenFocus(); + unlistenBlur(); + }; + } catch (error) { + console.error("Failed to setup visibility detection:", error); + setIsWindowVisible(true); + } + }; + + setupVisibilityDetection(); + }, []); + + const uiValue = useMemo(() => ({ + activeView, setActiveView, showIntro, setShowIntro, + logoAnimDone, setLogoAnimDone, isUiHidden, setIsUiHidden, + isWindowVisible, + showCredits, setShowCredits, showSpecialThanks, setShowSpecialThanks, focusSection, setFocusSection, + onNavigateToSkin, onNavigateToMenu, connected, + updateMessage, clearUpdateMessage + }), [activeView, showIntro, logoAnimDone, isUiHidden, isWindowVisible, showCredits, showSpecialThanks, focusSection, onNavigateToSkin, onNavigateToMenu, connected, updateMessage, clearUpdateMessage]); + + return ( + + + + + + {children} + + + + + + ); +} + +export const useUI = () => { const c = useContext(UIContext); if (!c) throw new Error("useUI must be used within LauncherProvider"); return c; }; +export const useConfig = () => { const c = useContext(ConfigContext); if (!c) throw new Error("useConfig must be used within LauncherProvider"); return c; }; +export const useAudio = () => { const c = useContext(AudioContext); if (!c) throw new Error("useAudio must be used within LauncherProvider"); return c; }; +export const useGame = () => { const c = useContext(GameContext); if (!c) throw new Error("useGame must be used within LauncherProvider"); return c; }; +export const useSkin = () => { const c = useContext(SkinContext); if (!c) throw new Error("useSkin must be used within LauncherProvider"); return c; }; diff --git a/src/css/App.css b/src/css/App.css new file mode 100644 index 0000000..1d76bf5 --- /dev/null +++ b/src/css/App.css @@ -0,0 +1 @@ +/* empty :P */ \ No newline at end of file diff --git a/src/css/index.css b/src/css/index.css new file mode 100644 index 0000000..433ff46 --- /dev/null +++ b/src/css/index.css @@ -0,0 +1,114 @@ +@import "tailwindcss"; + +@font-face { + font-family: 'Mojangles'; + src: url('/fonts/Mojangles.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +.gamepad-connected-indicator { + position: fixed; + bottom: 10px; + left: 10px; + color: #FFFF55; + font-size: 10px; + z-index: 1000; + opacity: 0.5; +} + +.mc-setup-nav-btn { + border: 4px solid transparent; + border-image: url('/images/Button_Background.png') 4 stretch; + image-rendering: pixelated; + background: rgba(0, 0, 0, 0.6); + transition: all 0.2s ease; +} + +.mc-setup-nav-btn:hover:not(:disabled) { + transform: scale(1.05); +} + +.mc-setup-nav-btn:active:not(:disabled) { + transform: scale(0.95); +} + +.mc-setup-nav-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +body { + margin: 0; + background-color: #000; + font-family: 'Mojangles', monospace; + -webkit-font-smoothing: none; +} + +.mc-button { + background-image: url('/images/button.png'); + background-size: 100% 100%; + image-rendering: pixelated; + transition: none; +} + +.mc-button:hover:not(:disabled) { + background-image: url('/images/button_highlighted.png'); +} + +.mc-text-shadow { + text-shadow: 1px 1px 0px rgba(63, 63, 63, 1); +} + +.mc-text-shadow-hover { + text-shadow: 1px 1px 0px rgba(63, 90, 63, 1); +} + + +@keyframes sga-burst { + 0% { + transform: translate(-50%, -50%) scale(0.5); + opacity: 1; + } + + 100% { + transform: translate(calc(-50% + var(--vX)), calc(-50% + var(--vY))) scale(1.2) rotate(var(--rot)); + opacity: 0; + } +} + +.particle-burst { + animation: sga-burst 0.8s ease-out forwards; + filter: drop-shadow(0 0 8px rgba(180, 100, 255, 0.9)); +} + +::-webkit-scrollbar { + width: 14px; +} + +::-webkit-scrollbar-track { + background: url('/images/backgroundframe.png') center; + background-size: 100% auto; + image-rendering: pixelated; +} + +::-webkit-scrollbar-thumb { + background: url('/images/SliderHandlerBackground.png') no-repeat center; + background-size: 100% 100%; + image-rendering: pixelated; + cursor: pointer; +} + +.no-animations * { + transition: none !important; + animation: none !important; +} + +.scrollbar-hide::-webkit-scrollbar { + display: none; +} + +.scrollbar-hide { + -ms-overflow-style: none; + scrollbar-width: none; +} \ No newline at end of file diff --git a/src/hooks/useAppConfig.ts b/src/hooks/useAppConfig.ts new file mode 100644 index 0000000..478d2a8 --- /dev/null +++ b/src/hooks/useAppConfig.ts @@ -0,0 +1,111 @@ +import { useState, useEffect, useCallback } from "react"; +import { useLocalStorage } from "./useLocalStorage"; +import { TauriService } from "../services/TauriService"; + +export function useAppConfig() { + const [username, setUsername] = useLocalStorage("lce-username", "Steve"); + const [theme, setTheme] = useLocalStorage("lce-theme", "Modern"); + const [layout, setLayout] = useLocalStorage("lce-layout", "KBM"); + const [vfxEnabled, setVfxEnabled] = useLocalStorage("lce-vfx", true); + const [animationsEnabled, setAnimationsEnabled] = useLocalStorage("lce-animations", true); + const [rpcEnabled, setRpcEnabled] = useLocalStorage("discord-rpc", true); + const [musicVol, setMusicVol] = useLocalStorage("lce-music", 50); + const [sfxVol, setSfxVol] = useLocalStorage("lce-sfx", 100); + const [isDayTime, setIsDayTime] = useLocalStorage("lce-daytime", true); + const [profile, setProfile] = useLocalStorage("lce-profile", "legacy_evolved"); + const [legacyMode, setLegacyMode] = useLocalStorage("lce-legacy-mode", false); + const [keepLauncherOpen, setKeepLauncherOpen] = useLocalStorage("lce-keep-open", false); + const [enableTrayIcon, setEnableTrayIcon] = useLocalStorage("lce-tray-icon", true); + const [hasCompletedSetup, setHasCompletedSetup] = useLocalStorage("lce-setup-completed", false); + + const [isLoaded, setIsLoaded] = useState(false); + const [linuxRunner, setLinuxRunner] = useState(); + const [perfBoost, setPerfBoost] = useState(false); + const [customEditions, setCustomEditions] = useState([]); + + useEffect(() => { + TauriService.loadConfig().then((config) => { + if (config.username) setUsername(config.username); + if (config.themeStyleId) setTheme(config.themeStyleId); + if (config.linuxRunner) setLinuxRunner(config.linuxRunner); + if (config.appleSiliconPerformanceBoost !== undefined) + setPerfBoost(config.appleSiliconPerformanceBoost); + if (config.customEditions) setCustomEditions(config.customEditions); + if (config.profile) setProfile(config.profile); + if (config.keepLauncherOpen !== undefined) setKeepLauncherOpen(config.keepLauncherOpen); + if (config.enableTrayIcon !== undefined) setEnableTrayIcon(config.enableTrayIcon); + if (config.vfxEnabled !== undefined) setVfxEnabled(config.vfxEnabled); + if (config.animationsEnabled !== undefined) setAnimationsEnabled(config.animationsEnabled); + if (config.rpcEnabled !== undefined) setRpcEnabled(config.rpcEnabled); + if (config.musicVol !== undefined && config.musicVol !== null) setMusicVol(config.musicVol); + if (config.sfxVol !== undefined && config.sfxVol !== null) setSfxVol(config.sfxVol); + if (config.legacyMode !== undefined) setLegacyMode(config.legacyMode); + setIsLoaded(true); + }); + }, []); + + useEffect(() => { + if (isLoaded) { + TauriService.updateTrayIcon(enableTrayIcon); + } + }, [enableTrayIcon, isLoaded]); + + const saveConfig = useCallback((skinBase64?: string | null) => { + TauriService.saveConfig({ + username, + skinBase64: skinBase64 || undefined, + themeStyleId: theme, + linuxRunner, + appleSiliconPerformanceBoost: perfBoost, + profile, + customEditions, + keepLauncherOpen, + enableTrayIcon, + animationsEnabled, + vfxEnabled, + rpcEnabled, + musicVol, + sfxVol, + legacyMode, + }).catch(console.error); + }, [username, theme, linuxRunner, perfBoost, profile, customEditions, keepLauncherOpen, enableTrayIcon, animationsEnabled, vfxEnabled, rpcEnabled, musicVol, sfxVol, legacyMode]); + + return { + username, + setUsername, + theme, + setTheme, + layout, + setLayout, + vfxEnabled, + setVfxEnabled, + animationsEnabled, + setAnimationsEnabled, + rpcEnabled, + setRpcEnabled, + musicVol: musicVol ?? 50, + setMusicVol, + sfxVol: sfxVol ?? 100, + setSfxVol, + isDayTime, + setIsDayTime, + legacyMode, + setLegacyMode, + keepLauncherOpen, + setKeepLauncherOpen, + enableTrayIcon, + setEnableTrayIcon, + profile, + setProfile, + linuxRunner, + setLinuxRunner, + perfBoost, + setPerfBoost, + customEditions, + setCustomEditions, + isLoaded, + hasCompletedSetup, + setHasCompletedSetup, + saveConfig, + }; +} diff --git a/src/hooks/useAudio.ts b/src/hooks/useAudio.ts deleted file mode 100644 index 6839d6c..0000000 --- a/src/hooks/useAudio.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { useRef, useEffect } from 'react'; -import { playSfx as playSfxService, ensureAudio } from '../services/audio'; - -export const useAudio = (musicVol: number, sfxVol: number, isMuted: boolean) => { - const musicRef = useRef(null); - const lastTrack = useRef(0); - - useEffect(() => { - if (musicRef.current) { - musicRef.current.volume = isMuted ? 0 : musicVol; - } - }, [musicVol, isMuted]); - - const playRandomMusic = () => { - if (!musicRef.current) return; - let track = Math.floor(Math.random() * 5) + 1; - if (track === lastTrack.current) track = (track % 5) + 1; - lastTrack.current = track; - musicRef.current.src = `/music/music${track}.ogg`; - musicRef.current.volume = isMuted ? 0 : musicVol; - musicRef.current.play().catch(() => {}); - }; - - const playSfx = (name: string, multiplier: number = 1.0) => { - playSfxService(name, sfxVol, isMuted, multiplier); - }; - - return { - musicRef, - playRandomMusic, - playSfx, - ensureAudio, - }; -}; diff --git a/src/hooks/useAudioController.ts b/src/hooks/useAudioController.ts new file mode 100644 index 0000000..e29c3c9 --- /dev/null +++ b/src/hooks/useAudioController.ts @@ -0,0 +1,183 @@ +import { useState, useEffect, useRef, useCallback } from "react"; + +const TRACKS = [ + "/music/Blind Spots.ogg", + "/music/Key.ogg", + "/music/Living Mice.ogg", + "/music/Oxygene.ogg", + "/music/Subwoofer Lullaby.ogg", +]; + +const SPLASHES = [ + "Legacy is back!", "Pixelated goodness!", "Console Edition vibe!", "100% Not Microsoft!", + "Symmetry is key!", "Does anyone even read these?", "Task failed successfully.", + "Hardware accelerated!", "It's a feature, not a bug.", "Look behind you.", + "Works on my machine.", "Now gluten-free!", "Mom, get the camera!", "Batteries not included.", + "May contain nuts.", "Press Alt+F4 for diamonds!", "Downloading more RAM...", + "Reinventing the wheel!", "The cake is a lie.", "Powered by copious amounts of coffee.", + "I'm running out of ideas.", "That's no moon...", "Now with 100% more nostalgia!", + "Legacy is the new modern.", "No microtransactions!", "As seen on TV!", "Ironic, isn't it?", + "Creeper? Aww man.", "Technoblade never dies!", +]; + +interface AudioControllerProps { + musicVol: number; + sfxVol: number; + showIntro: boolean; + isGameRunning: boolean; + isWindowVisible: boolean; +} + +export function useAudioController({ musicVol, sfxVol, showIntro, isGameRunning, isWindowVisible }: AudioControllerProps) { + const [currentTrack, setCurrentTrack] = useState(0); + const [audioElement, setAudioElement] = useState(null); + const [splashIndex, setSplashIndex] = useState(-1); + const musicPausedRef = useRef<{ at: number; track: number } | null>(null); + const fadeIntervalRef = useRef(null); + + const playSfx = useCallback((file: string) => { + const a = new Audio(`/sounds/${file}`); + a.volume = sfxVol / 100; + a.play().catch(() => { }); + }, [sfxVol]); + + const playClickSound = useCallback(() => playSfx("click.wav"), [playSfx]); + const playBackSound = useCallback(() => playSfx("back.ogg"), [playSfx]); + const playSplashSound = useCallback(() => playSfx("orb.ogg"), [playSfx]); + + const fadeOut = useCallback((audio: HTMLAudioElement, duration: number = 500) => { + return new Promise((resolve) => { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + const initialVolume = audio.volume; + const steps = 5; + const stepDuration = duration / steps; + let currentStep = 0; + fadeIntervalRef.current = setInterval(() => { + currentStep++; + const progress = currentStep / steps; + audio.volume = initialVolume * (1 - progress); + if (currentStep >= steps) { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + fadeIntervalRef.current = null; + audio.pause(); + audio.volume = initialVolume; + resolve(); + } + }, stepDuration); + }); + }, []); + + const fadeIn = useCallback((audio: HTMLAudioElement, targetVolume: number, duration: number = 500) => { + return new Promise((resolve) => { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + audio.volume = 0; + const playPromise = audio.play(); + if (playPromise !== undefined) { + playPromise.catch(() => { }); + } + + const steps = 5; + const stepDuration = duration / steps; + let currentStep = 0; + fadeIntervalRef.current = setInterval(() => { + currentStep++; + const progress = currentStep / steps; + audio.volume = targetVolume * progress; + if (currentStep >= steps) { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + fadeIntervalRef.current = null; + audio.volume = targetVolume; + resolve(); + } + }, stepDuration); + }); + }, []); + + const cycleSplash = useCallback(() => { + playSplashSound(); + let newIndex; + do { + newIndex = Math.floor(Math.random() * SPLASHES.length); + } while (newIndex === splashIndex && SPLASHES.length > 1); + setSplashIndex(newIndex); + }, [playSplashSound, splashIndex]); + + useEffect(() => { + if (showIntro) return; + if (audioElement) return; + + const audio = new Audio(TRACKS[currentTrack]); + audio.volume = musicVol / 100; + const handleEnded = () => setCurrentTrack((prev) => (prev + 1) % TRACKS.length); + audio.addEventListener("ended", handleEnded); + + const playPromise = audio.play(); + if (playPromise !== undefined) { + playPromise.catch(() => { + console.log("Autoplay prevented, waiting for user interaction"); + const startMusic = () => { + audio.play().catch(() => { }); + document.removeEventListener("click", startMusic); + document.removeEventListener("keydown", startMusic); + }; + document.addEventListener("click", startMusic, { once: true }); + document.addEventListener("keydown", startMusic, { once: true }); + }); + } + + setAudioElement(audio); + return () => { + audio.removeEventListener("ended", handleEnded); + audio.pause(); + }; + }, [showIntro, audioElement, currentTrack, musicVol]); + + useEffect(() => { + if (!audioElement) return; + audioElement.src = TRACKS[currentTrack]; + audioElement.play().catch(() => { }); + }, [currentTrack]); + + useEffect(() => { + if (!audioElement) return; + const shouldPause = isGameRunning || !isWindowVisible; + + if (shouldPause) { + if (!audioElement.paused || fadeIntervalRef.current) { + if (!musicPausedRef.current) { + musicPausedRef.current = { + at: audioElement.currentTime, + track: currentTrack, + }; + } + fadeOut(audioElement, 500); + } + } else if (musicPausedRef.current) { + const { at, track } = musicPausedRef.current; + musicPausedRef.current = null; + if (track === currentTrack) { + audioElement.currentTime = at; + } + fadeIn(audioElement, musicVol / 100, 500); + } + }, [isGameRunning, isWindowVisible, audioElement, currentTrack, musicVol, fadeOut, fadeIn]); + + useEffect(() => { + if (audioElement) { + audioElement.volume = musicVol / 100; + } + }, [musicVol, audioElement]); + + return { + currentTrack, + setCurrentTrack, + splashIndex, + setSplashIndex, + cycleSplash, + playClickSound, + playBackSound, + playSfx, + tracks: TRACKS, + splashes: SPLASHES, + }; +} diff --git a/src/hooks/useDiscordRPC.ts b/src/hooks/useDiscordRPC.ts new file mode 100644 index 0000000..e5ace3f --- /dev/null +++ b/src/hooks/useDiscordRPC.ts @@ -0,0 +1,62 @@ +import { useEffect } from "react"; +import RpcService from "../services/RpcService"; + +interface DiscordRPCProps { + rpcEnabled: boolean; + showIntro: boolean; + username: string; + profile: string; + activeView: string; + isGameRunning: boolean; + isWindowVisible: boolean; + downloadProgress: number | null; + downloadingId: string | null; + editions: any[]; +} + +export function useDiscordRPC({ + rpcEnabled, + showIntro, + username, + profile, + activeView, + isGameRunning, + isWindowVisible, + downloadProgress, + downloadingId, + editions, +}: DiscordRPCProps) { + useEffect(() => { + const updateRPC = async () => { + if (!rpcEnabled || showIntro || !username) return; + + if (!isWindowVisible && !isGameRunning && downloadProgress === null) return; + + const version = editions.find((e) => e.id === profile); + const versionName = version ? version.name : "Unknown Version"; + let details = "In Menus"; + let state = isGameRunning ? `Playing as ${username}` : `Logged in as ${username}`; + + if (isGameRunning) { + details = `Playing ${versionName}`; + } else if (downloadProgress !== null) { + const downloadingName = editions.find((e) => e.id === downloadingId)?.name || "Game Files"; + details = `Downloading ${downloadingName} (${downloadProgress.toFixed(0)}%)`; + } else { + const tabNames: Record = { + main: "Main Menu", + versions: "Selecting Version", + settings: "In Settings", + themes: "Browsing Themes", + skins: "Browsing Skins", + workshop: "Browsing Workshop", + }; + details = tabNames[activeView] || "In Menus"; + } + + await RpcService.updateActivity(details, state, isGameRunning); + }; + + updateRPC(); + }, [rpcEnabled, showIntro, username, profile, activeView, isGameRunning, isWindowVisible, Math.floor(downloadProgress || 0), downloadingId, editions]); +} diff --git a/src/hooks/useGameInstances.ts b/src/hooks/useGameInstances.ts deleted file mode 100644 index 328a6f0..0000000 --- a/src/hooks/useGameInstances.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { useState, useEffect } from 'react'; -import { listen } from "@tauri-apps/api/event"; -import { TauriService } from '../services/tauri'; -import { InstalledStatus, McNotification } from '../types'; - -export const useGameInstances = ( - playSfx: (name: string, multiplier?: number) => void, - setMcNotif: (notif: McNotification | null) => void -) => { - const [installingInstance, setInstallingInstance] = useState(null); - const [downloadProgress, setDownloadProgress] = useState(0); - const [installedStatus, setInstalledStatus] = useState({ - vanilla_tu19: false, - vanilla_tu24: false, - }); - - const updateAllStatus = async () => { - const v19 = await TauriService.checkGameInstalled("vanilla_tu19"); - const v24 = await TauriService.checkGameInstalled("vanilla_tu24"); - setInstalledStatus({ vanilla_tu19: v19, vanilla_tu24: v24 }); - }; - - const executeInstall = async (id: string, url: string) => { - setInstallingInstance(id); - setDownloadProgress(0); - try { - await TauriService.downloadAndInstall(url, id); - setMcNotif({ t: "Success!", m: "Ready to play." }); - playSfx('orb.ogg'); - setTimeout(() => setMcNotif(null), 4000); - updateAllStatus(); - } catch (e) { - console.error(e); - alert("Error during installation: " + e); - } - setInstallingInstance(null); - }; - - useEffect(() => { - updateAllStatus(); - const unlisten = listen("download-progress", (e) => - setDownloadProgress(Math.round(e.payload)) - ); - return () => { - unlisten.then((f) => f()); - }; - }, []); - - return { - installedStatus, - installingInstance, - downloadProgress, - executeInstall, - updateAllStatus, - }; -}; diff --git a/src/hooks/useGameManager.ts b/src/hooks/useGameManager.ts new file mode 100644 index 0000000..64c20e9 --- /dev/null +++ b/src/hooks/useGameManager.ts @@ -0,0 +1,225 @@ +import { useState, useEffect, useCallback, useMemo } from "react"; +import { getCurrentWindow } from "@tauri-apps/api/window"; +import { TauriService } from "../services/TauriService"; + +const appWindow = getCurrentWindow(); + +const BASE_EDITIONS = [ + { + id: "revelations_edition", + name: "Revelations", + desc: "Enhanced LCE with uncapped FPS, graphics fixes, hardcore hearts, and dedicated server security. Features LAN multiplayer, split-screen, and keyboard & mouse support.", + url: "https://github.com/itsRevela/MinecraftConsoles/releases/download/Nightly/LCREWindows64.zip", + titleImage: "/images/minecraft_title_revelations.png", + credits: { + developer: "itsRevela", + platform: "github", + url: "https://github.com/itsRevela" + } + }, + { + id: "360revived", + name: "360 Revived", + desc: "PC port of Xbox 360 Edition TU19 with desktop optimizations. Features keyboard & mouse, fullscreen, LAN multiplayer, dedicated server, and split-screen support.", + url: "https://github.com/BluTac10/360Revived/releases/download/nightly/LCEWindows64.zip", + titleImage: "/images/minecraft_title_360revived.png", + credits: { + developer: "BluTac10", + platform: "github", + url: "https://github.com/BluTac10" + } + }, + { + id: "legacy_evolved", + name: "Legacy Evolved", + desc: "Backports newer title updates to LCE TU19 base. Currently porting TU25 (98% complete) and TU31 (76% complete).", + url: "https://codeberg.org/piebot/LegacyEvolved/releases/download/nightly/LCEWindows64.zip", + titleImage: "/images/minecraft_title_LegacyEvolved.png", + credits: { + developer: "piebot", + platform: "codeberg", + url: "https://codeberg.org/piebot" + } + }, + { + id: "vanilla_tu19", + name: "Title Update 19", + desc: "Minecraft LCE v1.6.0560.0 with compilation fixes. Base version for modding with keyboard & mouse, fullscreen, LAN multiplayer, and dedicated server support.", + url: "https://github.com/smartcmd/MinecraftConsoles/releases/download/nightly/LCEWindows64.zip", + titleImage: "/images/minecraft_title_tu19.png", + credits: { + developer: "smartcmd", + platform: "github", + url: "https://github.com/smartcmd" + } + }, + { + id: "lmrp_placeholder", + name: "LMRP (Coming Soon)", + desc: "Legacy Minecraft Restoration Project - Classic mini-games and nostalgic gameplay. Stay tuned for updates!", + url: "", + titleImage: "/images/minecraft_title_lmrp.png", + credits: { + developer: "LMRP Team", + platform: "github", + url: "https://github.com/LMRP-Project" + } + }, +]; + +const PARTNERSHIP_SERVERS = [ + { + name: "Kowhaifans Clubhouse", + ip: "kowhaifan.ddns.net", + port: 25565, + }, +]; + +interface GameManagerProps { + profile: string; + setProfile: (id: string) => void; + customEditions: any[]; + setCustomEditions: (editions: any[]) => void; + keepLauncherOpen: boolean; +} + +export function useGameManager({ profile, setProfile, customEditions, setCustomEditions, keepLauncherOpen }: GameManagerProps) { + const [installs, setInstalls] = useState([]); + const [isGameRunning, setIsGameRunning] = useState(false); + const [downloadProgress, setDownloadProgress] = useState(null); + const [downloadingId, setDownloadingId] = useState(null); + const [isRunnerDownloading, setIsRunnerDownloading] = useState(false); + const [runnerDownloadProgress, setRunnerDownloadProgress] = useState(null); + const [error, setError] = useState(null); + + const editions = useMemo(() => [...BASE_EDITIONS, ...customEditions], [customEditions]); + + const checkInstalls = useCallback(async () => { + const results = await Promise.all( + editions.map(async (e) => { + const isInstalled = await TauriService.checkGameInstalled(e.id); + return isInstalled ? e.id : null; + }), + ); + setInstalls(results.filter((id): id is string => id !== null)); + }, [editions]); + + useEffect(() => { + checkInstalls(); + const unlistenDownload = TauriService.onDownloadProgress((p) => setDownloadProgress(p)); + const unlistenRunner = TauriService.onRunnerDownloadProgress((p) => setRunnerDownloadProgress(p)); + return () => { + unlistenDownload.then((u) => u()); + unlistenRunner.then((u) => u()); + }; + }, [customEditions, checkInstalls]); + + const downloadRunner = useCallback(async (name: string, url: string) => { + if (isRunnerDownloading) return; + setIsRunnerDownloading(true); + setRunnerDownloadProgress(0); + setError(null); + try { + await TauriService.downloadRunner(name, url); + setRunnerDownloadProgress(null); + } catch (e: any) { + console.error(e); + setError(typeof e === 'string' ? e : e.message || "Failed to download runner"); + } finally { + setIsRunnerDownloading(false); + } + }, [isRunnerDownloading]); + + const toggleInstall = useCallback(async (id: string) => { + if (downloadingId) return; + const edition = editions.find((e) => e.id === id); + if (!edition) return; + setError(null); + try { + setDownloadingId(id); + setDownloadProgress(0); + await TauriService.downloadAndInstall(edition.url, id); + await TauriService.syncDlc(id); + await checkInstalls(); + setProfile(id); + setDownloadProgress(null); + setDownloadingId(null); + } catch (e: any) { + console.error(e); + setError(typeof e === 'string' ? e : e.message || "Failed to install version"); + setDownloadProgress(null); + setDownloadingId(null); + } + }, [downloadingId, editions, checkInstalls, setProfile]); + + const handleUninstall = useCallback(async (id: string) => { + await TauriService.deleteInstance(id); + await checkInstalls(); + }, [checkInstalls]); + + const handleLaunch = useCallback(async () => { + if (isGameRunning) return; + setError(null); + setIsGameRunning(true); + try { + if (!keepLauncherOpen) { + await appWindow.hide(); + } + await TauriService.launchGame(profile, PARTNERSHIP_SERVERS); + } catch (e: any) { + console.error(e); + setError(typeof e === 'string' ? e : e.message || "Failed to launch game"); + } finally { + setIsGameRunning(false); + await appWindow.show(); + await appWindow.unminimize(); + await appWindow.setFocus(); + } + }, [isGameRunning, profile, keepLauncherOpen]); + + const stopGame = useCallback(async () => { + try { + await TauriService.stopGame(profile); + setIsGameRunning(false); + } catch (e) { + console.error(e); + } + }, [profile]); + + const addCustomEdition = useCallback((edition: { name: string; desc: string; url: string }) => { + const id = `custom_${Date.now()}`; + const newEdition = { ...edition, id, titleImage: "/images/minecraft_title_tucustom.png" }; + setCustomEditions([...customEditions, newEdition]); + return id; + }, [customEditions, setCustomEditions]); + + const deleteCustomEdition = useCallback((id: string) => { + setCustomEditions(customEditions.filter((e) => e.id !== id)); + TauriService.deleteInstance(id).catch(console.error); + }, [customEditions, setCustomEditions]); + + const updateCustomEdition = useCallback((id: string, updated: { name: string; desc: string; url: string }) => { + setCustomEditions(customEditions.map((e) => e.id === id ? { ...e, ...updated } : e)); + }, [customEditions, setCustomEditions]); + + return { + installs, + isGameRunning, + downloadProgress, + downloadingId, + isRunnerDownloading, + runnerDownloadProgress, + error, + setError, + editions, + toggleInstall, + handleUninstall, + handleLaunch, + stopGame, + addCustomEdition, + deleteCustomEdition, + updateCustomEdition, + downloadRunner, + checkInstalls, + }; +} diff --git a/src/hooks/useGamepad.ts b/src/hooks/useGamepad.ts new file mode 100644 index 0000000..6c6a196 --- /dev/null +++ b/src/hooks/useGamepad.ts @@ -0,0 +1,128 @@ +import { useEffect, useRef, useState, useCallback } from 'react'; + +export interface UseGamepadProps { + playSfx: (file: string) => void; + isWindowVisible: boolean; +} + +export const useGamepad = ({ playSfx, isWindowVisible }: UseGamepadProps) => { + const [connected, setConnected] = useState(false); + const requestRef = useRef(undefined); + const focusedRef = useRef(document.hasFocus()); + const lastButtons = useRef>({}); + const lastAxes = useRef>({}); + const stateRef = useRef({ playSfx }); + + useEffect(() => { + const onFocus = () => { focusedRef.current = true; }; + const onBlur = () => { + focusedRef.current = false; + lastButtons.current = {}; + lastAxes.current = {}; + }; + window.addEventListener('focus', onFocus); + window.addEventListener('blur', onBlur); + return () => { + window.removeEventListener('focus', onFocus); + window.removeEventListener('blur', onBlur); + }; + }, []); + + useEffect(() => { + stateRef.current = { playSfx }; + }, [playSfx]); + + const dispatchKey = (key: string, shiftKey = false) => { + window.dispatchEvent(new KeyboardEvent('keydown', { + key, shiftKey, bubbles: true, cancelable: true, view: window + })); + window.dispatchEvent(new KeyboardEvent('keyup', { + key, shiftKey, bubbles: true, cancelable: true, view: window + })); + }; + + const update = useCallback(() => { + if (!focusedRef.current) { + requestRef.current = requestAnimationFrame(update); + return; + } + try { + const gamepads = navigator.getGamepads ? navigator.getGamepads() : null; + if (gamepads) { + for (const gp of gamepads) { + if (!gp) continue; + const btnVal = (i: number): number => { + const btn = gp.buttons[i]; + if (!btn) return 0; + return typeof btn === "object" ? btn.value : (btn as any) ?? 0; + }; + const justPressed = (i: number) => btnVal(i) > 0.5 && !lastButtons.current[i]; + + if (justPressed(1)) dispatchKey('Enter'); + if (justPressed(2)) dispatchKey('Escape'); + if (justPressed(4)) dispatchKey('Tab', true); + if (justPressed(5)) dispatchKey('Tab'); + + const newButtons: Record = {}; + gp.buttons.forEach((btn, i) => { + newButtons[i] = (typeof btn === "object" ? btn.value : btn) > 0.5; + }); + lastButtons.current = newButtons; + + const deadzone = 0.5; + const axisY = gp.axes[2] ?? 0; + const prevY = lastAxes.current[2] ?? 0; + if (Math.abs(axisY) > deadzone && Math.abs(prevY) <= deadzone) { + dispatchKey(axisY < 0 ? 'ArrowDown' : 'ArrowUp'); + } + lastAxes.current[2] = axisY; + + const axisX = gp.axes[1] ?? 0; + const prevX = lastAxes.current[1] ?? 0; + if (Math.abs(axisX) > deadzone && Math.abs(prevX) <= deadzone) { + dispatchKey(axisX > 0 ? 'ArrowRight' : 'ArrowLeft'); + } + lastAxes.current[1] = axisX; + } + } + } catch (e) { + console.error(e); + } + requestRef.current = requestAnimationFrame(update); + }, []); + + useEffect(() => { + const handleConnect = () => setConnected(true); + const handleDisconnect = () => { + const gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + const hasGamepads = Array.from(gamepads).some(gp => gp !== null); + setConnected(hasGamepads); + }; + + window.addEventListener("gamepadconnected", handleConnect); + window.addEventListener("gamepaddisconnected", handleDisconnect); + + const initialGamepads = navigator.getGamepads ? navigator.getGamepads() : []; + if (Array.from(initialGamepads).some(gp => gp !== null)) { + setConnected(true); + } + + return () => { + window.removeEventListener("gamepadconnected", handleConnect); + window.removeEventListener("gamepaddisconnected", handleDisconnect); + }; + }, []); + + useEffect(() => { + if (connected && isWindowVisible) { + requestRef.current = requestAnimationFrame(update); + } else if (requestRef.current) { + cancelAnimationFrame(requestRef.current); + } + return () => { + if (requestRef.current) cancelAnimationFrame(requestRef.current); + }; + }, [connected, update, isWindowVisible]); + + return { connected }; +}; \ No newline at end of file diff --git a/src/hooks/useLauncher.ts b/src/hooks/useLauncher.ts deleted file mode 100644 index 6367e7a..0000000 --- a/src/hooks/useLauncher.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useState } from 'react'; -import { TauriService } from '../services/tauri'; - -export const useLauncher = ( - selectedInstance: string, - musicRef: React.RefObject, - isMuted: boolean, - musicVol: number, - playRandomMusic: () => void, - playSfx: (name: string, multiplier?: number) => void -) => { - const [isRunning, setIsRunning] = useState(false); - - const fadeAndLaunch = async () => { - playSfx('levelup.ogg', 0.4); - setIsRunning(true); - if (musicRef.current && !isMuted) { - const startVol = musicRef.current.volume; - const steps = 20; - let currentStep = 0; - const fade = setInterval(() => { - currentStep++; - if (musicRef.current) { - musicRef.current.volume = Math.max(0, startVol * (1 - currentStep / steps)); - } - if (currentStep >= steps) { - clearInterval(fade); - if (musicRef.current) musicRef.current.pause(); - } - }, 50); - } - setTimeout(async () => { - try { - await TauriService.launchGame(selectedInstance); - } catch (e) { - alert(`Failed to launch game: ${e}`); - } finally { - setIsRunning(false); - if (musicRef.current) { - musicRef.current.volume = isMuted ? 0 : musicVol; - playRandomMusic(); - } - } - }, 1500); - }; - - return { - isRunning, - fadeAndLaunch, - }; -}; diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts new file mode 100644 index 0000000..dfbd1db --- /dev/null +++ b/src/hooks/useLocalStorage.ts @@ -0,0 +1,24 @@ +import { useState, useCallback } from 'react'; + +export function useLocalStorage(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void] { + const [storedValue, setStoredValue] = useState(() => { + try { + const item = window.localStorage.getItem(key); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + return initialValue; + } + }); + + const setValue = useCallback((value: T | ((val: T) => T)) => { + try { + const valueToStore = value instanceof Function ? value(storedValue) : value; + setStoredValue(valueToStore); + window.localStorage.setItem(key, JSON.stringify(valueToStore)); + } catch (error) { + console.log(error); + } + }, [key, storedValue]); + + return [storedValue, setValue]; +} \ No newline at end of file diff --git a/src/hooks/usePlatform.ts b/src/hooks/usePlatform.ts new file mode 100644 index 0000000..aa1471b --- /dev/null +++ b/src/hooks/usePlatform.ts @@ -0,0 +1,19 @@ +import { useMemo } from 'react'; + + +export function usePlatform() { + const platform = useMemo(() => { + if (typeof window === 'undefined') return { isLinux: false, isMac: false, isWindows: false }; + + const ua = window.navigator.userAgent.toLowerCase(); + const plat = window.navigator.platform.toLowerCase(); + + const isLinux = plat.includes('linux') || ua.includes('linux'); + const isMac = plat.includes('mac') || ua.includes('mac'); + const isWindows = plat.includes('win') || ua.includes('win'); + + return { isLinux, isMac, isWindows }; + }, []); + + return platform; +} diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts deleted file mode 100644 index 6b0b81b..0000000 --- a/src/hooks/useSettings.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useState, useEffect } from 'react'; - -export const useSettings = () => { - const [musicVol, setMusicVol] = useState(parseFloat(localStorage.getItem("musicVol") || "0.4")); - const [sfxVol, setSfxVol] = useState(parseFloat(localStorage.getItem("sfxVol") || "0.7")); - const [isMuted, setIsMuted] = useState(localStorage.getItem("isMuted") === "true"); - - useEffect(() => { - localStorage.setItem("musicVol", musicVol.toString()); - localStorage.setItem("sfxVol", sfxVol.toString()); - localStorage.setItem("isMuted", isMuted.toString()); - }, [musicVol, sfxVol, isMuted]); - - return { - musicVol, - setMusicVol, - sfxVol, - setSfxVol, - isMuted, - setIsMuted, - }; -}; diff --git a/src/hooks/useSkinSync.ts b/src/hooks/useSkinSync.ts new file mode 100644 index 0000000..8f20e91 --- /dev/null +++ b/src/hooks/useSkinSync.ts @@ -0,0 +1,37 @@ +import { useState, useEffect } from "react"; +import { useLocalStorage } from "./useLocalStorage"; + +export function useSkinSync() { + const [skinUrl, setSkinUrl] = useLocalStorage("lce-skin", "/images/Default.png"); + const [skinBase64, setSkinBase64] = useState(null); + + useEffect(() => { + const syncSkin = async () => { + if (!skinUrl) return; + try { + const img = new Image(); + img.crossOrigin = "anonymous"; + img.onload = () => { + const cvs = document.createElement("canvas"); + cvs.width = 64; + cvs.height = 32; + const ctx = cvs.getContext("2d"); + if (ctx) { + ctx.drawImage(img, 0, 0, 64, 32, 0, 0, 64, 32); + setSkinBase64(cvs.toDataURL("image/png")); + } + }; + img.src = skinUrl; + } catch (e) { + console.error("Skin conversion failed:", e); + } + }; + syncSkin(); + }, [skinUrl]); + + return { + skinUrl, + setSkinUrl, + skinBase64, + }; +} diff --git a/src/hooks/useUpdateCheck.ts b/src/hooks/useUpdateCheck.ts new file mode 100644 index 0000000..f6fe239 --- /dev/null +++ b/src/hooks/useUpdateCheck.ts @@ -0,0 +1,49 @@ +import { useState, useEffect, useCallback } from "react"; +import pkg from "../../package.json"; + +const CURRENT_VERSION = pkg.version; +const REPO_URL = "https://api.github.com/repos/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher/releases/latest"; + +function isNewerVersion(latest: string, current: string): boolean { + const latestParts = latest.split('.').map(Number); + const currentParts = current.split('.').map(Number); + + for (let i = 0; i < Math.max(latestParts.length, currentParts.length); i++) { + const latestPart = latestParts[i] || 0; + const currentPart = currentParts[i] || 0; + + if (latestPart > currentPart) return true; + if (latestPart < currentPart) return false; + } + + return false; +} + +export function useUpdateCheck() { + const [updateMessage, setUpdateMessage] = useState(null); + + const checkUpdates = useCallback(async () => { + try { + const response = await fetch(REPO_URL); + if (!response.ok) return; + + const data = await response.json(); + const latestVersion = data.tag_name.replace(/^v/, ''); + + if (isNewerVersion(latestVersion, CURRENT_VERSION)) { + setUpdateMessage(`Version ${data.tag_name} is now available!`); + } + } catch (e) { + console.error("Failed to check for updates:", e); + } + }, []); + + useEffect(() => { + checkUpdates(); + }, [checkUpdates]); + + return { + updateMessage, + clearUpdateMessage: () => setUpdateMessage(null), + }; +} diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 85bda6d..0000000 --- a/src/index.css +++ /dev/null @@ -1,205 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* Fonts and Globals */ -@font-face { - font-family: 'Minecraft'; - src: url('/fonts/Mojangles.ttf') format('truetype'); -} - -* { - border-radius: 0 !important; - font-family: 'Minecraft', sans-serif !important; - image-rendering: pixelated; - font-weight: normal !important; -} - -body { - margin: 0; -} - -main { - background: url('/images/dirt-background.png') repeat !important; - background-size: 2000px !important; - position: relative; -} - -main::before { - content: ""; - position: absolute; - inset: 0; - z-index: 0; -} - -.no-scrollbar::-webkit-scrollbar { - display: none; -} - -.no-scrollbar { - -ms-overflow-style: none; - scrollbar-width: none; -} - -.sidebar-progress { - background: #2a2a2a; - border-top: 4px solid #000; - padding: 20px; - position: relative; - box-shadow: inset 0 4px #444; -} - -/* Legacy UI Components */ -.legacy-btn { - @apply transition-all duration-75 flex items-center justify-center; - background: #bebebe; - border: 4px solid #000 !important; - box-shadow: inset 4px 4px #ffffff, inset -4px -4px #555555 !important; - color: #3e3e3e !important; - cursor: pointer; -} - -.legacy-btn:hover:not(:disabled) { - background: #d0d0d0; - outline: 4px solid #fff; - outline-offset: -8px; -} - -.legacy-btn:active:not(:disabled) { - box-shadow: inset -4px -4px #ffffff, inset 4px 4px #555555 !important; -} - -.legacy-btn:disabled { - opacity: 0.6; - cursor: not-allowed; - filter: grayscale(1); -} - -.legacy-select { - appearance: none; - -webkit-appearance: none; - -moz-appearance: none; - background: #bebebe url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%233e3e3e' stroke-width='3' stroke-linecap='square' stroke-linejoin='miter'%3E%3Cpath d='M7 10l5 5 5-5'/%3E%3C/svg%3E") no-repeat right 12px center; - border: 4px solid #000 !important; - box-shadow: inset 4px 4px #ffffff, inset -4px -4px #555555 !important; - color: #3e3e3e !important; - cursor: pointer; - padding-right: 48px; -} - -.legacy-select:focus { - outline: 4px solid #fff; - outline-offset: -8px; -} - -.mc-progress-container { - background: #313131 !important; - border: 4px solid #000 !important; - height: 32px !important; - position: relative; - display: flex; - align-items: center; - padding: 0 4px; -} - -.mc-progress-bar { - background: #55FF55 !important; - height: 16px !important; - box-shadow: inset -2px -2px #00AA00, inset 2px 2px #AAFFAA !important; -} - -.mc-progress-text { - position: absolute; - width: 100%; - text-align: center; - color: #fff; - text-shadow: 2px 2px #000; - font-size: 14px; - z-index: 10; - pointer-events: none; -} - -.active-tab { - background: #388e3c !important; - box-shadow: inset 4px 4px #55ff55, inset -4px -4px #1a4d0a !important; - color: #fff !important; -} - -.reinstall-btn, -.confirm-red-btn, -.cancel-download-btn { - background: #ff5555 !important; - box-shadow: inset 4px 4px #ffaaaa, inset -4px -4px #aa0000 !important; - color: #fff !important; -} - -.mc-range { - appearance: none; - -webkit-appearance: none; - background: #000; - height: 12px; - border: 3px solid #555; - width: 100%; -} - -.mc-range::-webkit-slider-thumb { - -webkit-appearance: none; - width: 16px; - height: 24px; - background: #bebebe; - border: 3px solid #000; - box-shadow: inset 2px 2px #fff, inset -2px -2px #555; - cursor: pointer; -} - -.social-btn { - background: transparent; - border: 4px solid #000; - box-shadow: inset 4px 4px #555, inset -4px -4px #111; - width: 64px; - height: 64px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - transition: transform 0.1s; -} - -.social-btn:hover { - transform: scale(1.1); -} - -.btn-discord { - background: #5865F2 !important; - box-shadow: inset 4px 4px #8ea1e1, inset -4px -4px #313338 !important; -} - -.btn-github { - background: #333 !important; - box-shadow: inset 4px 4px #666, inset -4px -4px #000 !important; -} - -.btn-reddit { - background: #FF4500 !important; - box-shadow: inset 4px 4px #ff8b60, inset -4px -4px #942700 !important; -} - -.splash-text { - color: #ffff00; - text-shadow: 4px 4px #3f3f00; - white-space: nowrap; - pointer-events: none; - z-index: 20; - transform: rotate(-20deg); - animation: splash-pulse 0.5s infinite alternate; - transform-origin: center; -} - -@keyframes splash-pulse { - from { - transform: rotate(-20deg) scale(1); - } - to { - transform: rotate(-20deg) scale(1.05); - } -} diff --git a/src/main.tsx b/src/main.tsx index 02e3004..afe1914 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,16 +1,15 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App"; -import './index.css'; - -const rootElement = document.getElementById("root"); - -if (rootElement) { - ReactDOM.createRoot(rootElement).render( - - - - ); -} else { - console.error("ERREUR FATALE : La div avec l'id 'root' est introuvable dans index.html"); -} \ No newline at end of file +import React from "react"; +import ReactDOM from "react-dom/client"; +import "tauri-plugin-gamepad-api"; +import App from "./pages/App"; +import "./css/index.css"; +import "./css/App.css"; +import { LauncherProvider } from "./context/LauncherContext"; +// RpcService is now managed by LauncherProvider context +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + + + + + +); \ No newline at end of file diff --git a/src/pages/App.tsx b/src/pages/App.tsx new file mode 100644 index 0000000..61dbbb3 --- /dev/null +++ b/src/pages/App.tsx @@ -0,0 +1,369 @@ +import { useEffect, useState } from "react"; +import { motion, AnimatePresence, MotionConfig } from "framer-motion"; +import HomeView from "../components/views/HomeView"; +import SettingsView from "../components/views/SettingsView"; +import VersionsView from "../components/views/VersionsView"; +import ThemesView from "../components/views/ThemesView"; +import SkinsView from "../components/views/SkinsView"; +import WorkshopView from "../components/views/WorkshopView"; +import SetupView from "../components/views/SetupView"; +import SkinViewer from "../components/common/SkinViewer"; +import TeamModal from "../components/modals/TeamModal"; +import SpecialThanksModal from "../components/modals/SpecialThanksModal"; +import PanoramaBackground from "../components/common/PanoramaBackground"; +import { ClickParticles } from "../components/common/ClickParticles"; +import { AppHeader } from "../components/layout/AppHeader"; +import { DownloadOverlay } from "../components/layout/DownloadOverlay"; +import { AchievementToast } from "../components/common/AchievementToast"; +import { useUI, useConfig, useAudio, useGame, useSkin } from "../context/LauncherContext"; +import { getCurrentWindow } from "@tauri-apps/api/window"; +import { TauriService } from "../services/TauriService"; + +const appWindow = getCurrentWindow(); + +export default function App() { + const { + showIntro, setShowIntro, logoAnimDone, setLogoAnimDone, + activeView, setActiveView, isUiHidden, setIsUiHidden, + showCredits, setShowCredits, showSpecialThanks, setShowSpecialThanks, focusSection, + onNavigateToMenu, updateMessage, clearUpdateMessage + } = useUI(); + + const config = useConfig(); + const audio = useAudio(); + const game = useGame(); + const { skinUrl, setSkinUrl } = useSkin(); + + const [showSetup, setShowSetup] = useState(true); + const [displayIsDay, setDisplayIsDay] = useState(config.isDayTime); + + useEffect(() => { + setDisplayIsDay(config.isDayTime); + }, [config.isDayTime]); + + const selectedEdition = game.editions.find((e: any) => e.id === config.profile); + const selectedVersionName = selectedEdition?.name || ""; + + const titleImage = selectedEdition?.titleImage || "/images/MenuTitle.png"; + + useEffect(() => { + if (config.isLoaded) { + // Check localStorage directly to ensure accurate setup state + const setupCompleted = localStorage.getItem('lce-setup-completed') === 'true'; + setShowSetup(!setupCompleted); + } + }, [config.isLoaded]); + + useEffect(() => { + appWindow.show(); + // Only start intro timing if setup is not shown + if (!showSetup) { + setTimeout(() => setShowIntro(false), 2400); + setTimeout(() => setLogoAnimDone(true), 3400); + } else if (showSetup) { + // Skip intro entirely if setup is shown + setShowIntro(false); + setLogoAnimDone(true); + } + }, [showSetup]); + + useEffect(() => { + const handleContextMenu = (e: MouseEvent) => e.preventDefault(); + document.addEventListener("contextmenu", handleContextMenu); + return () => document.removeEventListener("contextmenu", handleContextMenu); + }, []); + + const uiFade = { + initial: { opacity: 0 }, + animate: { opacity: 1 }, + exit: { opacity: 0 }, + transition: { duration: config.animationsEnabled ? 0.5 : 0 } + }; + + const backgroundFade = { + initial: { opacity: 0 }, + animate: { opacity: 1 }, + exit: { opacity: 0 }, + transition: { duration: config.animationsEnabled ? 0.8 : 0 } + }; + + return ( + +
+ + +
+ + + + + +
+ {config.vfxEnabled && } + + + {showCredits && ( + setShowCredits(false)} + playClickSound={audio.playClickSound} + playSfx={audio.playSfx} + /> + )} + {showSpecialThanks && ( + setShowSpecialThanks(false)} + playClickSound={audio.playClickSound} + playSfx={audio.playSfx} + /> + )} + + + + + + + game.setError(null)} + /> + + TauriService.openUrl("https://emerald-legacy-launcher.github.io/")} + title="Update Available!" + variant="update" + /> + + + {showSetup ? ( + { + setShowSetup(false); + setShowIntro(true); + }} + /> + ) : showIntro ? ( + + + + ) : ( + + + {logoAnimDone && } + + + + {logoAnimDone && ( + <> + {!config.legacyMode && ( + + + + )} + + {!config.legacyMode && ( + + + {displayIsDay ? "Day" : "Night"} + + + + )} + + )} + + +
+
+ + + {logoAnimDone && ( + <> + +
+ {audio.splashIndex === -1 + ? `Welcome ${config.username}!` + : audio.splashes[audio.splashIndex]} +
+
+ {activeView === "main" && titleImage === "/images/MenuTitle.png" && ( + + {selectedVersionName} + + )} + + )} +
+
+
+ +
+
+ + {activeView === "main" && ( + + )} + + +
+ + {activeView === "main" && ( + + )} + {activeView === "settings" && ( + + )} + {activeView === "versions" && ( + + )} + {activeView === "workshop" && ( + + )} + {activeView === "themes" && ( + + )} + {activeView === "skins" && ( + + )} + +
+
+
+ + + {logoAnimDone && ( + +
Version: 1.0.0
+
+ Not affiliated with Mojang AB or Microsoft. "Minecraft" is a trademark of Mojang Synergies AB. +
+
+ {useUI().connected && "CONTROLLER CONNECTED"} +
+
+ )} +
+
+ )} +
+
+
+ ); +} diff --git a/src/services/RpcService.ts b/src/services/RpcService.ts new file mode 100644 index 0000000..7ae7c2c --- /dev/null +++ b/src/services/RpcService.ts @@ -0,0 +1,64 @@ +import { setActivity, start } from "tauri-plugin-drpc"; +import { Activity, ActivityType, Assets, Timestamps, Button } from "tauri-plugin-drpc/activity"; + +class RPC { + private startTime: number = Date.now(); + private initializationPromise: Promise | null = null; + private initialized: boolean = false; + + public async StartRPC() { + if (this.initialized) return; + if (sessionStorage.getItem('lce_rpc_started') === 'true') { + this.initialized = true; + return; + } + + if (this.initializationPromise) return this.initializationPromise; + this.initializationPromise = (async () => { + try { + await start("1482504445152460871"); + sessionStorage.setItem('lce_rpc_started', 'true'); + this.initialized = true; + } catch (e) { + console.error("Failed to start RPC:", e); + this.initializationPromise = null; + } + })(); + + return this.initializationPromise; + } + + public async updateActivity(details: string, state: string, isPlaying: boolean = false) { + if (!this.initialized) { + await this.StartRPC(); + if (!this.initialized) return; + } + + const activity = new Activity(); + activity.setDetails(details); + activity.setState(state); + activity.setActivity(ActivityType.Playing); + + const assets = new Assets(); + assets.setLargeImage("logo"); + assets.setLargeText("Emerald Legacy"); + assets.setSmallImage("app-icon"); + assets.setSmallText(isPlaying ? "Playing" : "In Menus"); + activity.setAssets(assets); + + activity.setTimestamps(new Timestamps(this.startTime)); + + activity.setButton([ + new Button("Discord", "https://discord.gg/RHGRUwpmVc"), + new Button("GitHub", "https://github.com/Emerald-Legacy-Launcher/Emerald-Legacy-Launcher") + ]); + + try { + await setActivity(activity); + } catch (e) { + console.error("Failed to set RPC activity:", e); + } + } +} + +export default new RPC(); \ No newline at end of file diff --git a/src/services/TauriService.ts b/src/services/TauriService.ts new file mode 100644 index 0000000..fa8dd28 --- /dev/null +++ b/src/services/TauriService.ts @@ -0,0 +1,173 @@ +import { invoke } from '@tauri-apps/api/core'; +import { listen } from '@tauri-apps/api/event'; + +export interface McServer { + name: string; + ip: string; + port: number; +} + +export interface SkinLibraryItem { + id: string; + name: string; + skinBase64: string; +} + +export interface CustomEdition { + id: string; + name: string; + desc: string; + url: string; +} + +export interface AppConfig { + username: string; + linuxRunner?: string; + skinBase64?: string; + skinLibrary?: SkinLibraryItem[]; + themeStyleId?: string; + themePaletteId?: string; + appleSiliconPerformanceBoost?: boolean; + customEditions?: CustomEdition[]; + profile?: string; + keepLauncherOpen?: boolean; + enableTrayIcon?: boolean; + animationsEnabled?: boolean; + vfxEnabled?: boolean; + rpcEnabled?: boolean; + musicVol?: number; + sfxVol?: number; + legacyMode?: boolean; +} + +export interface ThemePalette { + id: string; + name: string; + colors: any; +} + +export interface Runner { + id: string; + name: string; + path: string; + type: 'wine' | 'proton'; +} + +export interface MacOSSetupProgress { + stage: string; + message: string; + percent?: number; +} + +export class TauriService { + static async saveConfig(config: AppConfig): Promise { + return invoke('save_config', { config }); + } + + static async loadConfig(): Promise { + return invoke('load_config'); + } + + static async getExternalPalettes(): Promise { + return invoke('get_external_palettes'); + } + + static async importTheme(): Promise { + return invoke('import_theme'); + } + + static async getAvailableRunners(): Promise { + return invoke('get_available_runners'); + } + + static async downloadRunner(name: string, url: string): Promise { + return invoke('download_runner', { name, url }); + } + + static async checkGameInstalled(instanceId: string): Promise { + return invoke('check_game_installed', { instanceId }); + } + + static async openInstanceFolder(instanceId: string): Promise { + return invoke('open_instance_folder', { instanceId }); + } + + static async deleteInstance(instanceId: string): Promise { + return invoke('delete_instance', { instanceId }); + } + + static async cancelDownload(): Promise { + return invoke('cancel_download'); + } + + static async setupMacosRuntime(): Promise { + return invoke('setup_macos_runtime'); + } + + static async downloadAndInstall(url: string, instanceId: string): Promise { + return invoke('download_and_install', { url, instanceId }); + } + + static async launchGame(instanceId: string, servers: McServer[]): Promise { + return invoke('launch_game', { instanceId, servers }); + } + + static async stopGame(instanceId: string): Promise { + return invoke('stop_game', { instanceId }); + } + + static async syncDlc(instanceId: string): Promise { + return invoke('sync_dlc', { instanceId }); + } + + static async updateTrayIcon(visible: boolean): Promise { + return invoke('update_tray_icon', { visible }); + } + + static onDownloadProgress(callback: (percent: number) => void) { + return listen('download-progress', (event) => callback(event.payload)); + } + + static onRunnerDownloadProgress(callback: (percent: number) => void) { + return listen('runner-download-progress', (event) => callback(event.payload)); + } + + static onMacosProgress(callback: (payload: MacOSSetupProgress) => void) { + return listen('macos-setup-progress', (event) => callback(event.payload)); + } + + static async openUrl(url: string): Promise { + return invoke('plugin:opener|open_url', { url }); + } + + static async restartLauncher(): Promise { + return invoke('restart_launcher'); + } + + static async checkMacOSRuntimeInstalled(): Promise { + return invoke('check_macos_runtime_installed'); + } + + static async checkMacOSRuntimeInstalledFast(): Promise { + return invoke('check_macos_runtime_installed_fast'); + } + + static async setupMacOSRuntimeOptimized(): Promise { + return invoke('setup_macos_runtime_optimized'); + } + + static async fetchSkin(username: string): Promise<[string, string]> { + return invoke('fetch_skin', { username }); + } + + static async pathExists(_path: string): Promise { + // Simple web implementation using fetch to check if path exists + try { + // This is a simplified check - in a real implementation you'd use the Tauri API + // For now, we'll just check common paths via heuristics + return false; // Placeholder - will be implemented properly if needed + } catch { + return false; + } + } +} diff --git a/src/services/audio.ts b/src/services/audio.ts deleted file mode 100644 index 4d93c78..0000000 --- a/src/services/audio.ts +++ /dev/null @@ -1,45 +0,0 @@ -let audioCtx: AudioContext | null = null; -let sfxGain: GainNode | null = null; -const buffers: Record = {}; - -export const ensureAudio = async () => { - let currentCtx = audioCtx; - if (!currentCtx) { - const AC = (window as any).AudioContext || (window as any).webkitAudioContext; - if (!AC) return null; - const newCtx = new AC() as AudioContext; - const newGain = newCtx.createGain(); - newGain.connect(newCtx.destination); - audioCtx = newCtx; - sfxGain = newGain; - currentCtx = newCtx; - - const sounds = ['click.wav', 'orb.ogg', 'levelup.ogg', 'back.ogg', 'pop.wav', 'wood click.wav']; - sounds.forEach((s) => { - fetch(`/sounds/${s}`) - .then((r) => r.arrayBuffer()) - .then((b) => newCtx.decodeAudioData(b)) - .then((buf) => { - if (buf) buffers[s] = buf; - }); - }); - } - if (currentCtx.state === 'suspended') await currentCtx.resume(); - return { audioCtx, sfxGain, buffers }; -}; - -export const playSfx = async (n: string, sfxVol: number, isMuted: boolean, multiplier: number = 1.0) => { - const audioData = await ensureAudio(); - if (!audioData) return; - const { audioCtx, sfxGain, buffers } = audioData; - - if (!audioCtx || !sfxGain || !buffers[n] || isMuted) return; - - const s = audioCtx.createBufferSource(); - s.buffer = buffers[n]; - const g = audioCtx.createGain(); - g.gain.value = sfxVol * multiplier; - s.connect(g); - g.connect(audioCtx.destination); - s.start(0); -}; diff --git a/src/services/tauri.ts b/src/services/tauri.ts deleted file mode 100644 index f40c149..0000000 --- a/src/services/tauri.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { invoke } from "@tauri-apps/api/core"; -import { AppConfig, Runner } from "../types"; - -export const TauriService = { - loadConfig: () => invoke("load_config"), - saveConfig: (config: AppConfig) => invoke("save_config", { config }), - launchGame: (instanceId: string) => invoke("launch_game", { instanceId }), - downloadAndInstall: (url: string, instanceId: string) => invoke("download_and_install", { url, instanceId }), - checkGameInstalled: (instanceId: string) => invoke("check_game_installed", { instanceId }), - getAvailableRunners: () => invoke("get_available_runners"), - openInstanceFolder: (instanceId: string) => invoke("open_instance_folder", { instanceId }), - cancelDownload: () => invoke("cancel_download"), -}; diff --git a/src/services/unused.ts b/src/services/unused.ts new file mode 100644 index 0000000..ada22b4 --- /dev/null +++ b/src/services/unused.ts @@ -0,0 +1 @@ +// empty :P \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts deleted file mode 100644 index 5500c77..0000000 --- a/src/types/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface Runner { - id: string; - name: string; - path: string; - type: string; -} - -export interface AppConfig { - username: string; - linuxRunner?: string; -} - -export interface InstalledStatus { - vanilla_tu19: boolean; - vanilla_tu24: boolean; - [key: string]: boolean; -} - -export interface ReinstallModalData { - id: string; - url: string; -} - -export interface McNotification { - t: string; - m: string; -} diff --git a/src/types/unused.ts b/src/types/unused.ts new file mode 100644 index 0000000..ada22b4 --- /dev/null +++ b/src/types/unused.ts @@ -0,0 +1 @@ +// empty :P \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..7d0ff9e 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1 @@ -/// +/// diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index c1d2abe..0000000 --- a/tailwind.config.js +++ /dev/null @@ -1,10 +0,0 @@ -export default { - content: [ - "./index.html", - "./src/**/*.{js,ts,jsx,tsx}", - ], - theme: { - extend: {}, - }, - plugins: [], - } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f50b75c..9bdaa77 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,23 +1,25 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] -} +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json index 42872c5..165a9ba 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -1,10 +1,10 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts index 4fc4018..5bfc4ed 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,18 +1,17 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -export default defineConfig({ - plugins: [react()], - clearScreen: false, - optimizeDeps: { - entries: ['index.html'], - exclude: ['bin', 'game', 'src-tauri'] - }, - server: { - port: 1420, - strictPort: true, - watch: { - ignored: ["**/src-tauri/**", "**/bin/**", "**/game/**", "**/*.app/**"], - } - }, -}); \ No newline at end of file +import { defineConfig } from 'vite' +import tailwindcss from '@tailwindcss/vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [ + react(), + tailwindcss(), + ], + server: { + port: 1420, + strictPort: true, + watch: { + ignored: ["**/src-tauri/**"], + }, + }, +}) \ No newline at end of file