Merge pull request #2 from Macrame-App/development

Clean Development environment
This commit is contained in:
Jesse Malotaux 2025-05-08 23:34:24 +02:00 committed by GitHub
commit d914d0c3de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
147 changed files with 190 additions and 28789 deletions

10
.gitignore vendored
View file

@ -2,13 +2,19 @@
config.js config.js
devices/* devices/*
tmp/ tmp
log.txt log.txt
Macrame.exe Macrame.exe
public public/*
macros/* macros/*
!macros/TEST-*
panels/*
!panels/test_panel
builds builds
node_modules node_modules
ToDo.md ToDo.md

View file

@ -36,7 +36,7 @@ func EnvGet(key string) string {
if !configFileExists() { if !configFileExists() {
CreateConfigFile(configPath) CreateConfigFile(configPath)
CheckFeDevDir() CheckUIDevDir()
} }
data, err := os.ReadFile(configPath) data, err := os.ReadFile(configPath)
@ -63,12 +63,12 @@ func configFileExists() bool {
return err == nil return err == nil
} }
func CheckFeDevDir() { func CheckUIDevDir() {
log.Println("Checking FE dev directory...") log.Println("Checking FE dev directory...")
_, err := os.Stat("fe") _, err := os.Stat("ui")
if err != nil { if err != nil {
log.Println("Error checking FE dev directory:", err) log.Println("Error checking ui dev directory:", err)
return return
} }
@ -83,7 +83,7 @@ func copyConfigToFe() {
return return
} }
if err := os.WriteFile("fe/config.js", data, 0644); err != nil { if err := os.WriteFile("ui/config.js", data, 0644); err != nil {
log.Println("Error writing config.js:", err) log.Println("Error writing config.js:", err)
} }
} }

View file

@ -1,99 +0,0 @@
package app
import (
"be/app/helper"
"log"
"mime"
"net/http"
"path/filepath"
"strings"
)
func ApiCORS(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, *http.Request) {
origin := r.Header.Get("Origin")
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
if strings.HasPrefix(r.Host, "192.168.") {
log.Println("lan device")
w.Header().Set("Access-Control-Allow-Origin", origin)
}
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, Accept-Language, Accept-Encoding")
return w, r
}
func ApiGet(w http.ResponseWriter, r *http.Request) {
file := "" // base directory
if r.URL.Path != "/" {
file = "../public" + r.URL.Path // request
}
contentType := mime.TypeByExtension(filepath.Ext(file)) // get content type
if contentType != "" {
w.Header().Set("Content-Type", contentType) // set content type header
}
if contentType == "" {
file = "../public/index.html" // default
}
// log.Println("GET:", file)
http.ServeFile(w, r, file) // serve file
}
func ApiPost(w http.ResponseWriter, r *http.Request) {
access, data := helper.EndpointAccess(w, r)
if !access {
return
}
log.Println("api post", data == "")
if data != "" {
ApiAuth(data, w, r)
return
}
switch r.URL.Path {
case "/macro/record":
SaveMacro(w, r)
case "/macro/list":
ListMacros(w, r)
case "/macro/delete":
DeleteMacro(w, r)
case "/macro/play":
PlayMacro("", w, r)
case "/device/list":
DeviceList(w, r)
case "/device/access/check":
DeviceAccessCheck(w, r)
case "/device/access/request":
DeviceAccessRequest(w, r)
case "/device/link/ping":
PingLink(w, r)
case "/device/link/start":
StartLink(w, r)
case "/device/link/poll":
PollLink(w, r)
case "/device/link/remove":
RemoveLink("", w, r)
case "/device/handshake":
Handshake(w, r)
}
}
func ApiAuth(data string, w http.ResponseWriter, r *http.Request) {
log.Println("apiauth", data != "")
switch r.URL.Path {
case "/macro/play":
PlayMacro(data, w, r)
case "/device/link/remove":
RemoveLink(data, w, r)
}
}

View file

@ -1,245 +0,0 @@
package app
import (
"be/app/helper"
"be/app/structs"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
func DeviceList(w http.ResponseWriter, r *http.Request) {
log.Println("device list")
dir := "devices"
files, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
devices := make(map[string]map[string]interface{})
for _, file := range files {
filePath := dir + "/" + file.Name()
ext := filepath.Ext(filePath)
device := strings.TrimSuffix(file.Name(), ext)
log.Println(device, ext)
if _, ok := devices[device]; !ok {
devices[device] = make(map[string]interface{})
}
if ext == ".json" {
devices[device]["settings"] = readDeviceSettings(filePath)
}
if ext == ".key" {
devices[device]["key"] = true
}
}
result := map[string]interface{}{
"devices": devices,
}
json.NewEncoder(w).Encode(result)
}
func readDeviceSettings(filepath string) (settings structs.Settings) {
data, err := os.ReadFile(filepath)
if err != nil {
log.Println(err)
}
err = json.Unmarshal(data, &settings)
if err != nil {
log.Println(err)
}
log.Println(settings)
return settings
}
func DeviceAccessCheck(w http.ResponseWriter, r *http.Request) {
log.Println("device access check")
var req structs.Check
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
_, errSett := os.Stat("devices/" + req.Uuid + ".json")
_, errKey := os.Stat("devices/" + req.Uuid + ".key")
if (errSett == nil) && (errKey == nil) {
log.Println("authorized")
json.NewEncoder(w).Encode("authorized")
} else if (errSett == nil) && (errKey != nil) {
log.Println("unauthorized")
json.NewEncoder(w).Encode("unauthorized")
} else {
log.Println("unauthorized")
json.NewEncoder(w).Encode("unlinked")
}
return
}
func DeviceAccessRequest(w http.ResponseWriter, r *http.Request) {
var req structs.Request
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
deviceSettings := structs.Settings{Name: req.Name, Type: req.Type}
settingsJSON, err := json.Marshal(deviceSettings)
if err != nil {
log.Println(err)
return
}
err = os.WriteFile("devices/"+req.Uuid+".json", settingsJSON, 0644)
if err != nil {
log.Println(err)
return
}
json.NewEncoder(w).Encode("unauthorized")
}
func PingLink(w http.ResponseWriter, r *http.Request) {
log.Println("ping link")
var req structs.Check
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
json.NewEncoder(w).Encode(false)
return
}
key, keyErr := os.ReadFile("devices/" + req.Uuid + ".key")
pin, pinErr := os.ReadFile("devices/" + req.Uuid + ".tmp")
encryptedKey, encErr := helper.EncryptAES(string(pin), string(key))
log.Println(encryptedKey, string(pin), string(key))
if keyErr == nil && pinErr == nil && encErr == nil {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(encryptedKey))
return
}
json.NewEncoder(w).Encode(false)
}
func StartLink(w http.ResponseWriter, r *http.Request) {
log.Println("start link")
var req structs.Check
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
pin := fmt.Sprintf("%04d", rand.Intn(10000))
deviceKey := helper.GenerateKey()
err = helper.SaveDeviceKey(req.Uuid, deviceKey)
if err == nil && helper.TempPinFile(req.Uuid, pin) {
json.NewEncoder(w).Encode(pin)
}
return
}
func PollLink(w http.ResponseWriter, r *http.Request) {
var req structs.Check
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
json.NewEncoder(w).Encode(false)
return
}
if helper.CheckPinFile(req.Uuid) {
json.NewEncoder(w).Encode(true)
return
}
json.NewEncoder(w).Encode(false)
}
func RemoveLink(data string, w http.ResponseWriter, r *http.Request) {
req := &structs.Check{}
_, err := helper.ParseRequest(req, data, r)
if err != nil {
json.NewEncoder(w).Encode(false)
return
}
err = os.Remove("devices/" + req.Uuid + ".key")
if err != nil {
json.NewEncoder(w).Encode(false)
return
}
json.NewEncoder(w).Encode(true)
}
func Handshake(w http.ResponseWriter, r *http.Request) {
var req structs.Handshake
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return
}
deviceKey, err := helper.GetKeyByUuid(req.Uuid)
if err != nil {
json.NewEncoder(w).Encode(false)
return
}
decryptShake, _ := helper.DecryptAES(deviceKey, req.Shake)
if decryptShake == getDateStr() {
os.Remove("devices/" + req.Uuid + ".tmp")
json.NewEncoder(w).Encode(true)
return
} else {
os.Remove("devices/" + req.Uuid + ".key")
}
json.NewEncoder(w).Encode(false)
}
func getDateStr() string {
date := time.Now()
year, month, day := date.Date()
formattedDate := fmt.Sprintf("%04d%02d%02d", year, month, day)
return formattedDate
}

View file

@ -1,102 +0,0 @@
package helper
import (
"encoding/json"
"log"
"net"
"net/http"
"strings"
"be/app/structs"
. "be/app/structs"
)
func EndpointAccess(w http.ResponseWriter, r *http.Request) (bool, string) {
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
log.Fatal(err)
}
if (isLocal(ip) && isEndpointAllowed("Local", r.URL.Path)) ||
(isLanRemote(ip) && isEndpointAllowed("Remote", r.URL.Path)) {
log.Println(r.URL.Path, "endpoint access: accessible")
return true, ""
} else if isLanRemote(ip) && isEndpointAllowed("Auth", r.URL.Path) {
log.Println(r.URL.Path, "endpoint access: authorized")
data := decryptAuth(r)
return data != "", data
}
log.Println(r.URL.Path, "endpoint access: not authorized or accessible")
return false, ""
}
func isLocal(ip string) bool {
return ip == "127.0.0.1" || ip == "::1"
}
func isLanRemote(ip string) bool {
return strings.HasPrefix(ip, "192.168.")
}
func isEndpointAllowed(source string, endpoint string) bool {
var endpoints, err = getAllowedEndpoints(source)
if err != "" {
log.Println(err)
}
if (endpoints != nil) && (len(endpoints) > 0) {
for _, e := range endpoints {
if e == endpoint {
return true
}
}
}
return false
}
func getAllowedEndpoints(source string) (endpoints []string, err string) {
if source == "Local" {
return Endpoints.Local, ""
}
if source == "Remote" {
return Endpoints.Remote, ""
}
if source == "Auth" {
return Endpoints.Auth, ""
}
return []string{}, "No allowed endpoints"
}
func decryptAuth(r *http.Request) string {
var req structs.Authcall
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil || req.Uuid == "" || req.Data == "" {
return ""
}
deviceKey, errKey := GetKeyByUuid(req.Uuid)
decryptData, errDec := DecryptAES(deviceKey, req.Data)
if errKey != nil && errDec != nil || decryptData == "" {
return ""
}
return decryptData
}
func ParseRequest(req interface{}, data string, r *http.Request) (d interface{}, err error) {
if data != "" {
dataBytes := []byte(data)
return req, json.Unmarshal(dataBytes, &req)
} else {
return req, json.NewDecoder(r.Body).Decode(&req)
}
}

View file

@ -1,23 +0,0 @@
package helper
import (
"os/exec"
"runtime"
)
func OpenBrowser(url string) bool {
var args []string
switch runtime.GOOS {
case "darwin":
args = []string{"open"}
case "windows":
args = []string{"cmd", "/c", "start"}
default:
args = []string{"xdg-open"}
}
cmd := exec.Command(args[0], append(args[1:], url)...)
return cmd.Start() == nil
}

View file

@ -1,46 +0,0 @@
package helper
import (
"log"
"os"
"time"
)
func TempPinFile(Uuid string, pin string) bool {
log.Println("temp pin file", Uuid, pin)
err := os.WriteFile("devices/"+Uuid+".tmp", []byte(pin), 0644)
if err != nil {
log.Println(err)
return false
}
time.AfterFunc(1*time.Minute, func() {
log.Println("deleting", Uuid, pin)
os.Remove("devices/" + Uuid + ".tmp")
})
return true
}
func CheckPinFile(Uuid string) bool {
_, err := os.Stat("devices/" + Uuid + ".tmp")
return err == nil
}
func SaveDeviceKey(Uuid string, key string) error {
err := os.WriteFile("devices/"+Uuid+".key", []byte(key), 0644)
if err != nil {
return err
}
return nil
}
func GetKeyByUuid(Uuid string) (string, error) {
data, err := os.ReadFile("devices/" + Uuid + ".key")
if err != nil {
return "", err
}
return string(data), nil
}

View file

@ -1,105 +0,0 @@
package helper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"strings"
)
func EncryptAES(key string, plaintext string) (string, error) {
origData := []byte(plaintext)
// Create AES cipher
block, err := aes.NewCipher(keyToBytes(key))
if err != nil {
return "", err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
iv := []byte(EnvGet("MCRM__IV"))
blockMode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
cryptedString := base64.StdEncoding.EncodeToString(crypted)
return cryptedString, nil
}
func DecryptAES(key string, cryptedText string) (string, error) {
crypted, err := base64.StdEncoding.DecodeString(cryptedText)
if err != nil {
return "", err
}
block, err := aes.NewCipher(keyToBytes(key))
if err != nil {
return "", err
}
iv := []byte(EnvGet("MCRM__IV"))
blockMode := cipher.NewCBCDecrypter(block, iv)
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData, err = PKCS5UnPadding(origData)
if err != nil || len(origData) <= 3 {
return "", errors.New("invalid key")
}
origDataString := string(origData)
return origDataString, nil
}
func generateRandomString(length int) string {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(b)
}
func GenerateKey() string {
return strings.Replace(generateRandomString(24), "=", "", -1)
}
func keyToBytes(key string) []byte {
// Convert key to bytes
keyBytes := []byte(key)
// If key is 4 characters, append salt
if len(key) == 4 {
keyBytes = []byte(key + EnvGet("MCRM__SALT"))
}
return keyBytes
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) ([]byte, error) {
length := len(origData)
unpadding := int(origData[length-1])
if (unpadding >= length) || (unpadding == 0) {
return nil, errors.New("unpadding error")
}
return origData[:(length - unpadding)], nil
}

View file

@ -1,16 +0,0 @@
package helper
import (
"log"
"os"
"github.com/joho/godotenv"
)
func EnvGet(key string) string {
err := godotenv.Load("../.env")
if err != nil {
log.Fatal("Error loading .env file")
}
return os.Getenv("VITE_" + key)
}

View file

@ -1,64 +0,0 @@
package helper
import (
"encoding/json"
"log"
"os"
"regexp"
"strings"
"time"
"be/app/structs"
"github.com/go-vgo/robotgo"
)
func FormatMacroFileName(s string) string {
// Remove invalid characters
re := regexp.MustCompile(`[\/\?\*\>\<\:\\"\|\n]`)
s = re.ReplaceAllString(s, "")
// Replace spaces with underscores
s = strings.ReplaceAll(s, " ", "_")
// Remove special characters
re = regexp.MustCompile(`[!@#$%^&\(\)\[\]\{\}\~]`)
s = re.ReplaceAllString(s, "")
// Truncate the string
if len(s) > 255 {
s = s[:255]
}
return s
}
func ReadMacroFile(filename string) (steps []structs.Step, err error) {
log.Println(filename)
content, err := os.ReadFile(filename)
if err != nil {
log.Fatal("Error when opening file: ", err)
}
err = json.Unmarshal(content, &steps)
return steps, err
}
func RunMacroSteps(steps []structs.Step) {
for _, step := range steps {
// log.Println(step)
switch step.Type {
case "key":
robotgo.KeyToggle(step.Key, step.Direction)
// log.Println("Toggling", step.Key, "to", step.Direction)
case "delay":
time.Sleep(time.Duration(step.Location) * time.Millisecond)
// log.Println("Sleeping for", step.Value, "milliseconds")
default:
log.Println("Unknown step type:", step.Type)
}
}
}

View file

@ -1,88 +0,0 @@
package app
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"be/app/helper"
"be/app/structs"
)
func SaveMacro(w http.ResponseWriter, r *http.Request) {
var newMacro structs.NewMacro
body, err := io.ReadAll(r.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
err = json.Unmarshal(body, &newMacro)
if err != nil {
panic(err)
}
stepsJSON, err := json.Marshal(newMacro.Steps)
if err != nil {
panic(err)
}
err = os.WriteFile("../macros/"+helper.FormatMacroFileName(newMacro.Name)+".json", stepsJSON, 0644)
if err != nil {
panic(err)
}
}
func ListMacros(w http.ResponseWriter, r *http.Request) {
log.Println("listing macros")
dir := "../macros"
files, err := os.ReadDir(dir)
if err != nil {
log.Println(err)
}
var fileNames []string
for _, file := range files {
filename := filepath.Base(file.Name())
filename = strings.TrimSuffix(filename, filepath.Ext(filename))
filename = strings.Replace(filename, "_", " ", -1)
fileNames = append(fileNames, filename)
}
json.NewEncoder(w).Encode(fileNames)
}
func DeleteMacro(w http.ResponseWriter, r *http.Request) {}
func PlayMacro(data string, w http.ResponseWriter, r *http.Request) {
req := &structs.MacroRequest{}
_, err := helper.ParseRequest(req, data, r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
macro := req.Macro
var filename = helper.FormatMacroFileName(macro)
var filepath = fmt.Sprintf("../macros/%s.json", filename)
macroFile, err := helper.ReadMacroFile(filepath)
if err != nil {
fmt.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
helper.RunMacroSteps(macroFile)
}

View file

@ -1,37 +0,0 @@
package structs
type Allowed struct {
Local []string
Remote []string
Auth []string
}
var Endpoints = Allowed{
Local: []string{
"/macro/record",
"/macro/list",
"/macro/delete",
"/macro/play",
"/device/list",
"/device/access/check",
"/device/access/request",
"/device/link/ping",
"/device/link/start",
"/device/link/poll",
"/device/link/remove",
"/device/handshake",
},
Remote: []string{
"/macro/list",
"/device/access/check",
"/device/access/request",
"/device/link/ping",
"/device/link/end",
"/device/handshake",
"/device/auth",
},
Auth: []string{
"/macro/play",
"/device/link/remove",
},
}

View file

@ -1,31 +0,0 @@
package structs
type Settings struct {
Name string `json:"name"`
Type string `json:"type"`
}
type RemoteWebhook struct {
Event string `json:"event"`
Data string `json:"data"`
}
type Check struct {
Uuid string `json:"uuid"`
}
type Request struct {
Uuid string `json:"uuid"`
Name string `json:"name"`
Type string `json:"type"`
}
type Handshake struct {
Uuid string `json:"uuid"`
Shake string `json:"shake"`
}
type Authcall struct {
Uuid string `json:"uuid"`
Data string `json:"d"`
}

View file

@ -1,19 +0,0 @@
package structs
type MacroRequest struct {
Macro string `json:"macro"`
}
type Step struct {
Type string `json:"type"`
Key string `json:"key"`
Code string `json:"code"`
Location int `json:"location"`
Direction string `json:"direction"`
Value int `json:"value"`
}
type NewMacro struct {
Name string `json:"name"`
Steps []Step `json:"steps"`
}

View file

@ -1 +0,0 @@
{"name":"Unknown desktop","type":"desktop"}

View file

@ -1 +0,0 @@
3JYxP8LOq1Y2fhpgEtpXVJ3v4s3qdML3

View file

@ -1 +0,0 @@
{"name":"Unknown mobile","type":"mobile"}

View file

@ -1 +0,0 @@
4MqIbBoPsHizsWCyeqg6gd/wpQzfhc7e

View file

@ -1,38 +0,0 @@
module be
go 1.24.0
require (
github.com/go-vgo/robotgo v0.110.6
github.com/joho/godotenv v1.5.1
)
require (
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect
github.com/ebitengine/purego v0.8.2 // indirect
github.com/gen2brain/shm v0.1.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/jezek/xgb v1.1.1 // indirect
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
github.com/otiai10/gosseract v2.2.1+incompatible // indirect
github.com/otiai10/mint v1.6.3 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/robotn/xgb v0.10.0 // indirect
github.com/robotn/xgbutil v0.10.0 // indirect
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/vcaesar/gops v0.40.0 // indirect
github.com/vcaesar/imgo v0.40.2 // indirect
github.com/vcaesar/keycode v0.10.1 // indirect
github.com/vcaesar/tt v0.20.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.31.0 // indirect
)

View file

@ -1,80 +0,0 @@
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U=
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU=
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ=
github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-vgo/robotgo v0.110.6 h1:1tOxlmTXYg6F3Xs8IT++331MxY2nZ+Q3B6eW312llbo=
github.com/go-vgo/robotgo v0.110.6/go.mod h1:eBUjTHY1HYjzdi1+UWJUbxB+b9gE+l4Ei7vQU/9SnLw=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c h1:1IlzDla/ZATV/FsRn1ETf7ir91PHS2mrd4VMunEtd9k=
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I=
github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE=
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM=
github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw=
github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU=
github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs=
github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 h1:wAZbkTZkqDzWsqxPh2qkBd3KvFU7tcxV0BP0Rnhkxog=
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8=
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM=
github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM=
github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM=
github.com/vcaesar/imgo v0.40.2/go.mod h1:MVCl+FxHI2gTgmiHoi0n5xNCbYcfv9SVtdEOUC92+eo=
github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw=
github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>404 - BALLS</title>
<style>
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<h1>Balls found</h1>
<span>So not the content you're looking for.</span>
</body>
</html>

View file

@ -1,162 +0,0 @@
package macro
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/go-vgo/robotgo"
)
type Step struct {
Type string `json:"type"`
Key string `json:"key"`
Code string `json:"code"`
Location int `json:"location"`
Direction string `json:"direction"`
Value int `json:"value"`
}
var newMacro struct {
Name string `json:"name"`
Steps []Step `json:"steps"`
}
func Save(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
err = json.Unmarshal(body, &newMacro)
if err != nil {
panic(err)
}
stepsJSON, err := json.Marshal(newMacro.Steps)
if err != nil {
panic(err)
}
err = os.WriteFile("../macros/"+makeValidFilename(newMacro.Name)+".json", stepsJSON, 0644)
if err != nil {
panic(err)
}
}
func makeValidFilename(s string) string {
// Remove invalid characters
re := regexp.MustCompile(`[\/\?\*\>\<\:\\"\|\n]`)
s = re.ReplaceAllString(s, "")
// Replace spaces with underscores
s = strings.ReplaceAll(s, " ", "_")
// Remove special characters
re = regexp.MustCompile(`[!@#$%^&\(\)\[\]\{\}\~]`)
s = re.ReplaceAllString(s, "")
// Truncate the string
if len(s) > 255 {
s = s[:255]
}
return s
}
func List(w http.ResponseWriter, r *http.Request) {
log.Println("listing macros")
dir := "../macros"
files, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
var fileNames []string
for _, file := range files {
filename := filepath.Base(file.Name())
filename = strings.TrimSuffix(filename, filepath.Ext(filename))
filename = strings.Replace(filename, "_", " ", -1)
fileNames = append(fileNames, filename)
}
json.NewEncoder(w).Encode(fileNames)
}
func Delete(w http.ResponseWriter, r *http.Request) {}
func Play(w http.ResponseWriter, r *http.Request) {
type MacroRequest struct {
Macro string `json:"macro"`
}
var req MacroRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
macro := req.Macro
macroFile, err := readMacroFile(fmt.Sprintf("../macros/%s.json", makeValidFilename(macro)))
if err != nil {
fmt.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
playMacro(macroFile)
// fmt.Println(macroFile)
}
func readMacroFile(filename string) (steps []Step, err error) {
log.Println(filename)
// Let's first read the `config.json` file
content, err := os.ReadFile(filename)
if err != nil {
log.Fatal("Error when opening file: ", err)
}
// Now let's unmarshall the data into `steps`
err = json.Unmarshal(content, &steps)
if err != nil {
log.Fatal("Error during Unmarshal(): ", err)
}
return steps, nil
}
func playMacro(steps []Step) {
for _, step := range steps {
// log.Println(step)
switch step.Type {
case "key":
robotgo.KeyToggle(step.Key, step.Direction)
// log.Println("Toggling", step.Key, "to", step.Direction)
case "delay":
time.Sleep(time.Duration(step.Location) * time.Millisecond)
// log.Println("Sleeping for", step.Value, "milliseconds")
default:
log.Println("Unknown step type:", step.Type)
}
}
}

View file

@ -1,26 +0,0 @@
package main
import (
"log"
"net/http"
"be/app"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
apiInit(w, r)
})
log.Println(http.ListenAndServe(":6970", nil))
}
func apiInit(w http.ResponseWriter, r *http.Request) {
app.ApiCORS(w, r)
if r.Method == "GET" {
app.ApiGet(w, r)
} else if r.Method == "POST" {
app.ApiPost(w, r)
}
}

View file

@ -1 +0,0 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

Binary file not shown.

View file

@ -1,4 +0,0 @@
html,
body {
background-color: white;
}

View file

@ -0,0 +1,9 @@
[
{ "code": "lalt", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "f4", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lalt", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "f4", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,13 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "w", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "w", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "w", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "w", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "p", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "p", "direction": "up", "type": "key" }
]

9
macros/TEST-Files.json Normal file
View file

@ -0,0 +1,9 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "e", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "e", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1 @@
[{"code":"f11","direction":"down","type":"key"},{"type":"delay","value":15},{"code":"f11","direction":"up","type":"key"}]

9
macros/TEST-Home.json Normal file
View file

@ -0,0 +1,9 @@
[
{ "code": "lalt", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "home", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "home", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lalt", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,13 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 50 },
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 50 },
{ "code": "d", "direction": "down", "type": "key" },
{ "type": "delay", "value": 50 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 50 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 50 },
{ "code": "d", "direction": "up", "type": "key" }
]

9
macros/TEST-New_Tab.json Normal file
View file

@ -0,0 +1,9 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "t", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "t", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "n", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "n", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1 @@
[{"code":"audio_play|audio_pause","direction":"down","type":"key"},{"type":"delay","value":15},{"code":"audio_play|audio_pause","direction":"up","type":"key"}]

View file

@ -0,0 +1,13 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "r", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "r", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "i", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "i", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,13 @@
[
{ "code": "lctrl", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "esc", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "esc", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lshift", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lctrl", "direction": "up", "type": "key" }
]

View file

@ -0,0 +1,9 @@
[
{ "code": "lcmd", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "down", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "lcmd", "direction": "up", "type": "key" },
{ "type": "delay", "value": 15 },
{ "code": "tab", "direction": "up", "type": "key" }
]

View file

@ -1 +0,0 @@
[{"type":"key","key":"Control","code":"ControlLeft","location":1,"direction":"down","value":0},{"type":"delay","key":"","code":"","location":0,"direction":"","value":15},{"type":"key","key":"Shift","code":"ShiftLeft","location":1,"direction":"down","value":0},{"type":"delay","key":"","code":"","location":0,"direction":"","value":15},{"type":"key","key":"Escape","code":"Escape","location":0,"direction":"down","value":0},{"type":"delay","key":"","code":"","location":0,"direction":"","value":15},{"type":"key","key":"Escape","code":"Escape","location":0,"direction":"up","value":0},{"type":"delay","key":"","code":"","location":0,"direction":"","value":15},{"type":"key","key":"Shift","code":"ShiftLeft","location":1,"direction":"up","value":0},{"type":"delay","key":"","code":"","location":0,"direction":"","value":15},{"type":"key","key":"Control","code":"ControlLeft","location":1,"direction":"up","value":0}]

View file

@ -1,913 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
<title>Document</title>
<link rel="stylesheet" href="./output.css" />
</head>
<body id="panel-html__body" class="relative m-0">
<div
class="absolute inset-0 bg-slate-950 size-full grid grid-cols-[1fr_2fr_1fr] gap-2 p-2"
>
<div class="group-left">
<div id="menu-spacer" class="size-16"></div>
<div id="maps" class="ed-panel pnl__blue">
<h3>Maps</h3>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
class="ed-button btn__yellow btn__vertical"
id="System__map"
mcrm__button
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g style="fill: currentColor">
<circle cx="21.6" cy="17.1" r="0.9" />
<circle cx="21.6" cy="14.6" r="0.9" />
<circle cx="21.6" cy="12" r="0.9" />
<circle cx="15.4" cy="12" r="0.9" />
<circle cx="15.4" cy="7.9" r="1.9" />
<circle cx="21.6" cy="7.9" r="1.9" />
<circle cx="5.9" cy="7.6" r="5.4" />
<circle cx="5.9" cy="19.2" r="2.6" />
</g>
</svg>
System
</div>
<div
class="ed-button btn__orange btn__vertical"
id="Galaxy__map"
mcrm__button
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
style="fill: currentColor"
d="M22.1,8.9c-0.3,0-0.6,0.1-0.9,0.3L17,4.9c0.2-0.4,0.3-0.8,0.3-1.3c0-1.6-1.3-2.8-2.8-2.8S11.7,2,11.7,3.6
c0,0.8,0.4,1.6,0.9,2.1l-5.5,7.9c-0.5-0.2-1.1-0.3-1.7-0.3c-2.7,0-5,2.2-5,5s2.2,5,5,5s5-2.2,5-5c0-1.6-0.7-3-1.9-3.9l4.8-8.2
c0.3,0.2,0.7,0.2,1.1,0.2c0.6,0,1.1-0.2,1.5-0.5l4.7,3.8c-0.1,0.2-0.1,0.4-0.1,0.6c0,0.8,0.6,1.4,1.4,1.4s1.4-0.6,1.4-1.4
C23.5,9.6,22.9,8.9,22.1,8.9z"
/>
</svg>
Galaxy
</div>
</div>
</div>
<div id="fsd" class="ed-panel pnl__yellow">
<h3>Frame Shift Drive</h3>
<div
id="FSD__toggle"
class="ed-button btn__blue !rounded-b-none"
mcrm__button
>
Toggle FSD
</div>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
id="Super__Cruise"
class="!rounded-tl-none ed-button btn__yellow"
mcrm__button
>
Super Cruise
</div>
<div
id="Hyper__Space"
class="!rounded-tr-none ed-button btn__orange"
mcrm__button
>
Hyper Space
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-2">
<div
id="mode-switch"
class="grid gap-2 justify-items-center ed-panel pnl__white"
>
<h4>Mode</h4>
<span>Analysis</span>
<div
id="Mode__toggle"
class="ed-toggle toggle__vertical"
inactive-wrapper="border-sky-600 bg-sky-400/30"
inactive-indicator="bg-sky-400"
active-wrapper="border-red-600 bg-red-400/30"
active-indicator="bg-red-400"
mcrm__button
toggle__button
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<span>Combat</span>
</div>
<div
id="mode-switch"
class="grid gap-2 justify-items-center ed-panel pnl__red"
>
<h4>Hardpoints</h4>
<span>Retract</span>
<div
id="Hardpoints__toggle"
class="ed-toggle toggle__vertical"
inactive-wrapper="border-sky-600 bg-sky-400/30"
inactive-indicator="bg-sky-400"
active-wrapper="border-red-600 bg-red-400/30"
active-indicator="bg-red-400"
mcrm__button
toggle__button
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<span>Deploy</span>
</div>
</div>
</div>
<div class="group-middle">
<div id="ship-panels" class="ed-panel pnl__blue">
<h3>Panels</h3>
<div class="grid-cols-4 ed-button-group__horizontal">
<div
class="ed-button btn__orange"
id="External__panel"
mcrm__button
>
External
</div>
<div class="ed-button btn__yellow" id="Comms__panel" mcrm__button>
Comms
</div>
<div class="ed-button btn__yellow" id="Roles__panel" mcrm__button>
Roles
</div>
<div
class="ed-button btn__orange"
id="Internal__panel"
mcrm__button
>
Internal
</div>
</div>
</div>
<div class="grid grid-cols-[3fr_1fr_1fr] gap-2">
<div class="ed-panel pnl__blue">
<h3>Scanner</h3>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
id="Scanner__FSS"
class="ed-button btn__blue btn__filled"
mcrm__button
>
FSS
</div>
<div
id="Scanner__DiscScan"
class="ed-button btn__blue"
mcrm__button
>
Discovery
</div>
</div>
</div>
<div
id="Route__NextSystem"
class="ed-button btn__yellow !px-2"
mcrm__button
>
<div>
<span class="text-base opacity-80">Route:</span>
<strong>Next System</strong>
</div>
</div>
<div
id="Speed_0percent"
class="ed-button btn__white !px-2"
mcrm__button
>
<div>
<span class="text-base opacity-80">Speed:</span>
<strong>0%</strong>
</div>
</div>
</div>
<div class="ed-panel pnl__red">
<h3>Fighters</h3>
<div class="grid grid-cols-[2fr_1fr] gap-2">
<div class="grid gap-2">
<div class="grid-cols-2 ed-button-group__horizontal">
<div
class="!justify-start ed-button btn__red btn__filled btn__vertical"
id="Fighter_attack"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
style="fill: currentColor"
viewBox="0 0 24 24"
>
<path
d="M12,1.5C6.5,1.5,2,8,2,11.5s1.5,4.1,1.6,5.6c0.1,1,0.9,1.7,1.8,1.6c0.1,0-0.1-0.1,0.1-0.1v-2h1.2v1.9v2.1
c0,1,0.8,1.8,1.8,1.8H12h3.5c1,0,1.8-0.8,1.8-1.8v-2.1v-1.9h1.2v2c0.2,0-0.1,0.1,0.1,0.1c0.9,0.1,1.7-0.6,1.8-1.6
c0.2-1.5,1.6-2.1,1.6-5.6S17.5,1.5,12,1.5z M10.4,11.5c-0.6,1.4-2.3,2-3.7,1.4s-2-2.3-1.4-3.7C6,7.9,7.7,9.3,9.1,10
S11,10.2,10.4,11.5z M13,15.6c-0.3,0-0.7-0.3-0.8-0.6c-0.1-0.3-0.3-0.3-0.4,0c-0.1,0.3-0.5,0.6-0.8,0.6s-0.3-0.9,0.1-1.9l0.3-0.8
c0.4-1,0.9-1,1.3,0l0.3,0.8C13.3,14.7,13.3,15.6,13,15.6z M17.3,12.9c-1.4,0.6-3,0-3.7-1.4c-0.6-1.4-0.1-1,1.3-1.6s3.1-2.1,3.7-0.7
C19.3,10.7,18.7,12.3,17.3,12.9z"
/>
</svg>
Attack
</div>
<div
class="!justify-start text-red-400 ed-button btn__red btn__vertical"
id="Fighter__engage"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<path
d="M14,4.3c2.8,0.7,5,2.9,5.7,5.7h2.1C21,6.1,17.9,3,14,2.2V4.3z"
/>
<path
d="M4.3,10C5,7.2,7.2,5,10,4.3V2.2C6.1,3,3,6.1,2.2,10H4.3z"
/>
<path
d="M10,19.7C7.2,19,5,16.8,4.3,14H2.2c0.8,3.9,3.9,7,7.8,7.8V19.7z"
/>
<path
d="M19.7,14c-0.7,2.8-2.9,5-5.7,5.7v2.1c3.9-0.8,7-3.9,7.8-7.8H19.7z"
/>
<polygon points="13,1 11,1 11,6.5 13,6.5 13,1 " />
<polygon points="6.5,11 1,11 1,13 6.5,13 6.5,11 " />
<polygon points="23,11 17.5,11 17.5,13 23,13 23,11 " />
<polygon points="13,17.5 11,17.5 11,23 13,23 13,17.5 " />
</svg>
Engage
</div>
</div>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
class="!justify-start ed-button btn__orange btn__filled btn__vertical"
id="Fighter_defend"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<path
style="opacity: 0.8"
d="M12,2.4l0.3,0.1l7.2,2.6l0.6,0.2l0,0.7c0,0.5,0.6,12.6-7.9,15.4L12,21.6l-0.3-0.1C3.2,18.6,3.8,6.6,3.8,6.1l0-0.7l0.6-0.2
l7.2-2.6L12,2.4 M12,0.3l-1,0.4L3.8,3.3L1.9,4l-0.1,2c0,0.6-0.7,14.1,9.2,17.4l0.9,0.3l0.9-0.3c9.9-3.3,9.3-16.8,9.2-17.4l-0.1-2
l-1.9-0.7L13,0.7L12,0.3L12,0.3z"
/>
<path
d="M19.2,6.1L12,3.5L4.8,6.1c0,0-0.7,11.8,7.2,14.4C19.8,17.9,19.2,6.1,19.2,6.1z"
/>
</svg>
Defend
</div>
<div
class="!justify-start text-red-400 ed-button btn__orange btn__vertical"
id="Fighter__hold"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<polygon
style="opacity: 0.8"
points="13,1 11,1 11,6.5 13,6.5 13,1 "
/>
<polygon
style="opacity: 0.8"
points="6.5,11 1,11 1,13 6.5,13 6.5,11 "
/>
<polygon
style="opacity: 0.8"
points="23,11 17.5,11 17.5,13 23,13 23,11 "
/>
<polygon
style="opacity: 0.8"
points="13,17.5 11,17.5 11,23 13,23 13,17.5 "
/>
<path
style="opacity: 0.8"
d="M6.1,20c1.1,0.8,2.5,1.5,3.9,1.8v-2.1c-0.9-0.2-1.7-0.6-2.5-1.1L6.1,20z"
/>
<path
style="opacity: 0.8"
d="M4.3,14H2.2c0.3,1.4,0.9,2.8,1.8,3.9l1.5-1.5C4.9,15.7,4.5,14.9,4.3,14z"
/>
<path
style="opacity: 0.8"
d="M7.5,5.4C8.3,4.9,9.1,4.5,10,4.3V2.2C8.6,2.5,7.2,3.1,6.1,4L7.5,5.4z"
/>
<path
style="opacity: 0.8"
d="M5.4,7.5L4,6.1C3.1,7.2,2.5,8.6,2.2,10h2.1C4.5,9.1,4.9,8.3,5.4,7.5z"
/>
<path
style="opacity: 0.8"
d="M18.6,7.5c0.5,0.7,0.9,1.6,1.1,2.5h2.1c-0.3-1.4-0.9-2.8-1.8-3.9L18.6,7.5z"
/>
<path
style="opacity: 0.8"
d="M17.9,4c-1.1-0.8-2.5-1.5-3.9-1.8v2.1c0.9,0.2,1.7,0.6,2.5,1.1L17.9,4z"
/>
<path
style="opacity: 0.8"
d="M18.6,16.5l1.5,1.5c0.8-1.1,1.5-2.5,1.8-3.9h-2.1C19.5,14.9,19.1,15.7,18.6,16.5z"
/>
<path
style="opacity: 0.8"
d="M16.5,18.6c-0.7,0.5-1.6,0.9-2.5,1.1v2.1c1.4-0.3,2.8-0.9,3.9-1.8L16.5,18.6z"
/>
<polygon
points="21.2,19.8 13.4,12 21.2,4.2 19.8,2.8 12,10.6 4.2,2.8 2.8,4.2 10.6,12 2.8,19.8 4.2,21.2 12,13.4 19.8,21.2 "
/>
</svg>
Hold
</div>
</div>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
class="!justify-start ed-button btn__blue btn__filled btn__vertical"
id="Fighter_follow"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<polygon
points="11,13 2.5,13 4.5,15 0.3,19.2 4.8,23.7 9,19.5 11,21.5 "
/>
<polygon
points="11,11 11,2.5 9,4.5 4.8,0.3 0.3,4.8 4.5,9 2.5,11 "
/>
<polygon
points="13,11 21.5,11 19.5,9 23.7,4.8 19.2,0.3 15,4.5 13,2.5 "
/>
<polygon
points="13,13 13,21.5 15,19.5 19.2,23.7 23.7,19.2 19.5,15 21.5,13 "
/>
</svg>
Follow
</div>
<div
class="!justify-start text-red-400 ed-button btn__blue btn__vertical"
id="Fighter__recall"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<path
d="M12,1C5.9,1,1,5.9,1,12s4.9,11,11,11s11-4.9,11-11S18.1,1,12,1z M12,20c-4.4,0-8-3.6-8-8c0-3,1.6-5.5,4-6.9V10H5l7,7l7-7
h-3V5.1c2.4,1.4,4,4,4,6.9C20,16.4,16.4,20,12,20z"
/>
</svg>
Recall
</div>
</div>
</div>
<div>
<div class="h-full grid-rows-3 ed-button-group__vertical">
<div
id="Fighter__wingman1"
class="ed-button btn__yellow btn__vertical"
mcrm__button
>
<span class="text-base opacity-80">Wingman</span>
<strong>#1</strong>
</div>
<div
id="Fighter__wingman2"
class="ed-button btn__yellow btn__vertical"
mcrm__button
>
<span class="text-base opacity-80">Wingman</span>
<strong>#2</strong>
</div>
<div
id="Fighter__wingman3"
class="ed-button btn__yellow btn__vertical"
mcrm__button
>
<span class="text-base opacity-80">Wingman</span>
<strong>#3</strong>
</div>
</div>
</div>
</div>
</div>
<div class="ed-panel pnl__red">
<h3>Counter Measures</h3>
<div class="grid-cols-4 ed-button-group__horizontal">
<div id="CM__Heatsink" class="ed-button btn__red" mcrm__button>
Heatsink
</div>
<div
id="CM__Chaff"
class="ed-button btn__red btn__filled"
mcrm__button
>
Chaff
</div>
<div
id="CM__ECM"
class="ed-button btn__red btn__filled"
mcrm__button
>
ECM
</div>
<div id="CM__Shieldcell" class="ed-button btn__red" mcrm__button>
Shieldcell
</div>
</div>
</div>
</div>
<div class="group-right">
<div class="ed-panel pnl__white">
<h3>Flight Assist</h3>
<div class="grid grid-cols-2 gap-2">
<div class="grid gap-2 justify-items-center">
<div
id="FlightAssist__toggle"
class="ed-toggle toggle__horizontal"
inactive-wrapper="border-red-600 bg-red-400/30"
inactive-indicator="bg-red-400"
active-wrapper="border-lime-600 bg-lime-400/30"
active-indicator="bg-lime-400"
mcrm__button
toggle__button
active="true"
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<div class="flex justify-between w-full">
<span>Off</span>
<span>On</span>
</div>
</div>
<div
id="Rotational__Correction"
class="!px-2 ed-button btn__blue w-fit"
mcrm__button
>
<span class="text-xs">Rotational Correction</span>
</div>
</div>
</div>
<div
class="grid grid-cols-2 divide-x ed-panel pnl__white divider-white !p-0"
>
<div id="light-switch" class="grid gap-2 p-2 justify-items-center">
<h4>Lights</h4>
<div
id="Lights__toggle"
class="ed-toggle toggle__horizontal"
inactive-wrapper="border-white bg-white/30"
inactive-indicator="bg-white"
active-wrapper="border-sky-600 bg-sky-400/30"
active-indicator="bg-sky-400"
mcrm__button
toggle__button
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<div class="flex justify-between w-full">
<span>Off</span>
<span>On</span>
</div>
</div>
<div id="light-switch" class="grid gap-2 p-2 justify-items-center">
<h4>Night Vis.</h4>
<div
id="NightVis__toggle"
class="ed-toggle toggle__horizontal"
inactive-wrapper="border-white bg-white/30"
inactive-indicator="bg-white"
active-wrapper="border-lime-600 bg-lime-400/30"
active-indicator="bg-lime-400"
mcrm__button
toggle__button
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<div class="flex justify-between w-full">
<span>Off</span>
<span>On</span>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-2">
<div class="grid gap-2 text-center ed-panel pnl__orange">
<h4>Silent Running</h4>
<div
id="SilentRunning__toggle"
class="ed-toggle toggle__horizontal"
inactive-wrapper="border-white bg-white/30"
inactive-indicator="bg-white"
active-wrapper="border-red-600 bg-red-400/30"
active-indicator="bg-red-400"
mcrm__button
toggle__button
>
<div class="toggle__wrapper">
<div class="toggle__indicator"></div>
</div>
</div>
<div class="flex justify-between w-full">
<span>Off</span>
<span>On</span>
</div>
</div>
<div class="flex items-center justify-between">
<div
id="Jettison__Cargo"
class="flex flex-col items-center justify-center gap-2 text-center text-white border-red-500 rounded-full border-3 bg-red-500/80 aspect-square"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z"
/>
</svg>
<span> JETTISON CARGO </span>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-2">
<div
class="ed-button btn__blue btn__vertical"
dialog-trigger="#camera-dialog"
mcrm__dialog-trigger
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
style="fill: currentColor"
>
<path
d="M22.6,9.1c-0.1-0.5-0.3-1-0.5-1.6c-1.5,0-5.3,0-6.8,0c2.3,2.3,5.1,5.1,7.3,7.3C23.1,13.1,23.1,10.9,22.6,9.1z"
/>
<path
d="M6.6,12.8c0-3.2,0-7.2,0-10.4C4.4,3.7,2.6,5.7,1.7,8C2.3,8.6,6.6,12.8,6.6,12.8z"
/>
<path
d="M12.8,17.4c-3.2,0-7.2,0-10.4,0c1.2,2.2,3.2,3.9,5.6,4.8C8.6,21.7,12.8,17.4,12.8,17.4z"
/>
<path
d="M17.4,11.2c0,3.2,0,7.2,0,10.4c2.2-1.2,3.9-3.2,4.8-5.6C21.7,15.4,17.4,11.2,17.4,11.2z"
/>
<path
d="M11.2,6.6c3.2,0,7.2,0,10.4,0c-1.2-2.2-3.2-3.9-5.6-4.8C15.4,2.3,11.2,6.6,11.2,6.6z"
/>
<path
d="M7.6,16.4h1.2c-2.3-2.3-5.1-5.1-7.3-7.3c-0.7,2.4-0.5,5.1,0.5,7.3C2.7,16.4,6.9,16.4,7.6,16.4z"
/>
<path
d="M14.3,17.4c-1.3,1.3-3.8,3.8-5.2,5.2c2.4,0.7,5.1,0.5,7.3-0.5c0-1.5,0-5.3,0-6.8C15.9,15.8,14.8,16.9,14.3,17.4z"
/>
<path
d="M14.9,1.4c-2.4-0.7-5.1-0.5-7.3,0.5c0,1.5,0,5.3,0,6.8C8.1,8.2,13.5,2.8,14.9,1.4z"
/>
</svg>
<span> CAMERA </span>
</div>
<dialog id="camera-dialog" mcrm__dialog>
<div
class="dialog__content ed-panel pnl__blue !w-fit !bg-sky-900 relative !p-4"
>
<div class="dialog__close">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="size-8"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M18 6l-12 12" />
<path d="M6 6l12 12" />
</svg>
</div>
<h4>Camera</h4>
<div class="grid grid-cols-[1fr_2fr] gap-2 mt-4">
<div
id="Camera__Suite"
class="ed-button btn__orange btn__filled btn__vertical !text-gray-800"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-gradienter"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M3.227 14c.917 4 4.497 7 8.773 7c4.277 0 7.858 -3 8.773 -7"
/>
<path
d="M20.78 10a9 9 0 0 0 -8.78 -7a8.985 8.985 0 0 0 -8.782 7"
/>
<path d="M12 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
</svg>
<span>Camera Suite</span>
</div>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
id="Previous__Camera"
class="ed-button btn__yellow !text-gray-800 btn__filled !pt-8"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M20.341 4.247l-8 7a1 1 0 0 0 0 1.506l8 7c.647 .565 1.659 .106 1.659 -.753v-14c0 -.86 -1.012 -1.318 -1.659 -.753z"
/>
<path
d="M9.341 4.247l-8 7a1 1 0 0 0 0 1.506l8 7c.647 .565 1.659 .106 1.659 -.753v-14c0 -.86 -1.012 -1.318 -1.659 -.753z"
/>
</svg>
<div class="relative text-right w-28">
<span
class="absolute right-0 text-base opacity-90 bottom-full"
>
Previous
</span>
<strong>Camera</strong>
</div>
</div>
<div
id="Next__Camera"
class="!pt-8 ed-button btn__yellow"
mcrm__button
>
<div class="relative text-left w-28">
<span class="absolute text-base opacity-80 bottom-full">
Next
</span>
<strong>Camera</strong>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M2 5v14c0 .86 1.012 1.318 1.659 .753l8 -7a1 1 0 0 0 0 -1.506l-8 -7c-.647 -.565 -1.659 -.106 -1.659 .753z"
/>
<path
d="M13 5v14c0 .86 1.012 1.318 1.659 .753l8 -7a1 1 0 0 0 0 -1.506l-8 -7c-.647 -.565 -1.659 -.106 -1.659 .753z"
/>
</svg>
</div>
</div>
<div
id="Free__Camera"
class="ed-button btn__orange btn__vertical"
mcrm__button
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M18 9l3 3l-3 3" />
<path d="M15 12h6" />
<path d="M6 9l-3 3l3 3" />
<path d="M3 12h6" />
<path d="M9 18l3 3l3 -3" />
<path d="M12 15v6" />
<path d="M15 6l-3 -3l-3 3" />
<path d="M12 3v6" />
</svg>
<span>Free Camera</span>
</div>
<div class="grid-cols-2 ed-button-group__horizontal">
<div
id="Camera__Pos1"
class="ed-button btn__yellow !text-gray-800 btn__filled btn__vertical"
mcrm__button
>
<span class="text-base opacity-80">Position</span>
<strong>#1</strong>
</div>
<div
id="Camera__Pos2"
class="ed-button btn__yellow btn__vertical"
mcrm__button
>
<span class="text-base opacity-80">Position</span>
<strong>#2</strong>
</div>
</div>
</div>
</div>
</dialog>
</div>
<div class="flex items-end justify-end h-28">
<div id="clock">
<div class="hours-minutes"></div>
<sup class="seconds"></sup>
</div>
</div>
</div>
</div>
<script>
function onPanelLoaded() {
document
.querySelectorAll("#panel-html__body [toggle__button]")
.forEach((toggleButton) => {
if (toggleButton.getAttribute("active")) {
toggleClasses(toggleButton, true);
} else {
toggleClasses(toggleButton, false);
}
toggleButton.addEventListener("click", (e) => {
if (!toggleButton.getAttribute("active")) {
toggleButton.setAttribute("active", true);
toggleClasses(toggleButton, true);
} else {
toggleButton.removeAttribute("active");
toggleClasses(toggleButton, false);
}
});
});
function toggleClasses(toggleButton, active) {
const wrapper = toggleButton.querySelector(".toggle__wrapper");
const indicator = toggleButton.querySelector(".toggle__indicator");
const stateClasses = getStateClasses(toggleButton);
if (active) {
wrapper.classList.remove(...stateClasses.wrapper.inactive);
wrapper.classList.add(...stateClasses.wrapper.active);
indicator.classList.remove(...stateClasses.indicator.inactive);
indicator.classList.add(...stateClasses.indicator.active);
} else {
wrapper.classList.remove(...stateClasses.wrapper.active);
wrapper.classList.add(...stateClasses.wrapper.inactive);
indicator.classList.remove(...stateClasses.indicator.active);
indicator.classList.add(...stateClasses.indicator.inactive);
}
}
function getStateClasses(toggleButton) {
return {
wrapper: {
active: mapClasses(toggleButton.getAttribute("active-wrapper")),
inactive: mapClasses(
toggleButton.getAttribute("inactive-wrapper")
),
},
indicator: {
active: mapClasses(toggleButton.getAttribute("active-indicator")),
inactive: mapClasses(
toggleButton.getAttribute("inactive-indicator")
),
},
};
}
function mapClasses(classStr) {
return classStr.split(" ").map((c) => c.trim());
}
// document
// .querySelectorAll("[dialog-trigger]")
// .forEach((dialogTrigger) => {
// dialogTrigger.addEventListener("click", (e) => {
// document
// .querySelector(dialogTrigger.getAttribute("dialog-trigger"))
// .showModal();
// });
// });
// document
// .querySelectorAll("dialog, dialog .dialog__close")
// .forEach((dialogClose) => {
// const dialog = dialogClose.closest("dialog");
// dialogClose.addEventListener("click", (e) => {
// if (
// e.target.classList.contains("dialog__close") ||
// e.target.closest(".dialog__close") ||
// e.target.tagName == "DIALOG"
// ) {
// dialog.close();
// }
// });
// });
setInterval(() => {
const clockEl = document.querySelector("#clock");
const hoursMins = clockEl.querySelector(".hours-minutes");
const seconds = clockEl.querySelector(".seconds");
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const secondsStr = now.getSeconds();
hoursMins.innerHTML = formatTimeToHTML(
`${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}`
);
seconds.innerHTML = formatTimeToHTML(
secondsStr.toString().padStart(2, "0")
);
}, 1000);
function formatTimeToHTML(timeStr) {
let htmlStr = "";
timeStr.split("").forEach((char) => {
if (char === ":") htmlStr += "<i>:</i>";
else htmlStr += "<span>" + char + "</span>";
});
return htmlStr;
}
}
</script>
<script no-compile>
onPanelLoaded();
</script>
</body>
</html>

View file

@ -1,253 +0,0 @@
@import url(https://fonts.bunny.net/css?family=orbitron:400,600,800);
@layer theme, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);
@layer theme {
/* :root {
} */
}
html,
body,
#panel-html__body {
@apply relative;
}
#panel-html__body {
--font-sans: "Orbitron", sans-serif;
@apply font-sans text-sm font-light tracking-wide bg-gray-900 text-slate-50 size-full;
* {
box-sizing: border-box;
}
}
.group-left,
.group-middle,
.group-right {
@apply grid gap-2 h-fit;
}
.ed-panel {
@apply w-full p-2 border h-fit rounded-b-xl;
h3,
h4 {
@apply m-0 mb-1 font-extralight;
}
h3 {
@apply text-base;
}
h4 {
@apply text-sm;
}
&.pnl__blue {
@apply border-sky-300 bg-sky-500/30;
h3,
h4 {
@apply text-sky-100;
text-shadow: 0 0 0.2em var(--color-sky-300);
}
}
&.pnl__yellow {
@apply border-amber-300 bg-amber-500/30;
h3,
h4 {
@apply text-amber-100;
text-shadow: 0 0 0.2em var(--color-amber-300);
}
}
&.pnl__orange {
@apply border-orange-300 bg-orange-500/30;
h3,
h4 {
@apply text-orange-100;
text-shadow: 0 0 0.2em var(--color-orange-300);
}
}
&.pnl__red {
@apply border-rose-300 bg-rose-500/30;
h3,
h4 {
@apply text-rose-100;
text-shadow: 0 0 0.2em var(--color-rose-400);
}
}
&.pnl__white {
@apply border-white bg-white/20;
h3,
h4 {
@apply text-white;
text-shadow: 0 0 0.2em var(--color-white);
}
}
}
.ed-button {
@apply flex items-center justify-center px-4 py-2 text-base text-center rounded-lg border-3;
svg {
@apply block !size-5;
}
&.btn__vertical {
@apply flex-col;
}
&.btn__filled {
@apply text-gray-900;
}
&.btn__orange {
@apply text-orange-100 border-orange-400 bg-orange-500/50;
&.btn__filled {
@apply bg-orange-400;
}
}
&.btn__yellow {
@apply text-orange-100 border-amber-400 bg-amber-500/50;
&.btn__filled {
@apply bg-amber-400;
}
}
&.btn__blue {
@apply border-sky-400 bg-sky-500/50 text-sky-100;
&.btn__filled {
@apply bg-sky-500;
}
}
&.btn__red {
@apply border-rose-500 bg-rose-600/50 text-rose-100;
&.btn__filled {
@apply bg-rose-600;
}
}
&.btn__white {
@apply border-white bg-white/30;
&.btn__filled {
@apply bg-white;
}
}
}
.ed-button-group__horizontal {
@apply grid divide-x;
.ed-button {
@apply rounded-none;
&:first-child {
@apply rounded-l-lg;
}
&:last-child {
@apply rounded-r-lg;
}
}
}
.ed-button-group__vertical {
@apply grid divide-y;
.ed-button {
@apply rounded-none;
&:first-child {
@apply rounded-t-lg;
}
&:last-child {
@apply rounded-b-lg;
}
}
}
.ed-toggle {
.toggle__wrapper {
@apply relative p-1.5 border-2 rounded-full size-full;
}
.toggle__indicator {
@apply absolute transition rounded-full aspect-square;
}
&.toggle__horizontal {
@apply w-20 h-12;
.toggle__indicator {
@apply left-1.5 translate-x-0 h-[calc(100%-.75rem)];
}
&[active] .toggle__indicator {
@apply translate-x-full;
}
}
&.toggle__vertical {
@apply w-12 h-20;
.toggle__indicator {
@apply top-1.5 translate-y-0 w-[calc(100%-.75rem)];
}
&[active] .toggle__indicator {
@apply translate-y-full;
}
}
}
dialog[open] {
@apply absolute -translate-x-1/2 -translate-y-1/2 bg-transparent border-0 outline-0 top-1/2 left-1/2;
@apply backdrop:absolute backdrop:bg-black/50;
.dialog__close {
@apply absolute text-white top-3 right-3;
}
}
#clock {
@apply relative flex pr-16 text-3xl w-fit;
i {
@apply pl-1 not-italic;
}
.hours-minutes,
.seconds {
@apply flex gap-1;
}
span {
@apply inline-block w-[.75em] text-center;
}
sup {
@apply absolute right-0 w-16 pl-2 text-lg text-left opacity-80;
}
}

View file

@ -1,688 +0,0 @@
/*! tailwindcss v4.1.4 | MIT License | https://tailwindcss.com */
@import url(https://fonts.bunny.net/css?family=orbitron:400,600,800);
@layer properties;
@layer theme, utilities;
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
--color-red-400: oklch(70.4% 0.191 22.216);
--color-red-500: oklch(63.7% 0.237 25.331);
--color-red-600: oklch(57.7% 0.245 27.325);
--color-orange-100: oklch(95.4% 0.038 75.164);
--color-orange-300: oklch(83.7% 0.128 66.29);
--color-orange-400: oklch(75% 0.183 55.934);
--color-orange-500: oklch(70.5% 0.213 47.604);
--color-amber-100: oklch(96.2% 0.059 95.617);
--color-amber-300: oklch(87.9% 0.169 91.605);
--color-amber-400: oklch(82.8% 0.189 84.429);
--color-amber-500: oklch(76.9% 0.188 70.08);
--color-lime-400: oklch(84.1% 0.238 128.85);
--color-lime-600: oklch(64.8% 0.2 131.684);
--color-sky-100: oklch(95.1% 0.026 236.824);
--color-sky-300: oklch(82.8% 0.111 230.318);
--color-sky-400: oklch(74.6% 0.16 232.661);
--color-sky-500: oklch(68.5% 0.169 237.323);
--color-sky-600: oklch(58.8% 0.158 241.966);
--color-sky-900: oklch(39.1% 0.09 240.876);
--color-rose-100: oklch(94.1% 0.03 12.58);
--color-rose-300: oklch(81% 0.117 11.638);
--color-rose-400: oklch(71.2% 0.194 13.428);
--color-rose-500: oklch(64.5% 0.246 16.439);
--color-rose-600: oklch(58.6% 0.253 17.585);
--color-slate-50: oklch(98.4% 0.003 247.858);
--color-slate-950: oklch(12.9% 0.042 264.695);
--color-gray-800: oklch(27.8% 0.033 256.848);
--color-gray-900: oklch(21% 0.034 264.665);
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
--text-xs: 0.75rem;
--text-xs--line-height: calc(1 / 0.75);
--text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875);
--text-base: 1rem;
--text-base--line-height: calc(1.5 / 1);
--text-lg: 1.125rem;
--text-lg--line-height: calc(1.75 / 1.125);
--text-3xl: 1.875rem;
--text-3xl--line-height: calc(2.25 / 1.875);
--font-weight-extralight: 200;
--font-weight-light: 300;
--tracking-wide: 0.025em;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
}
@layer utilities {
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.inset-0 {
inset: calc(var(--spacing) * 0);
}
.right-0 {
right: calc(var(--spacing) * 0);
}
.bottom-full {
bottom: 100%;
}
.m-0 {
margin: calc(var(--spacing) * 0);
}
.mt-4 {
margin-top: calc(var(--spacing) * 4);
}
.flex {
display: flex;
}
.grid {
display: grid;
}
.aspect-square {
aspect-ratio: 1 / 1;
}
.size-8 {
width: calc(var(--spacing) * 8);
height: calc(var(--spacing) * 8);
}
.size-16 {
width: calc(var(--spacing) * 16);
height: calc(var(--spacing) * 16);
}
.size-full {
width: 100%;
height: 100%;
}
.h-28 {
height: calc(var(--spacing) * 28);
}
.h-full {
height: 100%;
}
.\!w-fit {
width: fit-content !important;
}
.w-28 {
width: calc(var(--spacing) * 28);
}
.w-fit {
width: fit-content;
}
.w-full {
width: 100%;
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-cols-\[1fr_2fr\] {
grid-template-columns: 1fr 2fr;
}
.grid-cols-\[1fr_2fr_1fr\] {
grid-template-columns: 1fr 2fr 1fr;
}
.grid-cols-\[2fr_1fr\] {
grid-template-columns: 2fr 1fr;
}
.grid-cols-\[3fr_1fr_1fr\] {
grid-template-columns: 3fr 1fr 1fr;
}
.grid-rows-3 {
grid-template-rows: repeat(3, minmax(0, 1fr));
}
.flex-col {
flex-direction: column;
}
.items-center {
align-items: center;
}
.items-end {
align-items: flex-end;
}
.\!justify-start {
justify-content: flex-start !important;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.justify-end {
justify-content: flex-end;
}
.justify-items-center {
justify-items: center;
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.divide-x {
:where(& > :not(:last-child)) {
--tw-divide-x-reverse: 0;
border-inline-style: var(--tw-border-style);
border-inline-start-width: calc(1px * var(--tw-divide-x-reverse));
border-inline-end-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
}
}
.rounded-full {
border-radius: calc(infinity * 1px);
}
.\!rounded-tl-none {
border-top-left-radius: 0 !important;
}
.\!rounded-tr-none {
border-top-right-radius: 0 !important;
}
.\!rounded-b-none {
border-bottom-right-radius: 0 !important;
border-bottom-left-radius: 0 !important;
}
.border-3 {
border-style: var(--tw-border-style);
border-width: 3px;
}
.border-lime-600 {
border-color: var(--color-lime-600);
}
.border-red-500 {
border-color: var(--color-red-500);
}
.border-red-600 {
border-color: var(--color-red-600);
}
.border-sky-600 {
border-color: var(--color-sky-600);
}
.border-white {
border-color: var(--color-white);
}
.\!bg-sky-900 {
background-color: var(--color-sky-900) !important;
}
.bg-lime-400 {
background-color: var(--color-lime-400);
}
.bg-lime-400\/30 {
background-color: color-mix(in srgb, oklch(84.1% 0.238 128.85) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-lime-400) 30%, transparent);
}
}
.bg-red-400 {
background-color: var(--color-red-400);
}
.bg-red-400\/30 {
background-color: color-mix(in srgb, oklch(70.4% 0.191 22.216) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-red-400) 30%, transparent);
}
}
.bg-red-500\/80 {
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 80%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-red-500) 80%, transparent);
}
}
.bg-sky-400 {
background-color: var(--color-sky-400);
}
.bg-sky-400\/30 {
background-color: color-mix(in srgb, oklch(74.6% 0.16 232.661) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-sky-400) 30%, transparent);
}
}
.bg-slate-950 {
background-color: var(--color-slate-950);
}
.bg-white {
background-color: var(--color-white);
}
.bg-white\/30 {
background-color: color-mix(in srgb, #fff 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 30%, transparent);
}
}
.\!p-0 {
padding: calc(var(--spacing) * 0) !important;
}
.\!p-4 {
padding: calc(var(--spacing) * 4) !important;
}
.p-2 {
padding: calc(var(--spacing) * 2);
}
.\!px-2 {
padding-inline: calc(var(--spacing) * 2) !important;
}
.\!pt-8 {
padding-top: calc(var(--spacing) * 8) !important;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-base {
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
}
.text-xs {
font-size: var(--text-xs);
line-height: var(--tw-leading, var(--text-xs--line-height));
}
.\!text-gray-800 {
color: var(--color-gray-800) !important;
}
.text-red-400 {
color: var(--color-red-400);
}
.text-white {
color: var(--color-white);
}
.opacity-80 {
opacity: 80%;
}
.opacity-90 {
opacity: 90%;
}
}
@layer theme;
html, body, #panel-html__body {
position: relative;
}
#panel-html__body {
--font-sans: "Orbitron", sans-serif;
width: 100%;
height: 100%;
background-color: var(--color-gray-900);
font-family: var(--font-sans);
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
--tw-font-weight: var(--font-weight-light);
font-weight: var(--font-weight-light);
--tw-tracking: var(--tracking-wide);
letter-spacing: var(--tracking-wide);
color: var(--color-slate-50);
* {
box-sizing: border-box;
}
}
.group-left, .group-middle, .group-right {
display: grid;
height: fit-content;
gap: calc(var(--spacing) * 2);
}
.ed-panel {
height: fit-content;
width: 100%;
border-bottom-right-radius: var(--radius-xl);
border-bottom-left-radius: var(--radius-xl);
border-style: var(--tw-border-style);
border-width: 1px;
padding: calc(var(--spacing) * 2);
h3, h4 {
margin: calc(var(--spacing) * 0);
margin-bottom: calc(var(--spacing) * 1);
--tw-font-weight: var(--font-weight-extralight);
font-weight: var(--font-weight-extralight);
}
h3 {
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
}
h4 {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
&.pnl__blue {
border-color: var(--color-sky-300);
background-color: color-mix(in srgb, oklch(68.5% 0.169 237.323) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-sky-500) 30%, transparent);
}
h3, h4 {
color: var(--color-sky-100);
text-shadow: 0 0 0.2em var(--color-sky-300);
}
}
&.pnl__yellow {
border-color: var(--color-amber-300);
background-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-amber-500) 30%, transparent);
}
h3, h4 {
color: var(--color-amber-100);
text-shadow: 0 0 0.2em var(--color-amber-300);
}
}
&.pnl__orange {
border-color: var(--color-orange-300);
background-color: color-mix(in srgb, oklch(70.5% 0.213 47.604) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-orange-500) 30%, transparent);
}
h3, h4 {
color: var(--color-orange-100);
text-shadow: 0 0 0.2em var(--color-orange-300);
}
}
&.pnl__red {
border-color: var(--color-rose-300);
background-color: color-mix(in srgb, oklch(64.5% 0.246 16.439) 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-rose-500) 30%, transparent);
}
h3, h4 {
color: var(--color-rose-100);
text-shadow: 0 0 0.2em var(--color-rose-400);
}
}
&.pnl__white {
border-color: var(--color-white);
background-color: color-mix(in srgb, #fff 20%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 20%, transparent);
}
h3, h4 {
color: var(--color-white);
text-shadow: 0 0 0.2em var(--color-white);
}
}
}
.ed-button {
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-lg);
border-style: var(--tw-border-style);
border-width: 3px;
padding-inline: calc(var(--spacing) * 4);
padding-block: calc(var(--spacing) * 2);
text-align: center;
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
svg {
display: block;
width: calc(var(--spacing) * 5) !important;
height: calc(var(--spacing) * 5) !important;
}
&.btn__vertical {
flex-direction: column;
}
&.btn__filled {
color: var(--color-gray-900);
}
&.btn__orange {
border-color: var(--color-orange-400);
background-color: color-mix(in srgb, oklch(70.5% 0.213 47.604) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-orange-500) 50%, transparent);
}
color: var(--color-orange-100);
&.btn__filled {
background-color: var(--color-orange-400);
}
}
&.btn__yellow {
border-color: var(--color-amber-400);
background-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-amber-500) 50%, transparent);
}
color: var(--color-orange-100);
&.btn__filled {
background-color: var(--color-amber-400);
}
}
&.btn__blue {
border-color: var(--color-sky-400);
background-color: color-mix(in srgb, oklch(68.5% 0.169 237.323) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-sky-500) 50%, transparent);
}
color: var(--color-sky-100);
&.btn__filled {
background-color: var(--color-sky-500);
}
}
&.btn__red {
border-color: var(--color-rose-500);
background-color: color-mix(in srgb, oklch(58.6% 0.253 17.585) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-rose-600) 50%, transparent);
}
color: var(--color-rose-100);
&.btn__filled {
background-color: var(--color-rose-600);
}
}
&.btn__white {
border-color: var(--color-white);
background-color: color-mix(in srgb, #fff 30%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 30%, transparent);
}
&.btn__filled {
background-color: var(--color-white);
}
}
}
.ed-button-group__horizontal {
display: grid;
:where(& > :not(:last-child)) {
--tw-divide-x-reverse: 0;
border-inline-style: var(--tw-border-style);
border-inline-start-width: calc(1px * var(--tw-divide-x-reverse));
border-inline-end-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
}
.ed-button {
border-radius: 0;
&:first-child {
border-top-left-radius: var(--radius-lg);
border-bottom-left-radius: var(--radius-lg);
}
&:last-child {
border-top-right-radius: var(--radius-lg);
border-bottom-right-radius: var(--radius-lg);
}
}
}
.ed-button-group__vertical {
display: grid;
:where(& > :not(:last-child)) {
--tw-divide-y-reverse: 0;
border-bottom-style: var(--tw-border-style);
border-top-style: var(--tw-border-style);
border-top-width: calc(1px * var(--tw-divide-y-reverse));
border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
}
.ed-button {
border-radius: 0;
&:first-child {
border-top-left-radius: var(--radius-lg);
border-top-right-radius: var(--radius-lg);
}
&:last-child {
border-bottom-right-radius: var(--radius-lg);
border-bottom-left-radius: var(--radius-lg);
}
}
}
.ed-toggle {
.toggle__wrapper {
position: relative;
width: 100%;
height: 100%;
border-radius: calc(infinity * 1px);
border-style: var(--tw-border-style);
border-width: 2px;
padding: calc(var(--spacing) * 1.5);
}
.toggle__indicator {
position: absolute;
aspect-ratio: 1 / 1;
border-radius: calc(infinity * 1px);
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
&.toggle__horizontal {
height: calc(var(--spacing) * 12);
width: calc(var(--spacing) * 20);
.toggle__indicator {
left: calc(var(--spacing) * 1.5);
height: calc(100% - .75rem);
--tw-translate-x: calc(var(--spacing) * 0);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
&[active] .toggle__indicator {
--tw-translate-x: 100%;
translate: var(--tw-translate-x) var(--tw-translate-y);
}
}
&.toggle__vertical {
height: calc(var(--spacing) * 20);
width: calc(var(--spacing) * 12);
.toggle__indicator {
top: calc(var(--spacing) * 1.5);
width: calc(100% - .75rem);
--tw-translate-y: calc(var(--spacing) * 0);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
&[active] .toggle__indicator {
--tw-translate-y: 100%;
translate: var(--tw-translate-x) var(--tw-translate-y);
}
}
}
dialog[open] {
position: absolute;
top: calc(1/2 * 100%);
left: calc(1/2 * 100%);
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
border-style: var(--tw-border-style);
border-width: 0px;
background-color: transparent;
outline-style: var(--tw-outline-style);
outline-width: 0px;
&::backdrop {
background-color: color-mix(in srgb, #000 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-black) 50%, transparent);
}
}
.dialog__close {
position: absolute;
top: calc(var(--spacing) * 3);
right: calc(var(--spacing) * 3);
color: var(--color-white);
}
}
#clock {
position: relative;
display: flex;
width: fit-content;
padding-right: calc(var(--spacing) * 16);
font-size: var(--text-3xl);
line-height: var(--tw-leading, var(--text-3xl--line-height));
i {
padding-left: calc(var(--spacing) * 1);
font-style: normal;
}
.hours-minutes, .seconds {
display: flex;
gap: calc(var(--spacing) * 1);
}
span {
display: inline-block;
width: .75em;
text-align: center;
}
sup {
position: absolute;
right: calc(var(--spacing) * 0);
width: calc(var(--spacing) * 16);
padding-left: calc(var(--spacing) * 2);
text-align: left;
font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height));
opacity: 80%;
}
}
@property --tw-divide-x-reverse {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-tracking {
syntax: "*";
inherits: false;
}
@property --tw-divide-y-reverse {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-x {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-y {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-z {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-divide-x-reverse: 0;
--tw-border-style: solid;
--tw-font-weight: initial;
--tw-tracking: initial;
--tw-divide-y-reverse: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-translate-z: 0;
--tw-outline-style: solid;
}
}
}

View file

@ -1,974 +0,0 @@
{
"name": "test_panel",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "test_panel",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@tailwindcss/cli": "^4.1.2",
"tailwindcss": "^4.1.2"
}
},
"node_modules/@parcel/watcher": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"detect-libc": "^1.0.3",
"is-glob": "^4.0.3",
"micromatch": "^4.0.5",
"node-addon-api": "^7.0.0"
},
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"@parcel/watcher-android-arm64": "2.5.1",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
"@parcel/watcher-freebsd-x64": "2.5.1",
"@parcel/watcher-linux-arm-glibc": "2.5.1",
"@parcel/watcher-linux-arm-musl": "2.5.1",
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
"@parcel/watcher-linux-arm64-musl": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-musl": "2.5.1",
"@parcel/watcher-win32-arm64": "2.5.1",
"@parcel/watcher-win32-ia32": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1"
}
},
"node_modules/@parcel/watcher-android-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-freebsd-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-ia32": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.1.4.tgz",
"integrity": "sha512-gP05Qihh+cZ2FqD5fa0WJXx3KEk2YWUYv/RBKAyiOg0V4vYVDr/xlLc0sacpnVEXM45BVUR9U2hsESufYs6YTA==",
"dev": true,
"dependencies": {
"@parcel/watcher": "^2.5.1",
"@tailwindcss/node": "4.1.4",
"@tailwindcss/oxide": "4.1.4",
"enhanced-resolve": "^5.18.1",
"mri": "^1.2.0",
"picocolors": "^1.1.1",
"tailwindcss": "4.1.4"
},
"bin": {
"tailwindcss": "dist/index.mjs"
}
},
"node_modules/@tailwindcss/node": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.4.tgz",
"integrity": "sha512-MT5118zaiO6x6hNA04OWInuAiP1YISXql8Z+/Y8iisV5nuhM8VXlyhRuqc2PEviPszcXI66W44bCIk500Oolhw==",
"dev": true,
"dependencies": {
"enhanced-resolve": "^5.18.1",
"jiti": "^2.4.2",
"lightningcss": "1.29.2",
"tailwindcss": "4.1.4"
}
},
"node_modules/@tailwindcss/oxide": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.4.tgz",
"integrity": "sha512-p5wOpXyOJx7mKh5MXh5oKk+kqcz8T+bA3z/5VWWeQwFrmuBItGwz8Y2CHk/sJ+dNb9B0nYFfn0rj/cKHZyjahQ==",
"dev": true,
"engines": {
"node": ">= 10"
},
"optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.1.4",
"@tailwindcss/oxide-darwin-arm64": "4.1.4",
"@tailwindcss/oxide-darwin-x64": "4.1.4",
"@tailwindcss/oxide-freebsd-x64": "4.1.4",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.4",
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.4",
"@tailwindcss/oxide-linux-arm64-musl": "4.1.4",
"@tailwindcss/oxide-linux-x64-gnu": "4.1.4",
"@tailwindcss/oxide-linux-x64-musl": "4.1.4",
"@tailwindcss/oxide-wasm32-wasi": "4.1.4",
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.4",
"@tailwindcss/oxide-win32-x64-msvc": "4.1.4"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.4.tgz",
"integrity": "sha512-xMMAe/SaCN/vHfQYui3fqaBDEXMu22BVwQ33veLc8ep+DNy7CWN52L+TTG9y1K397w9nkzv+Mw+mZWISiqhmlA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.4.tgz",
"integrity": "sha512-JGRj0SYFuDuAGilWFBlshcexev2hOKfNkoX+0QTksKYq2zgF9VY/vVMq9m8IObYnLna0Xlg+ytCi2FN2rOL0Sg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.4.tgz",
"integrity": "sha512-sdDeLNvs3cYeWsEJ4H1DvjOzaGios4QbBTNLVLVs0XQ0V95bffT3+scptzYGPMjm7xv4+qMhCDrkHwhnUySEzA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.4.tgz",
"integrity": "sha512-VHxAqxqdghM83HslPhRsNhHo91McsxRJaEnShJOMu8mHmEj9Ig7ToHJtDukkuLWLzLboh2XSjq/0zO6wgvykNA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.4.tgz",
"integrity": "sha512-OTU/m/eV4gQKxy9r5acuesqaymyeSCnsx1cFto/I1WhPmi5HDxX1nkzb8KYBiwkHIGg7CTfo/AcGzoXAJBxLfg==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.4.tgz",
"integrity": "sha512-hKlLNvbmUC6z5g/J4H+Zx7f7w15whSVImokLPmP6ff1QqTVE+TxUM9PGuNsjHvkvlHUtGTdDnOvGNSEUiXI1Ww==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.4.tgz",
"integrity": "sha512-X3As2xhtgPTY/m5edUtddmZ8rCruvBvtxYLMw9OsZdH01L2gS2icsHRwxdU0dMItNfVmrBezueXZCHxVeeb7Aw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.4.tgz",
"integrity": "sha512-2VG4DqhGaDSmYIu6C4ua2vSLXnJsb/C9liej7TuSO04NK+JJJgJucDUgmX6sn7Gw3Cs5ZJ9ZLrnI0QRDOjLfNQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.4.tgz",
"integrity": "sha512-v+mxVgH2kmur/X5Mdrz9m7TsoVjbdYQT0b4Z+dr+I4RvreCNXyCFELZL/DO0M1RsidZTrm6O1eMnV6zlgEzTMQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.4.tgz",
"integrity": "sha512-2TLe9ir+9esCf6Wm+lLWTMbgklIjiF0pbmDnwmhR9MksVOq+e8aP3TSsXySnBDDvTTVd/vKu1aNttEGj3P6l8Q==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
"@emnapi/runtime",
"@tybys/wasm-util",
"@emnapi/wasi-threads",
"tslib"
],
"cpu": [
"wasm32"
],
"dev": true,
"optional": true,
"dependencies": {
"@emnapi/core": "^1.4.0",
"@emnapi/runtime": "^1.4.0",
"@emnapi/wasi-threads": "^1.0.1",
"@napi-rs/wasm-runtime": "^0.2.8",
"@tybys/wasm-util": "^0.9.0",
"tslib": "^2.8.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.4.tgz",
"integrity": "sha512-VlnhfilPlO0ltxW9/BgfLI5547PYzqBMPIzRrk4W7uupgCt8z6Trw/tAj6QUtF2om+1MH281Pg+HHUJoLesmng==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.4.tgz",
"integrity": "sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"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,
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
"dev": true,
"bin": {
"detect-libc": "bin/detect-libc.js"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/enhanced-resolve": {
"version": "5.18.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"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,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"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
},
"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,
"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,
"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,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/jiti": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
"dev": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/lightningcss": {
"version": "1.29.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz",
"integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==",
"dev": true,
"dependencies": {
"detect-libc": "^2.0.3"
},
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"lightningcss-darwin-arm64": "1.29.2",
"lightningcss-darwin-x64": "1.29.2",
"lightningcss-freebsd-x64": "1.29.2",
"lightningcss-linux-arm-gnueabihf": "1.29.2",
"lightningcss-linux-arm64-gnu": "1.29.2",
"lightningcss-linux-arm64-musl": "1.29.2",
"lightningcss-linux-x64-gnu": "1.29.2",
"lightningcss-linux-x64-musl": "1.29.2",
"lightningcss-win32-arm64-msvc": "1.29.2",
"lightningcss-win32-x64-msvc": "1.29.2"
}
},
"node_modules/lightningcss-darwin-arm64": {
"version": "1.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz",
"integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-darwin-x64": {
"version": "1.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz",
"integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-freebsd-x64": {
"version": "1.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz",
"integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==",
"cpu": [
"x64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz",
"integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==",
"cpu": [
"arm"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz",
"integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==",
"cpu": [
"arm64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz",
"integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==",
"cpu": [
"arm64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz",
"integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==",
"cpu": [
"x64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz",
"integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==",
"cpu": [
"x64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz",
"integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==",
"cpu": [
"arm64"
],
"dev": true,
"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.29.2",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz",
"integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss/node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"dev": true,
"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,
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true
},
"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
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/tailwindcss": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz",
"integrity": "sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==",
"dev": true
},
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"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,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
}
}
}

View file

@ -1,16 +0,0 @@
{
"name": "test_panel",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "npx tailwindcss -i ./input.css -o ./output.css --watch"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@tailwindcss/cli": "^4.1.2",
"tailwindcss": "^4.1.2"
}
}

View file

@ -1,48 +0,0 @@
{
"dir": "",
"name": "Elite Dangerous",
"description": "A Semi Realistic button panel for Elite Dangerous, made by JaxxMoss.",
"aspectRatio": "16/10",
"macros": {
"CM__Chaff": "ED-CM-Chaff",
"CM__ECM": "ED-CM-ECM",
"CM__Heatsink": "ED-CM-Heat_Sink",
"CM__Shieldcell": "ED-CM-Schield_Cell",
"Camera__Pos1": "ED-Camera-Position1",
"Camera__Pos2": "ED-Camera-Position2",
"Camera__Suite": "ED-Camera-Suite",
"Comms__panel": "ED-Comms_Panel",
"External__panel": "ED-External_Panel",
"FSD__toggle": "ED-Toggle_FSD",
"Fighter__engage": "ED-Fighter-Engage",
"Fighter__hold": "ED-Fighter-Hold",
"Fighter__recall": "ED-Fighter-Recall",
"Fighter__wingman1": "ED-Fighter-Wingman1",
"Fighter__wingman2": "ED-Fighter-Wingman2",
"Fighter__wingman3": "ED-Fighter-Wingman3",
"Fighter_attack": "ED-Fighter-Attack",
"Fighter_defend": "ED-Fighter-Defend",
"Fighter_follow": "ED-Fighter-Follow",
"FlightAssist__toggle": "ED-Flight_Assist",
"Free__Camera": "ED-Camera-Free",
"Galaxy__map": "ED-Galaxy_Map",
"Hardpoints__toggle": "ED-Hardpoints_Switch",
"Hyper__Space": "ED-Hyperspace",
"Internal__panel": "ED-Internal_Panel",
"Jettison__Cargo": "ED-Jettison_Cargo",
"Lights__toggle": "ED-Flight_Assist",
"Mode__toggle": "ED-Mode_Switch",
"Next__Camera": "ED-Camera-Next",
"NightVis__toggle": "ED-Night_Vision",
"Previous__Camera": "ED-Camera-Previous",
"Roles__panel": "ED-Roles_Panel",
"Rotational__Correction": "ED-Rotational_Correction",
"Route__NextSystem": "ED-Route_Next_System",
"Scanner__DiscScan": "ED-Scanner_Discovery",
"Scanner__FSS": "ED-Scanner-FSS",
"SilentRunning__toggle": "ED-Silent_Running",
"Speed_0percent": "ED-0percent_Speed",
"Super__Cruise": "ED-Super_Cruise",
"System__map": "ED-System_Map"
}
}

View file

@ -1,17 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./index.html", // Ensure this path is correct
],
theme: {
extend: {},
},
safelist: [
{
pattern: /^(border|bg)-(blue|red|sky|orange|lime)-(200|400|300\/40)$/,
},
],
plugins: [],
preflight: false,
mode: "jit",
};

View file

@ -1 +1,24 @@
{"dir":"","name":"Test Panel 1","description":"This is the very first panel to be created. It is a test panel for a mobile phone.","aspectRatio":"10/20","macros":{"button_1":"Task_Manager","button_10":"Close_Browser_Window","button_11":"Previous_Tab","button_12":"Next_Tab","button_13":"Close_Tab","button_14":"New_Tab","button_15":"Fullscreen","button_16":"Home","button_2":"Close_Application","button_3":"RunDialog","button_4":"Files","button_5":"Settings","button_6":"New_Desktop","button_7":"Displays","button_8":"Task_view","button_9":"New_Window"}} {
"dir": "",
"name": "Test Panel 1",
"description": "This is the very first panel to be created. It is a test panel for a mobile phone.",
"aspectRatio": "10/20",
"macros": {
"button_1": "TEST-Task_Manager",
"button_10": "TEST-Close_Browser_Window",
"button_11": "TEST-Previous_Tab",
"button_12": "TEST-Next_Tab",
"button_13": "TEST-Close_Tab",
"button_14": "TEST-New_Tab",
"button_15": "TEST-Fullscreen",
"button_16": "TEST-Home",
"button_2": "TEST-Close_Application",
"button_3": "TEST-RunDialog",
"button_4": "TEST-Files",
"button_5": "TEST-Settings",
"button_6": "TEST-New_Desktop",
"button_7": "TEST-Displays",
"button_8": "TEST-Task_view",
"button_9": "TEST-New_Window"
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,87 +0,0 @@
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.alert[data-v-87f6de25] {
align-items: flex-start;
gap: calc(var(--spacing, .25rem) * 4);
border-radius: var(--radius-md, .375rem);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: color-mix(in oklab, var(--color-white, #fff) 10%, transparent);
background-color: color-mix(in oklab, var(--color-white, #fff) 10%, transparent);
padding: calc(var(--spacing, .25rem) * 4);
--tw-backdrop-blur: blur(var(--blur-md, 12px));
-webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
grid-template-columns: 1rem 1fr;
display: grid;
}
.alert.alert__info[data-v-87f6de25] {
background-color: color-mix(in oklab, var(--color-sky-400, oklch(.746 .16 232.661)) 40%, transparent);
color: var(--color-sky-100, oklch(.951 .026 236.824));
}
.alert.alert__success[data-v-87f6de25] {
background-color: color-mix(in oklab, var(--color-lime-400, oklch(.841 .238 128.85)) 10%, transparent);
color: var(--color-lime-400, oklch(.841 .238 128.85));
}
.alert.alert__warning[data-v-87f6de25] {
background-color: color-mix(in oklab, var(--color-amber-400, oklch(.828 .189 84.429)) 10%, transparent);
color: var(--color-amber-400, oklch(.828 .189 84.429));
}
.alert.alert__error[data-v-87f6de25] {
background-color: color-mix(in oklab, var(--color-rose-400, oklch(.712 .194 13.428)) 10%, transparent);
color: var(--color-rose-400, oklch(.712 .194 13.428));
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-backdrop-blur {
syntax: "*";
inherits: false
}
@property --tw-backdrop-brightness {
syntax: "*";
inherits: false
}
@property --tw-backdrop-contrast {
syntax: "*";
inherits: false
}
@property --tw-backdrop-grayscale {
syntax: "*";
inherits: false
}
@property --tw-backdrop-hue-rotate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-invert {
syntax: "*";
inherits: false
}
@property --tw-backdrop-opacity {
syntax: "*";
inherits: false
}
@property --tw-backdrop-saturate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-sepia {
syntax: "*";
inherits: false
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.device-overview[data-v-f4165abd] {
align-content: flex-start;
gap: calc(var(--spacing, .25rem) * 4);
display: grid;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.server-overview[data-v-3109048f] {
align-content: flex-start;
gap: calc(var(--spacing, .25rem) * 4);
display: grid;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */

View file

@ -1,106 +0,0 @@
import { D as computed, c as createElementBlock, o as openBlock, v as renderSlot, q as normalizeClass, m as ref, b as onMounted, n as onUpdated, f as createBaseVNode, h as createVNode, w as withCtx, u as unref, E as IconX } from "./index-GNAKlyBz.js";
const _hoisted_1$1 = ["href"];
const _sfc_main$1 = {
__name: "ButtonComp",
props: {
href: String,
variant: String,
size: String
},
setup(__props) {
const props = __props;
const classString = computed(() => {
let classes = "btn";
if (props.variant) classes += ` btn__${props.variant}`;
if (props.size) classes += ` btn__${props.size}`;
return classes;
});
return (_ctx, _cache) => {
return __props.href ? (openBlock(), createElementBlock("a", {
key: 0,
href: __props.href,
class: normalizeClass(classString.value)
}, [
renderSlot(_ctx.$slots, "default")
], 10, _hoisted_1$1)) : (openBlock(), createElementBlock("button", {
key: 1,
class: normalizeClass(classString.value)
}, [
renderSlot(_ctx.$slots, "default")
], 2));
};
}
};
const _hoisted_1 = { class: "dialog-container" };
const _sfc_main = {
__name: "DialogComp",
props: {
open: Boolean
},
emits: ["onOpen", "onClose", "onToggle"],
setup(__props, { expose: __expose, emit: __emit }) {
const dialog = ref(null);
const openDialog = ref();
const emit = __emit;
__expose({ toggleDialog });
const props = __props;
onMounted(() => {
if (props.open === true) toggleDialog(props.open);
});
onUpdated(() => {
if (props.open === true) toggleDialog(props.open);
});
function toggleDialog(openToggle) {
if (openToggle) {
dialog.value.showModal();
emit("onOpen");
} else {
dialog.value.close();
emit("onClose");
}
openDialog.value = openToggle;
emit("onToggle");
}
onMounted(() => {
openDialog.value = props.open;
if (dialog.value.innerHTML.includes("form")) {
dialog.value.querySelector("form").addEventListener("submit", () => {
toggleDialog();
});
}
});
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", _hoisted_1, [
createBaseVNode("div", {
class: "trigger",
onClick: _cache[0] || (_cache[0] = ($event) => toggleDialog(true))
}, [
renderSlot(_ctx.$slots, "trigger")
]),
createBaseVNode("dialog", {
ref_key: "dialog",
ref: dialog,
class: "mcrm-block block__dark"
}, [
createVNode(_sfc_main$1, {
class: "dialog__close p-0",
variant: "ghost",
size: "sm",
tabindex: "-1",
onClick: _cache[1] || (_cache[1] = ($event) => toggleDialog(false))
}, {
default: withCtx(() => [
createVNode(unref(IconX))
]),
_: 1
}),
renderSlot(_ctx.$slots, "content")
], 512)
]);
};
}
};
export {
_sfc_main$1 as _,
_sfc_main as a
};

View file

@ -1,357 +0,0 @@
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
button, .btn {
cursor: pointer;
align-items: center;
gap: calc(var(--spacing, .25rem) * 3);
border-radius: var(--radius-lg, .5rem);
border-style: var(--tw-border-style);
--tw-border-style: solid;
height: fit-content;
padding-inline: calc(var(--spacing, .25rem) * 4);
padding-block: calc(var(--spacing, .25rem) * 2);
--tw-font-weight: var(--font-weight-normal, 400);
font-weight: var(--font-weight-normal, 400);
--tw-tracking: var(--tracking-wide, .025em);
letter-spacing: var(--tracking-wide, .025em);
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
border-style: solid;
border-width: 1px;
transition: border-color .1s ease-in-out, background-color .2s;
display: flex;
}
:is(button, .btn):not(.button__subtle, .button__ghost):hover {
--tw-shadow-color: var(--color-black, #000);
}
:is(button, .btn)[disabled], :is(button, .btn).disabled {
pointer-events: none;
cursor: not-allowed;
opacity: .5;
}
:is(button, .btn) svg {
width: calc(var(--spacing, .25rem) * 5);
height: calc(var(--spacing, .25rem) * 5);
transition-property: stroke;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
--tw-duration: .4s;
--tw-ease: var(--ease-in-out, cubic-bezier(.4, 0, .2, 1));
transition-duration: .4s;
transition-timing-function: var(--ease-in-out, cubic-bezier(.4, 0, .2, 1));
}
:is(button, .btn).btn__sm svg {
width: calc(var(--spacing, .25rem) * 4);
height: calc(var(--spacing, .25rem) * 4);
}
:is(button, .btn).btn__lg svg {
width: calc(var(--spacing, .25rem) * 6);
height: calc(var(--spacing, .25rem) * 6);
}
:is(button, .btn):hover {
color: var(--color-white, #fff) !important;
}
:is(button, .btn):hover svg {
stroke: var(--color-white, #fff) !important;
}
:is(button, .btn).btn__primary {
border-color: var(--color-sky-100, oklch(.951 .026 236.824));
background-color: color-mix(in oklab, var(--color-sky-100, oklch(.951 .026 236.824)) 10%, transparent);
color: var(--color-sky-100, oklch(.951 .026 236.824));
}
:is(button, .btn).btn__primary svg {
stroke: var(--color-sky-200, oklch(.901 .058 230.902));
}
:is(button, .btn).btn__primary:hover {
border-color: var(--color-sky-300, oklch(.828 .111 230.318));
background-color: color-mix(in oklab, var(--color-sky-400, oklch(.746 .16 232.661)) 40%, transparent);
}
:is(button, .btn).btn__secondary {
border-color: var(--color-amber-100, oklch(.962 .059 95.617));
background-color: color-mix(in oklab, var(--color-amber-100, oklch(.962 .059 95.617)) 10%, transparent);
color: var(--color-amber-100, oklch(.962 .059 95.617));
}
:is(button, .btn).btn__secondary svg {
stroke: var(--color-amber-300, oklch(.879 .169 91.605));
}
:is(button, .btn).btn__secondary:hover {
border-color: var(--color-amber-400, oklch(.828 .189 84.429));
background-color: color-mix(in oklab, var(--color-amber-400, oklch(.828 .189 84.429)) 40%, transparent);
}
:is(button, .btn).btn__danger {
border-color: var(--color-rose-100, oklch(.941 .03 12.58));
background-color: color-mix(in oklab, var(--color-rose-200, oklch(.892 .058 10.001)) 20%, transparent);
color: var(--color-rose-200, oklch(.892 .058 10.001));
}
:is(button, .btn).btn__danger svg {
stroke: var(--color-rose-400, oklch(.712 .194 13.428));
}
:is(button, .btn).btn__danger:hover {
border-color: var(--color-rose-500, oklch(.645 .246 16.439));
background-color: color-mix(in oklab, var(--color-rose-400, oklch(.712 .194 13.428)) 40%, transparent);
color: var(--color-white, #fff);
}
:is(button, .btn).btn__dark {
border-color: var(--color-slate-400, oklch(.704 .04 256.788));
background-color: color-mix(in oklab, var(--color-slate-200, oklch(.929 .013 255.508)) 10%, transparent);
color: var(--color-slate-100, oklch(.968 .007 247.896));
}
:is(button, .btn).btn__dark svg {
stroke: var(--color-slate-300, oklch(.869 .022 252.894));
}
:is(button, .btn).btn__dark:hover {
border-color: var(--color-slate-200, oklch(.929 .013 255.508));
background-color: color-mix(in oklab, var(--color-slate-400, oklch(.704 .04 256.788)) 40%, transparent);
color: var(--color-white, #fff);
}
:is(button, .btn).btn__success {
border-color: var(--color-lime-100, oklch(.967 .067 122.328));
background-color: color-mix(in oklab, var(--color-lime-200, oklch(.938 .127 124.321)) 10%, transparent);
color: var(--color-lime-100, oklch(.967 .067 122.328));
}
:is(button, .btn).btn__success svg {
stroke: var(--color-lime-400, oklch(.841 .238 128.85));
}
:is(button, .btn).btn__success:hover {
border-color: var(--color-lime-500, oklch(.768 .233 130.85));
background-color: color-mix(in oklab, var(--color-lime-400, oklch(.841 .238 128.85)) 40%, transparent);
color: var(--color-white, #fff);
}
:is(button, .btn).btn__subtle {
color: var(--color-white, #fff);
background-color: #0000;
border-color: #0000;
}
@media (hover: hover) {
:is(button, .btn).btn__subtle:hover {
background-color: color-mix(in oklab, var(--color-white, #fff) 10%, transparent);
}
}
:is(button, .btn).btn__subtle:hover {
border-color: color-mix(in oklab, var(--color-white, #fff) 40%, transparent);
background-color: color-mix(in oklab, var(--color-white, #fff) 20%, transparent);
--tw-gradient-to: color-mix(in oklab, var(--color-white, #fff) 30%, transparent);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
:is(button, .btn).btn__ghost {
color: color-mix(in oklab, var(--color-white, #fff) 80%, transparent);
background-color: #0000;
border-color: #0000;
}
@media (hover: hover) {
:is(button, .btn).btn__ghost:hover {
color: var(--color-white, #fff);
}
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false
}
@property --tw-tracking {
syntax: "*";
inherits: false
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-ring-color {
syntax: "*";
inherits: false
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-duration {
syntax: "*";
inherits: false
}
@property --tw-ease {
syntax: "*";
inherits: false
}
@property --tw-gradient-position {
syntax: "*";
inherits: false
}
@property --tw-gradient-from {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-via {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-to {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-stops {
syntax: "*";
inherits: false
}
@property --tw-gradient-via-stops {
syntax: "*";
inherits: false
}
@property --tw-gradient-from-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 0%;
}
@property --tw-gradient-via-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 50%;
}
@property --tw-gradient-to-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 100%;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.dialog-container {
position: relative;
}
.dialog-container dialog {
pointer-events: none;
z-index: 50;
--tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
max-width: calc(100vw - 2rem);
translate: var(--tw-translate-x) var(--tw-translate-y);
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
color: var(--color-slate-200, oklch(.929 .013 255.508));
position: fixed;
top: 50%;
left: 50%;
}
.dialog-container dialog[open] {
pointer-events: auto;
}
.dialog-container dialog::backdrop {
background-color: color-mix(in oklab, var(--color-black, #000) 50%, transparent);
--tw-backdrop-blur: blur(var(--blur-xs, 4px));
-webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
}
.dialog-container dialog .dialog__close {
top: calc(var(--spacing, .25rem) * 4);
right: calc(var(--spacing, .25rem) * 4);
padding: calc(var(--spacing, .25rem) * 0);
color: var(--color-white, #fff);
position: absolute;
}
.dialog-container dialog .dialog__close svg {
width: calc(var(--spacing, .25rem) * 5);
height: calc(var(--spacing, .25rem) * 5);
}
.dialog__content > :first-child {
padding-right: calc(var(--spacing, .25rem) * 8);
}
@property --tw-translate-x {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-y {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-z {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-backdrop-blur {
syntax: "*";
inherits: false
}
@property --tw-backdrop-brightness {
syntax: "*";
inherits: false
}
@property --tw-backdrop-contrast {
syntax: "*";
inherits: false
}
@property --tw-backdrop-grayscale {
syntax: "*";
inherits: false
}
@property --tw-backdrop-hue-rotate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-invert {
syntax: "*";
inherits: false
}
@property --tw-backdrop-opacity {
syntax: "*";
inherits: false
}
@property --tw-backdrop-saturate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-sepia {
syntax: "*";
inherits: false
}

View file

@ -1,624 +0,0 @@
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-overview[data-v-f9a187e3] {
grid-template-rows: auto 1fr;
display: grid;
position: relative;
}
.macro-overview[data-v-f9a187e3]:after {
top: calc(var(--spacing, .25rem) * 0);
background-color: var(--color-slate-600, oklch(.446 .043 257.281));
--tw-content: "";
content: var(--tw-content);
width: 1px;
height: 100%;
position: absolute;
left: 100%;
}
.macro-overview .macro-overview__list[data-v-f9a187e3] {
align-content: flex-start;
gap: calc(var(--spacing, .25rem) * 1);
display: grid;
}
.macro-overview .macro-item[data-v-f9a187e3] {
align-items: center;
display: flex;
}
.macro-overview .macro-item button[data-v-f9a187e3] {
width: 100%;
}
@property --tw-content {
syntax: "*";
inherits: false;
initial-value: "";
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
kbd {
height: calc(var(--spacing, .25rem) * 9);
align-items: center;
gap: calc(var(--spacing, .25rem) * 2);
border-radius: var(--radius-md, .375rem);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: var(--color-slate-500, oklch(.554 .046 257.417));
background-color: var(--color-slate-700, oklch(.372 .044 257.287));
padding-block: calc(var(--spacing, .25rem) * 1);
padding-right: calc(var(--spacing, .25rem) * 2);
padding-left: calc(var(--spacing, .25rem) * 4);
font-family: var(--font-mono, "Fira Code", monospace);
font-size: var(--text-lg, 1.125rem);
line-height: var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));
--tw-font-weight: var(--font-weight-bold, 700);
font-weight: var(--font-weight-bold, 700);
white-space: nowrap;
color: var(--color-white, #fff);
text-transform: uppercase;
--tw-shadow-color: var(--color-slate-500, oklch(.554 .046 257.417));
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
box-shadow: 0 .2rem 0 .2rem var(--tw-shadow-color);
display: flex;
}
kbd:has(sup) {
padding-left: calc(var(--spacing, .25rem) * 2);
}
kbd sup {
margin-top: calc(var(--spacing, .25rem) * 1);
font-size: var(--text-xs, .75rem);
line-height: var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));
--tw-font-weight: var(--font-weight-light, 300);
font-weight: var(--font-weight-light, 300);
color: var(--color-slate-200, oklch(.929 .013 255.508));
}
kbd span.dir {
padding-left: calc(var(--spacing, .25rem) * 1);
color: var(--color-slate-200, oklch(.929 .013 255.508));
}
kbd.empty {
cursor: pointer;
border-color: var(--color-sky-300, oklch(.828 .111 230.318));
background-color: color-mix(in oklab, var(--color-sky-400, oklch(.746 .16 232.661)) 50%, transparent);
padding-right: calc(var(--spacing, .25rem) * 3);
padding-left: calc(var(--spacing, .25rem) * 3);
--tw-tracking: var(--tracking-widest, .1em);
letter-spacing: var(--tracking-widest, .1em);
--tw-shadow-color: var(--color-sky-600, oklch(.588 .158 241.966));
}
kbd.insert {
cursor: pointer;
border-color: var(--color-yellow-300, oklch(.905 .182 98.111));
background-color: color-mix(in oklab, var(--color-yellow-500, oklch(.795 .184 86.047)) 50%, transparent);
--tw-shadow-color: var(--color-yellow-600, oklch(.681 .162 75.834));
}
:has(kdb):not(.edit) kbd {
pointer-events: none;
cursor: default;
}
.edit kbd {
pointer-events: auto;
cursor: pointer;
}
.edit kbd:hover, .edit kbd.active {
border-color: var(--color-sky-400, oklch(.746 .16 232.661));
background-color: var(--color-sky-900, oklch(.391 .09 240.876));
--tw-shadow-color: var(--color-sky-700, oklch(.5 .134 242.749));
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-ring-color {
syntax: "*";
inherits: false
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-tracking {
syntax: "*";
inherits: false
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
span.delay[data-v-05e04cbb] {
cursor: default;
border-radius: var(--radius-sm, .25rem);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: var(--color-slate-400, oklch(.704 .04 256.788));
background-color: var(--color-slate-500, oklch(.554 .046 257.417));
padding-inline: calc(var(--spacing, .25rem) * 2);
padding-block: calc(var(--spacing, .25rem) * 1);
font-family: var(--font-sans, "Roboto", sans-serif);
font-size: var(--text-sm, .875rem);
line-height: var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));
--tw-font-weight: var(--font-weight-semibold, 600);
font-weight: var(--font-weight-semibold, 600);
color: var(--color-slate-950, oklch(.129 .042 264.695));
align-items: center;
display: flex;
}
span.delay.preset[data-v-05e04cbb] {
border-color: color-mix(in oklab, var(--color-amber-300, oklch(.879 .169 91.605)) 80%, transparent);
background-color: color-mix(in oklab, var(--color-amber-100, oklch(.962 .059 95.617)) 60%, transparent);
color: var(--color-amber-400, oklch(.828 .189 84.429));
}
span.delay i[data-v-05e04cbb] {
padding-left: calc(var(--spacing, .25rem) * 1);
--tw-font-weight: var(--font-weight-normal, 400);
font-weight: var(--font-weight-normal, 400);
opacity: .8;
font-style: normal;
}
.edit span.delay[data-v-05e04cbb] {
cursor: pointer;
}
.edit span.delay[data-v-05e04cbb]:hover, .edit span.delay.active[data-v-05e04cbb] {
border-color: var(--color-lime-500, oklch(.768 .233 130.85));
background-color: var(--color-lime-700, oklch(.532 .157 131.589));
color: var(--color-lime-200, oklch(.938 .127 124.321));
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-recorder__output[data-v-33cbf1af] {
top: calc(var(--spacing, .25rem) * 0);
left: calc(var(--spacing, .25rem) * 0);
align-items: center;
row-gap: calc(var(--spacing, .25rem) * 4);
height: fit-content;
padding: calc(var(--spacing, .25rem) * 4);
flex-wrap: wrap;
display: flex;
position: absolute;
}
hr.spacer[data-v-33cbf1af]:last-of-type {
display: none;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.recorder-input__container[data-v-9a99c4ac], .macro-recorder__input[data-v-9a99c4ac] {
inset: calc(var(--spacing, .25rem) * 0);
opacity: 0;
width: 100%;
height: 100%;
display: none;
position: absolute;
}
:is(.recorder-input__container, .macro-recorder__input).record[data-v-9a99c4ac] {
display: block;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.context-menu {
position: relative;
}
.context-menu .context-menu__content {
pointer-events: none;
z-index: 50;
margin-top: calc(var(--spacing, .25rem) * 2);
--tw-translate-y: -100%;
min-width: 100%;
translate: var(--tw-translate-x) var(--tw-translate-y);
border-radius: var(--radius-md, .375rem);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: color-mix(in oklab, var(--color-white, #fff) 50%, transparent);
background-color: color-mix(in oklab, var(--color-slate-100, oklch(.968 .007 247.896)) 60%, transparent);
color: var(--color-slate-800, oklch(.279 .041 260.031));
opacity: 0;
--tw-backdrop-blur: blur(var(--blur-3xl, 64px));
-webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
display: grid;
position: absolute;
top: 100%;
}
.context-menu .context-menu__content.open {
pointer-events: auto;
--tw-translate-y: calc(var(--spacing, .25rem) * 0);
translate: var(--tw-translate-x) var(--tw-translate-y);
opacity: 1;
}
.context-menu ul {
color: var(--color-slate-800, oklch(.279 .041 260.031));
}
:where(.context-menu ul > :not(:last-child)) {
--tw-divide-y-reverse: 0;
border-bottom-style: var(--tw-border-style);
border-top-style: var(--tw-border-style);
border-top-width: calc(1px * var(--tw-divide-y-reverse));
border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
border-color: var(--color-slate-300, oklch(.869 .022 252.894));
}
.context-menu ul li {
cursor: pointer;
align-items: center;
gap: calc(var(--spacing, .25rem) * 2);
padding: calc(var(--spacing, .25rem) * 2);
display: flex;
}
@media (hover: hover) {
.context-menu ul li:hover {
background-color: color-mix(in oklab, var(--color-black, #000) 10%, transparent);
}
}
.context-menu ul li svg {
width: calc(var(--spacing, .25rem) * 5);
height: calc(var(--spacing, .25rem) * 5);
}
@property --tw-translate-x {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-y {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-z {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-backdrop-blur {
syntax: "*";
inherits: false
}
@property --tw-backdrop-brightness {
syntax: "*";
inherits: false
}
@property --tw-backdrop-contrast {
syntax: "*";
inherits: false
}
@property --tw-backdrop-grayscale {
syntax: "*";
inherits: false
}
@property --tw-backdrop-hue-rotate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-invert {
syntax: "*";
inherits: false
}
@property --tw-backdrop-opacity {
syntax: "*";
inherits: false
}
@property --tw-backdrop-saturate {
syntax: "*";
inherits: false
}
@property --tw-backdrop-sepia {
syntax: "*";
inherits: false
}
@property --tw-divide-y-reverse {
syntax: "*";
inherits: false;
initial-value: 0;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
button.selected[data-v-601167b6] {
background-color: var(--color-sky-500, oklch(.685 .169 237.323));
--tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentColor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
--tw-ring-color: var(--color-sky-500, oklch(.685 .169 237.323));
--tw-ring-offset-width: 1px;
--tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-ring-color {
syntax: "*";
inherits: false
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.insert-output[data-v-d2aab140] {
margin-bottom: calc(var(--spacing, .25rem) * 4);
justify-content: center;
align-items: center;
width: 100%;
display: flex;
}
.insert-key__direction[data-v-d2aab140] {
margin-top: calc(var(--spacing, .25rem) * 6);
justify-content: center;
gap: calc(var(--spacing, .25rem) * 2);
display: flex;
}
button.selected[data-v-d2aab140] {
background-color: var(--color-sky-500, oklch(.685 .169 237.323));
--tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentColor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
--tw-ring-color: var(--color-sky-500, oklch(.685 .169 237.323));
--tw-ring-offset-width: 1px;
--tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false
}
@property --tw-ring-color {
syntax: "*";
inherits: false
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-edit__dialogs[data-v-bf9e32be] {
flex-grow: 1;
justify-content: flex-end;
display: flex;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-recorder__header[data-v-19251359] {
gap: calc(var(--spacing, .25rem) * 4);
width: 100%;
display: grid;
}
.macro-recorder__header .edit__buttons[data-v-19251359] {
justify-content: space-between;
gap: calc(var(--spacing, .25rem) * 2);
width: 100%;
display: flex;
}
.macro-recorder__header > div[data-v-19251359] {
align-items: flex-end;
gap: calc(var(--spacing, .25rem) * 2);
display: flex;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-recorder__footer[data-v-fec5e8b6] {
justify-content: space-between;
gap: calc(var(--spacing, .25rem) * 2);
display: flex;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-recorder {
height: 100%;
}
.recorder-interface {
gap: calc(var(--spacing, .25rem) * 4);
height: 100%;
transition-property: grid-template-rows;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
grid-template-rows: auto 1fr auto;
display: grid;
}
.recorder-interface__container {
border-radius: var(--radius-lg, .5rem);
border-style: var(--tw-border-style);
border-width: 1px;
border-color: var(--color-slate-600, oklch(.446 .043 257.281));
background-color: color-mix(in oklab, var(--color-slate-950, oklch(.129 .042 264.695)) 50%, transparent);
width: 100%;
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
position: relative;
overflow: auto;
}
.recorder-interface__container.record {
border-color: var(--color-rose-300, oklch(.81 .117 11.638));
background-color: color-mix(in oklab, var(--color-rose-400, oklch(.712 .194 13.428)) 10%, transparent);
}
.recorder-interface__container.edit {
border-color: var(--color-sky-300, oklch(.828 .111 230.318));
background-color: color-mix(in oklab, var(--color-sky-900, oklch(.391 .09 240.876)) 10%, transparent);
}
#macro-name {
border-color: #0000;
border-bottom-color: var(--color-slate-300, oklch(.869 .022 252.894));
width: 100%;
padding-block: calc(var(--spacing, .25rem) * 0);
font-size: var(--text-lg, 1.125rem);
line-height: var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));
outline-style: var(--tw-outline-style);
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));
transition-duration: var(--tw-duration, var(--default-transition-duration, .15s));
background-color: #0000;
border-radius: 0;
outline-width: 0;
}
#macro-name:focus {
border-color: #0000;
border-bottom-color: var(--color-sky-400, oklch(.746 .16 232.661));
background-color: color-mix(in oklab, var(--color-sky-400, oklch(.746 .16 232.661)) 10%, transparent);
}
.disabled {
pointer-events: none;
cursor: not-allowed;
opacity: .5;
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
.macro-panel__content[data-v-c7be9772] {
gap: calc(var(--spacing, .25rem) * 6);
padding-top: calc(var(--spacing, .25rem) * 2);
grid-template-columns: 25ch 1fr;
display: grid;
}

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
import { _ as _export_sfc, c as createElementBlock, o as openBlock } from "./index-GNAKlyBz.js";
const _sfc_main = {};
function _sfc_render(_ctx, _cache) {
return openBlock(), createElementBlock("div");
}
const PanelsView = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
PanelsView as default
};

View file

@ -1,9 +0,0 @@
import { _ as _export_sfc, c as createElementBlock, o as openBlock } from "./index-GNAKlyBz.js";
const _sfc_main = {};
function _sfc_render(_ctx, _cache) {
return openBlock(), createElementBlock("div");
}
const SettingsView = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
SettingsView as default
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,19 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="src/assets/Macrame-Logo-gradient.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.bunny.net" />
<link
href="https://fonts.bunny.net/css?family=fira-code:300,500,700|roboto:100,300,700"
rel="stylesheet"
/>
<title>Vite + Vue</title>
<script type="module" crossorigin src="/assets/index-GNAKlyBz.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DjeOPht9.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

View file

@ -1 +0,0 @@
exit status 1

View file

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before After
Before After

Some files were not shown because too many files have changed in this diff Show more