From e394f9d7f5968224103798bfa258b92389134dd2 Mon Sep 17 00:00:00 2001 From: lars-berger Date: Sun, 27 Oct 2024 06:30:22 +0000 Subject: [PATCH] feat: add settings UI (#132) --- .github/workflows/build.yaml | 8 +- .vscode/settings.json | 5 + Cargo.lock | 798 +++++----- .../example.zebar.json | 5 +- .../boilerplate-solid-ts/example.zebar.json | 5 +- examples/boilerplate-solid-ts/package.json | 2 +- examples/starter/vanilla.zebar.json | 5 +- examples/starter/with-glazewm.zebar.json | 5 +- examples/starter/with-komorebi.zebar.json | 5 +- packages/client-api/package.json | 6 +- packages/client-api/src/config/index.ts | 4 + .../src/config/monitor-selection.ts | 3 + .../client-api/src/config/widget-config.ts | 11 + .../client-api/src/config/widget-placement.ts | 17 + .../client-api/src/config/widget-preset.ts | 5 + .../src/desktop/desktop-commands.ts | 18 +- packages/client-api/src/desktop/widgets.ts | 30 +- packages/client-api/src/index.ts | 5 +- packages/desktop/Cargo.toml | 12 +- .../desktop/capabilities/settings-ui.json | 13 + .../capabilities/{main.json => widget.json} | 6 +- packages/desktop/package.json | 2 +- packages/desktop/src/cli.rs | 70 +- packages/desktop/src/commands.rs | 72 +- packages/desktop/src/common/length_value.rs | 43 +- packages/desktop/src/config.rs | 381 +++-- packages/desktop/src/main.rs | 296 ++-- packages/desktop/src/sys_tray.rs | 367 +++-- packages/desktop/src/widget_factory.rs | 410 +++-- packages/desktop/tauri.conf.json | 6 +- packages/settings-ui/README.md | 22 + packages/settings-ui/index.html | 22 + packages/settings-ui/package.json | 26 + packages/settings-ui/postcss.config.js | 5 + .../src/configs/WidgetConfigForm.tsx | 295 ++++ .../src/configs/WidgetConfigSidebar.tsx | 76 + .../settings-ui/src/configs/WidgetConfigs.tsx | 251 +++ packages/settings-ui/src/index.css | 85 + packages/settings-ui/src/index.tsx | 15 + packages/settings-ui/tailwind.config.cjs | 10 + packages/settings-ui/tsconfig.json | 14 + packages/settings-ui/vite.config.ts | 17 + pnpm-lock.yaml | 1379 +++++++++++++++-- resources/settings-schema.json | 11 +- resources/widget-schema.json | 8 +- 45 files changed, 3752 insertions(+), 1099 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 packages/client-api/src/config/index.ts create mode 100644 packages/client-api/src/config/monitor-selection.ts create mode 100644 packages/client-api/src/config/widget-config.ts create mode 100644 packages/client-api/src/config/widget-placement.ts create mode 100644 packages/client-api/src/config/widget-preset.ts create mode 100644 packages/desktop/capabilities/settings-ui.json rename packages/desktop/capabilities/{main.json => widget.json} (89%) create mode 100644 packages/settings-ui/README.md create mode 100644 packages/settings-ui/index.html create mode 100644 packages/settings-ui/package.json create mode 100644 packages/settings-ui/postcss.config.js create mode 100644 packages/settings-ui/src/configs/WidgetConfigForm.tsx create mode 100644 packages/settings-ui/src/configs/WidgetConfigSidebar.tsx create mode 100644 packages/settings-ui/src/configs/WidgetConfigs.tsx create mode 100644 packages/settings-ui/src/index.css create mode 100644 packages/settings-ui/src/index.tsx create mode 100644 packages/settings-ui/tailwind.config.cjs create mode 100644 packages/settings-ui/tsconfig.json create mode 100644 packages/settings-ui/vite.config.ts diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3b609c8f..7d94683d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -67,14 +67,14 @@ jobs: dotnet tool install --global AzureSignTool --version 5.0.0 - run: pnpm i + - run: pnpm run --filter zebar --filter @zebar/settings-ui build - name: Set version number shell: bash run: | - TMP_PATH=$(mktemp) - CONF_PATH=packages/desktop/tauri.conf.json - jq '.version="${{ inputs.version-number || '0.0.0' }}"' "$CONF_PATH" > "$TMP_PATH" - mv "$TMP_PATH" "$CONF_PATH" + CONF_PATH="packages/desktop/tauri.conf.json" + cat "$CONF_PATH" | jq '.version="${{ inputs.version-number || '0.0.0' }}"' > "$CONF_PATH.tmp" && \ + mv "$CONF_PATH.tmp" "$CONF_PATH" - name: Tauri build uses: tauri-apps/tauri-action@v0 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..926b40f7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "**/packages/settings-ui/**/*.css": "tailwindcss" + } +} diff --git a/Cargo.lock b/Cargo.lock index d1eafd9b..29afaccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,18 +125,22 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ashpd" -version = "0.8.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9" dependencies = [ "enumflags2", "futures-channel", "futures-util", "rand 0.8.5", + "raw-window-handle", "serde", "serde_repr", "tokio", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", "zbus", ] @@ -245,7 +249,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -274,13 +278,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -314,9 +318,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -426,9 +430,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -514,9 +518,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -589,9 +593,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -599,9 +603,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -611,14 +615,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -959,7 +963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -969,7 +973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1003,7 +1007,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1014,7 +1018,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1054,7 +1058,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1094,6 +1098,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.5", +] + [[package]] name = "dlopen2" version = "0.5.0" @@ -1125,9 +1138,15 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" version = "0.1.1" @@ -1172,9 +1191,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embed-resource" -version = "2.4.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edcacde9351c33139a41e3c97eb2334351a81a2791bebb0b243df837128f602" +checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" dependencies = [ "cc", "memchr", @@ -1223,7 +1242,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1291,9 +1310,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] @@ -1331,9 +1350,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1381,7 +1400,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1426,24 +1445,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1452,9 +1471,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1471,32 +1490,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", @@ -1617,19 +1636,6 @@ dependencies = [ "x11", ] -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows 0.48.0", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1671,7 +1677,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1759,7 +1765,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1838,7 +1844,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1853,7 +1859,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1872,7 +1878,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1887,9 +1893,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -2030,9 +2036,9 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2042,9 +2048,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -2066,9 +2072,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -2092,7 +2098,7 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "rustls", "rustls-pki-types", @@ -2109,7 +2115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.30", + "hyper 0.14.31", "native-tls", "tokio", "tokio-native-tls", @@ -2117,20 +2123,19 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -2213,12 +2218,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] @@ -2262,9 +2267,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-docker" @@ -2374,9 +2379,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -2552,15 +2557,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libgit2-sys" @@ -2584,6 +2589,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if 1.0.0", + "windows-targets 0.52.6", +] + [[package]] name = "libredox" version = "0.1.3" @@ -2629,21 +2644,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if 1.0.0", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - [[package]] name = "mac" version = "0.1.1" @@ -2731,7 +2731,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -2741,6 +2740,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -2778,16 +2778,17 @@ dependencies = [ [[package]] name = "muda" -version = "0.14.1" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba8ac4080fb1e097c2c22acae467e46e4da72d941f02e82b67a87a2a89fa38b1" +checksum = "b8123dfd4996055ac9b15a60ad263b44b01e539007523ad7a4a533a3d93b0591" dependencies = [ - "cocoa 0.26.0", "crossbeam-channel", "dpi", "gtk", "keyboard-types", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", "png", "serde", @@ -3059,7 +3060,7 @@ dependencies = [ "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3078,18 +3079,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", ] [[package]] @@ -3097,6 +3086,9 @@ name = "objc-sys" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" +dependencies = [ + "cc", +] [[package]] name = "objc2" @@ -3124,6 +3116,30 @@ dependencies = [ "objc2-quartz-core", ] +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-data" version = "0.2.2" @@ -3148,6 +3164,18 @@ dependencies = [ "objc2-metal", ] +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + [[package]] name = "objc2-encode" version = "4.0.3" @@ -3162,10 +3190,23 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", "block2", + "dispatch", "libc", "objc2", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" @@ -3192,21 +3233,71 @@ dependencies = [ ] [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-symbols" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "cc", + "objc2", + "objc2-foundation", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-ui-kit" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "objc", + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", ] [[package]] @@ -3220,9 +3311,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "open" @@ -3237,9 +3328,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -3258,7 +3349,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3269,9 +3360,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -3390,9 +3481,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "percent-encoding" @@ -3504,7 +3595,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3534,26 +3625,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -3579,9 +3650,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plist" @@ -3590,23 +3661,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", - "indexmap 2.5.0", - "quick-xml", + "indexmap 2.6.0", + "quick-xml 0.32.0", "serde", "time", ] [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", ] [[package]] @@ -3708,7 +3779,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3719,9 +3790,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -3751,6 +3822,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" version = "0.11.5" @@ -3917,9 +3997,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -3937,14 +4017,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3958,13 +4038,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -3975,9 +4055,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -3993,7 +4073,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-tls", "ipnet", "js-sys", @@ -4021,9 +4101,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -4036,7 +4116,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-rustls", "hyper-util", "ipnet", @@ -4048,7 +4128,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", @@ -4070,21 +4150,20 @@ dependencies = [ [[package]] name = "rfd" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" dependencies = [ "ashpd", - "block", - "dispatch", + "block2", "glib-sys", "gobject-sys", "gtk-sys", "js-sys", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", "raw-window-handle", "wasm-bindgen", "wasm-bindgen-futures", @@ -4143,9 +4222,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -4166,19 +4245,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -4193,9 +4271,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -4214,9 +4292,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -4233,6 +4311,7 @@ dependencies = [ "serde", "serde_json", "url", + "uuid", ] [[package]] @@ -4244,7 +4323,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4274,9 +4353,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -4339,7 +4418,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4350,14 +4429,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "6dbcf9b78a125ee667ae19388837dd12294b858d101fdd393cb9d5501ef09eb2" dependencies = [ "itoa 1.0.11", "memchr", @@ -4384,14 +4463,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -4410,15 +4489,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -4428,14 +4507,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4444,7 +4523,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "itoa 1.0.11", "ryu", "serde", @@ -4666,15 +4745,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "state" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -4732,7 +4802,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4765,9 +4835,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -4861,9 +4931,9 @@ dependencies = [ [[package]] name = "tao" -version = "0.30.1" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e7ede56f9ef03a0bb384c7b2bed4f3985ee7f3f79ec887c50d8466eec21096" +checksum = "a0dbbebe82d02044dfa481adca1550d6dd7bd16e086bc34fa0fbecceb5a63751" dependencies = [ "bitflags 2.6.0", "cocoa 0.26.0", @@ -4906,7 +4976,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4917,9 +4987,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.0.0-rc.15" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3c3b1c7ac5b72d59da307b84af900a0098c74c9d7369f65018cd8ec0eb50fb" +checksum = "44438500b50708bfc1e6083844e135d1b516325aae58710dcd8fb67e050ae87c" dependencies = [ "anyhow", "bytes", @@ -4944,12 +5014,11 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.12.7", + "reqwest 0.12.8", "serde", "serde_json", "serde_repr", "serialize-to-javascript", - "state", "swift-rs", "tauri-build", "tauri-macros", @@ -4969,9 +5038,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-rc.12" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5713e81e02e0b99f5219b275abbd7d2c0cc0f30180e25b1b650e08feeac63" +checksum = "935f9b3c49b22b3e2e485a57f46d61cd1ae07b1cbb2ba87387a387caf2d8c4e7" dependencies = [ "anyhow", "cargo_toml", @@ -4991,9 +5060,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-rc.12" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5370f2591dcc93d4ff08d9dd168f5097f79b34e859883586a409c627544190e3" +checksum = "95d7443dd4f0b597704b6a14b964ee2ed16e99928d8e6292ae9825f09fbcd30e" dependencies = [ "base64 0.22.1", "brotli", @@ -5007,7 +5076,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.77", + "syn 2.0.79", "tauri-utils", "thiserror", "time", @@ -5018,23 +5087,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-rc.11" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19442dc8ee002ab1926586f6aecb90114f3a1226766008b0c9ac2d9fec9eeb7e" +checksum = "4d2c0963ccfc3f5194415f2cce7acc975942a8797fbabfb0aa1ed6f59326ae7f" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.0.0-rc.12" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3368e91a98aa55ea4e3e8ccff516bc1ed2f85872c335ec35e9b345469032e0" +checksum = "b2e6660a409963e4d57b9bfab4addd141eeff41bd3a7fb14e13004a832cf7ef6" dependencies = [ "anyhow", "glob", @@ -5049,9 +5118,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.0.0-rc.7" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785722c81beb4a6b729ae55d06aeb68d47166c933e64b727e33254dcb5d4d82d" +checksum = "ddb2fe88b602461c118722c574e2775ab26a4e68886680583874b2f6520608b7" dependencies = [ "log", "raw-window-handle", @@ -5067,9 +5136,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.0.0-rc.5" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cb1dfbbea322afbc9dec49351bc29edf4e85e74d37d9a3fcc72d67ed55ffdbd" +checksum = "ab300488ebec3487ca5f56289692e7e45feb07eea8d5e1dba497f7dc9dd9c407" dependencies = [ "anyhow", "dunce", @@ -5088,14 +5157,14 @@ dependencies = [ [[package]] name = "tauri-plugin-http" -version = "2.0.0-rc.5" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf6e753f6b98a326ab5e2d604973e761a7970dec0c0bcd5ba83ce7392623dfa8" +checksum = "784333f1632d96c94346e8145bfe52970923a38a0e6eacd3dccaa12289275acf" dependencies = [ "data-url", "http 1.1.0", "regex", - "reqwest 0.12.7", + "reqwest 0.12.8", "schemars", "serde", "serde_json", @@ -5110,9 +5179,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.0.0-rc.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83800ddf78b820172efb5ed7310344e8e4f97fd30cd8237a3f20c12a79eb136" +checksum = "371fb9aca2823990a2d0db7970573be5fdf07881fcaa2b835b29631feb84aec1" dependencies = [ "encoding_rs", "log", @@ -5131,9 +5200,9 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.0.0-rc.4" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15679effe51bd7db0038e7c5aed2d26a20b7e7c4657b6df693f5fb67af7dcaec" +checksum = "a25ac834491d089699a2bc9266a662faf373c9f779f05a2235bc6e4d9e61769a" dependencies = [ "log", "serde", @@ -5146,9 +5215,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.0-rc.12" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f38d8aaa1e81d20e8e208e3e317f81b59fb75c530fbae8a90e72d02001d687" +checksum = "c8f437293d6f5e5dce829250f4dbdce4e0b52905e297a6689cc2963eb53ac728" dependencies = [ "dpi", "gtk", @@ -5165,9 +5234,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.0-rc.13" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1ef5171e14c8fe3b5a63e75004c20d057747bc3e7fdc5f8ded625f0b29f5c7" +checksum = "1431602bcc71f2f840ad623915c9842ecc32999b867c4a787d975a17a9625cc6" dependencies = [ "gtk", "http 1.1.0", @@ -5191,9 +5260,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-rc.12" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31fe4c9148e1b35225e1c00753f24b517ce00041d02eb4b4d6fd10613a47736c" +checksum = "c38b0230d6880cf6dd07b6d7dd7789a0869f98ac12146e0d18d1c1049215a045" dependencies = [ "brotli", "cargo_metadata", @@ -5221,6 +5290,7 @@ dependencies = [ "toml 0.8.2", "url", "urlpattern", + "uuid", "walkdir", ] @@ -5236,9 +5306,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if 1.0.0", "fastrand", @@ -5266,22 +5336,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5369,7 +5439,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5445,7 +5515,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -5458,34 +5528,13 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - [[package]] name = "tower-service" version = "0.3.3" @@ -5523,7 +5572,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5577,9 +5626,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.17.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044d7738b3d50f288ddef035b793228740ad4d927f5466b0af55dc15e7e03cfe" +checksum = "7c92af36a182b46206723bdf8a7942e20838cde1cf062e5b97854d57eb01763b" dependencies = [ "core-graphics 0.24.0", "crossbeam-channel", @@ -5697,9 +5746,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -5788,11 +5837,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom 0.2.15", + "serde", ] [[package]] @@ -5872,9 +5922,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -5883,24 +5933,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5910,9 +5960,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5920,28 +5970,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -5950,11 +6000,71 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -6035,7 +6145,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6122,15 +6232,6 @@ dependencies = [ "windows-version", ] -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows" version = "0.52.0" @@ -6203,7 +6304,7 @@ checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6214,7 +6315,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6225,7 +6326,7 @@ checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6236,7 +6337,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6547,14 +6648,12 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "wry" -version = "0.43.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4d715cf5fe88e9647f3d17b207b6d060d4a88e7171d4ccb2d2c657dd1d44728" +checksum = "6fa1c8c760041c64ce6be99f83d6cb55fe3fcd85a1ad46d32895f6e65cee87ba" dependencies = [ "base64 0.22.1", - "block", - "cocoa 0.26.0", - "core-graphics 0.24.0", + "block2", "crossbeam-channel", "dpi", "dunce", @@ -6567,8 +6666,11 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", "once_cell", "percent-encoding", "raw-window-handle", @@ -6727,7 +6829,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] diff --git a/examples/boilerplate-react-buildless/example.zebar.json b/examples/boilerplate-react-buildless/example.zebar.json index 52ee6eca..f01eecae 100644 --- a/examples/boilerplate-react-buildless/example.zebar.json +++ b/examples/boilerplate-react-buildless/example.zebar.json @@ -1,13 +1,14 @@ { - "$schema": "https://github.com/glzr-io/zebar/raw/v2.1.0/resources/widget-schema.json", + "$schema": "https://github.com/glzr-io/zebar/raw/v2.4.0/resources/widget-schema.json", "htmlPath": "./index.html", "zOrder": "normal", "shownInTaskbar": false, "focused": false, "resizable": false, "transparent": false, - "defaultPlacements": [ + "presets": [ { + "name": "default", "anchor": "top_left", "offsetX": "0px", "offsetY": "0px", diff --git a/examples/boilerplate-solid-ts/example.zebar.json b/examples/boilerplate-solid-ts/example.zebar.json index baf8aa05..2d4118fb 100644 --- a/examples/boilerplate-solid-ts/example.zebar.json +++ b/examples/boilerplate-solid-ts/example.zebar.json @@ -1,13 +1,14 @@ { - "$schema": "https://github.com/glzr-io/zebar/raw/v2.1.0/resources/widget-schema.json", + "$schema": "https://github.com/glzr-io/zebar/raw/v2.4.0/resources/widget-schema.json", "htmlPath": "./dist/index.html", "zOrder": "normal", "shownInTaskbar": false, "focused": false, "resizable": false, "transparent": false, - "defaultPlacements": [ + "presets": [ { + "name": "default", "anchor": "top_left", "offsetX": "0px", "offsetY": "0px", diff --git a/examples/boilerplate-solid-ts/package.json b/examples/boilerplate-solid-ts/package.json index c489af28..7c168b27 100644 --- a/examples/boilerplate-solid-ts/package.json +++ b/examples/boilerplate-solid-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite build --watch" }, "dependencies": { - "solid-js": "1.8.11", + "solid-js": "1.9.2", "zebar": "^2.0.0" }, "devDependencies": { diff --git a/examples/starter/vanilla.zebar.json b/examples/starter/vanilla.zebar.json index 06c39939..651ff9c6 100644 --- a/examples/starter/vanilla.zebar.json +++ b/examples/starter/vanilla.zebar.json @@ -1,13 +1,14 @@ { - "$schema": "https://github.com/glzr-io/zebar/raw/v2.1.0/resources/widget-schema.json", + "$schema": "https://github.com/glzr-io/zebar/raw/v2.4.0/resources/widget-schema.json", "htmlPath": "./vanilla.html", "zOrder": "normal", "shownInTaskbar": false, "focused": false, "resizable": false, "transparent": false, - "defaultPlacements": [ + "presets": [ { + "name": "default", "anchor": "top_left", "offsetX": "0px", "offsetY": "0px", diff --git a/examples/starter/with-glazewm.zebar.json b/examples/starter/with-glazewm.zebar.json index d4a389bb..02c5d616 100644 --- a/examples/starter/with-glazewm.zebar.json +++ b/examples/starter/with-glazewm.zebar.json @@ -1,13 +1,14 @@ { - "$schema": "https://github.com/glzr-io/zebar/raw/v2.1.0/resources/widget-schema.json", + "$schema": "https://github.com/glzr-io/zebar/raw/v2.4.0/resources/widget-schema.json", "htmlPath": "./with-glazewm.html", "zOrder": "normal", "shownInTaskbar": false, "focused": false, "resizable": false, "transparent": false, - "defaultPlacements": [ + "presets": [ { + "name": "default", "anchor": "top_left", "offsetX": "0px", "offsetY": "0px", diff --git a/examples/starter/with-komorebi.zebar.json b/examples/starter/with-komorebi.zebar.json index 9fcb867b..c7a14481 100644 --- a/examples/starter/with-komorebi.zebar.json +++ b/examples/starter/with-komorebi.zebar.json @@ -1,13 +1,14 @@ { - "$schema": "https://github.com/glzr-io/zebar/raw/v2.1.0/resources/widget-schema.json", + "$schema": "https://github.com/glzr-io/zebar/raw/v2.4.0/resources/widget-schema.json", "htmlPath": "./with-komorebi.html", "zOrder": "normal", "shownInTaskbar": false, "focused": false, "resizable": false, "transparent": false, - "defaultPlacements": [ + "presets": [ { + "name": "default", "anchor": "top_left", "offsetX": "0px", "offsetY": "0px", diff --git a/packages/client-api/package.json b/packages/client-api/package.json index c9de5fff..4ef397dc 100644 --- a/packages/client-api/package.json +++ b/packages/client-api/package.json @@ -25,9 +25,9 @@ "prepublishOnly": "npm run build" }, "dependencies": { - "@tauri-apps/api": "2.0.0-rc.5", - "@tauri-apps/plugin-dialog": "2.0.0-rc.1", - "@tauri-apps/plugin-shell": "2.0.0-rc.1", + "@tauri-apps/api": "2.0.2", + "@tauri-apps/plugin-dialog": "2.0.0", + "@tauri-apps/plugin-shell": "2.0.0", "glazewm": "1.6.0", "luxon": "3.4.4", "zod": "3.22.4" diff --git a/packages/client-api/src/config/index.ts b/packages/client-api/src/config/index.ts new file mode 100644 index 00000000..1706edf9 --- /dev/null +++ b/packages/client-api/src/config/index.ts @@ -0,0 +1,4 @@ +export * from './monitor-selection'; +export * from './widget-config'; +export * from './widget-placement'; +export * from './widget-preset'; diff --git a/packages/client-api/src/config/monitor-selection.ts b/packages/client-api/src/config/monitor-selection.ts new file mode 100644 index 00000000..a8e3a9f9 --- /dev/null +++ b/packages/client-api/src/config/monitor-selection.ts @@ -0,0 +1,3 @@ +export type MonitorSelection = { + type: 'all' | 'primary' | 'secondary'; +}; diff --git a/packages/client-api/src/config/widget-config.ts b/packages/client-api/src/config/widget-config.ts new file mode 100644 index 00000000..4a85d8ae --- /dev/null +++ b/packages/client-api/src/config/widget-config.ts @@ -0,0 +1,11 @@ +import type { WidgetPreset } from './widget-preset'; + +export type WidgetConfig = { + htmlPath: string; + zOrder: 'normal' | 'top_most' | 'bottom_most'; + shownInTaskbar: boolean; + focused: boolean; + resizable: boolean; + transparent: boolean; + presets: WidgetPreset[]; +}; diff --git a/packages/client-api/src/config/widget-placement.ts b/packages/client-api/src/config/widget-placement.ts new file mode 100644 index 00000000..5f5f9731 --- /dev/null +++ b/packages/client-api/src/config/widget-placement.ts @@ -0,0 +1,17 @@ +import type { MonitorSelection } from './monitor-selection'; + +export type WidgetPlacement = { + anchor: + | 'top_left' + | 'top_center' + | 'top_right' + | 'center' + | 'bottom_left' + | 'bottom_center' + | 'bottom_right'; + offsetX: string; + offsetY: string; + width: string; + height: string; + monitorSelection: MonitorSelection; +}; diff --git a/packages/client-api/src/config/widget-preset.ts b/packages/client-api/src/config/widget-preset.ts new file mode 100644 index 00000000..ddc800ee --- /dev/null +++ b/packages/client-api/src/config/widget-preset.ts @@ -0,0 +1,5 @@ +import type { WidgetPlacement } from './widget-placement'; + +export type WidgetPreset = { + name: string; +} & WidgetPlacement; diff --git a/packages/client-api/src/desktop/desktop-commands.ts b/packages/client-api/src/desktop/desktop-commands.ts index bc45979e..4df3de77 100644 --- a/packages/client-api/src/desktop/desktop-commands.ts +++ b/packages/client-api/src/desktop/desktop-commands.ts @@ -5,19 +5,31 @@ import { import { createLogger } from '../utils'; import type { ProviderConfig } from '~/providers'; +import type { WidgetPlacement } from '~/config'; const logger = createLogger('desktop-commands'); export const desktopCommands = { - openWidgetDefault, + startWidget, + startPreset, listenProvider, unlistenProvider, setAlwaysOnTop, setSkipTaskbar, }; -function openWidgetDefault(configPath: string): Promise { - return invoke('open_widget_default', { configPath }); +function startWidget( + configPath: string, + placement: WidgetPlacement, +): Promise { + return invoke('start_widget', { configPath, placement }); +} + +function startPreset( + configPath: string, + presetName: string, +): Promise { + return invoke('start_preset', { configPath, presetName }); } function listenProvider(args: { diff --git a/packages/client-api/src/desktop/widgets.ts b/packages/client-api/src/desktop/widgets.ts index dc996e14..3f81b9bd 100644 --- a/packages/client-api/src/desktop/widgets.ts +++ b/packages/client-api/src/desktop/widgets.ts @@ -1,6 +1,7 @@ import { join } from '@tauri-apps/api/path'; import { desktopCommands } from './desktop-commands'; +import type { WidgetPlacement } from '~/config'; export interface Widget { /** @@ -44,11 +45,14 @@ export function currentWidget(): Widget { } /** - * Opens a widget by its config path. Uses its default placements. + * Opens a widget by its config path and chosen placement. * * Config path is relative within the Zebar config directory. */ -export async function openWidgetDefault(configPath: string) { +export async function startWidget( + configPath: string, + placement: WidgetPlacement, +) { // Ensure the config path ends with '.zebar.json'. const filePath = configPath.endsWith('.zebar.json') ? configPath @@ -60,5 +64,25 @@ export async function openWidgetDefault(configPath: string) { filePath, ); - return desktopCommands.openWidgetDefault(absolutePath); + return desktopCommands.startWidget(absolutePath, placement); +} + +/** + * Opens a widget by its config path and a preset name. + * + * Config path is relative within the Zebar config directory. + */ +export async function startPreset(configPath: string, presetName: string) { + // Ensure the config path ends with '.zebar.json'. + const filePath = configPath.endsWith('.zebar.json') + ? configPath + : `${configPath}.zebar.json`; + + const absolutePath = await join( + getWidgetState().configPath, + '../', + filePath, + ); + + return desktopCommands.startPreset(absolutePath, presetName); } diff --git a/packages/client-api/src/index.ts b/packages/client-api/src/index.ts index 3f42d41b..23106cd4 100644 --- a/packages/client-api/src/index.ts +++ b/packages/client-api/src/index.ts @@ -1,8 +1,9 @@ -export * from './providers'; +export * from './config'; export { currentWidget, currentWindow, - openWidgetDefault, + startPreset, type Widget, type Window, } from './desktop'; +export * from './providers'; diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index 3fd1a879..1b56d76b 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -10,23 +10,23 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "2.0.0-rc", features = [] } +tauri-build = { version = "2.0", features = [] } [dependencies] anyhow = "1" async-trait = "0.1" clap = { version = "4", features = ["derive"] } reqwest = { version = "0.11", features = ["json"] } -tauri = { version = "2.0.0-rc", features = [ +tauri = { version = "2.0", features = [ "devtools", "macos-private-api", "protocol-asset", "tray-icon", ] } -tauri-plugin-dialog = "2.0.0-rc" -tauri-plugin-http = "2.0.0-rc" -tauri-plugin-shell = "2.0.0-rc" -tauri-plugin-single-instance = "2.0.0-rc" +tauri-plugin-dialog = "2.0" +tauri-plugin-http = "2.0" +tauri-plugin-shell = "2.0" +tauri-plugin-single-instance = "2.0" serde = { version = "1", features = ["derive"] } serde_json = "1" starship-battery = "0.8" diff --git a/packages/desktop/capabilities/settings-ui.json b/packages/desktop/capabilities/settings-ui.json new file mode 100644 index 00000000..ba90b3d4 --- /dev/null +++ b/packages/desktop/capabilities/settings-ui.json @@ -0,0 +1,13 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "settings-ui", + "description": "Settings UI capabilities", + "windows": ["settings"], + "permissions": [ + "core:app:default", + "core:event:default", + "core:path:allow-resolve-directory", + "core:path:default", + "core:window:default" + ] +} diff --git a/packages/desktop/capabilities/main.json b/packages/desktop/capabilities/widget.json similarity index 89% rename from packages/desktop/capabilities/main.json rename to packages/desktop/capabilities/widget.json index b454387d..ffab5a3a 100644 --- a/packages/desktop/capabilities/main.json +++ b/packages/desktop/capabilities/widget.json @@ -1,8 +1,8 @@ { "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Default capabilities", - "windows": ["*"], + "identifier": "widget", + "description": "Widget capabilities", + "windows": ["widget-*"], "remote": { "urls": ["http://asset.localhost", "asset://localhost"] }, diff --git a/packages/desktop/package.json b/packages/desktop/package.json index fb96cac1..0089c250 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -10,7 +10,7 @@ }, "dependencies": {}, "devDependencies": { - "@tauri-apps/cli": "2.0.0-rc.16", + "@tauri-apps/cli": "2.0.3", "typescript": "5.3.3" } } diff --git a/packages/desktop/src/cli.rs b/packages/desktop/src/cli.rs index 2b35ae16..9ae9d529 100644 --- a/packages/desktop/src/cli.rs +++ b/packages/desktop/src/cli.rs @@ -1,6 +1,8 @@ use std::{path::PathBuf, process}; -use clap::{Args, Parser, Subcommand}; +use clap::{Args, Parser, Subcommand, ValueEnum}; + +use crate::{common::LengthValue, config::AnchorPoint}; const VERSION: &'static str = env!("VERSION_NUMBER"); @@ -19,13 +21,21 @@ impl Cli { #[derive(Clone, Debug, PartialEq, Subcommand)] pub enum CliCommand { - /// Opens a widget by its config path. Uses its default placements. + /// Opens a widget by its config path and chosen placement. /// /// Config path is relative within the Zebar config directory (e.g. - /// `zebar open-widget-default ./material/config.yaml`). + /// `zebar start-widget --path starter/vanilla`). /// /// Starts Zebar if it is not already running. - OpenWidgetDefault(OpenWidgetDefaultArgs), + StartWidget(StartWidgetArgs), + + /// Opens a widget by its config path and a preset name. + /// + /// Config path is relative within the Zebar config directory (e.g. + /// `zebar start-preset --path start/vanilla --preset default`). + /// + /// Starts Zebar if it is not already running. + StartPreset(StartPresetArgs), /// Opens all widgets that are set to launch on startup. /// @@ -47,16 +57,56 @@ pub enum CliCommand { } #[derive(Args, Clone, Debug, PartialEq)] -pub struct OpenWidgetDefaultArgs { +pub struct StartWidgetArgs { /// Relative file path to widget config within the Zebar config /// directory. + #[clap(long = "path", value_hint = clap::ValueHint::FilePath)] pub config_path: PathBuf, - /// Absolute or relative path to the Zebar config directory. - /// - /// The default path is `%userprofile%/.glzr/zebar/` - #[clap(long, value_hint = clap::ValueHint::FilePath)] - pub config_dir: Option, + /// Anchor-point of the widget. + #[clap(long)] + pub anchor: AnchorPoint, + + /// Offset from the anchor-point. + #[clap(long)] + pub offset_x: LengthValue, + + /// Offset from the anchor-point. + #[clap(long)] + pub offset_y: LengthValue, + + /// Width of the widget in % or physical pixels. + #[clap(long)] + pub width: LengthValue, + + /// Height of the widget in % or physical pixels. + #[clap(long)] + pub height: LengthValue, + + /// Monitor(s) to place the widget on. + #[clap(long)] + pub monitor_type: MonitorType, +} + +/// TODO: Add support for `Index` and `Name` types. +#[derive(Clone, Debug, PartialEq, ValueEnum)] +#[clap(rename_all = "snake_case")] +pub enum MonitorType { + All, + Primary, + Secondary, +} + +#[derive(Args, Clone, Debug, PartialEq)] +pub struct StartPresetArgs { + /// Relative file path to widget config within the Zebar config + /// directory. + #[clap(long = "path", value_hint = clap::ValueHint::FilePath)] + pub config_path: PathBuf, + + /// Name of the preset within the target widget config. + #[clap(long = "preset")] + pub preset_name: String, } #[derive(Args, Clone, Debug, PartialEq)] diff --git a/packages/desktop/src/commands.rs b/packages/desktop/src/commands.rs index 2168aee3..fe439fb4 100644 --- a/packages/desktop/src/commands.rs +++ b/packages/desktop/src/commands.rs @@ -1,30 +1,78 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; use tauri::{State, Window}; use crate::{ common::WindowExt, - config::Config, + config::{Config, WidgetConfig, WidgetPlacement}, providers::{ProviderConfig, ProviderManager}, - widget_factory::WidgetFactory, + widget_factory::{WidgetFactory, WidgetOpenOptions, WidgetState}, }; #[tauri::command] -pub async fn open_widget_default( - config_path: String, +pub async fn widget_configs( config: State<'_, Arc>, +) -> Result, String> { + Ok(config.widget_configs().await) +} + +#[tauri::command] +pub async fn widget_states( + widget_factory: State<'_, Arc>, +) -> Result, String> { + Ok(widget_factory.states().await) +} + +#[tauri::command] +pub async fn start_widget( + config_path: String, + placement: WidgetPlacement, widget_factory: State<'_, Arc>, ) -> anyhow::Result<(), String> { - let widget_config = config - .widget_config_by_path(&PathBuf::from(config_path)) + widget_factory + .start_widget( + &PathBuf::from(config_path), + &WidgetOpenOptions::Standalone(placement), + ) .await - .and_then(|opt| { - opt.ok_or_else(|| anyhow::anyhow!("Widget config not found.")) - }) - .map_err(|err| err.to_string())?; + .map_err(|err| err.to_string()) +} +#[tauri::command] +pub async fn start_preset( + config_path: String, + preset_name: String, + widget_factory: State<'_, Arc>, +) -> anyhow::Result<(), String> { widget_factory - .open(widget_config) + .start_widget( + &PathBuf::from(config_path), + &WidgetOpenOptions::Preset(preset_name), + ) + .await + .map_err(|err| err.to_string()) +} + +#[tauri::command] +pub async fn stop_preset( + config_path: String, + preset_name: String, + widget_factory: State<'_, Arc>, +) -> anyhow::Result<(), String> { + widget_factory + .stop_by_preset(&PathBuf::from(config_path), &preset_name) + .await + .map_err(|err| err.to_string()) +} + +#[tauri::command] +pub async fn update_widget_config( + config_path: String, + new_config: WidgetConfig, + config: State<'_, Arc>, +) -> Result<(), String> { + config + .update_widget_config(&PathBuf::from(config_path), new_config) .await .map_err(|err| err.to_string()) } diff --git a/packages/desktop/src/common/length_value.rs b/packages/desktop/src/common/length_value.rs index b132518d..91245a7c 100644 --- a/packages/desktop/src/common/length_value.rs +++ b/packages/desktop/src/common/length_value.rs @@ -2,9 +2,9 @@ use std::str::FromStr; use anyhow::{bail, Context}; use regex::Regex; -use serde::{Deserialize, Deserializer, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; -#[derive(Debug, Clone, PartialEq, Serialize)] +#[derive(Debug, Clone, PartialEq)] pub struct LengthValue { pub amount: f32, pub unit: LengthUnit, @@ -20,7 +20,9 @@ pub enum LengthUnit { impl LengthValue { pub fn to_px(&self, total_px: i32) -> i32 { match self.unit { - LengthUnit::Percentage => (self.amount * total_px as f32) as i32, + LengthUnit::Percentage => { + (self.amount / 100. * total_px as f32) as i32 + } LengthUnit::Pixel => self.amount as i32, } } @@ -65,35 +67,32 @@ impl FromStr for LengthValue { let amount = captures .get(1) .and_then(|amount_str| f32::from_str(amount_str.into()).ok()) - // Store percentage units as a fraction of 1. - .map(|amount| match unit { - LengthUnit::Pixel => amount, - LengthUnit::Percentage => amount / 100.0, - }) .context(err_msg.to_string())?; Ok(LengthValue { amount, unit }) } } -/// Deserialize a `LengthValue` from either a string or a struct. +impl Serialize for LengthValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let s = match self.unit { + LengthUnit::Percentage => format!("{}%", self.amount), + LengthUnit::Pixel => format!("{}px", self.amount), + }; + + serializer.serialize_str(&s) + } +} + impl<'de> Deserialize<'de> for LengthValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - #[derive(Deserialize)] - #[serde(untagged)] - enum LengthValueDe { - Struct { amount: f32, unit: LengthUnit }, - String(String), - } - - match LengthValueDe::deserialize(deserializer)? { - LengthValueDe::Struct { amount, unit } => Ok(Self { amount, unit }), - LengthValueDe::String(str) => { - Self::from_str(&str).map_err(serde::de::Error::custom) - } - } + let s = String::deserialize(deserializer)?; + LengthValue::from_str(&s).map_err(serde::de::Error::custom) } } diff --git a/packages/desktop/src/config.rs b/packages/desktop/src/config.rs index 39c0eff0..50bfecca 100644 --- a/packages/desktop/src/config.rs +++ b/packages/desktop/src/config.rs @@ -1,11 +1,13 @@ use std::{ + collections::HashMap, fs::{self}, path::PathBuf, sync::Arc, }; use anyhow::Context; -use serde::{Deserialize, Serialize}; +use clap::ValueEnum; +use serde::{Deserialize, Deserializer, Serialize}; use tauri::{path::BaseDirectory, AppHandle, Manager}; use tokio::sync::{broadcast, Mutex}; use tracing::{error, info}; @@ -21,8 +23,46 @@ pub struct SettingsConfig { #[serde(rename = "$schema")] schema: Option, - /// Relative paths to widget configs to launch on startup. - pub startup_configs: Vec, + /// Widget configs to be launched on startup. + pub startup_configs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct StartupConfig { + /// Relative path to widget configs to launch on startup. + pub path: PathBuf, + + /// Preset name within the widget config. + pub preset: String, +} + +// Deserializer that handles `StartupConfig` objects and string format from +// v2.3.0 and earlier. +impl<'de> Deserialize<'de> for StartupConfig { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrObject { + String(String), + Object { path: PathBuf, preset: String }, + } + + let value = StringOrObject::deserialize(deserializer)?; + + Ok(match value { + StringOrObject::String(s) => StartupConfig { + path: PathBuf::from(s), + preset: "default".to_string(), + }, + StringOrObject::Object { path, preset } => { + StartupConfig { path, preset } + } + }) + } } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -50,11 +90,13 @@ pub struct WidgetConfig { /// Whether the Tauri window frame should be transparent. pub transparent: bool, - /// Where to place the widget. - pub default_placements: Vec, + /// Where to place the widget. Add alias for `defaultPlacements` for + /// compatibility with v2.3.0 and earlier. + #[serde(alias = "defaultPlacements")] + pub presets: Vec, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "snake_case")] pub enum ZOrder { BottomMost, @@ -64,6 +106,16 @@ pub enum ZOrder { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] +pub struct WidgetPreset { + #[serde(default = "default_preset_name")] + pub name: String, + + #[serde(flatten)] + pub placement: WidgetPlacement, +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] pub struct WidgetPlacement { /// Anchor-point of the widget. pub anchor: AnchorPoint, @@ -84,7 +136,8 @@ pub struct WidgetPlacement { pub monitor_selection: MonitorSelection, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, ValueEnum)] +#[clap(rename_all = "snake_case")] #[serde(rename_all = "snake_case")] pub enum AnchorPoint { TopLeft, @@ -98,7 +151,7 @@ pub enum AnchorPoint { BottomRight, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(tag = "type", content = "match", rename_all = "snake_case")] pub enum MonitorSelection { All, @@ -120,27 +173,17 @@ pub struct Config { pub settings: Arc>, /// List of widget configs. - pub widget_configs: Arc>>, + pub widget_configs: Arc>>, _settings_change_rx: broadcast::Receiver, pub settings_change_tx: broadcast::Sender, - _widget_configs_change_rx: broadcast::Receiver>, - - pub widget_configs_change_tx: broadcast::Sender>, -} - -#[derive(Clone, Debug)] -pub struct WidgetConfigEntry { - /// Absolute path to the widget's config file. - pub config_path: PathBuf, - - /// Absolute path to the widget's HTML file. - pub html_path: PathBuf, + _widget_configs_change_rx: + broadcast::Receiver>, - /// Parsed widget config. - pub config: WidgetConfig, + pub widget_configs_change_tx: + broadcast::Sender>, } impl Config { @@ -214,10 +257,8 @@ impl Config { None => { Self::create_from_examples(app_handle, dir)?; - Ok( - Self::read_settings(&dir)? - .context("Failed to create settings config.")?, - ) + Self::read_settings(&dir)? + .context("Failed to create settings config.") } } } @@ -245,7 +286,7 @@ impl Config { fs::write( &settings_path, - serde_json::to_string_pretty(&new_settings)?, + serde_json::to_string_pretty(&new_settings)? + "\n", )?; let mut settings = self.settings.lock().await; @@ -259,79 +300,39 @@ impl Config { /// Aggregates all valid widget configs at the 2nd-level of the given /// directory (i.e. `/*/*.zebar.json`). /// - /// Returns a vector of `WidgetConfigEntry` instances. + /// Returns a hashmap of config paths to their `WidgetConfig` instances. fn read_widget_configs( dir: &PathBuf, - ) -> anyhow::Result> { - let dir_entries = fs::read_dir(dir).with_context(|| { - format!("Failed to read directory: {}", dir.display()) - })?; - - // Scan the 2nd-level of the directory for config files. - let config_files = dir_entries - .into_iter() - .filter_map(|entry| { - let path = entry.ok()?.path(); - if path.is_dir() { - Some(fs::read_dir(path).ok()?) - } else { - None - } - }) + ) -> anyhow::Result> { + let dir_paths = fs::read_dir(dir) + .with_context(|| { + format!("Failed to read directory: {}", dir.display()) + })? + .filter_map(|entry| Some(entry.ok()?.path())); + + // Scan the 2nd-level of the config directory. + let subdir_paths = dir_paths + .filter(|path| path.is_dir()) + .filter_map(|dir| fs::read_dir(dir).ok()) .flatten() - .filter_map(|entry| { - let path = entry.ok()?.path(); - if path.is_file() && has_extension(&path, ".zebar.json") { - Some(path) - } else { - None - } - }) + .filter_map(|entry| Some(entry.ok()?.path())); + + // Collect the found config files. + let config_paths = subdir_paths + .filter(|path| path.is_file() && has_extension(&path, ".zebar.json")) .collect::>(); - let mut configs = Vec::new(); + let mut configs = HashMap::new(); // Parse the found config files. - for path in config_files { - let parse_res = - read_and_parse_json::(&path).and_then(|config| { - let config_path = path.to_absolute()?; - - let html_path = path - .parent() - .and_then(|parent| { - parent.join(&config.html_path).to_absolute().ok() - }) - .with_context(|| { - format!( - "HTML file not found at {} for config {}.", - config.html_path.display(), - config_path.display() - ) - })?; - - Ok(WidgetConfigEntry { - config, - config_path, - html_path, - }) - }); - - match parse_res { - Ok(config) => { - info!( - "Found valid widget config at: {}", - config.config_path.display() - ); - - configs.push(config); + for path in config_paths { + match Self::parse_widget_config(&path) { + Ok((config_path, config)) => { + info!("Found valid widget config at: {}", config_path.display()); + configs.insert(config_path, config); } Err(err) => { - error!( - "Failed to parse config at {}: {:?}", - path.display(), - err - ); + error!("{:?}", err); } } } @@ -339,10 +340,29 @@ impl Config { Ok(configs) } + fn parse_widget_config( + config_path: &PathBuf, + ) -> anyhow::Result<(PathBuf, WidgetConfig)> { + let abs_path = config_path.to_absolute().with_context(|| { + format!("Invalid widget config path '{}'.", config_path.display()) + })?; + + let config = + read_and_parse_json::(&abs_path).map_err(|err| { + anyhow::anyhow!( + "Failed to parse widget config at '{}': {:?}", + abs_path.display(), + err + ) + })?; + + Ok((abs_path, config)) + } + /// Initializes settings and widget configs at the given path. /// - /// `settings.json` is initialized with either `starter/vanilla.json` or - /// `starter/with-glazewm.json` as startup config. Widget configs are + /// `settings.json` is initialized with either `starter/vanilla` or + /// `starter/with-glazewm` as startup config. Widget configs are /// initialized from `examples/` directory. fn create_from_examples( app_handle: &AppHandle, @@ -361,137 +381,164 @@ impl Config { copy_dir_all(&starter_path, config_dir, false)?; - let default_startup_config = match is_app_installed("glazewm") { - true => "starter/with-glazewm.zebar.json", - false => "starter/vanilla.zebar.json", - }; - let default_settings = SettingsConfig { - schema: Some("https://github.com/glzr-io/zebar/raw/v2.1.0/resources/settings-schema.json".into()), - startup_configs: vec![default_startup_config.into()], + schema: Some("https://github.com/glzr-io/zebar/raw/v2.4.0/resources/settings-schema.json".into()), + startup_configs: vec![StartupConfig { + path: match is_app_installed("glazewm") { + true => "starter/with-glazewm.zebar.json".into(), + false => "starter/vanilla.zebar.json".into(), + }, + preset: "default".into(), + }], }; let settings_path = config_dir.join("settings.json"); fs::write( &settings_path, - serde_json::to_string_pretty(&default_settings)?, + serde_json::to_string_pretty(&default_settings)? + "\n", )?; Ok(()) } - pub async fn widget_configs(&self) -> Vec { + pub async fn widget_configs(&self) -> HashMap { self.widget_configs.lock().await.clone() } /// Returns the widget configs to open on startup. - pub async fn startup_widget_configs( + pub async fn startup_configs(&self) -> Vec { + self.settings.lock().await.startup_configs.clone() + } + + /// Returns the widget configs to open on startup. + pub async fn startup_configs_by_path( &self, - ) -> anyhow::Result> { - let startup_configs = - { self.settings.lock().await.startup_configs.clone() }; - - let mut result = Vec::new(); - - for config_path in startup_configs { - let abs_config_path = self.join_config_dir(&config_path); - let config = self - .widget_config_by_path(&abs_config_path) - .await - .unwrap_or(None) - .context(format!( - "Failed to get widget config at {}.", - abs_config_path.display() - ))?; - - result.push(config); + ) -> anyhow::Result> { + self + .startup_configs() + .await + .into_iter() + .map(|config| { + self + .to_absolute_path(&config.path) + .map(|abs_path| (abs_path, config)) + }) + .collect() + } + + /// Updates the widget config at the given path. + /// + /// Config path can be either absolute or relative. + pub async fn update_widget_config( + &self, + config_path: &PathBuf, + new_config: WidgetConfig, + ) -> anyhow::Result<()> { + info!("Updating widget config at {}.", config_path.display()); + + { + let mut widget_configs = self.widget_configs.lock().await; + + let config_entry = widget_configs.get_mut(config_path).context( + format!("Widget config not found at {}.", config_path.display()), + )?; + + // Update the config in state. + *config_entry = new_config.clone(); } - Ok(result) + // Emit the changed config. + self + .widget_configs_change_tx + .send(HashMap::from([(config_path.clone(), new_config.clone())]))?; + + // Write the updated config to file. + fs::write( + &config_path, + serde_json::to_string_pretty(&new_config)? + "\n", + )?; + + Ok(()) } /// Adds the given config to be launched on startup. /// - /// Config path must be absolute. + /// Config path can be either absolute or relative. pub async fn add_startup_config( &self, config_path: &PathBuf, + preset_name: &str, ) -> anyhow::Result<()> { - let startup_configs = self.startup_widget_configs().await?; + let mut new_settings = { self.settings.lock().await.clone() }; - // Check if the config is already set to be launched on startup. - if startup_configs - .iter() - .find(|config| config.config_path == *config_path) - .is_some() - { + let startup_config = StartupConfig { + path: self.to_relative_path(config_path), + preset: preset_name.to_string(), + }; + + if new_settings.startup_configs.contains(&startup_config) { return Ok(()); } - // Add the path to startup configs. - let mut new_settings = { self.settings.lock().await.clone() }; - new_settings - .startup_configs - .push(self.strip_config_dir(config_path)?); - - self.write_settings(new_settings).await?; - - Ok(()) + new_settings.startup_configs.push(startup_config); + self.write_settings(new_settings).await } /// Removes the given config from being launched on startup. /// - /// Config path must be absolute. + /// Config path can be either absolute or relative. pub async fn remove_startup_config( &self, config_path: &PathBuf, + preset_name: &str, ) -> anyhow::Result<()> { - let rel_path = self.strip_config_dir(config_path)?; - let mut new_settings = { self.settings.lock().await.clone() }; - new_settings - .startup_configs - .retain(|path| path != &rel_path); + let rel_path = self.to_relative_path(config_path); - self.write_settings(new_settings).await?; + new_settings.startup_configs.retain(|config| { + config.path != rel_path || config.preset != preset_name + }); - Ok(()) + self.write_settings(new_settings).await } /// Joins the given path with the config directory path. /// /// Returns an absolute path. - pub fn join_config_dir(&self, config_path: &PathBuf) -> PathBuf { - self.config_dir.join(config_path) + pub fn to_absolute_path( + &self, + config_path: &PathBuf, + ) -> anyhow::Result { + match config_path.is_absolute() { + false => self.config_dir.join(config_path).to_absolute(), + // Ensure path is canonicalized even if already absolute. + true => config_path.to_absolute(), + } } /// Strips the config directory path from the given path. /// /// Returns a relative path. - pub fn strip_config_dir( - &self, - config_path: &PathBuf, - ) -> anyhow::Result { + pub fn to_relative_path(&self, config_path: &PathBuf) -> PathBuf { config_path .strip_prefix(&self.config_dir) - .context("Failed to strip config directory path.") - .map(Into::into) + .unwrap_or(&config_path) + .into() } - /// Returns the widget config at the given absolute path. + /// Returns the widget config at the given path. + /// + /// Config path can be either absolute or relative. pub async fn widget_config_by_path( &self, config_path: &PathBuf, - ) -> anyhow::Result> { - let formatted_config_path = - PathBuf::from(config_path).to_absolute()?; + ) -> Option<(PathBuf, WidgetConfig)> { + let abs_path = self.to_absolute_path(config_path).ok()?; let widget_configs = self.widget_configs.lock().await; - let config_entry = widget_configs - .iter() - .find(|entry| entry.config_path == formatted_config_path); + let config = widget_configs.get(&abs_path)?; - Ok(config_entry.cloned()) + Some((abs_path, config.clone())) } /// Opens the config directory in the OS-dependent file explorer. @@ -544,3 +591,9 @@ fn is_app_installed(app_name: &str) -> bool { .unwrap_or(false) } } + +/// Helper function for setting the default value for a +/// `WidgetPreset::name` field. +fn default_preset_name() -> String { + "default".into() +} diff --git a/packages/desktop/src/main.rs b/packages/desktop/src/main.rs index a0ac65a9..48271efc 100644 --- a/packages/desktop/src/main.rs +++ b/packages/desktop/src/main.rs @@ -5,12 +5,16 @@ use std::{env, sync::Arc}; -use anyhow::Context; use clap::Parser; -use tauri::{async_runtime::block_on, Manager, RunEvent}; +use cli::MonitorType; +use config::{MonitorSelection, WidgetPlacement}; +use tauri::{ + async_runtime::block_on, AppHandle, Emitter, Manager, RunEvent, +}; use tokio::task; use tracing::{error, info, level_filters::LevelFilter}; use tracing_subscriber::EnvFilter; +use widget_factory::WidgetOpenOptions; use crate::{ cli::{Cli, CliCommand, QueryArgs}, @@ -45,130 +49,41 @@ async fn main() -> anyhow::Result<()> { let _ = unsafe { AttachConsole(ATTACH_PARENT_PROCESS) }; } - let cli = Cli::parse(); - - match cli.command() { - CliCommand::Query(args) => output_query(args), - _ => { - let start_res = start_app(cli); - - // If unable to start Zebar, the error is fatal and a message dialog - // is shown. - if let Err(err) = &start_res { - // TODO: Show error dialog. - error!("{:?}", err); - }; - - start_res - } - } -} - -/// Query state and print to the console. -fn output_query(args: QueryArgs) -> anyhow::Result<()> { - match args { - QueryArgs::Monitors => { - tauri::Builder::default() - .setup(|app| { - let monitors = MonitorState::new(app.handle()); - cli::print_and_exit(monitors.output_str()); - Ok(()) - }) - .run(tauri::generate_context!())?; - - Ok(()) - } - } -} - -/// Starts Zebar - either with a specific widget or all widgets. -fn start_app(cli: Cli) -> anyhow::Result<()> { - tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::from_env("LOG_LEVEL") - .add_directive(LevelFilter::INFO.into()), - ) - .init(); - tauri::async_runtime::set(tokio::runtime::Handle::current()); let app = tauri::Builder::default() - .setup(move |app| { + .setup(|app| { task::block_in_place(|| { block_on(async move { - let config_dir_override = match cli.command() { - CliCommand::OpenWidgetDefault(args) => args.config_dir, - CliCommand::Startup(args) => args.config_dir, - _ => None, - }; - - // Initialize `Config` in Tauri state. - let config = - Arc::new(Config::new(app.handle(), config_dir_override)?); - app.manage(config.clone()); - - // Initialize `MonitorState` in Tauri state. - let monitor_state = Arc::new(MonitorState::new(app.handle())); - app.manage(monitor_state.clone()); - - // Initialize `WidgetFactory` in Tauri state. - let widget_factory = Arc::new(WidgetFactory::new( - app.handle(), - config.clone(), - monitor_state.clone(), - )); - app.manage(widget_factory.clone()); - - // If this is not the first instance of the app, this will emit - // within the original instance and exit immediately. The CLI - // command is guaranteed to be one of the open commands here. - setup_single_instance( - app, - config.clone(), - widget_factory.clone(), - )?; - - // Prevent windows from showing up in the dock on MacOS. - #[cfg(target_os = "macos")] - app.set_activation_policy(tauri::ActivationPolicy::Accessory); - - // Allow assets to be resolved from the config directory. - app - .asset_protocol_scope() - .allow_directory(&config.config_dir, true)?; - - app.handle().plugin(tauri_plugin_shell::init())?; - app.handle().plugin(tauri_plugin_http::init())?; - app.handle().plugin(tauri_plugin_dialog::init())?; - - // Initialize `ProviderManager` in Tauri state. - let manager = Arc::new(ProviderManager::new(app.handle())); - app.manage(manager); - - // Open widgets based on CLI command. - open_widgets_by_cli_command( - cli, - config.clone(), - widget_factory.clone(), - ) - .await?; - - // Add application icon to system tray. - let tray = SysTray::new( - app.handle(), - config.clone(), - widget_factory.clone(), - ) - .await?; - - listen_events(config, monitor_state, widget_factory, tray); + let cli = Cli::parse(); + + match cli.command() { + CliCommand::Query(args) => output_query(app, args), + _ => { + let start_res = start_app(app, cli).await; + + // If unable to start Zebar, the error is fatal and a message + // dialog is shown. + if let Err(err) = &start_res { + // TODO: Show error dialog. + error!("{:?}", err); + }; + + start_res + } + }?; Ok(()) }) }) }) .invoke_handler(tauri::generate_handler![ - commands::open_widget_default, + commands::widget_configs, + commands::widget_states, + commands::start_widget, + commands::start_preset, + commands::stop_preset, + commands::update_widget_config, commands::listen_provider, commands::unlisten_provider, commands::set_always_on_top, @@ -188,12 +103,90 @@ fn start_app(cli: Cli) -> anyhow::Result<()> { Ok(()) } +/// Query state and print to the console. +fn output_query(app: &tauri::App, args: QueryArgs) -> anyhow::Result<()> { + match args { + QueryArgs::Monitors => { + let monitors = MonitorState::new(&app.handle()); + cli::print_and_exit(monitors.output_str()); + Ok(()) + } + } +} + +/// Starts Zebar - either with a specific widget or all widgets. +async fn start_app(app: &mut tauri::App, cli: Cli) -> anyhow::Result<()> { + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::from_env("LOG_LEVEL") + .add_directive(LevelFilter::INFO.into()), + ) + .init(); + + let config_dir_override = match cli.command() { + CliCommand::Startup(args) => args.config_dir, + _ => None, + }; + + // Initialize `Config` in Tauri state. + let config = Arc::new(Config::new(app.handle(), config_dir_override)?); + app.manage(config.clone()); + + // Initialize `MonitorState` in Tauri state. + let monitor_state = Arc::new(MonitorState::new(app.handle())); + app.manage(monitor_state.clone()); + + // Initialize `WidgetFactory` in Tauri state. + let widget_factory = Arc::new(WidgetFactory::new( + app.handle(), + config.clone(), + monitor_state.clone(), + )); + app.manage(widget_factory.clone()); + + // If this is not the first instance of the app, this will emit within + // the original instance and exit immediately. The CLI command is + // guaranteed to be one of the open commands here. + setup_single_instance(app, widget_factory.clone())?; + + // Prevent windows from showing up in the dock on MacOS. + #[cfg(target_os = "macos")] + app.set_activation_policy(tauri::ActivationPolicy::Accessory); + + // Allow assets to be resolved from the config directory. + app + .asset_protocol_scope() + .allow_directory(&config.config_dir, true)?; + + app.handle().plugin(tauri_plugin_shell::init())?; + app.handle().plugin(tauri_plugin_http::init())?; + app.handle().plugin(tauri_plugin_dialog::init())?; + + // Initialize `ProviderManager` in Tauri state. + let manager = Arc::new(ProviderManager::new(app.handle())); + app.manage(manager); + + // Open widgets based on CLI command. + open_widgets_by_cli_command(cli, widget_factory.clone()).await?; + + // Add application icon to system tray. + let tray = + SysTray::new(app.handle(), config.clone(), widget_factory.clone()) + .await?; + + listen_events(app.handle(), config, monitor_state, widget_factory, tray); + + Ok(()) +} + fn listen_events( + app_handle: &AppHandle, config: Arc, monitor_state: Arc, widget_factory: Arc, tray: Arc, ) { + let app_handle = app_handle.clone(); let mut widget_open_rx = widget_factory.open_tx.subscribe(); let mut widget_close_rx = widget_factory.close_tx.subscribe(); let mut settings_change_rx = config.settings_change_tx.subscribe(); @@ -204,13 +197,17 @@ fn listen_events( task::spawn(async move { loop { let res = tokio::select! { - Ok(_) = widget_open_rx.recv() => { + Ok(widget_state) = widget_open_rx.recv() => { info!("Widget opened."); - tray.refresh().await + tray.refresh().await; + app_handle.emit("widget-opened", widget_state); + Ok(()) }, - Ok(_) = widget_close_rx.recv() => { + Ok(widget_id) = widget_close_rx.recv() => { info!("Widget closed."); - tray.refresh().await + tray.refresh().await; + app_handle.emit("widget-closed", widget_id); + Ok(()) }, Ok(_) = settings_change_rx.recv() => { info!("Settings changed."); @@ -220,9 +217,9 @@ fn listen_events( info!("Monitors changed."); widget_factory.relaunch_all().await }, - Ok(_) = widget_configs_change_rx.recv() => { + Ok(changed_configs) = widget_configs_change_rx.recv() => { info!("Widget configs changed."); - widget_factory.relaunch_all().await + widget_factory.relaunch_by_paths(&changed_configs.keys().cloned().collect()).await }, }; @@ -236,12 +233,10 @@ fn listen_events( /// Setup single instance Tauri plugin. fn setup_single_instance( app: &tauri::App, - config: Arc, widget_factory: Arc, ) -> anyhow::Result<()> { app.handle().plugin(tauri_plugin_single_instance::init( move |_, args, _| { - let config = config.clone(); let widget_factory = widget_factory.clone(); task::spawn(async move { @@ -249,8 +244,7 @@ fn setup_single_instance( Ok(cli) => { // No-op if no subcommand is provided. if cli.command() != CliCommand::Empty { - open_widgets_by_cli_command(cli, config, widget_factory) - .await + open_widgets_by_cli_command(cli, widget_factory).await } else { Ok(()) } @@ -271,30 +265,44 @@ fn setup_single_instance( /// Opens widgets based on CLI command. async fn open_widgets_by_cli_command( cli: Cli, - config: Arc, widget_factory: Arc, ) -> anyhow::Result<()> { - let widget_configs = match cli.command() { - CliCommand::OpenWidgetDefault(args) => { - let widget_config = config - .widget_config_by_path(&config.join_config_dir(&args.config_path)) - .await? - .with_context(|| { - format!( - "Widget config not found at {}.", - args.config_path.display() - ) - })?; - - vec![widget_config] + let res = match cli.command() { + CliCommand::StartWidget(args) => { + widget_factory + .start_widget( + &args.config_path, + &WidgetOpenOptions::Standalone(WidgetPlacement { + anchor: args.anchor, + offset_x: args.offset_x, + offset_y: args.offset_y, + width: args.width, + height: args.height, + monitor_selection: match args.monitor_type { + MonitorType::All => MonitorSelection::All, + MonitorType::Primary => MonitorSelection::Primary, + MonitorType::Secondary => MonitorSelection::Secondary, + }, + }), + ) + .await + } + CliCommand::StartPreset(args) => { + widget_factory + .start_widget( + &args.config_path, + &WidgetOpenOptions::Preset(args.preset_name), + ) + .await } - _ => config.startup_widget_configs().await?, + CliCommand::Startup(_) | CliCommand::Empty => { + widget_factory.startup().await + } + _ => unreachable!(), }; - for widget_config in widget_configs { - if let Err(err) = widget_factory.open(widget_config).await { - error!("Failed to open window: {:?}", err); - } + if let Err(err) = res { + error!("Failed to open widgets: {:?}", err); } Ok(()) diff --git a/packages/desktop/src/sys_tray.rs b/packages/desktop/src/sys_tray.rs index cc6b4568..a4546575 100644 --- a/packages/desktop/src/sys_tray.rs +++ b/packages/desktop/src/sys_tray.rs @@ -4,25 +4,37 @@ use anyhow::{bail, Context}; use tauri::{ image::Image, menu::{CheckMenuItem, Menu, MenuBuilder, Submenu, SubmenuBuilder}, - tray::{TrayIcon, TrayIconBuilder}, - AppHandle, Wry, + tray::{ + MouseButton, MouseButtonState, TrayIcon, TrayIconBuilder, + TrayIconEvent, + }, + AppHandle, Manager, WebviewUrl, WebviewWindowBuilder, Wry, }; use tokio::task; use tracing::{error, info}; use crate::{ common::PathExt, - config::Config, - widget_factory::{WidgetFactory, WidgetState}, + config::{Config, StartupConfig, WidgetConfig, WidgetPreset}, + widget_factory::{WidgetFactory, WidgetOpenOptions, WidgetState}, }; #[derive(Debug, Clone)] enum MenuEvent { ShowConfigFolder, ReloadConfigs, + OpenSettings, Exit, - ToggleWidgetConfig { enable: bool, path: PathBuf }, - ToggleStartupWidgetConfig { enable: bool, path: PathBuf }, + ToggleWidgetPreset { + enable: bool, + preset: String, + path: PathBuf, + }, + ToggleStartupWidgetConfig { + enable: bool, + preset: String, + path: PathBuf, + }, } impl ToString for MenuEvent { @@ -30,18 +42,29 @@ impl ToString for MenuEvent { match self { MenuEvent::ShowConfigFolder => "show_config_folder".to_string(), MenuEvent::ReloadConfigs => "reload_configs".to_string(), + MenuEvent::OpenSettings => "open_settings".to_string(), MenuEvent::Exit => "exit".to_string(), - MenuEvent::ToggleWidgetConfig { enable, path } => { + MenuEvent::ToggleWidgetPreset { + enable, + preset, + path, + } => { format!( - "toggle_widget_config_{}_{}", + "toggle_widget_config_{}_{}_{}", enable, - path.to_unicode_string() + preset, + path.to_unicode_string(), ) } - MenuEvent::ToggleStartupWidgetConfig { enable, path } => { + MenuEvent::ToggleStartupWidgetConfig { + enable, + preset, + path, + } => { format!( - "toggle_startup_widget_config_{}_{}", + "toggle_startup_widget_config_{}_{}_{}", enable, + preset, path.to_unicode_string() ) } @@ -58,16 +81,19 @@ impl FromStr for MenuEvent { match parts.as_slice() { ["show", "config", "folder"] => Ok(Self::ShowConfigFolder), ["reload", "configs"] => Ok(Self::ReloadConfigs), + ["open", "settings"] => Ok(Self::OpenSettings), ["exit"] => Ok(Self::Exit), - ["toggle", "widget", "config", enable @ ("true" | "false"), path @ ..] => { - Ok(Self::ToggleWidgetConfig { + ["toggle", "widget", "config", enable @ ("true" | "false"), preset, path @ ..] => { + Ok(Self::ToggleWidgetPreset { enable: *enable == "true", + preset: preset.to_string(), path: PathBuf::from(path.join("_")), }) } - ["toggle", "startup", "widget", "config", enable @ ("true" | "false"), path @ ..] => { + ["toggle", "startup", "widget", "config", enable @ ("true" | "false"), preset, path @ ..] => { Ok(Self::ToggleStartupWidgetConfig { enable: *enable == "true", + preset: preset.to_string(), path: PathBuf::from(path.join("_")), }) } @@ -104,42 +130,59 @@ impl SysTray { } async fn create_tray_icon(&self) -> anyhow::Result { - let config = self.config.clone(); - let widget_factory = self.widget_factory.clone(); let tooltip = format!("Zebar v{}", env!("VERSION_NUMBER")); - let tray_icon = TrayIconBuilder::with_id("tray") + // Linting: `mut` needed for Windows where `tray_icon` is modified with + // additional click handler. + #[allow(unused_mut)] + let mut tray_icon = TrayIconBuilder::with_id("tray") .icon(self.icon_image()?) .menu(&self.create_tray_menu().await?) .tooltip(tooltip) - .on_menu_event(move |app, event| { - let app_handle = app.clone(); - let config = config.clone(); - let widget_factory = widget_factory.clone(); - - task::spawn(async move { - let event = MenuEvent::from_str(event.id.as_ref()); - - if let Ok(event) = event { - info!("Received tray menu event: {}", event.to_string()); - - let res = Self::handle_menu_event( - event, - app_handle, - config, - widget_factory, - ) - .await; - - if let Err(err) = res { - error!("{:?}", err); + .on_menu_event({ + let config = self.config.clone(); + let widget_factory = self.widget_factory.clone(); + + move |app_handle, event| { + if let Ok(menu_event) = MenuEvent::from_str(event.id.as_ref()) { + Self::handle_menu_event( + menu_event, + app_handle.clone(), + config.clone(), + widget_factory.clone(), + ); + } + } + }); + + // Show the settings window on left click (Windows-only). + #[cfg(windows)] + { + tray_icon = + tray_icon.menu_on_left_click(false).on_tray_icon_event({ + let app_handle = self.app_handle.clone(); + let config = self.config.clone(); + let widget_factory = self.widget_factory.clone(); + + move |_, event| { + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Down, + .. + } = event + { + Self::handle_menu_event( + MenuEvent::OpenSettings, + app_handle.clone(), + config.clone(), + widget_factory.clone(), + ); } } }); - }) - .build(&self.app_handle)?; + } - Ok(tray_icon) + Ok(tray_icon.build(&self.app_handle)?) } pub async fn refresh(&self) -> anyhow::Result<()> { @@ -164,41 +207,37 @@ impl SysTray { /// Creates and returns the main system tray menu. async fn create_tray_menu(&self) -> anyhow::Result> { - let widget_states = self.widget_factory.states_by_config_path().await; - - let startup_config_paths = self - .config - .startup_widget_configs() - .await? - .into_iter() - .map(|entry| entry.config_path) - .collect(); - - let configs_menu = self - .create_configs_menu(&widget_states, &startup_config_paths) - .await?; + let widget_configs = self.config.widget_configs().await; + let widget_states = self.widget_factory.states_by_path().await; + let startup_configs = self.config.startup_configs_by_path().await?; + + let configs_menu = self.create_configs_menu( + &widget_configs, + &widget_states, + &startup_configs, + )?; let mut tray_menu = MenuBuilder::new(&self.app_handle) + .text(MenuEvent::OpenSettings, "Open settings") .item(&configs_menu) - .text(MenuEvent::ShowConfigFolder, "Show config folder") .text(MenuEvent::ReloadConfigs, "Reload configs") .separator(); + // TODO: Set "Open settings" as the default menu item on Windows. + // Add submenus for currently active widget. if !widget_states.is_empty() { - for (config_path, states) in widget_states { - let label = format!( - "({}) {}", - states.len(), - Self::format_config_path(&self.config, &config_path) - ); - - tray_menu = tray_menu.item(&self.create_config_menu( - &config_path, - &label, - !states.is_empty(), - startup_config_paths.contains(&config_path), - )?); + for (config_path, config) in &widget_configs { + if let Some(_) = widget_states.get(config_path) { + let config_menu = self.create_config_menu( + &config_path, + config, + &widget_states, + &startup_configs, + )?; + + tray_menu = tray_menu.item(&config_menu); + } } tray_menu = tray_menu.separator(); @@ -210,88 +249,98 @@ impl SysTray { } /// Callback for system tray menu events. - async fn handle_menu_event( + fn handle_menu_event( event: MenuEvent, app_handle: AppHandle, config: Arc, widget_factory: Arc, - ) -> anyhow::Result<()> { - match event { - MenuEvent::ShowConfigFolder => { - info!("Opening config folder from system tray."); + ) { + task::spawn(async move { + info!("Received tray menu event: {:?}", event); - config + let event_res = match event { + MenuEvent::ShowConfigFolder => config .open_config_dir() - .context("Failed to open config folder.") + .context("Failed to open config folder."), + MenuEvent::ReloadConfigs => config.reload().await, + MenuEvent::OpenSettings => Self::open_settings_window(&app_handle), + MenuEvent::Exit => { + app_handle.exit(0); + Ok(()) + } + MenuEvent::ToggleWidgetPreset { + enable, + path, + preset, + } => match enable { + true => { + widget_factory + .start_widget(&path, &WidgetOpenOptions::Preset(preset)) + .await + } + false => widget_factory.stop_by_preset(&path, &preset).await, + }, + MenuEvent::ToggleStartupWidgetConfig { + enable, + preset, + path, + } => match enable { + true => config.add_startup_config(&path, &preset).await, + false => config.remove_startup_config(&path, &preset).await, + }, + }; + + if let Err(err) = event_res { + error!("Error handling menu event: {:?}", err); } - MenuEvent::ReloadConfigs => { - info!("Opening config folder from system tray."); + }); + } - config.reload().await - } - MenuEvent::Exit => { - info!("Exiting through system tray."); + fn open_settings_window(app_handle: &AppHandle) -> anyhow::Result<()> { + // Get existing settings window if it's already open. + let settings_window = app_handle.get_webview_window("settings"); - app_handle.exit(0); + match &settings_window { + None => { + WebviewWindowBuilder::new( + app_handle, + "settings", + WebviewUrl::default(), + ) + .title("Settings - Zebar") + .focused(true) + .inner_size(900., 600.) + .build() + .context("Failed to build the settings window.")?; Ok(()) } - MenuEvent::ToggleWidgetConfig { enable, path } => { - info!( - "Widget config '{}' to be enabled: {}", - path.display(), - enable - ); - - match enable { - true => { - let widget_config = config - .widget_config_by_path(&path) - .await? - .context("Widget config not found.")?; - - widget_factory.open(widget_config).await - } - false => widget_factory.stop_by_path(&path).await, - } - } - MenuEvent::ToggleStartupWidgetConfig { enable, path } => { - info!( - "Widget config '{}' to be launched on startup: {}", - path.display(), - enable - ); - - match enable { - true => config.add_startup_config(&path).await, - false => config.remove_startup_config(&path).await, - } - } + Some(window) => window + .set_focus() + .context("Failed to focus the settings window."), } } /// Creates and returns a submenu for the widget configs. - async fn create_configs_menu( + fn create_configs_menu( &self, + widget_configs: &HashMap, widget_states: &HashMap>, - startup_config_paths: &Vec, + startup_configs: &HashMap, ) -> anyhow::Result> { let mut configs_menu = SubmenuBuilder::new(&self.app_handle, "Widget configs"); // Add each widget config to the menu. - for widget_config in &self.config.widget_configs().await { - let label = - Self::format_config_path(&self.config, &widget_config.config_path); - - let menu_item = self.create_config_menu( - &widget_config.config_path, - &label, - widget_states.contains_key(&widget_config.config_path), - startup_config_paths.contains(&widget_config.config_path), + for (config_path, widget_config) in widget_configs { + let config_menu = self.create_config_menu( + config_path, + &widget_config, + widget_states, + startup_configs, )?; - configs_menu = configs_menu.item(&menu_item); + configs_menu = configs_menu.item(&config_menu); } Ok(configs_menu.build()?) @@ -301,19 +350,66 @@ impl SysTray { fn create_config_menu( &self, config_path: &PathBuf, - label: &str, - is_enabled: bool, + widget_config: &WidgetConfig, + widget_states: &HashMap>, + startup_configs: &HashMap, + ) -> anyhow::Result> { + let formatted_config_path = + Self::format_config_path(&self.config, config_path); + + let label = match widget_states.get(config_path) { + None => formatted_config_path, + Some(states) => { + format!("({}) {}", states.len(), formatted_config_path) + } + }; + + let mut presets_menu = SubmenuBuilder::new(&self.app_handle, label); + + // Add each widget config to the menu. + for preset in &widget_config.presets { + let preset_menu = self.create_preset_menu( + config_path, + &preset, + widget_states + .get(config_path) + .map(|states| { + states + .iter() + .filter(|state| { + state.open_options + == WidgetOpenOptions::Preset(preset.name.clone()) + }) + .count() + }) + .unwrap_or(0), + startup_configs.contains_key(config_path), + )?; + + presets_menu = presets_menu.item(&preset_menu); + } + + Ok(presets_menu.build()?) + } + + /// Creates and returns a submenu for the given widget config. + fn create_preset_menu( + &self, + config_path: &PathBuf, + preset: &WidgetPreset, + preset_count: usize, is_launched_on_startup: bool, ) -> anyhow::Result> { let enabled_item = CheckMenuItem::with_id( &self.app_handle, - MenuEvent::ToggleWidgetConfig { - enable: !is_enabled, + MenuEvent::ToggleWidgetPreset { + enable: preset_count == 0, + preset: preset.name.clone(), path: config_path.clone(), }, "Enabled", true, - is_enabled, + preset_count > 0, None::<&str>, )?; @@ -321,6 +417,7 @@ impl SysTray { &self.app_handle, MenuEvent::ToggleStartupWidgetConfig { enable: !is_launched_on_startup, + preset: preset.name.clone(), path: config_path.clone(), }, "Launch on startup", @@ -329,6 +426,11 @@ impl SysTray { None::<&str>, )?; + let label = match preset_count { + 0 => &preset.name, + _ => &format!("({}) {}", preset_count, preset.name), + }; + let config_menu = SubmenuBuilder::new(&self.app_handle, label) .item(&enabled_item) .item(&startup_item); @@ -341,10 +443,7 @@ impl SysTray { config: &Arc, config_path: &PathBuf, ) -> String { - let path = config - .strip_config_dir(config_path) - .unwrap_or(config_path.clone()) - .to_unicode_string(); + let path = config.to_relative_path(config_path).to_unicode_string(); path.strip_suffix(".zebar.json").unwrap_or(&path).into() } diff --git a/packages/desktop/src/widget_factory.rs b/packages/desktop/src/widget_factory.rs index 0a23ce93..9d78e295 100644 --- a/packages/desktop/src/widget_factory.rs +++ b/packages/desktop/src/widget_factory.rs @@ -7,7 +7,7 @@ use std::{ }, }; -use anyhow::{bail, Context}; +use anyhow::Context; use serde::Serialize; use tauri::{ AppHandle, Manager, PhysicalPosition, PhysicalSize, WebviewUrl, @@ -21,7 +21,7 @@ use tracing::{error, info}; use crate::{ common::{PathExt, WindowExt}, - config::{AnchorPoint, Config, WidgetConfig, WidgetConfigEntry}, + config::{AnchorPoint, Config, WidgetConfig, WidgetPlacement, ZOrder}, monitor_state::MonitorState, }; @@ -30,9 +30,9 @@ pub struct WidgetFactory { /// Handle to the Tauri application. app_handle: AppHandle, - _close_rx: broadcast::Receiver, + _close_rx: broadcast::Receiver, - pub close_tx: broadcast::Sender, + pub close_tx: broadcast::Sender, /// Reference to `Config`. config: Arc, @@ -72,6 +72,16 @@ pub struct WidgetState { /// Absolute path to the widget's HTML file. pub html_path: PathBuf, + + /// How the widget was opened. + pub open_options: WidgetOpenOptions, +} + +#[derive(Clone, Debug, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum WidgetOpenOptions { + Standalone(WidgetPlacement), + Preset(String), } impl WidgetFactory { @@ -97,30 +107,79 @@ impl WidgetFactory { } } - /// Opens widget from a given config entry. - pub async fn open( + /// Opens widget from a given config path. + /// + /// Config path must be absolute. + pub async fn start_widget( &self, - config_entry: WidgetConfigEntry, + config_path: &PathBuf, + open_options: &WidgetOpenOptions, ) -> anyhow::Result<()> { - let WidgetConfigEntry { - config, - config_path, - html_path, - } = &config_entry; + let (config_path, widget_config) = self + .config + .widget_config_by_path(config_path) + .await + .with_context(|| { + format!("No config found at path '{}'.", config_path.display()) + })?; + + // No-op if preset is already open. + if let WidgetOpenOptions::Preset(_) = open_options { + let is_preset_open = { + self + .widget_states + .lock() + .await + .values() + .find(|state| { + state.config_path == config_path + && state.open_options == *open_options + }) + .is_some() + }; - for (size, position) in self.widget_placements(config).await { - // Use running widget count as a unique label for the Tauri window. + if is_preset_open { + return Ok(()); + } + } + + // Extract placement from widget preset (if applicable). + let placement = match open_options { + WidgetOpenOptions::Standalone(placement) => placement, + WidgetOpenOptions::Preset(name) => { + &widget_config + .presets + .iter() + .find(|preset| preset.name == *name) + .with_context(|| { + format!( + "No preset with name '{}' at config '{}'.", + name, + config_path.display() + ) + })? + .placement + } + }; + + for (size, position) in self.widget_coordinates(placement).await { let new_count = self.widget_count.fetch_add(1, Ordering::Relaxed) + 1; - let widget_id = new_count.to_string(); - - if !html_path.exists() { - bail!( - "HTML file not found at {} for config {}.", - html_path.display(), - config_path.display() - ); - } + + // Use running widget count as a unique label for the Tauri window. + let widget_id = format!("widget-{}", new_count); + + let html_path = config_path + .parent() + .map(|dir| dir.join(&widget_config.html_path)) + .filter(|path| path.exists()) + .with_context(|| { + format!( + "HTML file not found at '{}' for config '{}'.", + widget_config.html_path.display(), + config_path.display() + ) + })?; info!( "Creating window for widget #{} from {}", @@ -139,13 +198,13 @@ impl WidgetFactory { webview_url, ) .title("Zebar") - .focused(config.focused) - .skip_taskbar(!config.shown_in_taskbar) + .focused(widget_config.focused) + .skip_taskbar(!widget_config.shown_in_taskbar) .visible_on_all_workspaces(true) - .transparent(config.transparent) + .transparent(widget_config.transparent) .shadow(false) .decorations(false) - .resizable(config.resizable) + .resizable(widget_config.resizable) .build()?; info!("Positioning widget to {:?} {:?}", size, position); @@ -162,9 +221,10 @@ impl WidgetFactory { let state = WidgetState { id: widget_id.clone(), - config: config.clone(), + config: widget_config.clone(), config_path: config_path.clone(), html_path: html_path.clone(), + open_options: open_options.clone(), }; _ = window.eval(&format!( @@ -178,10 +238,21 @@ impl WidgetFactory { let _ = window .as_ref() .window() - .set_tool_window(!config.shown_in_taskbar); + .set_tool_window(!widget_config.shown_in_taskbar); - let mut widget_states = self.widget_states.lock().await; - widget_states.insert(state.id.clone(), state.clone()); + // On MacOS, we need to set the window as above the menu bar for it + // to truly be always on top. + #[cfg(target_os = "macos")] + { + if widget_config.z_order == ZOrder::TopMost { + let _ = window.as_ref().window().set_above_menu_bar(); + } + } + + { + let mut widget_states = self.widget_states.lock().await; + widget_states.insert(state.id.clone(), state.clone()); + } self.register_window_events(&window, widget_id); self.open_tx.send(state)?; @@ -190,10 +261,26 @@ impl WidgetFactory { Ok(()) } + /// Opens presets that are configured to be launched on startup. + pub async fn startup(&self) -> anyhow::Result<()> { + let startup_configs = self.config.startup_configs().await; + + for startup_config in startup_configs { + self + .start_widget( + &startup_config.path, + &WidgetOpenOptions::Preset(startup_config.preset), + ) + .await?; + } + + Ok(()) + } + /// Converts a file path to a Tauri asset URL. /// /// Returns a string that can be used as a webview URL. - pub fn to_asset_url(file_path: &str) -> String { + fn to_asset_url(file_path: &str) -> String { if cfg!(target_os = "windows") { format!("http://asset.localhost/{}", file_path) } else { @@ -219,11 +306,12 @@ impl WidgetFactory { task::spawn(async move { let mut widget_states = widget_states.lock().await; - // Remove the widget state and broadcast the close event. - if let Some(state) = widget_states.remove(&widget_id) { - if let Err(err) = close_tx.send(state) { - error!("Failed to send window close event: {:?}", err); - } + // Remove the widget state. + let _ = widget_states.remove(&widget_id); + + // Broadcast the close event. + if let Err(err) = close_tx.send(widget_id) { + error!("Failed to send window close event: {:?}", err); } }); } @@ -231,86 +319,83 @@ impl WidgetFactory { } /// Returns coordinates for window placement based on the given config. - async fn widget_placements( + async fn widget_coordinates( &self, - config: &WidgetConfig, + placement: &WidgetPlacement, ) -> Vec<(PhysicalSize, PhysicalPosition)> { - let mut placements = vec![]; - - for placement in config.default_placements.iter() { - let monitors = self - .monitor_state - .monitors_by_selection(&placement.monitor_selection) - .await; - - for monitor in monitors { - let monitor_width = monitor.width as i32; - let monitor_height = monitor.height as i32; - - // Pixel values should be scaled by the monitor's scale factor, - // whereas percentage values are left as-is. This is - // because the percentage values are already relative to - // the monitor's size. - let window_width = placement - .width - .to_px_scaled(monitor_width, monitor.scale_factor); - - let window_height = placement - .height - .to_px_scaled(monitor_height, monitor.scale_factor); - - let window_size = PhysicalSize::new(window_width, window_height); - - let (anchor_x, anchor_y) = match placement.anchor { - AnchorPoint::TopLeft => (monitor.x, monitor.y), - AnchorPoint::TopCenter => ( - monitor.x + (monitor_width / 2) - (window_size.width / 2), - monitor.y, - ), - AnchorPoint::TopRight => { - (monitor.x + monitor_width - window_size.width, monitor.y) - } - AnchorPoint::CenterLeft => ( - monitor.x, - monitor.y + (monitor_height / 2) - (window_size.height / 2), - ), - AnchorPoint::Center => ( - monitor.x + (monitor_width / 2) - (window_size.width / 2), - monitor.y + (monitor_height / 2) - (window_size.height / 2), - ), - AnchorPoint::CenterRight => ( - monitor.x + monitor_width - window_size.width, - monitor.y + (monitor_height / 2) - (window_size.height / 2), - ), - AnchorPoint::BottomLeft => { - (monitor.x, monitor.y + monitor_height - window_size.height) - } - AnchorPoint::BottomCenter => ( - monitor.x + (monitor_width / 2) - (window_size.width / 2), - monitor.y + monitor_height - window_size.height, - ), - AnchorPoint::BottomRight => ( - monitor.x + monitor_width - window_size.width, - monitor.y + monitor_height - window_size.height, - ), - }; - - let offset_x = placement - .offset_x - .to_px_scaled(monitor_width, monitor.scale_factor); - - let offset_y = placement - .offset_y - .to_px_scaled(monitor_height, monitor.scale_factor); - - let window_position = - PhysicalPosition::new(anchor_x + offset_x, anchor_y + offset_y); - - placements.push((window_size, window_position)); - } + let mut coordinates = vec![]; + + let monitors = self + .monitor_state + .monitors_by_selection(&placement.monitor_selection) + .await; + + for monitor in monitors { + let monitor_width = monitor.width as i32; + let monitor_height = monitor.height as i32; + + // Pixel values should be scaled by the monitor's scale factor, + // whereas percentage values are left as-is. This is because the + // percentage values are already relative to the monitor's size. + let window_width = placement + .width + .to_px_scaled(monitor_width, monitor.scale_factor); + + let window_height = placement + .height + .to_px_scaled(monitor_height, monitor.scale_factor); + + let window_size = PhysicalSize::new(window_width, window_height); + + let (anchor_x, anchor_y) = match placement.anchor { + AnchorPoint::TopLeft => (monitor.x, monitor.y), + AnchorPoint::TopCenter => ( + monitor.x + (monitor_width / 2) - (window_size.width / 2), + monitor.y, + ), + AnchorPoint::TopRight => { + (monitor.x + monitor_width - window_size.width, monitor.y) + } + AnchorPoint::CenterLeft => ( + monitor.x, + monitor.y + (monitor_height / 2) - (window_size.height / 2), + ), + AnchorPoint::Center => ( + monitor.x + (monitor_width / 2) - (window_size.width / 2), + monitor.y + (monitor_height / 2) - (window_size.height / 2), + ), + AnchorPoint::CenterRight => ( + monitor.x + monitor_width - window_size.width, + monitor.y + (monitor_height / 2) - (window_size.height / 2), + ), + AnchorPoint::BottomLeft => { + (monitor.x, monitor.y + monitor_height - window_size.height) + } + AnchorPoint::BottomCenter => ( + monitor.x + (monitor_width / 2) - (window_size.width / 2), + monitor.y + monitor_height - window_size.height, + ), + AnchorPoint::BottomRight => ( + monitor.x + monitor_width - window_size.width, + monitor.y + monitor_height - window_size.height, + ), + }; + + let offset_x = placement + .offset_x + .to_px_scaled(monitor_width, monitor.scale_factor); + + let offset_y = placement + .offset_y + .to_px_scaled(monitor_height, monitor.scale_factor); + + let window_position = + PhysicalPosition::new(anchor_x + offset_x, anchor_y + offset_y); + + coordinates.push((window_size, window_position)); } - placements + coordinates } /// Closes a single widget by a given widget ID. @@ -326,11 +411,11 @@ impl WidgetFactory { } /// Closes all widgets with the given config path. - pub async fn stop_by_path( + pub async fn _stop_by_path( &self, config_path: &PathBuf, ) -> anyhow::Result<()> { - let widget_states = self.states_by_config_path().await; + let widget_states = self.states_by_path().await; let found_widget_states = widget_states .get(config_path) @@ -343,32 +428,101 @@ impl WidgetFactory { Ok(()) } + /// Closes all widgets of the given preset name. + pub async fn stop_by_preset( + &self, + config_path: &PathBuf, + preset_name: &str, + ) -> anyhow::Result<()> { + let widget_states = self.states_by_path().await; + + let found_widget_states = widget_states + .get(config_path) + .context("No widgets found with the given config path.")? + .iter() + .filter(|state| { + matches!( + &state.open_options, + WidgetOpenOptions::Preset(name) if name == preset_name + ) + }); + + for widget_state in found_widget_states { + self.stop_by_id(&widget_state.id)?; + } + + Ok(()) + } + /// Relaunches all currently open widgets. pub async fn relaunch_all(&self) -> anyhow::Result<()> { - let widget_states = self.states_by_config_path().await; + let widget_ids = + { self.widget_states.lock().await.keys().cloned().collect() }; + + self.relaunch_by_ids(&widget_ids).await + } - for (config_path, _) in widget_states { - let _ = self.stop_by_path(&config_path).await; + /// Relaunches widgets with the given widget ID's. + pub async fn relaunch_by_ids( + &self, + widget_ids: &Vec, + ) -> anyhow::Result<()> { + let changed_states = { + let mut widget_states = self.widget_states.lock().await; - let widget_config = self - .config - .widget_config_by_path(&config_path) - .await? - .context("Widget config not found.")?; + // Optimistically clear running widget states. + widget_ids + .iter() + .filter_map(|id| widget_states.remove(id)) + .collect::>() + }; - self.open(widget_config).await?; + for widget_state in changed_states { + info!( + "Relaunching widget #{} from {}", + widget_state.id, + widget_state.config_path.display() + ); + + let _ = self.stop_by_id(&widget_state.id); + + self + .start_widget( + &widget_state.config_path, + &widget_state.open_options, + ) + .await?; } Ok(()) } - /// Returns widget state by a given widget ID. - pub async fn state_by_id(&self, widget_id: &str) -> Option { - self.widget_states.lock().await.get(widget_id).cloned() + /// Relaunches widgets with the given config paths. + pub async fn relaunch_by_paths( + &self, + config_paths: &Vec, + ) -> anyhow::Result<()> { + let widget_ids = { + self + .widget_states + .lock() + .await + .iter() + .filter(|(_, state)| config_paths.contains(&state.config_path)) + .map(|(id, _)| id.clone()) + .collect::>() + }; + + self.relaunch_by_ids(&widget_ids).await + } + + /// Returns widget states by their widget ID's. + pub async fn states(&self) -> HashMap { + self.widget_states.lock().await.clone() } /// Returns widget states grouped by their config paths. - pub async fn states_by_config_path( + pub async fn states_by_path( &self, ) -> HashMap> { self.widget_states.lock().await.values().fold( diff --git a/packages/desktop/tauri.conf.json b/packages/desktop/tauri.conf.json index a800b0d0..1477e461 100644 --- a/packages/desktop/tauri.conf.json +++ b/packages/desktop/tauri.conf.json @@ -1,8 +1,8 @@ { - "$schema": "node_modules/@tauri-apps/cli/schema.json", + "$schema": "node_modules/@tauri-apps/cli/config.schema.json", "build": { - "devUrl": null, - "frontendDist": null + "devUrl": "http://localhost:4200", + "frontendDist": "../settings-ui/dist" }, "productName": "Zebar", "version": "0.0.0", diff --git a/packages/settings-ui/README.md b/packages/settings-ui/README.md new file mode 100644 index 00000000..a951337f --- /dev/null +++ b/packages/settings-ui/README.md @@ -0,0 +1,22 @@ +## Usage + +```bash +$ npm install # or pnpm install or yarn install +``` + +### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) + +## Available Scripts + +In the project directory, you can run: + +### `npm run dev` + +Runs the app in the development mode. + +### `npm run build` + +Builds the app for production to the `dist` folder.
+It bundles Solid in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
diff --git a/packages/settings-ui/index.html b/packages/settings-ui/index.html new file mode 100644 index 00000000..551f7a72 --- /dev/null +++ b/packages/settings-ui/index.html @@ -0,0 +1,22 @@ + + + + + + + Zebar Settings + + + + + + + +
+ + + diff --git a/packages/settings-ui/package.json b/packages/settings-ui/package.json new file mode 100644 index 00000000..095b5a44 --- /dev/null +++ b/packages/settings-ui/package.json @@ -0,0 +1,26 @@ +{ + "name": "@zebar/settings-ui", + "version": "0.0.0", + "description": "", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "dependencies": { + "@glzr/components": "1.0.2", + "@solidjs/router": "0.14.8", + "@tabler/icons-solidjs": "3.19.0", + "@tauri-apps/api": "2.0.2", + "smorf": "1.2.1", + "solid-js": "1.9.3", + "zebar": "^2.0.0" + }, + "devDependencies": { + "postcss": "8.4.47", + "tailwindcss": "3.4.13 ", + "tailwindcss-animate": "1.0.7", + "typescript": "5.3.3", + "vite": "5.4.10", + "vite-plugin-solid": "2.10.2" + } +} diff --git a/packages/settings-ui/postcss.config.js b/packages/settings-ui/postcss.config.js new file mode 100644 index 00000000..ee5f90b3 --- /dev/null +++ b/packages/settings-ui/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + tailwindcss: {}, + }, +}; diff --git a/packages/settings-ui/src/configs/WidgetConfigForm.tsx b/packages/settings-ui/src/configs/WidgetConfigForm.tsx new file mode 100644 index 00000000..7d2a2d46 --- /dev/null +++ b/packages/settings-ui/src/configs/WidgetConfigForm.tsx @@ -0,0 +1,295 @@ +import { + Button, + Card, + CardContent, + CardHeader, + CardTitle, + TextField, + SelectField, + SwitchField, + TooltipContent, + Tooltip, + TooltipTrigger, +} from '@glzr/components'; +import { IconTrash } from '@tabler/icons-solidjs'; +import { createForm, Field } from 'smorf'; +import { createEffect, on } from 'solid-js'; +import { WidgetConfig } from 'zebar'; + +export interface WidgetConfigFormProps { + config: WidgetConfig; + onChange: (config: WidgetConfig) => void; +} + +export function WidgetConfigForm(props: WidgetConfigFormProps) { + const configForm = createForm(props.config); + + // Update the form when the incoming config changes. + createEffect( + on( + () => props.config, + config => configForm.setValue(config), + ), + ); + + // Emit changes to the form value. + createEffect( + on( + () => configForm.value, + formValue => { + if (configForm.isDirty()) { + props.onChange(formValue); + } + }, + ), + ); + + function addNewPreset() { + configForm.setFieldValue('presets', presets => [ + ...presets, + { + name: presets.length ? `default${presets.length + 1}` : 'default', + anchor: 'center', + offsetX: '0px', + offsetY: '0px', + width: '50%', + height: '50%', + monitorSelection: { + type: 'all', + }, + }, + ]); + } + + function deletePreset(targetIndex: number) { + configForm.setFieldValue('presets', presets => + presets.filter((_, index) => index !== targetIndex), + ); + } + + return ( +
+ + + Widget settings + + + + + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + + + + + + + Presets + + + + {configForm.value.presets.map((_, index) => ( +
+
+ + {inputProps => ( + + )} + + + + ( + + )} + /> + Delete preset + +
+ +
+ + {inputProps => ( + + )} + + + + {inputProps => ( + + )} + +
+ +
+ {/* TODO: Change to px/percent input. */} + + {inputProps => ( + + )} + + + {/* TODO: Change to px/percent input. */} + + {inputProps => ( + + )} + +
+ +
+ {/* TODO: Change to px/percent input. */} + + {inputProps => ( + + )} + + + {/* TODO: Change to px/percent input. */} + + {inputProps => ( + + )} + +
+
+ ))} + + +
+
+
+ ); +} diff --git a/packages/settings-ui/src/configs/WidgetConfigSidebar.tsx b/packages/settings-ui/src/configs/WidgetConfigSidebar.tsx new file mode 100644 index 00000000..bed659fa --- /dev/null +++ b/packages/settings-ui/src/configs/WidgetConfigSidebar.tsx @@ -0,0 +1,76 @@ +import { + cn, + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from '@glzr/components'; +import { IconChevronDown, IconDiamonds } from '@tabler/icons-solidjs'; +import { createMemo, For } from 'solid-js'; +import { WidgetConfig } from 'zebar'; + +export interface WidgetConfigSidebarProps { + configs: Record; + selectedConfig: WidgetConfig | null; + selectedConfigPath: string | null; + onSelect: (configPath: string) => void; +} + +export function WidgetConfigSidebar(props: WidgetConfigSidebarProps) { + const configTree = createMemo(() => { + const tree: Record> = {}; + + Object.keys(props.configs) + .sort() + .forEach(configPath => { + const folder = configPath.split(/[/\\]/).at(-2); + + tree[folder] = { + ...(tree[folder] ?? {}), + [configPath]: props.configs[configPath], + }; + }); + + return tree; + }); + + return ( +
+

Widget configs

+
+ + {([folder, configs]) => ( + + + + {folder} + + + + + {([configPath]) => ( +
props.onSelect(configPath)} + > + + + {configPath + .split(/[/\\]/) + .at(-1) + .replace('.zebar.json', '')} + +
+ )} +
+
+
+ )} +
+
+
+ ); +} diff --git a/packages/settings-ui/src/configs/WidgetConfigs.tsx b/packages/settings-ui/src/configs/WidgetConfigs.tsx new file mode 100644 index 00000000..f15b954e --- /dev/null +++ b/packages/settings-ui/src/configs/WidgetConfigs.tsx @@ -0,0 +1,251 @@ +import { + Button, + cn, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@glzr/components'; +import { IconChevronDown } from '@tabler/icons-solidjs'; +import { invoke } from '@tauri-apps/api/core'; +import { listen, type Event } from '@tauri-apps/api/event'; +import { + createEffect, + createMemo, + createResource, + createSignal, + For, + on, + Show, +} from 'solid-js'; +import { Widget, WidgetConfig } from 'zebar'; + +import { WidgetConfigSidebar } from './WidgetConfigSidebar'; +import { WidgetConfigForm } from './WidgetConfigForm'; + +export function WidgetConfigs() { + const [configs, { mutate: mutateWidgetConfigs }] = createResource( + async () => invoke>('widget_configs'), + { initialValue: {} }, + ); + + const [widgetStates, { mutate: mutateWidgetStates }] = createResource( + async () => invoke>('widget_states'), + { initialValue: {} }, + ); + + createEffect(() => console.log('widgetStates', widgetStates())); + + const [selectedConfigPath, setSelectedConfigPath] = createSignal< + string | null + >(null); + + const [selectedPreset, setSelectedPreset] = createSignal( + null, + ); + + const selectedConfig = createMemo(() => configs()[selectedConfigPath()]); + + const presetNames = createMemo(() => + (selectedConfig()?.presets ?? []).map(preset => preset.name), + ); + + // Widget states for the selected config. + const selectedConfigStates = createMemo(() => { + const configPath = selectedConfigPath(); + return Object.values(widgetStates()).filter( + state => state.configPath === configPath, + ); + }); + + // Widget states for the selected preset. + const selectedPresetStates = createMemo(() => { + const preset = selectedPreset(); + return selectedConfigStates().filter( + // @ts-ignore - TODO + state => state.openOptions?.preset === preset, + ); + }); + + // Update widget states on open. + listen('widget-opened', (event: Event) => { + mutateWidgetStates(states => ({ + ...states, + [event.payload.id]: event.payload, + })); + }); + + // Update widget states on close. + listen('widget-closed', (event: Event) => { + mutateWidgetStates(states => { + const newStates = { ...states }; + delete newStates[event.payload]; + return newStates; + }); + }); + + // Select the first config alphabetically on initial load. + createEffect( + on( + () => configs(), + () => { + if (!selectedConfigPath()) { + setSelectedConfigPath(Object.keys(configs()).sort()[0] ?? null); + } + }, + ), + ); + + // Initialize the selected preset when a config is selected. + createEffect( + on( + () => selectedConfigPath(), + () => { + if (selectedConfig()) { + setSelectedPreset(selectedConfig().presets[0]?.name ?? null); + document.querySelector('#form-container').scrollTo(0, 0); + } + }, + ), + ); + + // Ensure selected preset is valid when presets change. + createEffect( + on( + () => presetNames(), + () => { + if ( + !selectedPreset() || + !presetNames().includes(selectedPreset()) + ) { + setSelectedPreset(presetNames()[0] ?? null); + } + }, + ), + ); + + async function onConfigChange( + configPath: string, + newConfig: WidgetConfig, + ) { + // Update the state with the new config values. + mutateWidgetConfigs(configs => ({ + ...configs, + [configPath]: newConfig, + })); + + // Send updated config values to backend. + await invoke('update_widget_config', { + configPath, + newConfig, + }); + } + + async function togglePreset(configPath: string, presetName: string) { + if (selectedPresetStates().length > 0) { + await invoke('stop_preset', { + configPath, + presetName, + }); + } else { + await invoke('start_preset', { + configPath, + presetName, + }); + } + } + + return ( +
+ {/* Sidebar. */} + + + {/* Main content. */} + } + > + {config => ( +
+
+

+ {selectedConfigPath().split(/[/\\]/).at(-1)} +

+ +

+ {selectedConfigPath()} +

+ + + onConfigChange(selectedConfigPath(), config) + } + /> +
+ + {/* Action bar. */} +
+
+ + {selectedConfigStates().length} open ( + {selectedPresetStates().length} for preset) + + + + + + + + + + + + {presetName => ( + setSelectedPreset(presetName)} + class={cn({ + 'bg-accent text-accent-foreground': + presetName === selectedPreset(), + })} + > + {presetName} + + )} + + + +
+
+
+ )} +
+
+ ); +} + +function WidgetSettingsEmptyState() { + return

No config selected.

; +} diff --git a/packages/settings-ui/src/index.css b/packages/settings-ui/src/index.css new file mode 100644 index 00000000..9786e76f --- /dev/null +++ b/packages/settings-ui/src/index.css @@ -0,0 +1,85 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, +body { + overflow: hidden; +} + +.tabler-icon { + stroke-width: 1; +} + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + [data-kb-theme='dark'] { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/packages/settings-ui/src/index.tsx b/packages/settings-ui/src/index.tsx new file mode 100644 index 00000000..df03f6e3 --- /dev/null +++ b/packages/settings-ui/src/index.tsx @@ -0,0 +1,15 @@ +/* @refresh reload */ +import './index.css'; +import { Route, Router } from '@solidjs/router'; +import { render } from 'solid-js/web'; + +import { WidgetConfigs } from './configs/WidgetConfigs'; + +render( + () => ( + + + + ), + document.getElementById('root')!, +); diff --git a/packages/settings-ui/tailwind.config.cjs b/packages/settings-ui/tailwind.config.cjs new file mode 100644 index 00000000..f5e2415a --- /dev/null +++ b/packages/settings-ui/tailwind.config.cjs @@ -0,0 +1,10 @@ +import tailwindConfig from '@glzr/components/tailwind.config.cjs'; + +/** @type {import('tailwindcss').Config} */ +module.exports = { + ...tailwindConfig, + content: [ + 'src/**/*.{ts,tsx}', + './node_modules/@glzr/components/dist/**/*.js', + ], +}; diff --git a/packages/settings-ui/tsconfig.json b/packages/settings-ui/tsconfig.json new file mode 100644 index 00000000..5d2faf0a --- /dev/null +++ b/packages/settings-ui/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true + } +} diff --git a/packages/settings-ui/vite.config.ts b/packages/settings-ui/vite.config.ts new file mode 100644 index 00000000..4fa5ad1d --- /dev/null +++ b/packages/settings-ui/vite.config.ts @@ -0,0 +1,17 @@ +import path from 'path'; +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; + +export default defineConfig({ + plugins: [solidPlugin()], + server: { + port: 4200, + }, + build: { target: 'esnext' }, + base: './', + resolve: { + alias: { + '~': path.resolve(__dirname, './src/app'), + }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acfcb7c8..e0993252 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: devDependencies: '@glzr/style-guide': specifier: 1.1.0 - version: 1.1.0(prettier@3.2.5)(typescript@5.3.3) + version: 1.1.0(prettier@3.2.5)(typescript@5.5.3) prettier: specifier: 3.2.5 version: 3.2.5 @@ -18,8 +18,8 @@ importers: examples/boilerplate-solid-ts: dependencies: solid-js: - specifier: 1.8.11 - version: 1.8.11 + specifier: 1.9.2 + version: 1.9.2 zebar: specifier: ^2.0.0 version: link:../../packages/client-api @@ -32,19 +32,19 @@ importers: version: 5.0.11(@types/node@20.11.17)(sass@1.70.0) vite-plugin-solid: specifier: 2.8.2 - version: 2.8.2(solid-js@1.8.11)(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)) + version: 2.8.2(solid-js@1.9.2)(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)) packages/client-api: dependencies: '@tauri-apps/api': - specifier: 2.0.0-rc.5 - version: 2.0.0-rc.5 + specifier: 2.0.2 + version: 2.0.2 '@tauri-apps/plugin-dialog': - specifier: 2.0.0-rc.1 - version: 2.0.0-rc.1 + specifier: 2.0.0 + version: 2.0.0 '@tauri-apps/plugin-shell': - specifier: 2.0.0-rc.1 - version: 2.0.0-rc.1 + specifier: 2.0.0 + version: 2.0.0 glazewm: specifier: 1.6.0 version: 1.6.0 @@ -63,7 +63,7 @@ importers: version: 0.20.0 tsup: specifier: 8.0.2 - version: 8.0.2(postcss@8.4.35)(typescript@5.3.3) + version: 8.0.2(postcss@8.4.47)(typescript@5.3.3) typescript: specifier: 5.3.3 version: 5.3.3 @@ -71,14 +71,61 @@ importers: packages/desktop: devDependencies: '@tauri-apps/cli': - specifier: 2.0.0-rc.16 - version: 2.0.0-rc.16 + specifier: 2.0.3 + version: 2.0.3 typescript: specifier: 5.3.3 version: 5.3.3 + packages/settings-ui: + dependencies: + '@glzr/components': + specifier: 1.0.2 + version: 1.0.2(solid-js@1.9.3) + '@solidjs/router': + specifier: 0.14.8 + version: 0.14.8(solid-js@1.9.3) + '@tabler/icons-solidjs': + specifier: 3.19.0 + version: 3.19.0(solid-js@1.9.3) + '@tauri-apps/api': + specifier: 2.0.2 + version: 2.0.2 + smorf: + specifier: 1.2.1 + version: 1.2.1(solid-js@1.9.3) + solid-js: + specifier: 1.9.3 + version: 1.9.3 + zebar: + specifier: ^2.0.0 + version: link:../client-api + devDependencies: + postcss: + specifier: 8.4.47 + version: 8.4.47 + tailwindcss: + specifier: '3.4.13 ' + version: 3.4.13 + tailwindcss-animate: + specifier: 1.0.7 + version: 1.0.7(tailwindcss@3.4.13) + typescript: + specifier: 5.3.3 + version: 5.3.3 + vite: + specifier: 5.4.10 + version: 5.4.10(@types/node@20.11.17)(sass@1.70.0) + vite-plugin-solid: + specifier: 2.10.2 + version: 2.10.2(solid-js@1.9.3)(vite@5.4.10(@types/node@20.11.17)(sass@1.70.0)) + packages: + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@ampproject/remapping@2.2.1': resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -239,6 +286,31 @@ packages: resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} engines: {node: '>=6.9.0'} + '@corvu/dialog@0.2.3': + resolution: {integrity: sha512-1p1lG2Pdu7CtDYw0FP+gdU0Db4zsB2ljOP7UxszZIQpvVvnrAYhNPfu/8IpscB38c0hZCodEnv5hR0NaEEA/Ag==} + peerDependencies: + solid-js: ^1.8 + + '@corvu/drawer@0.2.2': + resolution: {integrity: sha512-gj0dGnAc5fxoOe1E55uo8LPrHFxR+MaStn3UB8I1ZbtlJeeLDTK40uCc/Ee9xVxYpYNpUDX6ICGr3i23bsZyOA==} + peerDependencies: + solid-js: ^1.8 + + '@corvu/resizable@0.2.3': + resolution: {integrity: sha512-UwpObxqKlx1mc3G496Daz9NjK25Gx1V5fB8zIGazbq5tJs7aU8RjPW4png5OoNpMyxV7GQWjQtVc59zaAEVAJg==} + peerDependencies: + solid-js: ^1.8 + + '@corvu/utils@0.3.2': + resolution: {integrity: sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==} + peerDependencies: + solid-js: ^1.8 + + '@corvu/utils@0.4.2': + resolution: {integrity: sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==} + peerDependencies: + solid-js: ^1.8 + '@esbuild/aix-ppc64@0.19.11': resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} engines: {node: '>=12'} @@ -251,6 +323,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.19.11': resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} engines: {node: '>=12'} @@ -263,6 +341,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.19.11': resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} engines: {node: '>=12'} @@ -275,6 +359,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.19.11': resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} engines: {node: '>=12'} @@ -287,6 +377,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.19.11': resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} engines: {node: '>=12'} @@ -299,6 +395,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.19.11': resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} engines: {node: '>=12'} @@ -311,6 +413,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.19.11': resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} engines: {node: '>=12'} @@ -323,6 +431,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.19.11': resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} engines: {node: '>=12'} @@ -335,6 +449,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.19.11': resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} engines: {node: '>=12'} @@ -347,6 +467,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.19.11': resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} engines: {node: '>=12'} @@ -359,6 +485,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.19.11': resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} engines: {node: '>=12'} @@ -371,6 +503,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.19.11': resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} engines: {node: '>=12'} @@ -383,6 +521,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.19.11': resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} engines: {node: '>=12'} @@ -395,6 +539,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.19.11': resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} engines: {node: '>=12'} @@ -407,6 +557,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.19.11': resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} engines: {node: '>=12'} @@ -419,6 +575,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.19.11': resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} engines: {node: '>=12'} @@ -431,6 +593,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.19.11': resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} engines: {node: '>=12'} @@ -443,6 +611,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.19.11': resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} engines: {node: '>=12'} @@ -455,6 +629,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-x64@0.19.11': resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} engines: {node: '>=12'} @@ -467,6 +647,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.19.11': resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} engines: {node: '>=12'} @@ -479,6 +665,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.19.11': resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} engines: {node: '>=12'} @@ -491,6 +683,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.19.11': resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} engines: {node: '>=12'} @@ -503,6 +701,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.19.11': resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} engines: {node: '>=12'} @@ -515,6 +719,26 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@floating-ui/core@1.6.8': + resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==} + + '@floating-ui/dom@1.6.11': + resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==} + + '@floating-ui/utils@0.2.8': + resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} + + '@glzr/components@1.0.2': + resolution: {integrity: sha512-lpnj/mn05tMciI9TQH57VjyM5VdHpA14HHM89sCbpvMVYOxzI67DU+UxnjhWyLG5Ea7RX1sBUS2iR9fcmAsh7Q==} + peerDependencies: + solid-js: '>=1.7.0' + '@glzr/style-guide@1.1.0': resolution: {integrity: sha512-/AtA3ZXIbbJGaWjTjxK0BfM3IE92FxysIp3ltCzd9dbMrjRXBvQI6TZ0zUFJorZHV3f0vhyDSqEgjSTbAufv7w==} engines: {node: '>=16'} @@ -527,6 +751,12 @@ packages: typescript: optional: true + '@internationalized/date@3.5.6': + resolution: {integrity: sha512-jLxQjefH9VI5P9UQuqB6qNKnvFt1Ky1TPIzHGsIlCi7sZZoMR8SdYbBGRvM0y+Jtb+ez4ieBzmiAUcpmPYpyOw==} + + '@internationalized/number@3.5.4': + resolution: {integrity: sha512-h9huwWjNqYyE2FXZZewWqmCdkw1HeFds5q4Siuoms3hUQC5iPJK3aBmkFZoDSLN4UD0Bl8G22L/NdHpeOr+/7A==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -549,6 +779,16 @@ packages: '@jridgewell/trace-mapping@0.3.21': resolution: {integrity: sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==} + '@kobalte/core@0.13.7': + resolution: {integrity: sha512-COhjWk1KnCkl3qMJDvdrOsvpTlJ9gMLdemkAn5SWfbPn/lxJYabejnNOk+b/ILGg7apzQycgbuo48qb8ppqsAg==} + peerDependencies: + solid-js: ^1.8.15 + + '@kobalte/utils@0.9.1': + resolution: {integrity: sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w==} + peerDependencies: + solid-js: ^1.8.8 + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -574,139 +814,305 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.24.0': + resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.10.0': resolution: {integrity: sha512-lvu0jK97mZDJdpZKDnZI93I0Om8lSDaiPx3OiCk0RXn3E8CMPJNS/wxjAvSJJzhhZpfjXsjLWL8LnS6qET4VNQ==} cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.24.0': + resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.10.0': resolution: {integrity: sha512-uFpayx8I8tyOvDkD7X6n0PriDRWxcqEjqgtlxnUA/G9oS93ur9aZ8c8BEpzFmsed1TH5WZNG5IONB8IiW90TQg==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.24.0': + resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.10.0': resolution: {integrity: sha512-nIdCX03qFKoR/MwQegQBK+qZoSpO3LESurVAC6s6jazLA1Mpmgzo3Nj3H1vydXp/JM29bkCiuF7tDuToj4+U9Q==} cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.24.0': + resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-linux-arm-gnueabihf@4.10.0': resolution: {integrity: sha512-Fz7a+y5sYhYZMQFRkOyCs4PLhICAnxRX/GnWYReaAoruUzuRtcf+Qnw+T0CoAWbHCuz2gBUwmWnUgQ67fb3FYw==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.10.0': resolution: {integrity: sha512-yPtF9jIix88orwfTi0lJiqINnlWo6p93MtZEoaehZnmCzEmLL0eqjA3eGVeyQhMtxdV+Mlsgfwhh0+M/k1/V7Q==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.24.0': + resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.10.0': resolution: {integrity: sha512-9GW9yA30ib+vfFiwjX+N7PnjTnCMiUffhWj4vkG4ukYv1kJ4T9gHNg8zw+ChsOccM27G9yXrEtMScf1LaCuoWQ==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.24.0': + resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.10.0': resolution: {integrity: sha512-X1ES+V4bMq2ws5fF4zHornxebNxMXye0ZZjUrzOrf7UMx1d6wMQtfcchZ8SqUnQPPHdOyOLW6fTcUiFgHFadRA==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.24.0': + resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.10.0': resolution: {integrity: sha512-w/5OpT2EnI/Xvypw4FIhV34jmNqU5PZjZue2l2Y3ty1Ootm3SqhI+AmfhlUYGBTd9JnpneZCDnt3uNOiOBkMyw==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.24.0': + resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.10.0': resolution: {integrity: sha512-q/meftEe3QlwQiGYxD9rWwB21DoKQ9Q8wA40of/of6yGHhZuGfZO0c3WYkN9dNlopHlNT3mf5BPsUSxoPuVQaw==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.24.0': + resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + cpu: [x64] + os: [linux] + '@rollup/rollup-win32-arm64-msvc@4.10.0': resolution: {integrity: sha512-NrR6667wlUfP0BHaEIKgYM/2va+Oj+RjZSASbBMnszM9k+1AmliRjHc3lJIiOehtSSjqYiO7R6KLNrWOX+YNSQ==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.24.0': + resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.10.0': resolution: {integrity: sha512-FV0Tpt84LPYDduIDcXvEC7HKtyXxdvhdAOvOeWMWbQNulxViH2O07QXkT/FffX4FqEI02jEbCJbr+YcuKdyyMg==} cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.24.0': + resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.10.0': resolution: {integrity: sha512-OZoJd+o5TaTSQeFFQ6WjFCiltiYVjIdsXxwu/XZ8qRpsvMQr4UsVrE5UyT9RIvsnuF47DqkJKhhVZ2Q9YW9IpQ==} cpu: [x64] os: [win32] - '@tauri-apps/api@2.0.0-rc.5': - resolution: {integrity: sha512-JWs69pE9NsQdcqTpEVBepAZ08+jgQWuthIiTiaWRq/YlCLgnqq0KfC9sDem55uJ0YpgsytZuyj+m6b6q8oiD2g==} + '@rollup/rollup-win32-x64-msvc@4.24.0': + resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + cpu: [x64] + os: [win32] + + '@solid-primitives/event-listener@2.3.3': + resolution: {integrity: sha512-DAJbl+F0wrFW2xmcV8dKMBhk9QLVLuBSW+TR4JmIfTaObxd13PuL7nqaXnaYKDWOYa6otB00qcCUIGbuIhSUgQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/keyed@1.2.2': + resolution: {integrity: sha512-oBziY40JK4XmJ57XGkFl8j0GtEarSu0hhjdkUQgqL/U0QQE3TZrRo9uhgH7I6VGJKBKG7SAraTPE6S5lVLM1ow==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/map@0.4.13': + resolution: {integrity: sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/media@2.2.9': + resolution: {integrity: sha512-QUmU62D4/d9YWx/4Dvr/UZasIkIpqNXz7wosA5GLmesRW9XlPa3G5M6uOmTw73SByHNTCw0D6x8bSdtvvLgzvQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/memo@1.3.9': + resolution: {integrity: sha512-OIlGcsEPXr6U23fDaSEm8iqezWDT4SNSjLTekWQVOu4qHostnMPlqU8xo1Jf0I7OgRuqA0wTMQ5cu0bYjeR/ZQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/props@3.1.11': + resolution: {integrity: sha512-jZAKWwvDRHjiydIumDgMj68qviIbowQ1ci7nkEAgzgvanNkhKSQV8iPgR2jMk1uv7S2ZqXYHslVQTgJel/TEyg==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/refs@1.0.8': + resolution: {integrity: sha512-+jIsWG8/nYvhaCoG2Vg6CJOLgTmPKFbaCrNQKWfChalgUf9WrVxWw0CdJb3yX15n5lUcQ0jBo6qYtuVVmBLpBw==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/resize-observer@2.0.26': + resolution: {integrity: sha512-KbPhwal6ML9OHeUTZszBbt6PYSMj89d4wVCLxlvDYL4U0+p+xlCEaqz6v9dkCwm/0Lb+Wed7W5T1dQZCP3JUUw==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/rootless@1.4.5': + resolution: {integrity: sha512-GFJE9GC3ojx0aUKqAUZmQPyU8fOVMtnVNrkdk2yS4kd17WqVSpXpoTmo9CnOwA+PG7FTzdIkogvfLQSLs4lrww==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/scheduled@1.4.3': + resolution: {integrity: sha512-HfWN5w7b7FEc6VPLBKnnE302h90jsLMuR28Fcf7neRGGf8jBj6wm6/UFQ00VlKexHFMR6KQ2u4VBh5a1ZcqM8g==} + peerDependencies: + solid-js: ^1.6.12 - '@tauri-apps/cli-darwin-arm64@2.0.0-rc.16': - resolution: {integrity: sha512-lISZU4gG0c9PbY7h/j/gW7nJLxZEygNBrYEET6zN8R99Znf5rSO+CfjenaMcJUUj6yTAd8gzdakRpLqNSAWegA==} + '@solid-primitives/set@0.5.0': + resolution: {integrity: sha512-ccMQ89GtBrCZpGk4GKnWe+WurYe+UlK4yyiPxb0KetHqsBRLYcOkYHSDMmERNw3rwn8Cb/aVprKH0khoJqZe8g==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/static-store@0.0.8': + resolution: {integrity: sha512-ZecE4BqY0oBk0YG00nzaAWO5Mjcny8Fc06CdbXadH9T9lzq/9GefqcSe/5AtdXqjvY/DtJ5C6CkcjPZO0o/eqg==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/trigger@1.1.0': + resolution: {integrity: sha512-00BbAiXV66WwjHuKZc3wr0+GLb9C24mMUmi3JdTpNFgHBbrQGrIHubmZDg36c5/7wH+E0GQtOOanwQS063PO+A==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/utils@6.2.3': + resolution: {integrity: sha512-CqAwKb2T5Vi72+rhebSsqNZ9o67buYRdEJrIFzRXz3U59QqezuuxPsyzTSVCacwS5Pf109VRsgCJQoxKRoECZQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solidjs/router@0.14.8': + resolution: {integrity: sha512-S+rD5Twp0820cM03wEIYtb7/4KN7Cfr3BP+qPIqb7IXO/SZ72tWqHEMQsmcjDbr4yVfpA+5Sq0Y+xcq09y1gQA==} + peerDependencies: + solid-js: ^1.8.6 + + '@swc/helpers@0.5.13': + resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + + '@tabler/icons-solidjs@3.19.0': + resolution: {integrity: sha512-wtYft78GxbQvLu/I6XAqBdXGmLsw/oDnniL9/BcFmSQLthtqLEZiq3V7dwF924U364cc/NysTXoWbQMRR45uCA==} + peerDependencies: + solid-js: ^1.4.7 + + '@tabler/icons@3.19.0': + resolution: {integrity: sha512-A4WEWqpdbTfnpFEtwXqwAe9qf9sp1yRPvzppqAuwcoF0q5YInqB+JkJtSFToCyBpPVeLxJUxxkapLvt2qQgnag==} + + '@tauri-apps/api@2.0.2': + resolution: {integrity: sha512-3wSwmG+1kr6WrgAFKK5ijkNFPp8TT3FLj3YHUb5EwMO+3FxX4uWlfSWkeeBy+Kc1RsKzugtYLuuya+98Flj+3w==} + + '@tauri-apps/cli-darwin-arm64@2.0.3': + resolution: {integrity: sha512-jIsbxGWS+As1ZN7umo90nkql/ZAbrDK0GBT6UsgHSz5zSwwArICsZFFwE1pLZip5yoiV5mn3TGG2c1+v+0puzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.0.0-rc.16': - resolution: {integrity: sha512-D9uxPCxpyYcTSQulJGFX3POAKPOJd8WcWHFH8x6YVM1cIx6EWRXIE1sZnPUOjFr7qCg+bSdYdr8/BFHcZGcApQ==} + '@tauri-apps/cli-darwin-x64@2.0.3': + resolution: {integrity: sha512-ROITHtLTA1muyrwgyuwyasmaLCGtT4as/Kd1kerXaSDtFcYrnxiM984ZD0+FDUEDl5BgXtYa/sKKkKQFjgmM0A==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.16': - resolution: {integrity: sha512-WsVdKm4D1I1XV8I9yRnmOINZRwwWfh6xcLV3m19+B9g6TohK8RkRxWfxvs3TLQlWOLQ6lo8BzS9rzXB+KtjDpg==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.0.3': + resolution: {integrity: sha512-bQ3EZwCFfrLg/ZQ2I8sLuifSxESz4TP56SleTkKsPtTIZgNnKpM88PRDz4neiRroHVOq8NK0X276qi9LjGcXPw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.16': - resolution: {integrity: sha512-2jpZDagNs6rrqposHJihHBayttgOl5aB2+bYiVEC6ye+haiFtmYmpdaPOaVIw+YVQs6lepf5PVrisCoU9DmYsg==} + '@tauri-apps/cli-linux-arm64-gnu@2.0.3': + resolution: {integrity: sha512-aLfAA8P9OTErVUk3sATxtXqpAtlfDPMPp4fGjDysEELG/MyekGhmh2k/kG/i32OdPeCfO+Nr37wJksARJKubGw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.16': - resolution: {integrity: sha512-SNEDcB+sWOls/B0a+UpUHVa/oegvlXXKYWsTxuXtgWIr5VbWG7rXLZ3fZpLLP3SpRVGTGTnABcyqshFbWSqqKQ==} + '@tauri-apps/cli-linux-arm64-musl@2.0.3': + resolution: {integrity: sha512-I4MVD7nf6lLLRmNQPpe5beEIFM6q7Zkmh77ROA5BNu/+vHNL5kiTMD+bmd10ZL2r753A6pO7AvqkIxcBuIl0tg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.16': - resolution: {integrity: sha512-Zsq29MM1ooeH1+chQBa7ffDFnzAZebBBFdsvs4e05tS1H8gn4oKE+PSMn9p/okzVXykEk9ri2/n7BG1XFeifMA==} + '@tauri-apps/cli-linux-x64-gnu@2.0.3': + resolution: {integrity: sha512-C6Jkx2zZGKkoi+sg5FK9GoH/0EvAaOgrZfF5azV5EALGba46g7VpWcZgp9zFUd7K2IzTi+0OOY8TQ2OVfKZgew==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-linux-x64-musl@2.0.0-rc.16': - resolution: {integrity: sha512-g+pwSuis2YMxhJJ/pJYwp/Nps5CWvlv/5MV5UfDvClkCkeAyzIqVX+HbBLPcs5S0CePUQNeP0j4d4jBWUqZZQg==} + '@tauri-apps/cli-linux-x64-musl@2.0.3': + resolution: {integrity: sha512-qi4ghmTfSAl+EEUDwmwI9AJUiOLNSmU1RgiGgcPRE+7A/W+Am9UnxYySAiRbB/gJgTl9sj/pqH5Y9duP1/sqHg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.16': - resolution: {integrity: sha512-PpPqdMTwJSDAK4KnNjvh77ShSkY+7pih1f6e50EtXar8bjC17e3XcEqFhDNne5mxEVTLYhibs6p1JLPad0ZjRA==} + '@tauri-apps/cli-win32-arm64-msvc@2.0.3': + resolution: {integrity: sha512-UXxHkYmFesC97qVmZre4vY7oDxRDtC2OeKNv0bH+iSnuUp/ROxzJYGyaelnv9Ybvgl4YVqDCnxgB28qMM938TA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.16': - resolution: {integrity: sha512-io2yIcEcG7YLP+9n13NbilB93SjcB7jIl8GbURC4XZT4/4t9D1PWHpJr5hySVsGRLCz5e8NzwC5RlnenNzmpPQ==} + '@tauri-apps/cli-win32-ia32-msvc@2.0.3': + resolution: {integrity: sha512-D+xoaa35RGlkXDpnL5uDTpj29untuC5Wp6bN9snfgFDagD0wnFfC8+2ZQGu16bD0IteWqDI0OSoIXhNvy+F+wg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.16': - resolution: {integrity: sha512-Rfkmxe3k+cBVA/kVYt8O25QrQqWKJlH9AiH7Q3C6xBzzG9PCSRMBszCp+JhBF8jhVlwNmOBv6UG+lm85kspwGg==} + '@tauri-apps/cli-win32-x64-msvc@2.0.3': + resolution: {integrity: sha512-eWV9XWb4dSYHXl13OtYWLjX1JHphUEkHkkGwJrhr8qFBm7RbxXxQvrsUEprSi51ug/dwJenjJgM4zR8By4htfw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tauri-apps/cli@2.0.0-rc.16': - resolution: {integrity: sha512-wdjZg/M3dcxiqgWG6VRnABpX0dYxRww93t0d1MYoZxFDrnyoUz5kYwFQ0v4J9u0qenEgskjoypvon7V/Nj9qrg==} + '@tauri-apps/cli@2.0.3': + resolution: {integrity: sha512-JwEyhc5BAVpn4E8kxzY/h7+bVOiXQdudR1r3ODMfyyumZBfgIWqpD/WuTcPq6Yjchju1BSS+80jAE/oYwI/RKg==} engines: {node: '>= 10'} hasBin: true - '@tauri-apps/plugin-dialog@2.0.0-rc.1': - resolution: {integrity: sha512-H28gh6BfZtjflHQ+HrmWwunDriBI3AQLAKnMs50GA6zeNUULqbQr7VXbAAKeJL/0CmWcecID4PKXVoSlaWRhEg==} + '@tauri-apps/plugin-dialog@2.0.0': + resolution: {integrity: sha512-ApNkejXP2jpPBSifznPPcHTXxu9/YaRW+eJ+8+nYwqp0lLUtebFHG4QhxitM43wwReHE81WAV1DQ/b+2VBftOA==} - '@tauri-apps/plugin-shell@2.0.0-rc.1': - resolution: {integrity: sha512-JtNROc0rqEwN/g93ig5pK4cl1vUo2yn+osCpY9de64cy/d9hRzof7AuYOgvt/Xcd5VPQmlgo2AGvUh5sQRSR1A==} + '@tauri-apps/plugin-shell@2.0.0': + resolution: {integrity: sha512-OpW2+ycgJLrEoZityWeWYk+6ZWP9VyiAfbO+N/O8VfLkqyOym8kXh7odKDfINx9RAotkSGBtQM4abyKfJDkcUg==} '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -723,6 +1129,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/luxon@3.4.2': resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} @@ -756,6 +1165,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -811,6 +1223,10 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + caniuse-lite@1.0.30001576: resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==} @@ -822,6 +1238,13 @@ packages: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} + class-variance-authority@0.7.0: + resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} + + clsx@2.0.0: + resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} + engines: {node: '>=6'} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -846,6 +1269,11 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -878,16 +1306,35 @@ packages: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} electron-to-chromium@1.4.630: resolution: {integrity: sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==} + embla-carousel-reactive-utils@8.3.0: + resolution: {integrity: sha512-EYdhhJ302SC4Lmkx8GRsp0sjUhEN4WyFXPOk0kGu9OXZSRMmcBlRgTvHcq8eKJE1bXWBsOi1T83B+BSSVZSmwQ==} + peerDependencies: + embla-carousel: 8.3.0 + + embla-carousel-solid@8.3.0: + resolution: {integrity: sha512-QYwzYD+X65oX7agioW3BXEONH1aIrJDW5VgsDLy+Cqf3SzxMLcgh6V9BB8etdaQ6v+PRRZy/t12kkvCX1PFK0g==} + peerDependencies: + solid-js: ^1.0.0 + + embla-carousel@8.3.0: + resolution: {integrity: sha512-Ve8dhI4w28qBqR8J+aMtv7rLK89r1ZA5HocwFz6uMB/i5EiC7bGI7y+AM80yAVUJw3qqaZYK7clmZMUR8kM3UA==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -904,6 +1351,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -940,6 +1392,9 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -968,6 +1423,10 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -989,6 +1448,10 @@ packages: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} @@ -1011,6 +1474,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -1069,6 +1536,10 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -1086,6 +1557,10 @@ packages: engines: {node: '>=6'} hasBin: true + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + lilconfig@3.0.0: resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} engines: {node: '>=14'} @@ -1172,6 +1647,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -1192,6 +1671,9 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.10.1: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} @@ -1203,14 +1685,33 @@ packages: picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + postcss-load-config@4.0.2: resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} @@ -1223,10 +1724,27 @@ packages: ts-node: optional: true + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.35: resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + prettier-plugin-astro@0.12.3: resolution: {integrity: sha512-GthUSu3zCvmtVyqlArosez0xE08vSJ0R1sWurxIWpABaCkNGYFANoUdFkqmIo54EV2uPLGcVJzOucWvCjPBWvg==} engines: {node: ^14.15.0 || >=16.0.0} @@ -1251,6 +1769,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1259,6 +1780,10 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1268,6 +1793,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.24.0: + resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-applescript@5.0.0: resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} engines: {node: '>=12'} @@ -1290,14 +1820,14 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - seroval-plugins@1.0.4: - resolution: {integrity: sha512-DQ2IK6oQVvy8k+c2V5x5YCtUa/GGGsUwUBNN9UqohrZ0rWdUapBFpNMYP1bCyRHoxOJjdKGl+dieacFIpU/i1A==} + seroval-plugins@1.1.1: + resolution: {integrity: sha512-qNSy1+nUj7hsCOon7AO4wdAIo9P0jrzAMp18XhiOzA6/uO5TKtP7ScozVJ8T293oRIvi5wyCHSM4TrJo/c/GJA==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.0.4: - resolution: {integrity: sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg==} + seroval@1.1.1: + resolution: {integrity: sha512-rqEO6FZk8mv7Hyv4UCj3FD3b6Waqft605TLfsCe/BiaylRpyyMC0b+uA5TJKawX3KzMrdi3wsLbCaLplrQmBvQ==} engines: {node: '>=10'} shebang-command@2.0.0: @@ -1323,14 +1853,47 @@ packages: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - solid-js@1.8.11: - resolution: {integrity: sha512-WdwmER+TwBJiN4rVQTVBxocg+9pKlOs41KzPYntrC86xO5sek8TzBYozPEZPL1IRWDouf2lMrvSbIs3CanlPvQ==} + smorf@1.2.1: + resolution: {integrity: sha512-Vec1HgBE3/4YYtrN+q8kAL/I3Ew+SitEMqX8H4v2SxibVElVSJXtiSskW0wSlcOIXApEXGkBqH+FJTlFIdjQpA==} + peerDependencies: + solid-js: '>=1.7.0' + + solid-dismissible@0.1.1: + resolution: {integrity: sha512-9kcKBJIMdS+586cA1g63HYWxKh3h89leeNHbPZ1csYjuni+NvPBtNr11l0iEX2AKKEt6FHk6qNhc/gjoYAW1pA==} + peerDependencies: + solid-js: ^1.8 + + solid-focus-trap@0.1.7: + resolution: {integrity: sha512-NSJiIkL+WTWGgca+OKQA9rV3bD51lT23iLn1Z+Ap1Qk3rJBxQ8SoEAQ0FvXoQThtyXFKAK1ibcVBBMMEcu6YMw==} + peerDependencies: + solid-js: ^1.8 + + solid-js@1.9.2: + resolution: {integrity: sha512-fe/K03nV+kMFJYhAOE8AIQHcGxB4rMIEoEyrulbtmf217NffbbwBqJnJI4ovt16e+kaIt0czE2WA7mP/pYN9yg==} + + solid-js@1.9.3: + resolution: {integrity: sha512-5ba3taPoZGt9GY3YlsCB24kCg0Lv/rie/HTD4kG6h4daZZz7+yK02xn8Vx8dLYBc9i6Ps5JwAbEiqjmKaLB3Ag==} + + solid-presence@0.1.8: + resolution: {integrity: sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA==} + peerDependencies: + solid-js: ^1.8 + + solid-prevent-scroll@0.1.10: + resolution: {integrity: sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw==} + peerDependencies: + solid-js: ^1.8 solid-refresh@0.6.3: resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} peerDependencies: solid-js: ^1.3 + solid-transition-size@0.1.4: + resolution: {integrity: sha512-ocHVnbfy23CgfaH4cEUR/AFg0Y3CEL8Oh3n9Qv8OHFJgPh+zkmERKZQfi/xH5XvxDCizg8VjPrVUhiHB1Gza8g==} + peerDependencies: + solid-js: ^1.8 + sort-object-keys@1.1.3: resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} @@ -1342,6 +1905,10 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} @@ -1382,10 +1949,27 @@ packages: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} + tailwind-merge@2.5.4: + resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} + + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + + tailwindcss@3.4.13: + resolution: {integrity: sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==} + engines: {node: '>=14.0.0'} + hasBin: true + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -1440,11 +2024,20 @@ packages: typescript: optional: true + type-fest@4.26.1: + resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} + engines: {node: '>=16'} + typescript@5.3.3: resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} + engines: {node: '>=14.17'} + hasBin: true + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -1458,17 +2051,58 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + validate-html-nesting@1.2.2: resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} + vite-plugin-solid@2.10.2: + resolution: {integrity: sha512-AOEtwMe2baBSXMXdo+BUwECC8IFHcKS6WQV/1NEd+Q7vHPap5fmIhLcAzr+DUJ04/KHx/1UBU0l1/GWP+rMAPQ==} + peerDependencies: + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^1.7.2 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + '@testing-library/jest-dom': + optional: true + vite-plugin-solid@2.8.2: resolution: {integrity: sha512-HcvMs6DTxBaO4kE3psnirPQBCUUdYeQkCNKuB2TpEkJsxb6BGP6/7qkbbCSMxn25PyNdjvzVi1WXi0ou8KPgHw==} peerDependencies: solid-js: ^1.7.2 vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - vite@5.0.11: - resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + vite@5.0.11: + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@5.4.10: + resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -1476,6 +2110,7 @@ packages: less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -1488,6 +2123,8 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: @@ -1534,6 +2171,8 @@ packages: snapshots: + '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.2.1': dependencies: '@jridgewell/gen-mapping': 0.3.3 @@ -1742,151 +2381,282 @@ snapshots: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + '@corvu/dialog@0.2.3(solid-js@1.9.3)': + dependencies: + '@corvu/utils': 0.4.2(solid-js@1.9.3) + solid-dismissible: 0.1.1(solid-js@1.9.3) + solid-focus-trap: 0.1.7(solid-js@1.9.3) + solid-js: 1.9.3 + solid-presence: 0.1.8(solid-js@1.9.3) + solid-prevent-scroll: 0.1.10(solid-js@1.9.3) + + '@corvu/drawer@0.2.2(solid-js@1.9.3)': + dependencies: + '@corvu/dialog': 0.2.3(solid-js@1.9.3) + '@corvu/utils': 0.3.2(solid-js@1.9.3) + '@solid-primitives/memo': 1.3.9(solid-js@1.9.3) + solid-js: 1.9.3 + solid-transition-size: 0.1.4(solid-js@1.9.3) + + '@corvu/resizable@0.2.3(solid-js@1.9.3)': + dependencies: + '@corvu/utils': 0.4.2(solid-js@1.9.3) + solid-js: 1.9.3 + + '@corvu/utils@0.3.2(solid-js@1.9.3)': + dependencies: + '@floating-ui/dom': 1.6.11 + solid-js: 1.9.3 + + '@corvu/utils@0.4.2(solid-js@1.9.3)': + dependencies: + '@floating-ui/dom': 1.6.11 + solid-js: 1.9.3 + '@esbuild/aix-ppc64@0.19.11': optional: true '@esbuild/aix-ppc64@0.20.0': optional: true + '@esbuild/aix-ppc64@0.21.5': + optional: true + '@esbuild/android-arm64@0.19.11': optional: true '@esbuild/android-arm64@0.20.0': optional: true + '@esbuild/android-arm64@0.21.5': + optional: true + '@esbuild/android-arm@0.19.11': optional: true '@esbuild/android-arm@0.20.0': optional: true + '@esbuild/android-arm@0.21.5': + optional: true + '@esbuild/android-x64@0.19.11': optional: true '@esbuild/android-x64@0.20.0': optional: true + '@esbuild/android-x64@0.21.5': + optional: true + '@esbuild/darwin-arm64@0.19.11': optional: true '@esbuild/darwin-arm64@0.20.0': optional: true + '@esbuild/darwin-arm64@0.21.5': + optional: true + '@esbuild/darwin-x64@0.19.11': optional: true '@esbuild/darwin-x64@0.20.0': optional: true + '@esbuild/darwin-x64@0.21.5': + optional: true + '@esbuild/freebsd-arm64@0.19.11': optional: true '@esbuild/freebsd-arm64@0.20.0': optional: true + '@esbuild/freebsd-arm64@0.21.5': + optional: true + '@esbuild/freebsd-x64@0.19.11': optional: true '@esbuild/freebsd-x64@0.20.0': optional: true + '@esbuild/freebsd-x64@0.21.5': + optional: true + '@esbuild/linux-arm64@0.19.11': optional: true '@esbuild/linux-arm64@0.20.0': optional: true + '@esbuild/linux-arm64@0.21.5': + optional: true + '@esbuild/linux-arm@0.19.11': optional: true '@esbuild/linux-arm@0.20.0': optional: true + '@esbuild/linux-arm@0.21.5': + optional: true + '@esbuild/linux-ia32@0.19.11': optional: true '@esbuild/linux-ia32@0.20.0': optional: true + '@esbuild/linux-ia32@0.21.5': + optional: true + '@esbuild/linux-loong64@0.19.11': optional: true '@esbuild/linux-loong64@0.20.0': optional: true + '@esbuild/linux-loong64@0.21.5': + optional: true + '@esbuild/linux-mips64el@0.19.11': optional: true '@esbuild/linux-mips64el@0.20.0': optional: true + '@esbuild/linux-mips64el@0.21.5': + optional: true + '@esbuild/linux-ppc64@0.19.11': optional: true '@esbuild/linux-ppc64@0.20.0': optional: true + '@esbuild/linux-ppc64@0.21.5': + optional: true + '@esbuild/linux-riscv64@0.19.11': optional: true '@esbuild/linux-riscv64@0.20.0': optional: true + '@esbuild/linux-riscv64@0.21.5': + optional: true + '@esbuild/linux-s390x@0.19.11': optional: true '@esbuild/linux-s390x@0.20.0': optional: true + '@esbuild/linux-s390x@0.21.5': + optional: true + '@esbuild/linux-x64@0.19.11': optional: true '@esbuild/linux-x64@0.20.0': optional: true + '@esbuild/linux-x64@0.21.5': + optional: true + '@esbuild/netbsd-x64@0.19.11': optional: true '@esbuild/netbsd-x64@0.20.0': optional: true + '@esbuild/netbsd-x64@0.21.5': + optional: true + '@esbuild/openbsd-x64@0.19.11': optional: true '@esbuild/openbsd-x64@0.20.0': optional: true + '@esbuild/openbsd-x64@0.21.5': + optional: true + '@esbuild/sunos-x64@0.19.11': optional: true '@esbuild/sunos-x64@0.20.0': optional: true + '@esbuild/sunos-x64@0.21.5': + optional: true + '@esbuild/win32-arm64@0.19.11': optional: true '@esbuild/win32-arm64@0.20.0': optional: true + '@esbuild/win32-arm64@0.21.5': + optional: true + '@esbuild/win32-ia32@0.19.11': optional: true '@esbuild/win32-ia32@0.20.0': optional: true + '@esbuild/win32-ia32@0.21.5': + optional: true + '@esbuild/win32-x64@0.19.11': optional: true '@esbuild/win32-x64@0.20.0': optional: true - '@glzr/style-guide@1.1.0(prettier@3.2.5)(typescript@5.3.3)': + '@esbuild/win32-x64@0.21.5': + optional: true + + '@floating-ui/core@1.6.8': + dependencies: + '@floating-ui/utils': 0.2.8 + + '@floating-ui/dom@1.6.11': + dependencies: + '@floating-ui/core': 1.6.8 + '@floating-ui/utils': 0.2.8 + + '@floating-ui/utils@0.2.8': {} + + '@glzr/components@1.0.2(solid-js@1.9.3)': + dependencies: + '@corvu/drawer': 0.2.2(solid-js@1.9.3) + '@corvu/resizable': 0.2.3(solid-js@1.9.3) + '@kobalte/core': 0.13.7(solid-js@1.9.3) + '@tabler/icons-solidjs': 3.19.0(solid-js@1.9.3) + class-variance-authority: 0.7.0 + embla-carousel-solid: 8.3.0(solid-js@1.9.3) + solid-js: 1.9.3 + tailwind-merge: 2.5.4 + + '@glzr/style-guide@1.1.0(prettier@3.2.5)(typescript@5.5.3)': dependencies: prettier-plugin-astro: 0.12.3 prettier-plugin-packagejson: 2.4.5(prettier@3.2.5) optionalDependencies: prettier: 3.2.5 - typescript: 5.3.3 + typescript: 5.5.3 + + '@internationalized/date@3.5.6': + dependencies: + '@swc/helpers': 0.5.13 + + '@internationalized/number@3.5.4': + dependencies: + '@swc/helpers': 0.5.13 '@isaacs/cliui@8.0.2': dependencies: @@ -1914,6 +2684,29 @@ snapshots: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + '@kobalte/core@0.13.7(solid-js@1.9.3)': + dependencies: + '@floating-ui/dom': 1.6.11 + '@internationalized/date': 3.5.6 + '@internationalized/number': 3.5.4 + '@kobalte/utils': 0.9.1(solid-js@1.9.3) + '@solid-primitives/props': 3.1.11(solid-js@1.9.3) + '@solid-primitives/resize-observer': 2.0.26(solid-js@1.9.3) + solid-js: 1.9.3 + solid-presence: 0.1.8(solid-js@1.9.3) + solid-prevent-scroll: 0.1.10(solid-js@1.9.3) + + '@kobalte/utils@0.9.1(solid-js@1.9.3)': + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.9.3) + '@solid-primitives/keyed': 1.2.2(solid-js@1.9.3) + '@solid-primitives/map': 0.4.13(solid-js@1.9.3) + '@solid-primitives/media': 2.2.9(solid-js@1.9.3) + '@solid-primitives/props': 3.1.11(solid-js@1.9.3) + '@solid-primitives/refs': 1.0.8(solid-js@1.9.3) + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1941,94 +2734,231 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.10.0': optional: true + '@rollup/rollup-android-arm-eabi@4.24.0': + optional: true + '@rollup/rollup-android-arm64@4.10.0': optional: true + '@rollup/rollup-android-arm64@4.24.0': + optional: true + '@rollup/rollup-darwin-arm64@4.10.0': optional: true + '@rollup/rollup-darwin-arm64@4.24.0': + optional: true + '@rollup/rollup-darwin-x64@4.10.0': optional: true + '@rollup/rollup-darwin-x64@4.24.0': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.10.0': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.10.0': optional: true + '@rollup/rollup-linux-arm64-gnu@4.24.0': + optional: true + '@rollup/rollup-linux-arm64-musl@4.10.0': optional: true + '@rollup/rollup-linux-arm64-musl@4.24.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.10.0': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.24.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.10.0': optional: true + '@rollup/rollup-linux-x64-gnu@4.24.0': + optional: true + '@rollup/rollup-linux-x64-musl@4.10.0': optional: true + '@rollup/rollup-linux-x64-musl@4.24.0': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.10.0': optional: true + '@rollup/rollup-win32-arm64-msvc@4.24.0': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.10.0': optional: true + '@rollup/rollup-win32-ia32-msvc@4.24.0': + optional: true + '@rollup/rollup-win32-x64-msvc@4.10.0': optional: true - '@tauri-apps/api@2.0.0-rc.5': {} + '@rollup/rollup-win32-x64-msvc@4.24.0': + optional: true + + '@solid-primitives/event-listener@2.3.3(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/keyed@1.2.2(solid-js@1.9.3)': + dependencies: + solid-js: 1.9.3 + + '@solid-primitives/map@0.4.13(solid-js@1.9.3)': + dependencies: + '@solid-primitives/trigger': 1.1.0(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/media@2.2.9(solid-js@1.9.3)': + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.9.3) + '@solid-primitives/rootless': 1.4.5(solid-js@1.9.3) + '@solid-primitives/static-store': 0.0.8(solid-js@1.9.3) + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/memo@1.3.9(solid-js@1.9.3)': + dependencies: + '@solid-primitives/scheduled': 1.4.3(solid-js@1.9.3) + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/props@3.1.11(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/refs@1.0.8(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/resize-observer@2.0.26(solid-js@1.9.3)': + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.9.3) + '@solid-primitives/rootless': 1.4.5(solid-js@1.9.3) + '@solid-primitives/static-store': 0.0.8(solid-js@1.9.3) + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/rootless@1.4.5(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/scheduled@1.4.3(solid-js@1.9.3)': + dependencies: + solid-js: 1.9.3 + + '@solid-primitives/set@0.5.0(solid-js@1.9.3)': + dependencies: + '@solid-primitives/trigger': 1.1.0(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/static-store@0.0.8(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/trigger@1.1.0(solid-js@1.9.3)': + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.9.3) + solid-js: 1.9.3 + + '@solid-primitives/utils@6.2.3(solid-js@1.9.3)': + dependencies: + solid-js: 1.9.3 + + '@solidjs/router@0.14.8(solid-js@1.9.3)': + dependencies: + solid-js: 1.9.3 + + '@swc/helpers@0.5.13': + dependencies: + tslib: 2.6.2 + + '@tabler/icons-solidjs@3.19.0(solid-js@1.9.3)': + dependencies: + '@tabler/icons': 3.19.0 + solid-js: 1.9.3 + + '@tabler/icons@3.19.0': {} - '@tauri-apps/cli-darwin-arm64@2.0.0-rc.16': + '@tauri-apps/api@2.0.2': {} + + '@tauri-apps/cli-darwin-arm64@2.0.3': optional: true - '@tauri-apps/cli-darwin-x64@2.0.0-rc.16': + '@tauri-apps/cli-darwin-x64@2.0.3': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.16': + '@tauri-apps/cli-linux-arm-gnueabihf@2.0.3': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.16': + '@tauri-apps/cli-linux-arm64-gnu@2.0.3': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.16': + '@tauri-apps/cli-linux-arm64-musl@2.0.3': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.16': + '@tauri-apps/cli-linux-x64-gnu@2.0.3': optional: true - '@tauri-apps/cli-linux-x64-musl@2.0.0-rc.16': + '@tauri-apps/cli-linux-x64-musl@2.0.3': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.16': + '@tauri-apps/cli-win32-arm64-msvc@2.0.3': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.16': + '@tauri-apps/cli-win32-ia32-msvc@2.0.3': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.16': + '@tauri-apps/cli-win32-x64-msvc@2.0.3': optional: true - '@tauri-apps/cli@2.0.0-rc.16': + '@tauri-apps/cli@2.0.3': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.0.0-rc.16 - '@tauri-apps/cli-darwin-x64': 2.0.0-rc.16 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.0.0-rc.16 - '@tauri-apps/cli-linux-arm64-gnu': 2.0.0-rc.16 - '@tauri-apps/cli-linux-arm64-musl': 2.0.0-rc.16 - '@tauri-apps/cli-linux-x64-gnu': 2.0.0-rc.16 - '@tauri-apps/cli-linux-x64-musl': 2.0.0-rc.16 - '@tauri-apps/cli-win32-arm64-msvc': 2.0.0-rc.16 - '@tauri-apps/cli-win32-ia32-msvc': 2.0.0-rc.16 - '@tauri-apps/cli-win32-x64-msvc': 2.0.0-rc.16 + '@tauri-apps/cli-darwin-arm64': 2.0.3 + '@tauri-apps/cli-darwin-x64': 2.0.3 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.0.3 + '@tauri-apps/cli-linux-arm64-gnu': 2.0.3 + '@tauri-apps/cli-linux-arm64-musl': 2.0.3 + '@tauri-apps/cli-linux-x64-gnu': 2.0.3 + '@tauri-apps/cli-linux-x64-musl': 2.0.3 + '@tauri-apps/cli-win32-arm64-msvc': 2.0.3 + '@tauri-apps/cli-win32-ia32-msvc': 2.0.3 + '@tauri-apps/cli-win32-x64-msvc': 2.0.3 - '@tauri-apps/plugin-dialog@2.0.0-rc.1': + '@tauri-apps/plugin-dialog@2.0.0': dependencies: - '@tauri-apps/api': 2.0.0-rc.5 + '@tauri-apps/api': 2.0.2 - '@tauri-apps/plugin-shell@2.0.0-rc.1': + '@tauri-apps/plugin-shell@2.0.0': dependencies: - '@tauri-apps/api': 2.0.0-rc.5 + '@tauri-apps/api': 2.0.2 '@types/babel__core@7.20.5': dependencies: @@ -2053,6 +2983,8 @@ snapshots: '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} + '@types/luxon@3.4.2': {} '@types/node@20.11.17': @@ -2081,6 +3013,8 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@5.0.2: {} + array-union@2.1.0: {} babel-plugin-jsx-dom-expressions@0.37.13(@babel/core@7.23.7): @@ -2133,6 +3067,8 @@ snapshots: cac@6.7.14: {} + camelcase-css@2.0.1: {} + caniuse-lite@1.0.30001576: {} chalk@2.4.2: @@ -2153,6 +3089,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + class-variance-authority@0.7.0: + dependencies: + clsx: 2.0.0 + + clsx@2.0.0: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -2175,6 +3117,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cssesc@3.0.0: {} + csstype@3.1.3: {} debug@4.3.4: @@ -2199,14 +3143,30 @@ snapshots: detect-newline@4.0.1: {} + didyoumean@1.2.2: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 + dlv@1.1.3: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.4.630: {} + embla-carousel-reactive-utils@8.3.0(embla-carousel@8.3.0): + dependencies: + embla-carousel: 8.3.0 + + embla-carousel-solid@8.3.0(solid-js@1.9.3): + dependencies: + embla-carousel: 8.3.0 + embla-carousel-reactive-utils: 8.3.0(embla-carousel@8.3.0) + solid-js: 1.9.3 + + embla-carousel@8.3.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -2263,6 +3223,32 @@ snapshots: '@esbuild/win32-ia32': 0.20.0 '@esbuild/win32-x64': 0.20.0 + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + escalade@3.1.1: {} escape-string-regexp@1.0.5: {} @@ -2315,6 +3301,8 @@ snapshots: fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} get-stdin@9.0.0: {} @@ -2331,6 +3319,10 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + glob@10.3.10: dependencies: foreground-child: 3.1.1 @@ -2360,6 +3352,10 @@ snapshots: has-flag@3.0.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + html-entities@2.3.3: {} human-signals@2.1.0: {} @@ -2375,6 +3371,10 @@ snapshots: dependencies: binary-extensions: 2.2.0 + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + is-docker@2.2.1: {} is-docker@3.0.0: {} @@ -2413,6 +3413,8 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jiti@1.21.6: {} + joycon@3.1.1: {} js-tokens@4.0.0: {} @@ -2421,6 +3423,8 @@ snapshots: json5@2.2.3: {} + lilconfig@2.1.0: {} + lilconfig@3.0.0: {} lines-and-columns@1.2.4: {} @@ -2484,6 +3488,8 @@ snapshots: object-assign@4.1.1: {} + object-hash@3.0.0: {} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -2503,6 +3509,8 @@ snapshots: path-key@4.0.0: {} + path-parse@1.0.7: {} + path-scurry@1.10.1: dependencies: lru-cache: 10.1.0 @@ -2512,23 +3520,57 @@ snapshots: picocolors@1.0.0: {} + picocolors@1.1.0: {} + picomatch@2.3.1: {} + pify@2.3.0: {} + pirates@4.0.6: {} - postcss-load-config@4.0.2(postcss@8.4.35): + postcss-import@15.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.47): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.47 + + postcss-load-config@4.0.2(postcss@8.4.47): dependencies: lilconfig: 3.0.0 yaml: 2.3.4 optionalDependencies: - postcss: 8.4.35 + postcss: 8.4.47 + + postcss-nested@6.2.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} postcss@8.4.35: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.1.0 source-map-js: 1.0.2 + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + prettier-plugin-astro@0.12.3: dependencies: '@astrojs/compiler': 1.8.2 @@ -2548,12 +3590,22 @@ snapshots: queue-microtask@1.2.3: {} + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 resolve-from@5.0.0: {} + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + reusify@1.0.4: {} rollup@4.10.0: @@ -2575,6 +3627,28 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.10.0 fsevents: 2.3.3 + rollup@4.24.0: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.24.0 + '@rollup/rollup-android-arm64': 4.24.0 + '@rollup/rollup-darwin-arm64': 4.24.0 + '@rollup/rollup-darwin-x64': 4.24.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 + '@rollup/rollup-linux-arm-musleabihf': 4.24.0 + '@rollup/rollup-linux-arm64-gnu': 4.24.0 + '@rollup/rollup-linux-arm64-musl': 4.24.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 + '@rollup/rollup-linux-riscv64-gnu': 4.24.0 + '@rollup/rollup-linux-s390x-gnu': 4.24.0 + '@rollup/rollup-linux-x64-gnu': 4.24.0 + '@rollup/rollup-linux-x64-musl': 4.24.0 + '@rollup/rollup-win32-arm64-msvc': 4.24.0 + '@rollup/rollup-win32-ia32-msvc': 4.24.0 + '@rollup/rollup-win32-x64-msvc': 4.24.0 + fsevents: 2.3.3 + run-applescript@5.0.0: dependencies: execa: 5.1.1 @@ -2593,16 +3667,16 @@ snapshots: dependencies: chokidar: 3.5.3 immutable: 4.3.4 - source-map-js: 1.0.2 + source-map-js: 1.2.1 optional: true semver@6.3.1: {} - seroval-plugins@1.0.4(seroval@1.0.4): + seroval-plugins@1.1.1(seroval@1.1.1): dependencies: - seroval: 1.0.4 + seroval: 1.1.1 - seroval@1.0.4: {} + seroval@1.1.1: {} shebang-command@2.0.0: dependencies: @@ -2618,18 +3692,62 @@ snapshots: slash@4.0.0: {} - solid-js@1.8.11: + smorf@1.2.1(solid-js@1.9.3): + dependencies: + '@solid-primitives/set': 0.5.0(solid-js@1.9.3) + solid-js: 1.9.3 + type-fest: 4.26.1 + + solid-dismissible@0.1.1(solid-js@1.9.3): + dependencies: + '@corvu/utils': 0.4.2(solid-js@1.9.3) + solid-js: 1.9.3 + + solid-focus-trap@0.1.7(solid-js@1.9.3): + dependencies: + '@corvu/utils': 0.3.2(solid-js@1.9.3) + solid-js: 1.9.3 + + solid-js@1.9.2: + dependencies: + csstype: 3.1.3 + seroval: 1.1.1 + seroval-plugins: 1.1.1(seroval@1.1.1) + + solid-js@1.9.3: dependencies: csstype: 3.1.3 - seroval: 1.0.4 - seroval-plugins: 1.0.4(seroval@1.0.4) + seroval: 1.1.1 + seroval-plugins: 1.1.1(seroval@1.1.1) + + solid-presence@0.1.8(solid-js@1.9.3): + dependencies: + '@corvu/utils': 0.4.2(solid-js@1.9.3) + solid-js: 1.9.3 + + solid-prevent-scroll@0.1.10(solid-js@1.9.3): + dependencies: + '@corvu/utils': 0.4.2(solid-js@1.9.3) + solid-js: 1.9.3 + + solid-refresh@0.6.3(solid-js@1.9.2): + dependencies: + '@babel/generator': 7.23.6 + '@babel/helper-module-imports': 7.22.15 + '@babel/types': 7.23.6 + solid-js: 1.9.2 - solid-refresh@0.6.3(solid-js@1.8.11): + solid-refresh@0.6.3(solid-js@1.9.3): dependencies: '@babel/generator': 7.23.6 '@babel/helper-module-imports': 7.22.15 '@babel/types': 7.23.6 - solid-js: 1.8.11 + solid-js: 1.9.3 + + solid-transition-size@0.1.4(solid-js@1.9.3): + dependencies: + '@corvu/utils': 0.3.2(solid-js@1.9.3) + solid-js: 1.9.3 sort-object-keys@1.1.3: {} @@ -2645,6 +3763,8 @@ snapshots: source-map-js@1.0.2: {} + source-map-js@1.2.1: {} + source-map@0.8.0-beta.0: dependencies: whatwg-url: 7.1.0 @@ -2691,11 +3811,46 @@ snapshots: dependencies: has-flag: 3.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + synckit@0.8.5: dependencies: '@pkgr/utils': 2.4.2 tslib: 2.6.2 + tailwind-merge@2.5.4: {} + + tailwindcss-animate@1.0.7(tailwindcss@3.4.13): + dependencies: + tailwindcss: 3.4.13 + + tailwindcss@3.4.13: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.0 + postcss: 8.4.47 + postcss-import: 15.1.0(postcss@8.4.47) + postcss-js: 4.0.1(postcss@8.4.47) + postcss-load-config: 4.0.2(postcss@8.4.47) + postcss-nested: 6.2.0(postcss@8.4.47) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -2724,7 +3879,7 @@ snapshots: tslib@2.6.2: {} - tsup@8.0.2(postcss@8.4.35)(typescript@5.3.3): + tsup@8.0.2(postcss@8.4.47)(typescript@5.3.3): dependencies: bundle-require: 4.0.2(esbuild@0.19.11) cac: 6.7.14 @@ -2734,21 +3889,26 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2(postcss@8.4.35) + postcss-load-config: 4.0.2(postcss@8.4.47) resolve-from: 5.0.0 rollup: 4.10.0 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: - postcss: 8.4.35 + postcss: 8.4.47 typescript: 5.3.3 transitivePeerDependencies: - supports-color - ts-node + type-fest@4.26.1: {} + typescript@5.3.3: {} + typescript@5.5.3: + optional: true + undici-types@5.26.5: optional: true @@ -2760,17 +3920,32 @@ snapshots: escalade: 3.1.1 picocolors: 1.0.0 + util-deprecate@1.0.2: {} + validate-html-nesting@1.2.2: {} - vite-plugin-solid@2.8.2(solid-js@1.8.11)(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)): + vite-plugin-solid@2.10.2(solid-js@1.9.3)(vite@5.4.10(@types/node@20.11.17)(sass@1.70.0)): + dependencies: + '@babel/core': 7.23.7 + '@types/babel__core': 7.20.5 + babel-preset-solid: 1.8.9(@babel/core@7.23.7) + merge-anything: 5.1.7 + solid-js: 1.9.3 + solid-refresh: 0.6.3(solid-js@1.9.3) + vite: 5.4.10(@types/node@20.11.17)(sass@1.70.0) + vitefu: 0.2.5(vite@5.4.10(@types/node@20.11.17)(sass@1.70.0)) + transitivePeerDependencies: + - supports-color + + vite-plugin-solid@2.8.2(solid-js@1.9.2)(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)): dependencies: '@babel/core': 7.23.7 '@babel/preset-typescript': 7.23.3(@babel/core@7.23.7) '@types/babel__core': 7.20.5 babel-preset-solid: 1.8.9(@babel/core@7.23.7) merge-anything: 5.1.7 - solid-js: 1.8.11 - solid-refresh: 0.6.3(solid-js@1.8.11) + solid-js: 1.9.2 + solid-refresh: 0.6.3(solid-js@1.9.2) vite: 5.0.11(@types/node@20.11.17)(sass@1.70.0) vitefu: 0.2.5(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)) transitivePeerDependencies: @@ -2786,10 +3961,24 @@ snapshots: fsevents: 2.3.3 sass: 1.70.0 + vite@5.4.10(@types/node@20.11.17)(sass@1.70.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: 4.24.0 + optionalDependencies: + '@types/node': 20.11.17 + fsevents: 2.3.3 + sass: 1.70.0 + vitefu@0.2.5(vite@5.0.11(@types/node@20.11.17)(sass@1.70.0)): optionalDependencies: vite: 5.0.11(@types/node@20.11.17)(sass@1.70.0) + vitefu@0.2.5(vite@5.4.10(@types/node@20.11.17)(sass@1.70.0)): + optionalDependencies: + vite: 5.4.10(@types/node@20.11.17)(sass@1.70.0) + webidl-conversions@4.0.2: {} whatwg-url@7.1.0: diff --git a/resources/settings-schema.json b/resources/settings-schema.json index d4ef2c3c..ce64cdb4 100644 --- a/resources/settings-schema.json +++ b/resources/settings-schema.json @@ -6,7 +6,16 @@ "startupConfigs": { "type": "array", "items": { - "type": "string" + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "preset": { + "type": "string" + } + }, + "required": ["path", "preset"] } } }, diff --git a/resources/widget-schema.json b/resources/widget-schema.json index c60bbd92..1250aeaa 100644 --- a/resources/widget-schema.json +++ b/resources/widget-schema.json @@ -22,12 +22,15 @@ "transparent": { "type": "boolean" }, - "defaultPlacements": { + "presets": { "type": "array", "items": [ { "type": "object", "properties": { + "name": { + "type": "string" + }, "anchor": { "type": "string", "enum": [ @@ -113,6 +116,7 @@ } }, "required": [ + "name", "anchor", "offsetX", "offsetY", @@ -131,6 +135,6 @@ "focused", "resizable", "transparent", - "defaultPlacements" + "presets" ] }