summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore57
-rwxr-xr-x.vscode/build.sh10
-rwxr-xr-x.vscode/config.sh12
-rw-r--r--.vscode/defsettings.json12
-rwxr-xr-x.vscode/setup.sh68
-rw-r--r--.vscode/tasks.json142
-rw-r--r--LICENSE31
-rw-r--r--README.md101
-rw-r--r--assets/logo.pngbin0 -> 21108 bytes
-rw-r--r--backend/Dockerfile9
-rw-r--r--backend/Makefile14
-rwxr-xr-xbackend/entrypoint.sh8
-rw-r--r--backend/src/main.c5
-rw-r--r--decky.pyi184
-rw-r--r--defaults/defaults.txt13
-rw-r--r--main.py57
-rw-r--r--package.json50
-rw-r--r--plugin.json11
-rw-r--r--pnpm-lock.yaml1763
-rw-r--r--py_modules/.keep0
-rw-r--r--rollup.config.js5
-rwxr-xr-xsrc/index.tsx115
-rw-r--r--src/types.d.ts14
-rw-r--r--tsconfig.json22
24 files changed, 2703 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d384256
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,57 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+*.swp
+
+pids
+logs
+results
+tmp
+
+# Coverage reports
+coverage
+
+# API keys and secrets
+.env
+
+# Dependency directory
+node_modules
+bower_components
+.pnpm-store
+
+# Editors
+.idea
+*.iml
+
+# OS metadata
+.DS_Store
+Thumbs.db
+
+# Ignore built ts files
+dist/
+
+__pycache__/
+
+/.yalc
+yalc.lock
+
+.vscode/settings.json
+
+# Ignore output folder
+
+backend/out
+
+# Make sure to ignore any instance of the loader's decky_plugin.py
+decky_plugin.py
+
+# Ignore decky CLI for building plugins
+out
+out/*
+cli/
+cli/*
+cli/decky
diff --git a/.vscode/build.sh b/.vscode/build.sh
new file mode 100755
index 0000000..2310ff0
--- /dev/null
+++ b/.vscode/build.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+CLI_LOCATION="$(pwd)/cli"
+echo "Building plugin in $(pwd)"
+printf "Please input sudo password to proceed.\n"
+
+# read -s sudopass
+
+# printf "\n"
+
+echo $sudopass | sudo -E $CLI_LOCATION/decky plugin build $(pwd)
diff --git a/.vscode/config.sh b/.vscode/config.sh
new file mode 100755
index 0000000..b45c794
--- /dev/null
+++ b/.vscode/config.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
+# printf "${SCRIPT_DIR}\n"
+# printf "$(dirname $0)\n"
+if ! [[ -e "${SCRIPT_DIR}/settings.json" ]]; then
+ printf '.vscode/settings.json does not exist. Creating it with default settings. Exiting afterwards. Run your task again.\n\n'
+ cp "${SCRIPT_DIR}/defsettings.json" "${SCRIPT_DIR}/settings.json"
+ exit 1
+else
+ printf '.vscode/settings.json does exist. Congrats.\n'
+ printf 'Make sure to change settings.json to match your deck.\n'
+fi \ No newline at end of file
diff --git a/.vscode/defsettings.json b/.vscode/defsettings.json
new file mode 100644
index 0000000..9734ed5
--- /dev/null
+++ b/.vscode/defsettings.json
@@ -0,0 +1,12 @@
+{
+ "deckip" : "steamdeck.local",
+ "deckport" : "22",
+ "deckuser" : "deck",
+ "deckpass" : "ssap",
+ "deckkey" : "-i ${env:HOME}/.ssh/id_rsa",
+ "deckdir" : "/home/deck",
+ "pluginname": "Example Plugin",
+ "python.analysis.extraPaths": [
+ "./py_modules"
+ ]
+}
diff --git a/.vscode/setup.sh b/.vscode/setup.sh
new file mode 100755
index 0000000..84ae7d2
--- /dev/null
+++ b/.vscode/setup.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+PNPM_INSTALLED="$(which pnpm)"
+DOCKER_INSTALLED="$(which docker)"
+CLI_INSTALLED="$(pwd)/cli/decky"
+
+# echo "$PNPM_INSTALLED"
+# echo "$DOCKER_INSTALLED"
+# echo "$CLI_INSTALLED"
+
+echo "If you are using alpine linux, do not expect any support."
+if [[ "$PNPM_INSTALLED" =~ "which" ]]; then
+ echo "pnpm is not currently installed, you can install it via your distro's package managment system or via a script that will attempt to do a manual install based on your system. If you wish to proceed with installing via the script then answer "no" (capitals do not matter) and proceed with the rest of the script. Otherwise, just hit enter to proceed and use the script."
+ read run_pnpm_script
+ if [[ "$run_pnpm_script" =~ "n" ]]; then
+ echo "You have chose to install pnpm via npm or your distros package manager. Please make sure to do so before attempting to build your plugin."
+ else
+ CURL_INSTALLED="$(which curl)"
+ WGET_INSTALLED="$(which wget)"
+ if [[ "$CURL_INSTALLED" =~ "which" ]]; then
+ printf "curl not found, attempting with wget.\n"
+ if [[ "$WGET_INSTALLED" =~ "which" ]]; then
+ printf "wget not found, please install wget or curl.\n"
+ printf "Could not install pnpm as curl and wget were not found.\n"
+ else
+ wget -qO- https://get.pnpm.io/install.sh | sh -
+ fi
+ else
+ curl -fsSL https://get.pnpm.io/install.sh | sh -
+ fi
+ fi
+fi
+
+if [[ "$DOCKER_INSTALLED" =~ "which" ]]; then
+ echo "Docker is not currently installed, in order build plugins with a backend you will need to have Docker installed. Please install Docker via the preferred method for your distribution."
+fi
+
+if ! test -f "$CLI_INSTALLED"; then
+ echo "The Decky CLI tool (binary file is just called "decky") is used to build your plugin as a zip file which you can then install on your Steam Deck to perform testing. We highly recommend you install it. Hitting enter now will run the script to install Decky CLI and extract it to a folder called cli in the current plugin directory. You can also type 'no' and hit enter to skip this but keep in mind you will not have a usable plugin without building it."
+ read run_cli_script
+ if [[ "$run_cli_script" =~ "n" ]]; then
+ echo "You have chosen to not install the Decky CLI tool to build your plugins. Please install this tool to build and test your plugin before submitting it to the Plugin Database."
+ else
+
+ SYSTEM_ARCH="$(uname -a)"
+
+ mkdir "$(pwd)"/cli
+ if [[ "$SYSTEM_ARCH" =~ "x86_64" ]]; then
+
+ if [[ "$SYSTEM_ARCH" =~ "Linux" ]]; then
+ curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-linux-x86_64"
+ fi
+
+ if [[ "$SYSTEM_ARCH" =~ "Darwin" ]]; then
+ curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-macOS-x86_64"
+ fi
+
+ else
+ echo "System Arch not found! The only supported systems are Linux x86_64 and Apple x86_64/ARM64, not $SYSTEM_ARCH"
+ fi
+
+ if [[ "$SYSTEM_ARCH" =~ "arm64" ]]; then
+ curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-macOS-aarch64"
+ fi
+
+ chmod +x "$(pwd)"/cli/decky
+ echo "Decky CLI tool is now installed and you can build plugins into easy zip files using the "Build Zip" Task in vscodium."
+ fi
+fi
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..9b966cd
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,142 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ //PRELIMINARY SETUP TASKS
+ //Dependency setup task
+ {
+ "label": "depsetup",
+ "type": "shell",
+ "group": "none",
+ "detail": "Install depedencies for basic setup",
+ "command": "${workspaceFolder}/.vscode/setup.sh",
+ // // placeholder for windows scripts, not currently planned
+ // "windows": {
+ // "command": "call -c ${workspaceFolder}\\.vscode\\setup.bat",
+ // },
+ "problemMatcher": []
+ },
+ //pnpm setup task to grab all needed modules
+ {
+ "label": "pnpmsetup",
+ "type": "shell",
+ "group": "none",
+ "detail": "Setup pnpm",
+ "command": "which pnpm && pnpm i",
+ "problemMatcher": []
+ },
+ //Preliminary "All-in-one" setup task
+ {
+ "label": "setup",
+ "detail": "Set up depedencies, pnpm and update Decky Frontend Library.",
+ "dependsOrder": "sequence",
+ "dependsOn": [
+ "depsetup",
+ "pnpmsetup",
+ "updatefrontendlib"
+ ],
+ "problemMatcher": []
+ },
+ //Preliminary Deploy Config Setup
+ {
+ "label": "settingscheck",
+ "type": "shell",
+ "group": "none",
+ "detail": "Check that settings.json has been created",
+ "command": "${workspaceFolder}/.vscode/config.sh",
+ // // placeholder for windows scripts, not currently planned
+ // "windows": {
+ // "command": "call ${workspaceFolder}\\.vscode\\config.bat",
+ // },
+ "problemMatcher": []
+ },
+ //BUILD TASKS
+ {
+ "label": "cli-build",
+ "group": "build",
+ "detail": "Build plugin with CLI",
+ "command": "${workspaceFolder}/.vscode/build.sh",
+ // // placeholder for windows logic, not currently planned
+ // "windows": {
+ // "command": "call ${workspaceFolder}\\.vscode\\build.bat",
+ // },
+ "problemMatcher": []
+ },
+ //"All-in-one" build task
+ {
+ "label": "build",
+ "group": "build",
+ "detail": "Build decky-plugin-template",
+ "dependsOrder": "sequence",
+ "dependsOn": [
+ "setup",
+ "settingscheck",
+ "cli-build",
+ ],
+ "problemMatcher": []
+ },
+ //DEPLOY TASKS
+ //Copies the zip file of the built plugin to the plugins folder
+ {
+ "label": "copyzip",
+ "detail": "Deploy plugin zip to deck",
+ "type": "shell",
+ "group": "none",
+ "dependsOn": [
+ "chmodplugins"
+ ],
+ "command": "rsync -azp --chmod=D0755,F0755 --rsh='ssh -p ${config:deckport} ${config:deckkey}' out/ ${config:deckuser}@${config:deckip}:${config:deckdir}/homebrew/plugins",
+ "problemMatcher": []
+ },
+ //
+ {
+ "label": "extractzip",
+ "detail": "",
+ "type": "shell",
+ "group": "none",
+ "command": "echo '${config:deckdir}/homebrew/plugins/${config:pluginname}.zip' && ssh ${config:deckuser}@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo ${config:deckpass} | sudo -S mkdir -m 755 -p \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" && echo ${config:deckpass} | sudo -S chown ${config:deckuser}:${config:deckuser} \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" && echo ${config:deckpass} | sudo -S bsdtar -xzpf \"${config:deckdir}/homebrew/plugins/${config:pluginname}.zip\" -C \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" --strip-components=1 --fflags '",
+ "problemMatcher": []
+ },
+ //"All-in-one" deploy task
+ {
+ "label": "deploy",
+ "dependsOrder": "sequence",
+ "group": "none",
+ "dependsOn": [
+ "copyzip",
+ "extractzip"
+ ],
+ "problemMatcher": []
+ },
+ //"All-in-on" build & deploy task
+ {
+ "label": "builddeploy",
+ "detail": "Builds plugin and deploys to deck",
+ "dependsOrder": "sequence",
+ "group": "none",
+ "dependsOn": [
+ "build",
+ "deploy"
+ ],
+ "problemMatcher": []
+ },
+ //GENERAL TASKS
+ //Update Decky Frontend Library, aka DFL
+ {
+ "label": "updatefrontendlib",
+ "type": "shell",
+ "group": "build",
+ "detail": "Update @decky/ui aka DFL",
+ "command": "pnpm update @decky/ui --latest",
+ "problemMatcher": []
+ },
+ //Used chmod plugins folder to allow copy-over of files
+ {
+ "label": "chmodplugins",
+ "detail": "chmods plugins folder to prevent perms issues",
+ "type": "shell",
+ "group": "none",
+ "command": "ssh ${config:deckuser}@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo '${config:deckpass}' | sudo -S chmod -R ug+rw ${config:deckdir}/homebrew/plugins/'",
+ "problemMatcher": []
+ },
+ ]
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c64c284
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+BSD 3-Clause License
+
+Copyright (c) 2024, Hypothetical Plugin Developer
+Original Copyright (c) 2022-2024, Steam Deck Homebrew
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..de27fae
--- /dev/null
+++ b/README.md
@@ -0,0 +1,101 @@
+# Decky Plugin Template [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://deckbrew.xyz/discord)
+
+Reference example for using [decky-frontend-lib](https://github.com/SteamDeckHomebrew/decky-frontend-lib) (@decky/ui) in a [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader) plugin.
+
+### **Please also refer to the [wiki](https://wiki.deckbrew.xyz/en/user-guide/home#plugin-development) for important information on plugin development and submissions/updates. currently documentation is split between this README and the wiki which is something we are hoping to rectify in the future.**
+
+## Developers
+
+### Dependencies
+
+This template relies on the user having Node.js v16.14+ and `pnpm` (v9) installed on their system.
+Please make sure to install pnpm v9 to prevent issues with CI during plugin submission.
+`pnpm` can be downloaded from `npm` itself which is recommended.
+
+#### Linux
+
+```bash
+sudo npm i -g pnpm@9
+```
+
+If you would like to build plugins that have their own custom backends, Docker is required as it is used by the Decky CLI tool.
+
+### Making your own plugin
+
+1. You can fork this repo or utilize the "Use this template" button on Github.
+2. In your local fork/own plugin-repository run these commands:
+ 1. ``pnpm i``
+ 2. ``pnpm run build``
+ - These setup pnpm and build the frontend code for testing.
+3. Consult the [decky-frontend-lib](https://github.com/SteamDeckHomebrew/decky-frontend-lib) repository for ways to accomplish your tasks.
+ - Documentation and examples are still rough,
+ - Decky loader primarily targets Steam Deck hardware so keep this in mind when developing your plugin.
+4. If using VSCodium/VSCode, run the `setup` and `build` and `deploy` tasks. If not using VSCodium etc. you can derive your own makefile or just manually utilize the scripts for these commands as you see fit.
+
+If you use VSCode or it's derivatives (we suggest [VSCodium](https://vscodium.com/)!) just run the `setup` and `build` tasks. It's really that simple.
+
+#### Other important information
+
+Everytime you change the frontend code (`index.tsx` etc) you will need to rebuild using the commands from step 2 above or the build task if you're using vscode or a derivative.
+
+Note: If you are receiving build errors due to an out of date library, you should run this command inside of your repository:
+
+```bash
+pnpm update @decky/ui --latest
+```
+
+### Backend support
+
+If you are developing with a backend for a plugin and would like to submit it to the [decky-plugin-database](https://github.com/SteamDeckHomebrew/decky-plugin-database) you will need to have all backend code located in ``backend/src``, with backend being located in the root of your git repository.
+When building your plugin, the source code will be built and any finished binary or binaries will be output to ``backend/out`` (which is created during CI.)
+If your buildscript, makefile or any other build method does not place the binary files in the ``backend/out`` directory they will not be properly picked up during CI and your plugin will not have the required binaries included for distribution.
+
+Example:
+In our makefile used to demonstrate the CI process of building and distributing a plugin backend, note that the makefile explicitly creates the `out` folder (``backend/out``) and then compiles the binary into that folder. Here's the relevant snippet.
+
+```make
+hello:
+ mkdir -p ./out
+ gcc -o ./out/hello ./src/main.c
+```
+
+The CI does create the `out` folder itself but we recommend creating it yourself if possible during your build process to ensure the build process goes smoothly.
+
+Note: When locally building your plugin it will be placed into a folder called 'out' this is different from the concept described above.
+
+The out folder is not sent to the final plugin, but is then put into a ``bin`` folder which is found at the root of the plugin's directory.
+More information on the bin folder can be found below in the distribution section below.
+
+### Distribution
+
+We recommend following the instructions found in the [decky-plugin-database](https://github.com/SteamDeckHomebrew/decky-plugin-database) on how to get your plugin up on the plugin store. This is the best way to get your plugin in front of users.
+You can also choose to do distribution via a zip file containing the needed files, if that zip file is uploaded to a URL it can then be downloaded and installed via decky-loader.
+
+**NOTE: We do not currently have a method to install from a downloaded zip file in "game-mode" due to lack of a usable file-picking dialog.**
+
+Layout of a plugin zip ready for distribution:
+```
+pluginname-v1.0.0.zip (version number is optional but recommended for users sake)
+ |
+ pluginname/ <directory>
+ | | |
+ | | bin/ <directory> (optional)
+ | | |
+ | | binary (optional)
+ | |
+ | dist/ <directory> [required]
+ | |
+ | index.js [required]
+ |
+ package.json [required]
+ plugin.json [required]
+ main.py {required if you are using the python backend of decky-loader: serverAPI}
+ README.md (optional but recommended)
+ LICENSE(.md) [required, filename should be roughly similar, suffix not needed]
+```
+
+Note regarding licenses: Including a license is required for the plugin store if your chosen license requires the license to be included alongside usage of source-code/binaries!
+
+Standard procedure for licenses is to have your chosen license at the top of the file, and to leave the original license for the plugin-template at the bottom. If this is not the case on submission to the plugin database, you will be asked to fix this discrepancy.
+
+We cannot and will not distribute your plugin on the Plugin Store if it's license requires it's inclusion but you have not included a license to be re-distributed with your plugin in the root of your git repository.
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..48c4851
--- /dev/null
+++ b/assets/logo.png
Binary files differ
diff --git a/backend/Dockerfile b/backend/Dockerfile
new file mode 100644
index 0000000..f46e170
--- /dev/null
+++ b/backend/Dockerfile
@@ -0,0 +1,9 @@
+# we support images for building with a vanilla SteamOS base,
+# or versions with ootb support for rust or go
+# developers can also customize these images via this Dockerfile
+#FROM ghcr.io/steamdeckhomebrew/holo-toolchain-rust:latest
+#FROM ghcr.io/steamdeckhomebrew/holo-toolchain-go:latest
+FROM ghcr.io/steamdeckhomebrew/holo-base:latest
+
+# entrypoint.sh should always be located in the backend folder
+ENTRYPOINT [ "/backend/entrypoint.sh" ] \ No newline at end of file
diff --git a/backend/Makefile b/backend/Makefile
new file mode 100644
index 0000000..a1e5dc5
--- /dev/null
+++ b/backend/Makefile
@@ -0,0 +1,14 @@
+# This is the default target, which will be built when
+# you invoke make
+.PHONY: all
+all: hello
+
+# This rule tells make how to build hello from hello.cpp
+hello:
+ mkdir -p ./out
+ gcc -o ./out/hello ./src/main.c
+
+# This rule tells make to delete hello and hello.o
+.PHONY: clean
+clean:
+ rm -f hello \ No newline at end of file
diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh
new file mode 100755
index 0000000..af04d23
--- /dev/null
+++ b/backend/entrypoint.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+echo "Container's IP address: `awk 'END{print $1}' /etc/hosts`"
+
+cd /backend
+
+make \ No newline at end of file
diff --git a/backend/src/main.c b/backend/src/main.c
new file mode 100644
index 0000000..b3b8fed
--- /dev/null
+++ b/backend/src/main.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+int main() {
+ printf("Hello World\n");
+ return 0;
+} \ No newline at end of file
diff --git a/decky.pyi b/decky.pyi
new file mode 100644
index 0000000..a72c74c
--- /dev/null
+++ b/decky.pyi
@@ -0,0 +1,184 @@
+"""
+This module exposes various constants and helpers useful for decky plugins.
+
+* Plugin's settings and configurations should be stored under `DECKY_PLUGIN_SETTINGS_DIR`.
+* Plugin's runtime data should be stored under `DECKY_PLUGIN_RUNTIME_DIR`.
+* Plugin's persistent log files should be stored under `DECKY_PLUGIN_LOG_DIR`.
+
+Avoid writing outside of `DECKY_HOME`, storing under the suggested paths is strongly recommended.
+
+Some basic migration helpers are available: `migrate_any`, `migrate_settings`, `migrate_runtime`, `migrate_logs`.
+
+A logging facility `logger` is available which writes to the recommended location.
+"""
+
+__version__ = '1.0.0'
+
+import logging
+
+from typing import Any
+
+"""
+Constants
+"""
+
+HOME: str
+"""
+The home directory of the effective user running the process.
+Environment variable: `HOME`.
+If `root` was specified in the plugin's flags it will be `/root` otherwise the user whose home decky resides in.
+e.g.: `/home/deck`
+"""
+
+USER: str
+"""
+The effective username running the process.
+Environment variable: `USER`.
+It would be `root` if `root` was specified in the plugin's flags otherwise the user whose home decky resides in.
+e.g.: `deck`
+"""
+
+DECKY_VERSION: str
+"""
+The version of the decky loader.
+Environment variable: `DECKY_VERSION`.
+e.g.: `v2.5.0-pre1`
+"""
+
+DECKY_USER: str
+"""
+The user whose home decky resides in.
+Environment variable: `DECKY_USER`.
+e.g.: `deck`
+"""
+
+DECKY_USER_HOME: str
+"""
+The home of the user where decky resides in.
+Environment variable: `DECKY_USER_HOME`.
+e.g.: `/home/deck`
+"""
+
+DECKY_HOME: str
+"""
+The root of the decky folder.
+Environment variable: `DECKY_HOME`.
+e.g.: `/home/deck/homebrew`
+"""
+
+DECKY_PLUGIN_SETTINGS_DIR: str
+"""
+The recommended path in which to store configuration files (created automatically).
+Environment variable: `DECKY_PLUGIN_SETTINGS_DIR`.
+e.g.: `/home/deck/homebrew/settings/decky-plugin-template`
+"""
+
+DECKY_PLUGIN_RUNTIME_DIR: str
+"""
+The recommended path in which to store runtime data (created automatically).
+Environment variable: `DECKY_PLUGIN_RUNTIME_DIR`.
+e.g.: `/home/deck/homebrew/data/decky-plugin-template`
+"""
+
+DECKY_PLUGIN_LOG_DIR: str
+"""
+The recommended path in which to store persistent logs (created automatically).
+Environment variable: `DECKY_PLUGIN_LOG_DIR`.
+e.g.: `/home/deck/homebrew/logs/decky-plugin-template`
+"""
+
+DECKY_PLUGIN_DIR: str
+"""
+The root of the plugin's directory.
+Environment variable: `DECKY_PLUGIN_DIR`.
+e.g.: `/home/deck/homebrew/plugins/decky-plugin-template`
+"""
+
+DECKY_PLUGIN_NAME: str
+"""
+The name of the plugin as specified in the 'plugin.json'.
+Environment variable: `DECKY_PLUGIN_NAME`.
+e.g.: `Example Plugin`
+"""
+
+DECKY_PLUGIN_VERSION: str
+"""
+The version of the plugin as specified in the 'package.json'.
+Environment variable: `DECKY_PLUGIN_VERSION`.
+e.g.: `0.0.1`
+"""
+
+DECKY_PLUGIN_AUTHOR: str
+"""
+The author of the plugin as specified in the 'plugin.json'.
+Environment variable: `DECKY_PLUGIN_AUTHOR`.
+e.g.: `John Doe`
+"""
+
+DECKY_PLUGIN_LOG: str
+"""
+The path to the plugin's main logfile.
+Environment variable: `DECKY_PLUGIN_LOG`.
+e.g.: `/home/deck/homebrew/logs/decky-plugin-template/plugin.log`
+"""
+
+"""
+Migration helpers
+"""
+
+
+def migrate_any(target_dir: str, *files_or_directories: str) -> dict[str, str]:
+ """
+ Migrate files and directories to a new location and remove old locations.
+ Specified files will be migrated to `target_dir`.
+ Specified directories will have their contents recursively migrated to `target_dir`.
+
+ Returns the mapping of old -> new location.
+ """
+
+
+def migrate_settings(*files_or_directories: str) -> dict[str, str]:
+ """
+ Migrate files and directories relating to plugin settings to the recommended location and remove old locations.
+ Specified files will be migrated to `DECKY_PLUGIN_SETTINGS_DIR`.
+ Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_SETTINGS_DIR`.
+
+ Returns the mapping of old -> new location.
+ """
+
+
+def migrate_runtime(*files_or_directories: str) -> dict[str, str]:
+ """
+ Migrate files and directories relating to plugin runtime data to the recommended location and remove old locations
+ Specified files will be migrated to `DECKY_PLUGIN_RUNTIME_DIR`.
+ Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_RUNTIME_DIR`.
+
+ Returns the mapping of old -> new location.
+ """
+
+
+def migrate_logs(*files_or_directories: str) -> dict[str, str]:
+ """
+ Migrate files and directories relating to plugin logs to the recommended location and remove old locations.
+ Specified files will be migrated to `DECKY_PLUGIN_LOG_DIR`.
+ Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_LOG_DIR`.
+
+ Returns the mapping of old -> new location.
+ """
+
+
+"""
+Logging
+"""
+
+logger: logging.Logger
+"""The main plugin logger writing to `DECKY_PLUGIN_LOG`."""
+
+"""
+Event handling
+"""
+# TODO better docstring im lazy
+async def emit(event: str, *args: Any) -> None:
+ """
+ Send an event to the frontend.
+ """ \ No newline at end of file
diff --git a/defaults/defaults.txt b/defaults/defaults.txt
new file mode 100644
index 0000000..ebf140b
--- /dev/null
+++ b/defaults/defaults.txt
@@ -0,0 +1,13 @@
+If you have plain-text json configs, theme templates, or templates for usage for your plugin of any description you should have those files be in here.
+Those files will be pulled into the zip during the build process and included with the upload. Example: CssLoader with it's themes in "default/themes" would have the "themes" folder will be added alongside with the dist folder, main.py, LICENSE and README files in the subfolder of the zip containing the plugin.
+Files can also be put in here such as a config, just keep in mind that they this directory cannot be utilized to put files in arbitrary locations, just within the extracted root folder of the plugin, ex: CssLoader has "defaults/themes/..." setup in it's repo, but when packaged to go to the store, the file structure will be:
+
+- LICENSE
+- README
+- dist
+ - index.js
+- main.py
+- package.json
+- plugin.json
+- themes
+ - exampletheme.css \ No newline at end of file
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..65a10da
--- /dev/null
+++ b/main.py
@@ -0,0 +1,57 @@
+import os
+
+# The decky plugin module is located at decky-loader/plugin
+# For easy intellisense checkout the decky-loader code repo
+# and add the `decky-loader/plugin/imports` path to `python.analysis.extraPaths` in `.vscode/settings.json`
+import decky
+import asyncio
+
+class Plugin:
+ # A normal method. It can be called from the TypeScript side using @decky/api.
+ async def add(self, left: int, right: int) -> int:
+ return left + right
+
+ async def long_running(self):
+ await asyncio.sleep(15)
+ # Passing through a bunch of random data, just as an example
+ await decky.emit("timer_event", "Hello from the backend!", True, 2)
+
+ # Asyncio-compatible long-running code, executed in a task when the plugin is loaded
+ async def _main(self):
+ self.loop = asyncio.get_event_loop()
+ decky.logger.info("Hello World!")
+
+ # Function called first during the unload process, utilize this to handle your plugin being stopped, but not
+ # completely removed
+ async def _unload(self):
+ decky.logger.info("Goodnight World!")
+ pass
+
+ # Function called after `_unload` during uninstall, utilize this to clean up processes and other remnants of your
+ # plugin that may remain on the system
+ async def _uninstall(self):
+ decky.logger.info("Goodbye World!")
+ pass
+
+ async def start_timer(self):
+ self.loop.create_task(self.long_running())
+
+ # Migrations that should be performed before entering `_main()`.
+ async def _migration(self):
+ decky.logger.info("Migrating")
+ # Here's a migration example for logs:
+ # - `~/.config/decky-template/template.log` will be migrated to `decky.decky_LOG_DIR/template.log`
+ decky.migrate_logs(os.path.join(decky.DECKY_USER_HOME,
+ ".config", "decky-template", "template.log"))
+ # Here's a migration example for settings:
+ # - `~/homebrew/settings/template.json` is migrated to `decky.decky_SETTINGS_DIR/template.json`
+ # - `~/.config/decky-template/` all files and directories under this root are migrated to `decky.decky_SETTINGS_DIR/`
+ decky.migrate_settings(
+ os.path.join(decky.DECKY_HOME, "settings", "template.json"),
+ os.path.join(decky.DECKY_USER_HOME, ".config", "decky-template"))
+ # Here's a migration example for runtime data:
+ # - `~/homebrew/template/` all files and directories under this root are migrated to `decky.decky_RUNTIME_DIR/`
+ # - `~/.local/share/decky-template/` all files and directories under this root are migrated to `decky.decky_RUNTIME_DIR/`
+ decky.migrate_runtime(
+ os.path.join(decky.DECKY_HOME, "template"),
+ os.path.join(decky.DECKY_USER_HOME, ".local", "share", "decky-template"))
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9501ba3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "decky-plugin-template",
+ "version": "0.0.1",
+ "description": "A template to quickly create decky plugins from scratch, based on TypeScript and webpack",
+ "type": "module",
+ "scripts": {
+ "build": "rollup -c",
+ "watch": "rollup -c -w",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/SteamDeckHomebrew/decky-plugin-template.git"
+ },
+ "keywords": [
+ "decky",
+ "plugin",
+ "plugin-template",
+ "steam-deck",
+ "deck"
+ ],
+ "author": "You <you@you.tld>",
+ "license": "BSD-3-Clause",
+ "bugs": {
+ "url": "https://github.com/SteamDeckHomebrew/decky-plugin-template/issues"
+ },
+ "homepage": "https://github.com/SteamDeckHomebrew/decky-plugin-template#readme",
+ "devDependencies": {
+ "@decky/rollup": "^1.0.1",
+ "@decky/ui": "^4.7.2",
+ "@types/react": "18.3.3",
+ "@types/react-dom": "18.3.0",
+ "@types/webpack": "^5.28.5",
+ "rollup": "^4.22.5",
+ "typescript": "^5.6.2"
+ },
+ "dependencies": {
+ "@decky/api": "^1.1.2",
+ "react-icons": "^5.3.0",
+ "tslib": "^2.7.0"
+ },
+ "pnpm": {
+ "peerDependencyRules": {
+ "ignoreMissing": [
+ "react",
+ "react-dom"
+ ]
+ }
+ }
+}
diff --git a/plugin.json b/plugin.json
new file mode 100644
index 0000000..568bded
--- /dev/null
+++ b/plugin.json
@@ -0,0 +1,11 @@
+{
+ "name": "Example Plugin",
+ "author": "John Doe",
+ "flags": ["debug", "_root"],
+ "api_version": 1,
+ "publish": {
+ "tags": ["template", "root"],
+ "description": "Decky example plugin.",
+ "image": "https://opengraph.githubassets.com/1/SteamDeckHomebrew/PluginLoader"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..8f954a4
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,1763 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@decky/api':
+ specifier: ^1.1.2
+ version: 1.1.2
+ react-icons:
+ specifier: ^5.3.0
+ version: 5.3.0(react@18.3.1)
+ tslib:
+ specifier: ^2.7.0
+ version: 2.7.0
+ devDependencies:
+ '@decky/rollup':
+ specifier: ^1.0.1
+ version: 1.0.1
+ '@decky/ui':
+ specifier: ^4.7.2
+ version: 4.7.2
+ '@types/react':
+ specifier: 18.3.3
+ version: 18.3.3
+ '@types/react-dom':
+ specifier: 18.3.0
+ version: 18.3.0
+ '@types/webpack':
+ specifier: ^5.28.5
+ version: 5.28.5
+ rollup:
+ specifier: ^4.22.5
+ version: 4.22.5
+ typescript:
+ specifier: ^5.6.2
+ version: 5.6.2
+
+packages:
+
+ '@decky/api@1.1.2':
+ resolution: {integrity: sha512-lTMqRpHOrGTCyH2c1jJvkmWhOq2dcnX5/ioHbfCVmyQOBik1OM1BnzF1uROsnNDC5GkRvl3J/ATqYp6vhYpRqw==}
+
+ '@decky/rollup@1.0.1':
+ resolution: {integrity: sha512-dx1VJwD7ul14PA/aZvOwAfY/GujHzqZJ+MFb4OIUVi63/z4KWMSuZrK6QWo0S4LrNW3RzB3ua6LT0WcJaNY9gw==}
+
+ '@decky/ui@4.7.2':
+ resolution: {integrity: sha512-jYXVhbyyupXAcCuFqr7G2qjYVjp8hlMGF8zl8ALv67y0YhikAtfhA2rGUjCuaV3kdo9YrpBh8djRUJXdFPg/Eg==}
+
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
+ '@jridgewell/gen-mapping@0.3.5':
+ resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/set-array@1.2.1':
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/source-map@0.3.6':
+ resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+
+ '@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'}
+
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
+ '@rollup/plugin-commonjs@26.0.3':
+ resolution: {integrity: sha512-2BJcolt43MY+y5Tz47djHkodCC3c1VKVrBDKpVqHKpQ9z9S158kCCqB8NF6/gzxLdNlYW9abB3Ibh+kOWLp8KQ==}
+ engines: {node: '>=16.0.0 || 14 >= 14.17'}
+ peerDependencies:
+ rollup: ^2.68.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-json@6.1.0':
+ resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-node-resolve@15.3.0':
+ resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^2.78.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-replace@5.0.7':
+ resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-typescript@11.1.6':
+ resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^2.14.0||^3.0.0||^4.0.0
+ tslib: '*'
+ typescript: '>=3.7.0'
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+ tslib:
+ optional: true
+
+ '@rollup/pluginutils@5.1.2':
+ resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/rollup-android-arm-eabi@4.22.5':
+ resolution: {integrity: sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.22.5':
+ resolution: {integrity: sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.22.5':
+ resolution: {integrity: sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.22.5':
+ resolution: {integrity: sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.22.5':
+ resolution: {integrity: sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.22.5':
+ resolution: {integrity: sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.22.5':
+ resolution: {integrity: sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.22.5':
+ resolution: {integrity: sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.22.5':
+ resolution: {integrity: sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.22.5':
+ resolution: {integrity: sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.22.5':
+ resolution: {integrity: sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.22.5':
+ resolution: {integrity: sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.22.5':
+ resolution: {integrity: sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.22.5':
+ resolution: {integrity: sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.22.5':
+ resolution: {integrity: sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.22.5':
+ resolution: {integrity: sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@types/estree@1.0.6':
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+ '@types/glob@7.2.0':
+ resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/minimatch@5.1.2':
+ resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
+
+ '@types/node@22.7.4':
+ resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==}
+
+ '@types/prop-types@15.7.13':
+ resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==}
+
+ '@types/react-dom@18.3.0':
+ resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
+
+ '@types/react@18.3.3':
+ resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
+
+ '@types/resolve@1.20.2':
+ resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+
+ '@types/webpack@5.28.5':
+ resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==}
+
+ '@webassemblyjs/ast@1.12.1':
+ resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
+
+ '@webassemblyjs/floating-point-hex-parser@1.11.6':
+ resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==}
+
+ '@webassemblyjs/helper-api-error@1.11.6':
+ resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==}
+
+ '@webassemblyjs/helper-buffer@1.12.1':
+ resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==}
+
+ '@webassemblyjs/helper-numbers@1.11.6':
+ resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==}
+
+ '@webassemblyjs/helper-wasm-bytecode@1.11.6':
+ resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==}
+
+ '@webassemblyjs/helper-wasm-section@1.12.1':
+ resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==}
+
+ '@webassemblyjs/ieee754@1.11.6':
+ resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==}
+
+ '@webassemblyjs/leb128@1.11.6':
+ resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==}
+
+ '@webassemblyjs/utf8@1.11.6':
+ resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==}
+
+ '@webassemblyjs/wasm-edit@1.12.1':
+ resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==}
+
+ '@webassemblyjs/wasm-gen@1.12.1':
+ resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==}
+
+ '@webassemblyjs/wasm-opt@1.12.1':
+ resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==}
+
+ '@webassemblyjs/wasm-parser@1.12.1':
+ resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==}
+
+ '@webassemblyjs/wast-printer@1.12.1':
+ resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==}
+
+ '@xtuc/ieee754@1.2.0':
+ resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
+
+ '@xtuc/long@4.2.2':
+ resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
+
+ acorn-import-attributes@1.9.5:
+ resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
+ peerDependencies:
+ acorn: ^8
+
+ acorn@8.12.1:
+ resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ aggregate-error@3.1.0:
+ resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+ engines: {node: '>=8'}
+
+ ajv-keywords@3.5.2:
+ resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
+ peerDependencies:
+ ajv: ^6.9.1
+
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.1.0:
+ resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
+ engines: {node: '>=12'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+
+ brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.24.0:
+ resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ caniuse-lite@1.0.30001664:
+ resolution: {integrity: sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==}
+
+ chrome-trace-event@1.0.4:
+ resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
+ engines: {node: '>=6.0'}
+
+ clean-stack@2.2.0:
+ resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+ engines: {node: '>=6'}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+ commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
+ del@5.1.0:
+ resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==}
+ engines: {node: '>=8'}
+
+ dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ electron-to-chromium@1.5.29:
+ resolution: {integrity: sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ enhanced-resolve@5.17.1:
+ resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==}
+ engines: {node: '>=10.13.0'}
+
+ es-module-lexer@1.5.4:
+ resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ eslint-scope@5.1.1:
+ resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+ engines: {node: '>=8.0.0'}
+
+ esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+
+ estraverse@4.3.0:
+ resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
+ engines: {node: '>=4.0'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@0.6.1:
+ resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ events@3.3.0:
+ resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+ engines: {node: '>=0.8.x'}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fastq@1.17.1:
+ resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ foreground-child@3.3.0:
+ resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
+ engines: {node: '>=14'}
+
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
+ 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==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-to-regexp@0.4.1:
+ resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+
+ glob@10.4.5:
+ resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ hasBin: true
+
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
+
+ globby@10.0.2:
+ resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==}
+ engines: {node: '>=8'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ is-core-module@2.15.1:
+ resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
+ engines: {node: '>= 0.4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-module@1.0.0:
+ resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-path-cwd@2.2.0:
+ resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
+ engines: {node: '>=6'}
+
+ is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+
+ is-reference@1.2.1:
+ resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
+
+ is-reference@3.0.2:
+ resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
+
+ is-what@5.0.2:
+ resolution: {integrity: sha512-vI7Ui0qzNQ2ClDZd0bC7uqRk3T1imbX5cZODmVlqqdqiwmSIUX3CNSiRgFjFMJ987sVCMSa7xZeEDtpJduPg4A==}
+ engines: {node: '>=18'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
+ jest-worker@27.5.1:
+ resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
+ engines: {node: '>= 10.13.0'}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ loader-runner@4.3.0:
+ resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
+ engines: {node: '>=6.11.5'}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ magic-string@0.30.11:
+ resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
+
+ merge-anything@6.0.2:
+ resolution: {integrity: sha512-U8x6DL/YVudOcf82B6hd8GFg+6gF6hEHYwzqdo67GrH6vnDZ5YBq6BYX3hHWyCnG3CcqJDB1a9tj9fzMI3RL9Q==}
+ engines: {node: '>=18'}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ neo-async@2.6.2:
+ resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
+ node-releases@2.0.18:
+ resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ p-map@3.0.0:
+ resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==}
+ engines: {node: '>=8'}
+
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
+ path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+
+ picocolors@1.1.0:
+ resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ randombytes@2.1.0:
+ resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+
+ react-icons@5.3.0:
+ resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==}
+ peerDependencies:
+ react: '*'
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+
+ reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
+ hasBin: true
+
+ rollup-plugin-delete@2.1.0:
+ resolution: {integrity: sha512-TEbqJd7giLvzQDTu4jSPufwhTJs/iYVN2LfR/YIYkqjC/oZ0/h9Q0AeljifIhzBzJYZtHQTWKEbMms5fbh54pw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ rollup: '*'
+
+ rollup-plugin-external-globals@0.11.0:
+ resolution: {integrity: sha512-LR+sH2WkgWMPxsA5o5rT7uW7BeWXSeygLe60QQi9qoN/ufaCuHDaVOIbndIkqDPnZt/wZugJh5DCzkZFdSWlLQ==}
+ peerDependencies:
+ rollup: ^2.25.0 || ^3.3.0 || ^4.1.4
+
+ rollup-plugin-import-assets@1.1.1:
+ resolution: {integrity: sha512-u5zJwOjguTf2N+wETq2weNKGvNkuVc1UX/fPgg215p5xPvGOaI6/BTc024E9brvFjSQTfIYqgvwogQdipknu1g==}
+ peerDependencies:
+ rollup: '>=1.9.0'
+
+ rollup-pluginutils@2.8.2:
+ resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
+
+ rollup@4.22.5:
+ resolution: {integrity: sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ schema-utils@3.3.0:
+ resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==}
+ engines: {node: '>= 10.13.0'}
+
+ serialize-javascript@6.0.2:
+ resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+
+ supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ tapable@2.2.1:
+ resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+ engines: {node: '>=6'}
+
+ terser-webpack-plugin@5.3.10:
+ resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
+ engines: {node: '>= 10.13.0'}
+ peerDependencies:
+ '@swc/core': '*'
+ esbuild: '*'
+ uglify-js: '*'
+ webpack: ^5.1.0
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ esbuild:
+ optional: true
+ uglify-js:
+ optional: true
+
+ terser@5.34.0:
+ resolution: {integrity: sha512-y5NUX+U9HhVsK/zihZwoq4r9dICLyV2jXGOriDAVOeKhq3LKVjgJbGO90FisozXLlJfvjHqgckGmJFBb9KYoWQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tslib@2.7.0:
+ resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
+
+ typescript@5.6.2:
+ resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@6.19.8:
+ resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+
+ update-browserslist-db@1.1.1:
+ resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ url-join@4.0.1:
+ resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==}
+
+ watchpack@2.4.2:
+ resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==}
+ engines: {node: '>=10.13.0'}
+
+ webpack-sources@3.2.3:
+ resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
+ engines: {node: '>=10.13.0'}
+
+ webpack@5.95.0:
+ resolution: {integrity: sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ peerDependencies:
+ webpack-cli: '*'
+ peerDependenciesMeta:
+ webpack-cli:
+ optional: true
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+snapshots:
+
+ '@decky/api@1.1.2': {}
+
+ '@decky/rollup@1.0.1':
+ dependencies:
+ '@rollup/plugin-commonjs': 26.0.3(rollup@4.22.5)
+ '@rollup/plugin-json': 6.1.0(rollup@4.22.5)
+ '@rollup/plugin-node-resolve': 15.3.0(rollup@4.22.5)
+ '@rollup/plugin-replace': 5.0.7(rollup@4.22.5)
+ '@rollup/plugin-typescript': 11.1.6(rollup@4.22.5)(tslib@2.7.0)(typescript@5.6.2)
+ merge-anything: 6.0.2
+ rollup: 4.22.5
+ rollup-plugin-delete: 2.1.0(rollup@4.22.5)
+ rollup-plugin-external-globals: 0.11.0(rollup@4.22.5)
+ rollup-plugin-import-assets: 1.1.1(rollup@4.22.5)
+ tslib: 2.7.0
+ typescript: 5.6.2
+
+ '@decky/ui@4.7.2': {}
+
+ '@isaacs/cliui@8.0.2':
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: wrap-ansi@7.0.0
+
+ '@jridgewell/gen-mapping@0.3.5':
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/set-array@1.2.1': {}
+
+ '@jridgewell/source-map@0.3.6':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ '@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.17.1
+
+ '@pkgjs/parseargs@0.11.0':
+ optional: true
+
+ '@rollup/plugin-commonjs@26.0.3(rollup@4.22.5)':
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ commondir: 1.0.1
+ estree-walker: 2.0.2
+ glob: 10.4.5
+ is-reference: 1.2.1
+ magic-string: 0.30.11
+ optionalDependencies:
+ rollup: 4.22.5
+
+ '@rollup/plugin-json@6.1.0(rollup@4.22.5)':
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ optionalDependencies:
+ rollup: 4.22.5
+
+ '@rollup/plugin-node-resolve@15.3.0(rollup@4.22.5)':
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ '@types/resolve': 1.20.2
+ deepmerge: 4.3.1
+ is-module: 1.0.0
+ resolve: 1.22.8
+ optionalDependencies:
+ rollup: 4.22.5
+
+ '@rollup/plugin-replace@5.0.7(rollup@4.22.5)':
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ magic-string: 0.30.11
+ optionalDependencies:
+ rollup: 4.22.5
+
+ '@rollup/plugin-typescript@11.1.6(rollup@4.22.5)(tslib@2.7.0)(typescript@5.6.2)':
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ resolve: 1.22.8
+ typescript: 5.6.2
+ optionalDependencies:
+ rollup: 4.22.5
+ tslib: 2.7.0
+
+ '@rollup/pluginutils@5.1.2(rollup@4.22.5)':
+ dependencies:
+ '@types/estree': 1.0.6
+ estree-walker: 2.0.2
+ picomatch: 2.3.1
+ optionalDependencies:
+ rollup: 4.22.5
+
+ '@rollup/rollup-android-arm-eabi@4.22.5':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.22.5':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.22.5':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.22.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.22.5':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.22.5':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.22.5':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.22.5':
+ optional: true
+
+ '@types/estree@1.0.6': {}
+
+ '@types/glob@7.2.0':
+ dependencies:
+ '@types/minimatch': 5.1.2
+ '@types/node': 22.7.4
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/minimatch@5.1.2': {}
+
+ '@types/node@22.7.4':
+ dependencies:
+ undici-types: 6.19.8
+
+ '@types/prop-types@15.7.13': {}
+
+ '@types/react-dom@18.3.0':
+ dependencies:
+ '@types/react': 18.3.3
+
+ '@types/react@18.3.3':
+ dependencies:
+ '@types/prop-types': 15.7.13
+ csstype: 3.1.3
+
+ '@types/resolve@1.20.2': {}
+
+ '@types/webpack@5.28.5':
+ dependencies:
+ '@types/node': 22.7.4
+ tapable: 2.2.1
+ webpack: 5.95.0
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+ - webpack-cli
+
+ '@webassemblyjs/ast@1.12.1':
+ dependencies:
+ '@webassemblyjs/helper-numbers': 1.11.6
+ '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+
+ '@webassemblyjs/floating-point-hex-parser@1.11.6': {}
+
+ '@webassemblyjs/helper-api-error@1.11.6': {}
+
+ '@webassemblyjs/helper-buffer@1.12.1': {}
+
+ '@webassemblyjs/helper-numbers@1.11.6':
+ dependencies:
+ '@webassemblyjs/floating-point-hex-parser': 1.11.6
+ '@webassemblyjs/helper-api-error': 1.11.6
+ '@xtuc/long': 4.2.2
+
+ '@webassemblyjs/helper-wasm-bytecode@1.11.6': {}
+
+ '@webassemblyjs/helper-wasm-section@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/helper-buffer': 1.12.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+ '@webassemblyjs/wasm-gen': 1.12.1
+
+ '@webassemblyjs/ieee754@1.11.6':
+ dependencies:
+ '@xtuc/ieee754': 1.2.0
+
+ '@webassemblyjs/leb128@1.11.6':
+ dependencies:
+ '@xtuc/long': 4.2.2
+
+ '@webassemblyjs/utf8@1.11.6': {}
+
+ '@webassemblyjs/wasm-edit@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/helper-buffer': 1.12.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+ '@webassemblyjs/helper-wasm-section': 1.12.1
+ '@webassemblyjs/wasm-gen': 1.12.1
+ '@webassemblyjs/wasm-opt': 1.12.1
+ '@webassemblyjs/wasm-parser': 1.12.1
+ '@webassemblyjs/wast-printer': 1.12.1
+
+ '@webassemblyjs/wasm-gen@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+ '@webassemblyjs/ieee754': 1.11.6
+ '@webassemblyjs/leb128': 1.11.6
+ '@webassemblyjs/utf8': 1.11.6
+
+ '@webassemblyjs/wasm-opt@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/helper-buffer': 1.12.1
+ '@webassemblyjs/wasm-gen': 1.12.1
+ '@webassemblyjs/wasm-parser': 1.12.1
+
+ '@webassemblyjs/wasm-parser@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/helper-api-error': 1.11.6
+ '@webassemblyjs/helper-wasm-bytecode': 1.11.6
+ '@webassemblyjs/ieee754': 1.11.6
+ '@webassemblyjs/leb128': 1.11.6
+ '@webassemblyjs/utf8': 1.11.6
+
+ '@webassemblyjs/wast-printer@1.12.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.12.1
+ '@xtuc/long': 4.2.2
+
+ '@xtuc/ieee754@1.2.0': {}
+
+ '@xtuc/long@4.2.2': {}
+
+ acorn-import-attributes@1.9.5(acorn@8.12.1):
+ dependencies:
+ acorn: 8.12.1
+
+ acorn@8.12.1: {}
+
+ aggregate-error@3.1.0:
+ dependencies:
+ clean-stack: 2.2.0
+ indent-string: 4.0.0
+
+ ajv-keywords@3.5.2(ajv@6.12.6):
+ dependencies:
+ ajv: 6.12.6
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ansi-regex@5.0.1: {}
+
+ ansi-regex@6.1.0: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@6.2.1: {}
+
+ array-union@2.1.0: {}
+
+ balanced-match@1.0.2: {}
+
+ brace-expansion@1.1.11:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.1:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.24.0:
+ dependencies:
+ caniuse-lite: 1.0.30001664
+ electron-to-chromium: 1.5.29
+ node-releases: 2.0.18
+ update-browserslist-db: 1.1.1(browserslist@4.24.0)
+
+ buffer-from@1.1.2: {}
+
+ caniuse-lite@1.0.30001664: {}
+
+ chrome-trace-event@1.0.4: {}
+
+ clean-stack@2.2.0: {}
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ commander@2.20.3: {}
+
+ commondir@1.0.1: {}
+
+ concat-map@0.0.1: {}
+
+ cross-spawn@7.0.3:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ csstype@3.1.3: {}
+
+ deepmerge@4.3.1: {}
+
+ del@5.1.0:
+ dependencies:
+ globby: 10.0.2
+ graceful-fs: 4.2.11
+ is-glob: 4.0.3
+ is-path-cwd: 2.2.0
+ is-path-inside: 3.0.3
+ p-map: 3.0.0
+ rimraf: 3.0.2
+ slash: 3.0.0
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ eastasianwidth@0.2.0: {}
+
+ electron-to-chromium@1.5.29: {}
+
+ emoji-regex@8.0.0: {}
+
+ emoji-regex@9.2.2: {}
+
+ enhanced-resolve@5.17.1:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.1
+
+ es-module-lexer@1.5.4: {}
+
+ escalade@3.2.0: {}
+
+ eslint-scope@5.1.1:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@4.3.0: {}
+
+ estraverse@5.3.0: {}
+
+ estree-walker@0.6.1: {}
+
+ estree-walker@2.0.2: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.6
+
+ events@3.3.0: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.2:
+ 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
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fastq@1.17.1:
+ dependencies:
+ reusify: 1.0.4
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ foreground-child@3.3.0:
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+
+ fs.realpath@1.0.0: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-to-regexp@0.4.1: {}
+
+ glob@10.4.5:
+ dependencies:
+ foreground-child: 3.3.0
+ jackspeak: 3.4.3
+ minimatch: 9.0.5
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
+ path-scurry: 1.11.1
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ globby@10.0.2:
+ dependencies:
+ '@types/glob': 7.2.0
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ glob: 7.2.3
+ ignore: 5.3.2
+ merge2: 1.4.1
+ slash: 3.0.0
+
+ graceful-fs@4.2.11: {}
+
+ has-flag@4.0.0: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ ignore@5.3.2: {}
+
+ indent-string@4.0.0: {}
+
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ is-core-module@2.15.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-module@1.0.0: {}
+
+ is-number@7.0.0: {}
+
+ is-path-cwd@2.2.0: {}
+
+ is-path-inside@3.0.3: {}
+
+ is-reference@1.2.1:
+ dependencies:
+ '@types/estree': 1.0.6
+
+ is-reference@3.0.2:
+ dependencies:
+ '@types/estree': 1.0.6
+
+ is-what@5.0.2: {}
+
+ isexe@2.0.0: {}
+
+ jackspeak@3.4.3:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ jest-worker@27.5.1:
+ dependencies:
+ '@types/node': 22.7.4
+ merge-stream: 2.0.0
+ supports-color: 8.1.1
+
+ js-tokens@4.0.0: {}
+
+ json-parse-even-better-errors@2.3.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ loader-runner@4.3.0: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ lru-cache@10.4.3: {}
+
+ magic-string@0.30.11:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ merge-anything@6.0.2:
+ dependencies:
+ is-what: 5.0.2
+
+ merge-stream@2.0.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.11
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ minipass@7.1.2: {}
+
+ neo-async@2.6.2: {}
+
+ node-releases@2.0.18: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ p-map@3.0.0:
+ dependencies:
+ aggregate-error: 3.1.0
+
+ package-json-from-dist@1.0.1: {}
+
+ path-is-absolute@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-parse@1.0.7: {}
+
+ path-scurry@1.11.1:
+ dependencies:
+ lru-cache: 10.4.3
+ minipass: 7.1.2
+
+ path-type@4.0.0: {}
+
+ picocolors@1.1.0: {}
+
+ picomatch@2.3.1: {}
+
+ punycode@2.3.1: {}
+
+ queue-microtask@1.2.3: {}
+
+ randombytes@2.1.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ react-icons@5.3.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ resolve@1.22.8:
+ dependencies:
+ is-core-module: 2.15.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ reusify@1.0.4: {}
+
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ rollup-plugin-delete@2.1.0(rollup@4.22.5):
+ dependencies:
+ del: 5.1.0
+ rollup: 4.22.5
+
+ rollup-plugin-external-globals@0.11.0(rollup@4.22.5):
+ dependencies:
+ '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+ estree-walker: 3.0.3
+ is-reference: 3.0.2
+ magic-string: 0.30.11
+ rollup: 4.22.5
+
+ rollup-plugin-import-assets@1.1.1(rollup@4.22.5):
+ dependencies:
+ rollup: 4.22.5
+ rollup-pluginutils: 2.8.2
+ url-join: 4.0.1
+
+ rollup-pluginutils@2.8.2:
+ dependencies:
+ estree-walker: 0.6.1
+
+ rollup@4.22.5:
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.22.5
+ '@rollup/rollup-android-arm64': 4.22.5
+ '@rollup/rollup-darwin-arm64': 4.22.5
+ '@rollup/rollup-darwin-x64': 4.22.5
+ '@rollup/rollup-linux-arm-gnueabihf': 4.22.5
+ '@rollup/rollup-linux-arm-musleabihf': 4.22.5
+ '@rollup/rollup-linux-arm64-gnu': 4.22.5
+ '@rollup/rollup-linux-arm64-musl': 4.22.5
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.22.5
+ '@rollup/rollup-linux-riscv64-gnu': 4.22.5
+ '@rollup/rollup-linux-s390x-gnu': 4.22.5
+ '@rollup/rollup-linux-x64-gnu': 4.22.5
+ '@rollup/rollup-linux-x64-musl': 4.22.5
+ '@rollup/rollup-win32-arm64-msvc': 4.22.5
+ '@rollup/rollup-win32-ia32-msvc': 4.22.5
+ '@rollup/rollup-win32-x64-msvc': 4.22.5
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-buffer@5.2.1: {}
+
+ schema-utils@3.3.0:
+ dependencies:
+ '@types/json-schema': 7.0.15
+ ajv: 6.12.6
+ ajv-keywords: 3.5.2(ajv@6.12.6)
+
+ serialize-javascript@6.0.2:
+ dependencies:
+ randombytes: 2.1.0
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ signal-exit@4.1.0: {}
+
+ slash@3.0.0: {}
+
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.6.1: {}
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string-width@5.1.2:
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-ansi@7.1.0:
+ dependencies:
+ ansi-regex: 6.1.0
+
+ supports-color@8.1.1:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ tapable@2.2.1: {}
+
+ terser-webpack-plugin@5.3.10(webpack@5.95.0):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ jest-worker: 27.5.1
+ schema-utils: 3.3.0
+ serialize-javascript: 6.0.2
+ terser: 5.34.0
+ webpack: 5.95.0
+
+ terser@5.34.0:
+ dependencies:
+ '@jridgewell/source-map': 0.3.6
+ acorn: 8.12.1
+ commander: 2.20.3
+ source-map-support: 0.5.21
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ tslib@2.7.0: {}
+
+ typescript@5.6.2: {}
+
+ undici-types@6.19.8: {}
+
+ update-browserslist-db@1.1.1(browserslist@4.24.0):
+ dependencies:
+ browserslist: 4.24.0
+ escalade: 3.2.0
+ picocolors: 1.1.0
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ url-join@4.0.1: {}
+
+ watchpack@2.4.2:
+ dependencies:
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+
+ webpack-sources@3.2.3: {}
+
+ webpack@5.95.0:
+ dependencies:
+ '@types/estree': 1.0.6
+ '@webassemblyjs/ast': 1.12.1
+ '@webassemblyjs/wasm-edit': 1.12.1
+ '@webassemblyjs/wasm-parser': 1.12.1
+ acorn: 8.12.1
+ acorn-import-attributes: 1.9.5(acorn@8.12.1)
+ browserslist: 4.24.0
+ chrome-trace-event: 1.0.4
+ enhanced-resolve: 5.17.1
+ es-module-lexer: 1.5.4
+ eslint-scope: 5.1.1
+ events: 3.3.0
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+ json-parse-even-better-errors: 2.3.1
+ loader-runner: 4.3.0
+ mime-types: 2.1.35
+ neo-async: 2.6.2
+ schema-utils: 3.3.0
+ tapable: 2.2.1
+ terser-webpack-plugin: 5.3.10(webpack@5.95.0)
+ watchpack: 2.4.2
+ webpack-sources: 3.2.3
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@8.1.0:
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ wrappy@1.0.2: {}
diff --git a/py_modules/.keep b/py_modules/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/py_modules/.keep
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 0000000..17e71a7
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,5 @@
+import deckyPlugin from "@decky/rollup";
+
+export default deckyPlugin({
+ // Add your extra Rollup options here
+}) \ No newline at end of file
diff --git a/src/index.tsx b/src/index.tsx
new file mode 100755
index 0000000..16cd6cb
--- /dev/null
+++ b/src/index.tsx
@@ -0,0 +1,115 @@
+import {
+ ButtonItem,
+ PanelSection,
+ PanelSectionRow,
+ Navigation,
+ staticClasses
+} from "@decky/ui";
+import {
+ addEventListener,
+ removeEventListener,
+ callable,
+ definePlugin,
+ toaster,
+ // routerHook
+} from "@decky/api"
+import { useState } from "react";
+import { FaShip } from "react-icons/fa";
+
+// import logo from "../assets/logo.png";
+
+// This function calls the python function "add", which takes in two numbers and returns their sum (as a number)
+// Note the type annotations:
+// the first one: [first: number, second: number] is for the arguments
+// the second one: number is for the return value
+const add = callable<[first: number, second: number], number>("add");
+
+// This function calls the python function "start_timer", which takes in no arguments and returns nothing.
+// It starts a (python) timer which eventually emits the event 'timer_event'
+const startTimer = callable<[], void>("start_timer");
+
+function Content() {
+ const [result, setResult] = useState<number | undefined>();
+
+ const onClick = async () => {
+ const result = await add(Math.random(), Math.random());
+ setResult(result);
+ };
+
+ return (
+ <PanelSection title="Panel Section">
+ <PanelSectionRow>
+ <ButtonItem
+ layout="below"
+ onClick={onClick}
+ >
+ {result ?? "Add two numbers via Python"}
+ </ButtonItem>
+ </PanelSectionRow>
+ <PanelSectionRow>
+ <ButtonItem
+ layout="below"
+ onClick={() => startTimer()}
+ >
+ {"Start Python timer"}
+ </ButtonItem>
+ </PanelSectionRow>
+
+ {/* <PanelSectionRow>
+ <div style={{ display: "flex", justifyContent: "center" }}>
+ <img src={logo} />
+ </div>
+ </PanelSectionRow> */}
+
+ {/*<PanelSectionRow>
+ <ButtonItem
+ layout="below"
+ onClick={() => {
+ Navigation.Navigate("/decky-plugin-test");
+ Navigation.CloseSideMenus();
+ }}
+ >
+ Router
+ </ButtonItem>
+ </PanelSectionRow>*/}
+ </PanelSection>
+ );
+};
+
+export default definePlugin(() => {
+ console.log("Template plugin initializing, this is called once on frontend startup")
+
+ // serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
+ // exact: true,
+ // });
+
+ // Add an event listener to the "timer_event" event from the backend
+ const listener = addEventListener<[
+ test1: string,
+ test2: boolean,
+ test3: number
+ ]>("timer_event", (test1, test2, test3) => {
+ console.log("Template got timer_event with:", test1, test2, test3)
+ toaster.toast({
+ title: "template got timer_event",
+ body: `${test1}, ${test2}, ${test3}`
+ });
+ });
+
+ return {
+ // The name shown in various decky menus
+ name: "Test Plugin",
+ // The element displayed at the top of your plugin's menu
+ titleView: <div className={staticClasses.Title}>Decky Example Plugin</div>,
+ // The content of your plugin's menu
+ content: <Content />,
+ // The icon displayed in the plugin list
+ icon: <FaShip />,
+ // The function triggered when your plugin unloads
+ onDismount() {
+ console.log("Unloading")
+ removeEventListener("timer_event", listener);
+ // serverApi.routerHook.removeRoute("/decky-plugin-test");
+ },
+ };
+});
diff --git a/src/types.d.ts b/src/types.d.ts
new file mode 100644
index 0000000..dfc0472
--- /dev/null
+++ b/src/types.d.ts
@@ -0,0 +1,14 @@
+declare module "*.svg" {
+ const content: string;
+ export default content;
+}
+
+declare module "*.png" {
+ const content: string;
+ export default content;
+}
+
+declare module "*.jpg" {
+ const content: string;
+ export default content;
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..626c60f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "outDir": "dist",
+ "module": "ESNext",
+ "target": "ES2020",
+ "jsx": "react",
+ "jsxFactory": "window.SP_REACT.createElement",
+ "jsxFragmentFactory": "window.SP_REACT.Fragment",
+ "declaration": false,
+ "moduleResolution": "node",
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "esModuleInterop": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "strict": true,
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"]
+}