diff --git a/Cargo.lock b/Cargo.lock index 1f0cdba..76a51f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ "alloc-no-stdlib", ] @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "async-broadcast" @@ -140,7 +140,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -175,7 +175,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -259,9 +259,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -299,9 +299,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.3" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -347,9 +347,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" dependencies = [ "serde", ] @@ -360,7 +360,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cairo-sys-rs", "glib", "libc", @@ -381,9 +381,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" dependencies = [ "serde_core", ] @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.63" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "shlex", @@ -466,9 +466,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "num-traits", @@ -527,7 +527,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "core-graphics-types", "foreign-types 0.5.0", @@ -540,7 +540,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "libc", ] @@ -636,7 +636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -686,7 +686,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -699,7 +699,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -710,7 +710,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -721,7 +721,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -747,7 +747,6 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -769,7 +768,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -829,7 +828,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -843,7 +842,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -866,7 +865,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -877,7 +876,7 @@ checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ "bit-set", "cssparser", - "foldhash 0.2.0", + "foldhash", "html5ever", "precomputed-hash", "selectors", @@ -943,9 +942,9 @@ checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "embed-resource" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd" dependencies = [ "cc", "memchr", @@ -985,7 +984,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1110,12 +1109,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -1172,7 +1165,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1258,7 +1251,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1433,15 +1426,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", ] [[package]] @@ -1482,7 +1473,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "futures-channel", "futures-core", "futures-executor", @@ -1510,7 +1501,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1607,7 +1598,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1616,15 +1607,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.17.1" @@ -1667,9 +1649,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1885,12 +1867,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -1963,9 +1939,9 @@ dependencies = [ [[package]] name = "inotify-sys" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +checksum = "9ea94e891b3606826e9c998be69ddca42247dad8ad50b1649a5cb7e1c9ae06fd" dependencies = [ "libc", ] @@ -2046,18 +2022,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -2089,7 +2064,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "serde", "unicode-segmentation", ] @@ -2110,16 +2085,10 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libappindicator" version = "0.9.0" @@ -2187,9 +2156,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -2217,9 +2186,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "markup5ever" @@ -2234,15 +2203,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -2307,9 +2276,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" dependencies = [ "crossbeam-channel", "dpi", @@ -2349,7 +2318,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys", @@ -2379,7 +2348,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -2453,7 +2422,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2462,7 +2431,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9bff0aa1d48904a1385ea2a8b97576fbdcbc9a3cfccd0d31fe978e1c4038c5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libloading 0.8.9", "nvml-wrapper-sys", "static_assertions", @@ -2495,7 +2464,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2508,7 +2477,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-foundation", ] @@ -2529,7 +2498,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", ] @@ -2540,7 +2509,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -2573,7 +2542,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -2600,7 +2569,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2612,7 +2581,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -2623,7 +2592,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -2635,7 +2604,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-cloud-kit", @@ -2666,7 +2635,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-app-kit", @@ -2682,11 +2651,11 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "openssl" -version = "0.10.80" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -2702,7 +2671,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2713,9 +2682,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.116" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -2840,7 +2809,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2907,7 +2876,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", @@ -2958,16 +2927,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "primal-check" version = "0.3.4" @@ -3050,9 +3009,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -3140,7 +3099,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -3182,14 +3141,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -3210,9 +3169,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -3313,7 +3272,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -3322,9 +3281,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "zeroize", ] @@ -3401,7 +3360,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3416,7 +3375,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "core-foundation-sys", "libc", @@ -3439,7 +3398,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cssparser", "derive_more", "log", @@ -3501,7 +3460,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3512,7 +3471,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3536,7 +3495,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3559,9 +3518,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64 0.22.1", "bs58", @@ -3579,14 +3538,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3608,7 +3567,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3687,9 +3646,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" @@ -3829,9 +3788,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3855,7 +3814,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3891,7 +3850,7 @@ version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "core-foundation", "core-graphics", @@ -3933,7 +3892,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3950,9 +3909,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.11.2" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" +checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" dependencies = [ "anyhow", "bytes", @@ -4002,9 +3961,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" dependencies = [ "anyhow", "cargo_toml", @@ -4023,9 +3982,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" dependencies = [ "base64 0.22.1", "brotli", @@ -4039,7 +3998,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.117", + "syn 2.0.118", "tauri-utils", "thiserror 2.0.18", "time", @@ -4050,23 +4009,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e126abc9e84e35cdfd01596140a73a1850cdb0df0a23acf0185776c30b469a6e" +checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020" dependencies = [ "anyhow", "glob", @@ -4125,9 +4084,9 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" version = "2.4.1" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#4350ca652d33e3face88d7c97a78830553545550" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#d1573877226e609461761aa538cd0ca4f24d22be" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "log", "serde", "serde_json", @@ -4138,9 +4097,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" dependencies = [ "cookie", "dpi", @@ -4163,9 +4122,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.11.2" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", "http", @@ -4189,9 +4148,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" dependencies = [ "anyhow", "brotli", @@ -4243,7 +4202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -4285,7 +4244,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4296,17 +4255,16 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -4316,15 +4274,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -4380,7 +4338,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4572,7 +4530,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-util", "http", @@ -4615,7 +4573,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4639,9 +4597,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.23.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" +checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" dependencies = [ "crossbeam-channel", "dirs 6.0.0", @@ -4771,15 +4729,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-xid" -version = "0.2.6" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "url" @@ -4820,11 +4772,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.2" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "serde_core", "wasm-bindgen", @@ -4908,27 +4860,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -4939,9 +4882,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.72" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -4949,9 +4892,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4959,48 +4902,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.5.0" @@ -5014,23 +4935,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -5038,9 +4947,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" dependencies = [ "phf", "phf_codegen", @@ -5114,7 +5023,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5130,7 +5039,7 @@ dependencies = [ [[package]] name = "widgetsack" -version = "0.0.48" +version = "0.0.49" dependencies = [ "fontdb", "futures-util", @@ -5348,7 +5257,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5359,7 +5268,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5370,7 +5279,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5381,7 +5290,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5819,100 +5728,12 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck 0.5.0", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck 0.5.0", - "indexmap 2.14.0", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "wrapcenum-derive" version = "0.4.1" @@ -5922,7 +5743,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6021,9 +5842,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -6038,7 +5859,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] @@ -6086,7 +5907,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "zbus_names", "zvariant", "zvariant_utils", @@ -6105,22 +5926,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6140,15 +5961,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" @@ -6180,7 +6001,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6212,7 +6033,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "zvariant_utils", ] @@ -6225,6 +6046,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.117", + "syn 2.0.118", "winnow 1.0.3", ] diff --git a/client/.eslintignore b/client/.eslintignore deleted file mode 100644 index 3897265..0000000 --- a/client/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs deleted file mode 100644 index a5cd659..0000000 --- a/client/.eslintrc.cjs +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - root: true, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - 'prettier' - ], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'react', 'react-hooks'], - parserOptions: { - sourceType: 'module', - ecmaVersion: 2022, - ecmaFeatures: { jsx: true } - }, - env: { - browser: true, - es2022: true, - node: true - }, - settings: { - react: { version: 'detect' } - }, - overrides: [ - { - // Test code may use non-null assertions on values it has just constructed / knows are defined - // (e.g. asserting on a Patch's `monitor`). Production code keeps the strict rule. - files: ['**/*.test.ts', '**/*.test.tsx'], - rules: { '@typescript-eslint/no-non-null-assertion': 'off' } - } - ] -}; diff --git a/client/eslint.config.js b/client/eslint.config.js new file mode 100644 index 0000000..0aa723f --- /dev/null +++ b/client/eslint.config.js @@ -0,0 +1,42 @@ +import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; +import prettier from 'eslint-config-prettier'; +import globals from 'globals'; + +// Flat config (ESLint 9). Mirrors the old .eslintrc.cjs stack: eslint:recommended + +// typescript-eslint recommended + react (+ jsx-runtime) + react-hooks, with prettier last to +// switch off formatting rules. The old .eslintignore is folded into `ignores` below — flat config +// no longer reads that file. +export default tseslint.config( + { + ignores: [ + 'build/**', + 'coverage/**', + 'test-results/**', + 'playwright-report/**', + 'blob-report/**', + '.playwright-mcp/**', + 'playwright/.cache/**' + ] + }, + js.configs.recommended, + ...tseslint.configs.recommended, + react.configs.flat.recommended, + react.configs.flat['jsx-runtime'], + reactHooks.configs.flat.recommended, + { + settings: { react: { version: 'detect' } }, + languageOptions: { + globals: { ...globals.browser, ...globals.node } + } + }, + prettier, + { + // Test code may use non-null assertions on values it has just constructed / knows are defined + // (e.g. asserting on a Patch's `monitor`). Production code keeps the strict rule. + files: ['**/*.test.ts', '**/*.test.tsx'], + rules: { '@typescript-eslint/no-non-null-assertion': 'off' } + } +); diff --git a/client/gallery/Gallery.tsx b/client/gallery/Gallery.tsx index 234c0bf..9c256e1 100644 --- a/client/gallery/Gallery.tsx +++ b/client/gallery/Gallery.tsx @@ -273,7 +273,7 @@ export default function Gallery() { key: f.key, label: f.label, kind: f.kind, - help: 'help' in f ? f.help ?? null : null + help: 'help' in f ? (f.help ?? null) : null })) }; }) diff --git a/client/gallery/gallery.css b/client/gallery/gallery.css index f56796b..56d3035 100644 --- a/client/gallery/gallery.css +++ b/client/gallery/gallery.css @@ -18,7 +18,10 @@ body { padding: 28px 32px 64px; background: #0b0f14; color: #cfe3ea; - font: 14px/1.5 'Segoe UI', system-ui, sans-serif; + font: + 14px/1.5 'Segoe UI', + system-ui, + sans-serif; } h1 { @@ -84,8 +87,11 @@ figcaption { width: 1074px; height: 380px; border-radius: 12px; - background: linear-gradient(180deg, rgba(12, 22, 28, 0.82), rgba(8, 14, 18, 0.88)), var(--shot-bg); - box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.06); + background: + linear-gradient(180deg, rgba(12, 22, 28, 0.82), rgba(8, 14, 18, 0.88)), var(--shot-bg); + box-shadow: + 0 18px 60px rgba(0, 0, 0, 0.5), + inset 0 0 0 1px rgba(255, 255, 255, 0.06); overflow: hidden; } @@ -101,7 +107,9 @@ figcaption { border-radius: 12px; background-size: cover; background-position: center; - box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.06); + box-shadow: + 0 18px 60px rgba(0, 0, 0, 0.5), + inset 0 0 0 1px rgba(255, 255, 255, 0.06); } .autotheme-stage { flex: 0 0 auto; diff --git a/client/gallery/iframe-demo.html b/client/gallery/iframe-demo.html index 74da8cd..3b3a4a0 100644 --- a/client/gallery/iframe-demo.html +++ b/client/gallery/iframe-demo.html @@ -1,4 +1,4 @@ - + @@ -14,7 +14,10 @@ justify-content: center; background: radial-gradient(120% 120% at 30% 20%, #1a3640, #0d1f26 70%); color: #dceff4; - font: 14px/1.5 'Segoe UI', system-ui, sans-serif; + font: + 14px/1.5 'Segoe UI', + system-ui, + sans-serif; } .card { text-align: center; diff --git a/client/gallery/index.html b/client/gallery/index.html index 75d36e4..4c5cabb 100644 --- a/client/gallery/index.html +++ b/client/gallery/index.html @@ -1,4 +1,4 @@ - + diff --git a/client/gallery/studio.html b/client/gallery/studio.html index 295af67..f070e8a 100644 --- a/client/gallery/studio.html +++ b/client/gallery/studio.html @@ -1,4 +1,4 @@ - + diff --git a/client/index.html b/client/index.html index 094991d..da94155 100644 --- a/client/index.html +++ b/client/index.html @@ -1,4 +1,4 @@ - + diff --git a/client/package-lock.json b/client/package-lock.json index 02ea9fb..d758ee2 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -26,6 +26,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { + "@eslint/js": "^9.39.4", "@playwright/test": "^1.60.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", @@ -33,20 +34,21 @@ "@testing-library/user-event": "^14.5.2", "@types/react": "^19.0.2", "@types/react-dom": "^19.0.2", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", - "@vitejs/plugin-react": "^4.3.4", - "@vitest/coverage-v8": "^2.1.9", - "eslint": "^8.57.1", - "eslint-config-prettier": "^8.10.0", - "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-hooks": "^5.1.0", - "happy-dom": "^15.11.7", - "prettier": "^2.8.8", + "@vitejs/plugin-react": "^6.0.3", + "@vitest/coverage-v8": "^4.1.9", + "eslint": "^9.39.4", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^16.5.0", + "happy-dom": "^20.10.6", + "prettier": "^3.9.4", "tslib": "^2.8.1", - "typescript": "~5.3.3", - "vite": "^5.4.11", - "vitest": "^2.1.8" + "typescript": "^6.0.3", + "typescript-eslint": "^8.62.1", + "vite": "^8.1.3", + "vite-node": "^6.0.0", + "vitest": "^4.1.9" } }, "node_modules/@adobe/css-tools": { @@ -55,19 +57,6 @@ "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", "dev": true }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -162,15 +151,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -180,12 +160,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/@babel/helper-globals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", @@ -225,15 +199,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", - "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", @@ -289,36 +254,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", - "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", - "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", @@ -373,10 +308,13 @@ } }, "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "engines": { + "node": ">=18" + } }, "node_modules/@codemirror/autocomplete": { "version": "6.20.3", @@ -390,12 +328,12 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", - "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.4.tgz", + "integrity": "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==", "dependencies": { "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.6.0", + "@codemirror/state": "^6.7.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } @@ -413,9 +351,9 @@ } }, "node_modules/@codemirror/language": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", - "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.4.tgz", + "integrity": "sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -426,9 +364,9 @@ } }, "node_modules/@codemirror/lint": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.6.tgz", - "integrity": "sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", + "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.42.0", @@ -436,536 +374,250 @@ } }, "node_modules/@codemirror/state": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", - "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.7.0.tgz", + "integrity": "sha512-Zbl9NyscLMZkfXPQnNAIIAFftidrA1UbcJEIMp24C0Bukc2I5T8wJS0wsXYsnDOqCFJUeJ1BITGNs5CqPDSmSg==", "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "node_modules/@codemirror/view": { - "version": "6.43.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.0.tgz", - "integrity": "sha512-V7ZCLQO3Jus9hzh2jVCCPW3mO4IBMr43O37PqSUYautJSnnJF41YlgLw21x0fLJTYvJ+Vkm6Gp+qKGH9pltgXA==", + "version": "6.43.4", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.4.tgz", + "integrity": "sha512-YImu23iyKfncJzT7sRy+rEqEhSc8RhOHqDxwy4WzXRKJwYm6iwf/9OJk5ctCAdZ6yi2ZqaGEvmf55fSVqMDrgg==", "dependencies": { - "@codemirror/state": "^6.6.0", + "@codemirror/state": "^6.7.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", "dev": true, "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", "dev": true, "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", "dev": true, "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { - "node": ">=12" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, "engines": { - "node": ">=12" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" + "node": ">=18.18" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", - "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@jitl/quickjs-ffi-types": { "version": "0.32.0", "resolved": "https://registry.npmjs.org/@jitl/quickjs-ffi-types/-/quickjs-ffi-types-0.32.0.tgz", @@ -1000,9 +652,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1030,9 +682,9 @@ "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==" }, "node_modules/@lezer/css": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", - "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.4.tgz", + "integrity": "sha512-N+tn9tej2hPvyKgHEApMOQfHczDJCwxrRFS3SPn9QjYN+uwHvEDnCgKRrb3mxDYxRS8sKMM8fhC3+lc04Abz5Q==", "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", @@ -1056,62 +708,44 @@ } }, "node_modules/@marijn/find-cluster-break": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", - "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz", + "integrity": "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==" }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "dev": true, + "optional": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@tybys/wasm-util": "^0.10.3" }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@oxc-project/types": { + "version": "0.138.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.138.0.tgz", + "integrity": "sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==", "dev": true, - "optional": true, - "engines": { - "node": ">=14" + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, "node_modules/@playwright/test": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", - "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", "dev": true, "dependencies": { - "playwright": "1.60.0" + "playwright": "1.61.1" }, "bin": { "playwright": "cli.js" @@ -1120,29 +754,10 @@ "node": ">=18" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz", - "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz", - "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.4.tgz", + "integrity": "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==", "cpu": [ "arm64" ], @@ -1150,12 +765,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz", - "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.4.tgz", + "integrity": "sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==", "cpu": [ "arm64" ], @@ -1163,12 +781,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz", - "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.4.tgz", + "integrity": "sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==", "cpu": [ "x64" ], @@ -1176,25 +797,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz", - "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==", - "cpu": [ - "arm64" ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz", - "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.4.tgz", + "integrity": "sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==", "cpu": [ "x64" ], @@ -1202,25 +813,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz", - "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==", - "cpu": [ - "arm" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz", - "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.4.tgz", + "integrity": "sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==", "cpu": [ "arm" ], @@ -1228,25 +829,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz", - "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==", - "cpu": [ - "arm64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz", - "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.4.tgz", + "integrity": "sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==", "cpu": [ "arm64" ], @@ -1254,51 +845,31 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz", - "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==", - "cpu": [ - "loong64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz", - "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.4.tgz", + "integrity": "sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz", - "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==", - "cpu": [ - "ppc64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz", - "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.4.tgz", + "integrity": "sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==", "cpu": [ "ppc64" ], @@ -1306,38 +877,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz", - "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz", - "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==", - "cpu": [ - "riscv64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz", - "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.4.tgz", + "integrity": "sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==", "cpu": [ "s390x" ], @@ -1345,12 +893,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", - "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.4.tgz", + "integrity": "sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==", "cpu": [ "x64" ], @@ -1358,12 +909,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz", - "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.4.tgz", + "integrity": "sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==", "cpu": [ "x64" ], @@ -1371,25 +925,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz", - "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==", - "cpu": [ - "x64" ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz", - "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.4.tgz", + "integrity": "sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==", "cpu": [ "arm64" ], @@ -1397,51 +941,49 @@ "optional": true, "os": [ "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz", - "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==", - "cpu": [ - "arm64" ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz", - "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.4.tgz", + "integrity": "sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==", "cpu": [ - "ia32" + "wasm32" ], "dev": true, "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz", - "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.4.tgz", + "integrity": "sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz", - "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.4.tgz", + "integrity": "sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==", "cpu": [ "x64" ], @@ -1449,12 +991,27 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true }, "node_modules/@tauri-apps/api": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz", - "integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz", + "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/tauri" @@ -1544,52 +1101,37 @@ "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, + "optional": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "tslib": "^2.4.0" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.28.2" - } + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true }, "node_modules/@types/estree": { "version": "1.0.9", @@ -1604,17 +1146,18 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.1.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz", - "integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz", + "integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==", "dev": true, - "optional": true, - "peer": true + "dependencies": { + "undici-types": "~8.3.0" + } }, "node_modules/@types/react": { - "version": "19.2.16", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.16.tgz", - "integrity": "sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "dev": true, "dependencies": { "csstype": "^3.2.2" @@ -1629,124 +1172,167 @@ "@types/react": "^19.2.0" } }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", "dev": true }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.1.tgz", + "integrity": "sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/type-utils": "8.62.1", + "@typescript-eslint/utils": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.62.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.1.tgz", + "integrity": "sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "debug": "^4.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", + "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", + "dev": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.62.1", + "@typescript-eslint/types": "^8.62.1", + "debug": "^4.4.3" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz", + "integrity": "sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz", + "integrity": "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/utils": "8.62.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", + "integrity": "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1754,126 +1340,168 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.1.tgz", + "integrity": "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz", + "integrity": "sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.62.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", - "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", - "dev": true - }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.3.tgz", + "integrity": "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==", "dev": true, "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" + "@rolldown/pluginutils": "^1.0.1" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } } }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.9.tgz", - "integrity": "sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.9.tgz", + "integrity": "sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.7", + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.9", + "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.12", - "magicast": "^0.3.5", - "std-env": "^3.8.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^1.2.0" + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.9", - "vitest": "2.1.9" + "@vitest/browser": "4.1.9", + "vitest": "4.1.9" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1882,36 +1510,38 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", - "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.9.tgz", + "integrity": "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.9", + "@vitest/utils": "4.1.9", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", - "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.9.tgz", + "integrity": "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.9", + "@vitest/spy": "4.1.9", "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { @@ -1922,84 +1552,73 @@ } } }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", - "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.9.tgz", + "integrity": "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==", "dev": true, "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", - "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.9.tgz", + "integrity": "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==", "dev": true, "dependencies": { - "@vitest/utils": "2.1.9", - "pathe": "^1.1.2" + "@vitest/utils": "4.1.9", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", - "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.9.tgz", + "integrity": "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "@vitest/pretty-format": "4.1.9", + "@vitest/utils": "4.1.9", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", - "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.9.tgz", + "integrity": "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==", "dev": true, - "dependencies": { - "tinyspy": "^3.0.2" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", - "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.9.tgz", + "integrity": "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.9", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" + "@vitest/pretty-format": "4.1.9", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2110,15 +1729,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -2221,6 +1831,23 @@ "node": ">=12" } }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.4.tgz", + "integrity": "sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -2252,9 +1879,9 @@ "dev": true }, "node_modules/baseline-browser-mapping": { - "version": "2.10.33", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", - "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "version": "2.10.41", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz", + "integrity": "sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==", "dev": true, "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -2264,31 +1891,19 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, "funding": [ { @@ -2305,10 +1920,10 @@ } ], "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -2318,13 +1933,25 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-image-size": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz", + "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", + "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=20.19.0" } }, "node_modules/call-bind": { @@ -2384,9 +2011,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001800", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz", + "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==", "dev": true, "funding": [ { @@ -2404,17 +2031,10 @@ ] }, "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, "engines": { "node": ">=18" } @@ -2435,15 +2055,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, - "engines": { - "node": ">= 16" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2480,9 +2091,9 @@ "dev": true }, "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.7.tgz", + "integrity": "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==" }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2578,15 +2189,6 @@ } } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2636,30 +2238,15 @@ "node": ">=6" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -2667,9 +2254,9 @@ "dev": true }, "node_modules/downshift": { - "version": "9.3.6", - "resolved": "https://registry.npmjs.org/downshift/-/downshift-9.3.6.tgz", - "integrity": "sha512-xEKP1vbt/k7Siu481TKibmj8EyL6iyBwaRJgb6gCsFyLeiyZ1KEJnApS9R1U71hTdK5ym0R99AOYRROcTz1PeQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-9.4.0.tgz", + "integrity": "sha512-yIwyzRYzycKwMZhvOahsn4BmRr4Ffi0JymdWOtTDhR+LGDEXCZHTcwgUbNBC/oZLT6YrR46iwJe/BrQUS5ClQQ==", "dependencies": { "@babel/runtime": "^7.28.6", "compute-scroll-into-view": "^3.1.1", @@ -2681,11 +2268,6 @@ "react": ">=16.12.0" } }, - "node_modules/downshift/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2700,28 +2282,16 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/electron-to-chromium": { - "version": "1.5.366", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz", - "integrity": "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "1.5.384", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.384.tgz", + "integrity": "sha512-g6KAKY1vkYsADvSPWvdJsuYT0ixdcu6lUtD9P/wJKGBEDlZVXh2AX42j1mPqqaQPDluWjara9ziQ7xqAeXCt5A==", "dev": true }, "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "dev": true, "engines": { "node": ">=0.12" @@ -2798,6 +2368,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2817,9 +2405,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", - "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", "dev": true, "dependencies": { "call-bind": "^1.0.9", @@ -2844,9 +2432,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.0.tgz", + "integrity": "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==", "dev": true }, "node_modules/es-object-atoms": { @@ -2889,14 +2477,17 @@ } }, "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", "dev": true, "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -2905,44 +2496,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "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" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2965,69 +2518,75 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", - "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } @@ -3065,15 +2624,22 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "node_modules/eslint-plugin-react/node_modules/doctrine": { @@ -3088,29 +2654,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", - "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.2", - "node-exports-info": "^1.6.0", - "object-keys": "^1.1.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/eslint-plugin-react/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3121,25 +2664,19 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { @@ -3154,43 +2691,51 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -3220,6 +2765,15 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3230,9 +2784,9 @@ } }, "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "engines": { "node": ">=12.0.0" @@ -3244,34 +2798,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3284,37 +2810,33 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, "node_modules/find-up": { @@ -3334,22 +2856,22 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "node_modules/for-each": { @@ -3367,32 +2889,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3413,17 +2913,20 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3513,26 +3016,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3546,15 +3029,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3576,26 +3056,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -3608,24 +3068,22 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/happy-dom": { - "version": "15.11.7", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-15.11.7.tgz", - "integrity": "sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==", + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.10.6.tgz", + "integrity": "sha512-6QD0ilzDDt93tX44y8tbmZdAcdTRYDhUP+Asgi6pC8Pp5IA3cvaZGyoVN/EGtlq9ziT65iPuBBn3ASLr6hCgVw==", "dev": true, "dependencies": { - "entities": "^4.5.0", - "webidl-conversions": "^7.0.0", - "whatwg-mimetype": "^3.0.0" + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "buffer-image-size": "^0.6.4", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.21.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/has-bigints": { @@ -3715,6 +3173,21 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3722,18 +3195,18 @@ "dev": true }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -3764,22 +3237,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -3921,6 +3378,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3945,15 +3417,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-generator-function": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", @@ -4009,15 +3472,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", @@ -4034,15 +3488,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -4214,20 +3659,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-reports": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", @@ -4258,30 +3689,15 @@ "node": ">= 0.4" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "dev": true, "funding": [ { @@ -4312,6 +3728,12 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4348,20 +3770,278 @@ "object.values": "^1.1.6" }, "engines": { - "node": ">=4.0" + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.8.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/locate-path": { @@ -4396,17 +4076,14 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true - }, "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } }, "node_modules/lz-string": { "version": "1.5.0", @@ -4427,14 +4104,14 @@ } }, "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", "dev": true, "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" } }, "node_modules/make-dir": { @@ -4461,28 +4138,6 @@ "node": ">= 0.4" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -4493,9 +4148,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -4504,15 +4159,6 @@ "node": "*" } }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4520,9 +4166,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", "dev": true, "funding": [ { @@ -4543,16 +4189,10 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/node-exports-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", - "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", "dev": true, "dependencies": { "array.prototype.flatmap": "^1.3.3", @@ -4577,9 +4217,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", - "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "dev": true, "engines": { "node": ">=18" @@ -4685,13 +4325,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/obug": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", "dev": true, - "dependencies": { - "wrappy": "1" + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "engines": { + "node": ">=12.20.0" } }, "node_modules/optionator": { @@ -4758,12 +4402,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4785,15 +4423,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4809,46 +4438,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "engines": { - "node": ">= 14.16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4856,24 +4451,24 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/playwright": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", - "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", "dev": true, "dependencies": { - "playwright-core": "1.60.0" + "playwright-core": "1.61.1" }, "bin": { "playwright": "cli.js" @@ -4886,9 +4481,9 @@ } }, "node_modules/playwright-core": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", - "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -4897,20 +4492,6 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -4921,9 +4502,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", "dev": true, "funding": [ { @@ -4958,15 +4539,15 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.4.tgz", + "integrity": "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -4998,6 +4579,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5022,26 +4609,6 @@ "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/quickjs-emscripten-core": { "version": "0.32.0", "resolved": "https://registry.npmjs.org/quickjs-emscripten-core/-/quickjs-emscripten-core-0.32.0.tgz", @@ -5070,19 +4637,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/redent": { "version": "3.0.0", @@ -5139,6 +4696,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -5148,52 +4728,37 @@ "node": ">=4" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/rolldown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.4.tgz", + "integrity": "sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "@oxc-project/types": "=0.138.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { - "rimraf": "bin.js" + "rolldown": "bin/cli.mjs" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.4", + "@rolldown/binding-darwin-arm64": "1.1.4", + "@rolldown/binding-darwin-x64": "1.1.4", + "@rolldown/binding-freebsd-x64": "1.1.4", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.4", + "@rolldown/binding-linux-arm64-gnu": "1.1.4", + "@rolldown/binding-linux-arm64-musl": "1.1.4", + "@rolldown/binding-linux-ppc64-gnu": "1.1.4", + "@rolldown/binding-linux-s390x-gnu": "1.1.4", + "@rolldown/binding-linux-x64-gnu": "1.1.4", + "@rolldown/binding-linux-x64-musl": "1.1.4", + "@rolldown/binding-openharmony-arm64": "1.1.4", + "@rolldown/binding-wasm32-wasi": "1.1.4", + "@rolldown/binding-win32-arm64-msvc": "1.1.4", + "@rolldown/binding-win32-x64-msvc": "1.1.4" } }, "node_modules/safe-array-concat": { @@ -5254,9 +4819,9 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" }, "node_modules/semver": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", - "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -5333,14 +4898,14 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -5410,27 +4975,6 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5447,9 +4991,9 @@ "dev": true }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", "dev": true }, "node_modules/stop-iteration-iterator": { @@ -5465,71 +5009,6 @@ "node": ">= 0.4" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -5568,18 +5047,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5589,15 +5069,15 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -5623,31 +5103,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -5701,162 +5156,56 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/test-exclude": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz", - "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^10.2.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/test-exclude/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true }, - "node_modules/test-exclude/node_modules/glob/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/test-exclude/node_modules/glob/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.2" - }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=18" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.5" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "dev": true, - "engines": { - "node": "^18.0.0 || >=20.0.0" + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "engines": { "node": ">=14.0.0" } }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" + "node": ">=18.12" }, - "engines": { - "node": ">=8.0" + "peerDependencies": { + "typescript": ">=4.8.4" } }, "node_modules/tslib": { @@ -5864,27 +5213,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5897,18 +5225,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -5984,9 +5300,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5996,6 +5312,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.62.1.tgz", + "integrity": "sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.62.1", + "@typescript-eslint/parser": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/utils": "8.62.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -6014,6 +5353,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -6054,20 +5399,22 @@ } }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.3.tgz", + "integrity": "sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==", "dev": true, "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.16", + "rolldown": "~1.1.3", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6076,23 +5423,33 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, - "less": { + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { "optional": true }, - "lightningcss": { + "jiti": { + "optional": true + }, + "less": { "optional": true }, "sass": { @@ -6109,127 +5466,124 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, "node_modules/vite-node": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", - "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-6.0.0.tgz", + "integrity": "sha512-oj4PVrT+pDh6GYf5wfUXkcZyekYS8kKPfLPXVl8qe324Ec6l4K2DUKNadRbZ3LQl0qGcDz+PyOo7ZAh00Y+JjQ==", "dev": true, "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" + "cac": "^7.0.0", + "es-module-lexer": "^2.0.0", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "vite": "^8.0.0" }, "bin": { - "vite-node": "vite-node.mjs" + "vite-node": "dist/cli.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://opencollective.com/antfu" } }, - "node_modules/vite/node_modules/rollup": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz", - "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==", + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "dependencies": { - "@types/estree": "1.0.9" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.61.0", - "@rollup/rollup-android-arm64": "4.61.0", - "@rollup/rollup-darwin-arm64": "4.61.0", - "@rollup/rollup-darwin-x64": "4.61.0", - "@rollup/rollup-freebsd-arm64": "4.61.0", - "@rollup/rollup-freebsd-x64": "4.61.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", - "@rollup/rollup-linux-arm-musleabihf": "4.61.0", - "@rollup/rollup-linux-arm64-gnu": "4.61.0", - "@rollup/rollup-linux-arm64-musl": "4.61.0", - "@rollup/rollup-linux-loong64-gnu": "4.61.0", - "@rollup/rollup-linux-loong64-musl": "4.61.0", - "@rollup/rollup-linux-ppc64-gnu": "4.61.0", - "@rollup/rollup-linux-ppc64-musl": "4.61.0", - "@rollup/rollup-linux-riscv64-gnu": "4.61.0", - "@rollup/rollup-linux-riscv64-musl": "4.61.0", - "@rollup/rollup-linux-s390x-gnu": "4.61.0", - "@rollup/rollup-linux-x64-gnu": "4.61.0", - "@rollup/rollup-linux-x64-musl": "4.61.0", - "@rollup/rollup-openbsd-x64": "4.61.0", - "@rollup/rollup-openharmony-arm64": "4.61.0", - "@rollup/rollup-win32-arm64-msvc": "4.61.0", - "@rollup/rollup-win32-ia32-msvc": "4.61.0", - "@rollup/rollup-win32-x64-gnu": "4.61.0", - "@rollup/rollup-win32-x64-msvc": "4.61.0", - "fsevents": "~2.3.2" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/vitest": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", - "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", - "dev": true, - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.9.tgz", + "integrity": "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==", + "dev": true, + "dependencies": { + "@vitest/expect": "4.1.9", + "@vitest/mocker": "4.1.9", + "@vitest/pretty-format": "4.1.9", + "@vitest/runner": "4.1.9", + "@vitest/snapshot": "4.1.9", + "@vitest/spy": "4.1.9", + "@vitest/utils": "4.1.9", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.9", + "@vitest/browser-preview": "4.1.9", + "@vitest/browser-webdriverio": "4.1.9", + "@vitest/coverage-istanbul": "4.1.9", + "@vitest/coverage-v8": "4.1.9", + "@vitest/ui": "4.1.9", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { @@ -6240,6 +5594,9 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, @@ -6248,15 +5605,6 @@ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -6346,9 +5694,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", - "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", @@ -6391,116 +5739,64 @@ "node": ">=0.10.0" } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "node": ">=10.0.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" } } } diff --git a/client/package.json b/client/package.json index c66d07b..926f6fd 100644 --- a/client/package.json +++ b/client/package.json @@ -20,6 +20,7 @@ "gen:gallery": "npm run gen:shots && npm run gen:docs" }, "devDependencies": { + "@eslint/js": "^9.39.4", "@playwright/test": "^1.60.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", @@ -27,20 +28,21 @@ "@testing-library/user-event": "^14.5.2", "@types/react": "^19.0.2", "@types/react-dom": "^19.0.2", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", - "@vitejs/plugin-react": "^4.3.4", - "@vitest/coverage-v8": "^2.1.9", - "eslint": "^8.57.1", - "eslint-config-prettier": "^8.10.0", - "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-hooks": "^5.1.0", - "happy-dom": "^15.11.7", - "prettier": "^2.8.8", + "@vitejs/plugin-react": "^6.0.3", + "@vitest/coverage-v8": "^4.1.9", + "eslint": "^9.39.4", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^16.5.0", + "happy-dom": "^20.10.6", + "prettier": "^3.9.4", "tslib": "^2.8.1", - "typescript": "~5.3.3", - "vite": "^5.4.11", - "vitest": "^2.1.8" + "typescript": "^6.0.3", + "typescript-eslint": "^8.62.1", + "vite": "^8.1.3", + "vite-node": "^6.0.0", + "vitest": "^4.1.9" }, "type": "module", "dependencies": { diff --git a/client/scripts/screenshots.mjs b/client/scripts/screenshots.mjs index 586d9bc..7056fd2 100644 --- a/client/scripts/screenshots.mjs +++ b/client/scripts/screenshots.mjs @@ -46,7 +46,7 @@ async function main() { ? null : new Promise((res) => { img.onload = img.onerror = res; - }) + }) ) ); }); diff --git a/client/src/lib/components/NowPlaying/priority.test.ts b/client/src/lib/components/NowPlaying/priority.test.ts index 7d99b6d..f0c5026 100644 --- a/client/src/lib/components/NowPlaying/priority.test.ts +++ b/client/src/lib/components/NowPlaying/priority.test.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - import { describe, expect, it } from 'vitest'; import type { PlaybackModel, SessionModel, SessionRecord } from '../../../stores/stores'; import { diff --git a/client/src/lib/core/dragSnap.ts b/client/src/lib/core/dragSnap.ts index 7ff9bef..fe95eb3 100644 --- a/client/src/lib/core/dragSnap.ts +++ b/client/src/lib/core/dragSnap.ts @@ -17,7 +17,7 @@ export type Pointer = { x: number; y: number; shift: boolean }; export function armedZone(zones: Zone[], p: Pointer): Zone | null { if (!p.shift) return null; const id = hitTestZone(zones, p.x, p.y); - return id ? zones.find((z) => z.id === id) ?? null : null; + return id ? (zones.find((z) => z.id === id) ?? null) : null; } /** Build a {@link ZoneMatch} from a zone widget's config (matchExe/matchClass/matchTitle), or diff --git a/client/src/lib/core/haRegistry.ts b/client/src/lib/core/haRegistry.ts index ab749a2..c669aeb 100644 --- a/client/src/lib/core/haRegistry.ts +++ b/client/src/lib/core/haRegistry.ts @@ -78,7 +78,7 @@ export function buildRegistryTree(reg: HaRegistry, live: Record c.id !== draggingId).length, into: true - } + } : { parentId: node.id, index: i, merge: child.id }; } } diff --git a/client/src/lib/core/schedule.ts b/client/src/lib/core/schedule.ts index 2e27851..2c457cf 100644 --- a/client/src/lib/core/schedule.ts +++ b/client/src/lib/core/schedule.ts @@ -15,12 +15,12 @@ export function intervalMs(s: string): number | null { unit === 'ms' ? 1 : unit === 's' - ? 1000 - : unit === 'm' - ? 60_000 - : unit === 'h' - ? 3_600_000 - : 86_400_000; + ? 1000 + : unit === 'm' + ? 60_000 + : unit === 'h' + ? 3_600_000 + : 86_400_000; const ms = n * mult; return ms > 0 ? ms : null; } diff --git a/client/src/lib/core/solve.ts b/client/src/lib/core/solve.ts index 5d604c9..718b108 100644 --- a/client/src/lib/core/solve.ts +++ b/client/src/lib/core/solve.ts @@ -414,7 +414,7 @@ export function resolveGroup(grp: Group, library?: Library): ResolvedGroup { grp.def && library ? library.defs.find((d) => d.id === grp.def) : undefined; const baseChild: LayoutNode | undefined = def ? def.child : grp.child; - const size: Size = def ? def.size : grp.size ?? { w: 0, h: 0 }; + const size: Size = def ? def.size : (grp.size ?? { w: 0, h: 0 }); if (!baseChild) return { child: emptyContainer(grp.id + ':empty'), size }; diff --git a/client/src/lib/core/templatingDocs.ts b/client/src/lib/core/templatingDocs.ts index 5afcfda..6f3a659 100644 --- a/client/src/lib/core/templatingDocs.ts +++ b/client/src/lib/core/templatingDocs.ts @@ -32,7 +32,7 @@ function exprFieldsTable(metas: WidgetMeta[]): string { for (const m of metas) { for (const f of (m.configFields ?? []).filter(isExpr)) { const accepts = f.result === 'text' ? 'template → text' : 'formula → number'; - const note = f.target && f.target !== f.key ? `overrides \`${f.target}\`` : f.help ?? ''; + const note = f.target && f.target !== f.key ? `overrides \`${f.target}\`` : (f.help ?? ''); rows.push(`| \`${m.type}\` | \`${f.key}\` | ${accepts} | ${cell(note)} |`); } } diff --git a/client/src/lib/core/widget.ts b/client/src/lib/core/widget.ts index 3147acf..f0e08c4 100644 --- a/client/src/lib/core/widget.ts +++ b/client/src/lib/core/widget.ts @@ -181,17 +181,17 @@ const num = ( key: string, label: string, extra: { min?: number; max?: number; step?: number } & FieldMeta = {} -): ConfigField => ({ key, label, kind: 'number', ...extra } as ConfigField); +): ConfigField => ({ key, label, kind: 'number', ...extra }) as ConfigField; const text = (key: string, label: string, extra: FieldMeta = {}): ConfigField => - ({ key, label, kind: 'text', ...extra } as ConfigField); + ({ key, label, kind: 'text', ...extra }) as ConfigField; const color = (key: string, label: string, extra: FieldMeta = {}): ConfigField => - ({ key, label, kind: 'color', ...extra } as ConfigField); + ({ key, label, kind: 'color', ...extra }) as ConfigField; const expr = ( key: string, label: string, result: 'number' | 'text', extra: { target?: string } & FieldMeta = {} -): ConfigField => ({ key, label, kind: 'expr', result, ...extra } as ConfigField); +): ConfigField => ({ key, label, kind: 'expr', result, ...extra }) as ConfigField; // The built-in meters as data (reproduces the old createWidget switch exactly, so the // default look/behaviour is unchanged). Components are attached in registry.ts. diff --git a/client/src/lib/core/widgetDocs.ts b/client/src/lib/core/widgetDocs.ts index 769b1c3..bdf5e13 100644 --- a/client/src/lib/core/widgetDocs.ts +++ b/client/src/lib/core/widgetDocs.ts @@ -57,7 +57,7 @@ function widgetSection(meta: WidgetMeta): string { ? '- **Sensor:** none (self-sourcing)' : `- **Sensor:** binds a \`${binds}\` sensor${ meta.defaultSensor ? ` (default \`${meta.defaultSensor}\`)` : '' - }` + }` ); if (meta.defaultSize) facts.push(`- **Default size:** ${meta.defaultSize.w}×${meta.defaultSize.h}`); diff --git a/client/src/lib/formula/packageSandbox.ts b/client/src/lib/formula/packageSandbox.ts index 7083088..79c1b51 100644 --- a/client/src/lib/formula/packageSandbox.ts +++ b/client/src/lib/formula/packageSandbox.ts @@ -35,8 +35,7 @@ export type PackageSandbox = { }; export type CreateSandboxResult = - | { ok: true; sandbox: PackageSandbox } - | { ok: false; error: string }; + { ok: true; sandbox: PackageSandbox } | { ok: false; error: string }; /** * Compile `script` (a CommonJS-style source.js that assigns `module.exports`) into a fresh, @@ -64,7 +63,7 @@ export async function createPackageSandbox(script: string): Promise { if (disposed) return; disposed = true; diff --git a/client/src/lib/llm/source.test.ts b/client/src/lib/llm/source.test.ts index b0b5c46..738fb4c 100644 --- a/client/src/lib/llm/source.test.ts +++ b/client/src/lib/llm/source.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; // Outer-ring Tauri adapter for streamed LLM tokens. We mock @tauri-apps/api/event's `listen` and the // store's pure `handleDelta` so the reference-counting + attach race can be exercised without a Tauri @@ -10,7 +10,7 @@ vi.mock('../../stores/llmStore', () => ({ handleDelta: (...a: unknown[]) => hand // `listen` is reconfigured per test. By default it resolves immediately to a spy unlisten fn. const unlistenSpy = vi.fn(); -let listen: ReturnType; +let listen: Mock<(...args: unknown[]) => unknown>; vi.mock('@tauri-apps/api/event', () => ({ listen: (...a: unknown[]) => listen(...a) })); type Source = typeof import('./source'); diff --git a/client/src/lib/stt.test.ts b/client/src/lib/stt.test.ts index 2aa2211..3c2a1e6 100644 --- a/client/src/lib/stt.test.ts +++ b/client/src/lib/stt.test.ts @@ -106,7 +106,10 @@ describe('stt', () => { onstop: (() => void) | null = null; onerror: (() => void) | null = null; started = false; - constructor(public stream: unknown, public opts: unknown) { + constructor( + public stream: unknown, + public opts: unknown + ) { created.push(this); } start(): void { @@ -134,7 +137,10 @@ describe('stt', () => { 'Blob', class { type: string; - constructor(public parts: Uint8Array[], opts?: { type?: string }) { + constructor( + public parts: Uint8Array[], + opts?: { type?: string } + ) { this.type = opts?.type ?? ''; } arrayBuffer(): Promise { diff --git a/client/src/lib/viewTransition.test.ts b/client/src/lib/viewTransition.test.ts index ca635da..52d2469 100644 --- a/client/src/lib/viewTransition.test.ts +++ b/client/src/lib/viewTransition.test.ts @@ -1,8 +1,12 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import { prefersReducedMotion, startViewTransition } from './viewTransition'; -type VTDoc = Document & { startViewTransition?: (cb: () => void) => unknown }; -const doc = document as VTDoc; +// TS 6's lib.dom types `startViewTransition` as a required overload; override it with an optional, +// loose signature so the test can assign a mock (or undefined) to it. +type VTDoc = Omit & { + startViewTransition?: (cb: () => void) => unknown; +}; +const doc = document as unknown as VTDoc; const origMatchMedia = window.matchMedia; const origVT = doc.startViewTransition; @@ -12,7 +16,7 @@ afterEach(() => { }); const setReducedMotion = (reduced: boolean): void => { - window.matchMedia = vi.fn(() => ({ matches: reduced } as unknown as MediaQueryList)); + window.matchMedia = vi.fn(() => ({ matches: reduced }) as unknown as MediaQueryList); }; describe('viewTransition', () => { diff --git a/client/src/lib/widgets/AudioSwitcherHost.tsx b/client/src/lib/widgets/AudioSwitcherHost.tsx index 032df34..839d04b 100644 --- a/client/src/lib/widgets/AudioSwitcherHost.tsx +++ b/client/src/lib/widgets/AudioSwitcherHost.tsx @@ -26,8 +26,8 @@ export default function AudioSwitcherHost({ color }: Props) { useEffect(() => { let alive = true; - void refresh(); const onFocus = (): void => void refresh(); + onFocus(); // initial load (kept off the effect's sync path — refresh setStates after an await) window.addEventListener('focus', onFocus); const timer = window.setInterval(() => { if (alive) void refresh(); diff --git a/client/src/lib/widgets/BackgroundPanel.test.tsx b/client/src/lib/widgets/BackgroundPanel.test.tsx index c4f5857..8b4cba1 100644 --- a/client/src/lib/widgets/BackgroundPanel.test.tsx +++ b/client/src/lib/widgets/BackgroundPanel.test.tsx @@ -1,4 +1,4 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; import { fireEvent, render } from '@testing-library/react'; // The only module call the panel makes itself is the stateless open-folder helper — mock the Tauri @@ -7,14 +7,14 @@ vi.mock('../overlay', () => ({ openWallpapersDir: vi.fn() })); import BackgroundPanel from './BackgroundPanel'; import { openWallpapersDir } from '../overlay'; -import type { BackgroundSpec } from '../core/layoutTree'; +import type { BackgroundKind, BackgroundSpec } from '../core/layoutTree'; import type { AutoTheme } from './canvas/useAutoTheme'; type Handlers = { - patchBg: ReturnType; - setBgKind: ReturnType; - clearBg: ReturnType; - refreshWallpapers: ReturnType; + patchBg: Mock<(patch: Partial) => void>; + setBgKind: Mock<(kind: BackgroundKind) => void>; + clearBg: Mock<() => void>; + refreshWallpapers: Mock<() => void>; }; function handlers(): Handlers { diff --git a/client/src/lib/widgets/BoxField.tsx b/client/src/lib/widgets/BoxField.tsx index 07a9bb3..bba6360 100644 --- a/client/src/lib/widgets/BoxField.tsx +++ b/client/src/lib/widgets/BoxField.tsx @@ -23,8 +23,8 @@ const toSides = (v: Pad | undefined): Sides => v === undefined ? { t: 0, r: 0, b: 0, l: 0 } : typeof v === 'number' - ? { t: v, r: v, b: v, l: v } - : v; + ? { t: v, r: v, b: v, l: v } + : v; const uniform = (s: Sides): boolean => s.t === s.r && s.r === s.b && s.b === s.l; diff --git a/client/src/lib/widgets/Canvas.css b/client/src/lib/widgets/Canvas.css index 34fc273..aa8948b 100644 --- a/client/src/lib/widgets/Canvas.css +++ b/client/src/lib/widgets/Canvas.css @@ -97,7 +97,8 @@ left: -1px; width: 1px; background: transparent; - transition: background var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + background var(--motion-fast, 100ms) var(--ease-out, ease-out), box-shadow var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -208,7 +209,8 @@ background: var(--ui-surface); pointer-events: auto; cursor: pointer; - transition: color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + color var(--motion-fast, 100ms) var(--ease-out, ease-out), background var(--motion-fast, 100ms) var(--ease-out, ease-out), transform var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -244,7 +246,8 @@ placeholders only cover empty cells, so nothing interactive sits beneath them. */ z-index: 4; /* Ease the empty-cell highlight in so a grid feels receptive, not jumpy, as you sweep over it. */ - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), background var(--motion-fast, 100ms) var(--ease-out, ease-out); } .canvas .grid-cell:hover { @@ -280,7 +283,8 @@ position: absolute; background: rgba(var(--ui-accent-rgb), 0.45); pointer-events: none; - transition: background var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + background var(--motion-fast, 100ms) var(--ease-out, ease-out), box-shadow var(--motion-fast, 100ms) var(--ease-out, ease-out); } /* On hover (or keyboard focus) the midpoint tick brightens + glows, so the boundary reads as @@ -476,7 +480,8 @@ padding: var(--space-2) var(--space-4); border-radius: var(--radius-control); cursor: pointer; - transition: background var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + background var(--motion-fast, 100ms) var(--ease-out, ease-out), border-left-color var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -864,7 +869,8 @@ /* Keep multi-token labels (e.g. "● Save" / "✓ Saved") on a single row — the bar is a fixed-height flex strip, so a wrapped label would clip instead of growing the bar. */ white-space: nowrap; - transition: color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + color var(--motion-fast, 100ms) var(--ease-out, ease-out), border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), background var(--motion-fast, 100ms) var(--ease-out, ease-out), opacity var(--motion-fast, 100ms) var(--ease-out, ease-out), @@ -986,7 +992,8 @@ padding: var(--space-2) var(--space-5); cursor: pointer; font-family: monospace; - transition: background var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + background var(--motion-fast, 100ms) var(--ease-out, ease-out), border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), transform var(--motion-fast, 100ms) var(--ease-out, ease-out); } diff --git a/client/src/lib/widgets/Canvas.tsx b/client/src/lib/widgets/Canvas.tsx index d36297e..be51a9f 100644 --- a/client/src/lib/widgets/Canvas.tsx +++ b/client/src/lib/widgets/Canvas.tsx @@ -50,7 +50,6 @@ import { collectRenderables, collectSplitters, gridCellRects, - type Renderable, resolveGroup } from '../core/solve'; import { assembleStyles } from '../core/style'; @@ -213,7 +212,9 @@ export default function Canvas({ studio = false }: Props) { const pluginList = useMemo(() => listPlugins(), []); // Stable telemetry hub (item 5): one per Canvas, provided via Context (replaces setContext). - const hub = useRef(createTelemetryHub()).current; + // Lazy useState (not useRef(...).current) so it isn't a ref read during render — the hub is + // created once and never replaced, so the value is a stable reference exactly as before. + const [hub] = useState(() => createTelemetryHub()); // Diagnostics bridge: every window (overlay + main + studio) answers the studio's Diagnostics-panel // poll with its heap/counts and obeys targeted debug commands (open devtools / toggle click-through). @@ -417,7 +418,7 @@ export default function Canvas({ studio = false }: Props) { const editingDef = useMemo( () => previewDef ?? - (editingDefId && library ? library.defs.find((d) => d.id === editingDefId) ?? null : null), + (editingDefId && library ? (library.defs.find((d) => d.id === editingDefId) ?? null) : null), [previewDef, editingDefId, library] ); const designing = studio && editingDef != null; @@ -466,15 +467,18 @@ export default function Canvas({ studio = false }: Props) { width: `${stageSize.w}px`, height: `${stageSize.h}px`, transform: `translate(${panX}px,${panY}px) scale(${zoom})` - } + } : {}; // Studio lays out into the stage box — the monitor work area normally, the def's size while - // designing a widget (so its flow tree solves at the widget's own dimensions). useLayoutEffect so - // workArea tracks a monitor<->def swap in the SAME frame (no one-frame mis-solve flash). - useLayoutEffect(() => { - if (studio) setWorkArea({ x: 0, y: 0, w: stageSize.w, h: stageSize.h }); - }, [studio, stageSize.w, stageSize.h]); + // designing a widget (so its flow tree solves at the widget's own dimensions). Done during render + // (store-previous pattern) rather than in a layout effect, so workArea tracks a monitor<->def swap + // in the SAME render pass (no one-frame mis-solve flash, and no post-commit setState cascade). + const [prevStageSize, setPrevStageSize] = useState<{ w: number; h: number } | null>(null); + if (studio && (prevStageSize?.w !== stageSize.w || prevStageSize?.h !== stageSize.h)) { + setPrevStageSize({ w: stageSize.w, h: stageSize.h }); + setWorkArea({ x: 0, y: 0, w: stageSize.w, h: stageSize.h }); + } const updateWorkArea = useCallback(async () => { if (studio) return; // the effect above owns the studio work area @@ -549,8 +553,8 @@ export default function Canvas({ studio = false }: Props) { // the overlay (synced cross-window via the 'storage' event). const [overlayPrefs, setOverlayPrefs] = useOverlayPrefs(); // Freshest prefs for the stable syncRects callback (which reads them without re-subscribing). + // Mirrored in the commit effect S1 below (not during render). const overlayPrefsRef = useRef(overlayPrefs); - overlayPrefsRef.current = overlayPrefs; // This window's role: the primary `main` overlay carries no ?monitor= param; secondary overlays do. // The main overlay is ALWAYS interactive (see overlayPresentation) so its webview can never get stuck // behind a click-through surface (e.g. an un-clickable crash page). @@ -649,7 +653,7 @@ export default function Canvas({ studio = false }: Props) { // The selected container's solved box (plain id — flow-tree containers aren't group-namespaced), // so the Inspector can cap pad/gap to it (guardrail against collapsing the content out of view). const selectedContainerBox = selectedContainer - ? combinedSolved.get(selectedContainer.id) ?? null + ? (combinedSolved.get(selectedContainer.id) ?? null) : null; const isGridCell = !!( selectedContainer && findParent(monitor.root, selectedContainer.id)?.kind === 'grid' @@ -693,8 +697,8 @@ export default function Canvas({ studio = false }: Props) { const editingDefName = previewDef ? previewDef.name : editingDefId && library - ? library.defs.find((d) => d.id === editingDefId)?.name ?? editingDefId - : ''; + ? (library.defs.find((d) => d.id === editingDefId)?.name ?? editingDefId) + : ''; const placement = useMemo<'flow' | 'floating' | null>(() => { if (selectedId === null) return null; @@ -721,7 +725,7 @@ export default function Canvas({ studio = false }: Props) { return m; }, [sensorEntries]); const configFields = useMemo( - () => (selectedWidget ? getMeta(selectedWidget.type)?.configFields ?? [] : []), + () => (selectedWidget ? (getMeta(selectedWidget.type)?.configFields ?? []) : []), [selectedWidget] ); // Audio output devices for the spectrum widget's device picker (studio only — the inspector lives @@ -784,8 +788,8 @@ export default function Canvas({ studio = false }: Props) { label: isContainer(n) ? `▦ ${n.kind} · ${n.id}` : isGroup(n.unit) - ? `group ${n.unit.name ?? n.id}` - : `${(n.unit as WidgetInstance).type} · ${n.id}` + ? `group ${n.unit.name ?? n.id}` + : `${(n.unit as WidgetInstance).type} · ${n.id}` })), [multiNodes] ); @@ -860,9 +864,15 @@ export default function Canvas({ studio = false }: Props) { }, [renderables, studio, zoom, measuredRef]); // Latest values for callbacks that run outside the render (listeners / async). const interactiveItemsRef = useRef(interactiveItems); - interactiveItemsRef.current = interactiveItems; const editModeRef = useRef(editMode); - editModeRef.current = editMode; + // Sync effect S1: keep the refs the passive-overlay syncRects path reads current. Declared ABOVE + // the effects that call syncRects (measured-rects + presentation) so those see the latest values + // on every commit — these are the only refs read synchronously inside an effect body. + useEffect(() => { + overlayPrefsRef.current = overlayPrefs; + interactiveItemsRef.current = interactiveItems; + editModeRef.current = editMode; + }); const syncRects = useCallback(() => { const p = overlayPrefsRef.current; @@ -928,7 +938,7 @@ export default function Canvas({ studio = false }: Props) { // An explicit '' (default tokens) on the monitor is honored — it's a string, so the ?? keeps it. const lock = obj?.themeLock !== false; patch.themeLock = lock; - const t = lock ? obj?.theme : mon?.theme ?? obj?.theme; + const t = lock ? obj?.theme : (mon?.theme ?? obj?.theme); if (typeof t === 'string' && t !== stateThemeRef.current) { patch.selectedTheme = t; nextTheme = t; @@ -952,9 +962,9 @@ export default function Canvas({ studio = false }: Props) { dispatch({ type: 'setBaseline' }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch, adoptTheme]); - // myMonitor latest, for reloadLayout/persist reading inside listeners. + // myMonitor latest, for reloadLayout/persist reading inside listeners. Mirrored in the commit + // effect S3 near the end of the component (not during render). const myMonitorRef = useRef(myMonitor); - myMonitorRef.current = myMonitor; // --- third-party plugin packages --- // Discover + apply the enabled ones once per window (both roles — an overlay needs an enabled @@ -968,8 +978,9 @@ export default function Canvas({ studio = false }: Props) { }, [studio, navSection]); // --- syncPrimaryOverlays (primary main window only) --- + // monitorRef is mirrored in the commit effect S3; reloadLayout also writes it imperatively during + // init so the first syncPrimaryOverlays sees the freshly-loaded monitor. const monitorRef = useRef(monitor); - monitorRef.current = monitor; const syncPrimaryOverlays = useCallback(async () => { await reconcileOverlays(); await setMainWindowVisible(monitorHasWidgets(monitorRef.current)); @@ -1149,10 +1160,9 @@ export default function Canvas({ studio = false }: Props) { if (savedFlashTimer.current) clearTimeout(savedFlashTimer.current); savedFlashTimer.current = window.setTimeout(() => setSavedFlash(false), 2200); }, [studio, clearPreviewWrite, persistToDisk, dispatch]); + // Mirrored in the commit effect S3 (read only from the studio-close listener). const pendingExtrasRef = useRef(pendingExtras); - pendingExtrasRef.current = pendingExtras; const commitSaveRef = useRef(commitSave); - commitSaveRef.current = commitSave; // Window-close guard (studio only): if there are unsaved changes, PROMPT to save / discard / keep // editing instead of silently closing (the studio live-previews edits to disk, so a blind close @@ -1188,8 +1198,7 @@ export default function Canvas({ studio = false }: Props) { return () => unlisten(); }, [studio]); - const savedBaselineRef = useRef(savedBaseline); - savedBaselineRef.current = savedBaseline; + const savedBaselineRef = useRef(savedBaseline); // mirrored in the commit effect S3 // Restore the editor AND the on-disk layout to the saved baseline, reverting the live preview. // We write the baseline values DIRECTLY (writeBaseline) rather than via persistToDisk because // the reducer's revert set lags a render — the disk write must use the baseline immediately. @@ -1213,8 +1222,7 @@ export default function Canvas({ studio = false }: Props) { applyTheme(); dispatch({ type: 'resetHistory' }); }, [studio, dispatch, revertDraftToDisk, applyTheme]); - const dirtyRef = useRef(dirty); - dirtyRef.current = dirty; + const dirtyRef = useRef(dirty); // mirrored in the commit effect S3 // --- sacks (item 10): export the studio's shareable state, import + merge one back --- const { sackInfos, exportSack, importSack } = useSacks({ @@ -1238,10 +1246,13 @@ export default function Canvas({ studio = false }: Props) { }); // Entering a def edit (from anywhere) switches to the Widget designer section, where its - // widget-sized design canvas is revealed. - useEffect(() => { + // widget-sized design canvas is revealed. Done during render (store-previous pattern) so it isn't + // a post-commit setState cascade; fires on the transition of editingDefId to a non-null value. + const [prevEditingDefId, setPrevEditingDefId] = useState(editingDefId); + if (editingDefId !== prevEditingDefId) { + setPrevEditingDefId(editingDefId); if (studio && editingDefId != null) setNavSection('widget-designer'); - }, [studio, editingDefId]); + } // Settings: remove all widgets on this monitor (undoable; Save to apply). const clearMonitor = useCallback(() => { @@ -1258,6 +1269,20 @@ export default function Canvas({ studio = false }: Props) { })); }, [commitOp]); + // Context-menu state (5d). Declared here — ahead of switchMonitor and the widget/outline/canvas + // handlers that call setMenu — so setMenu is never referenced before its declaration. `cellIndex` + // is set only when opened from an empty grid cell → "Add inside" targets that cell. `wx/wy` capture + // the opening click in WORLD coords (computed in the opening handlers, where DOM reads are legal) + // so menuStack can hit-test during render without touching a ref/the DOM. + const [menu, setMenu] = useState<{ + x: number; + y: number; + id: string; + cellIndex?: number; + wx?: number; + wy?: number; + } | null>(null); + // --- studio: switch monitor --- const switchMonitor = useCallback( async (key: string) => { @@ -1267,6 +1292,7 @@ export default function Canvas({ studio = false }: Props) { await revertDraftToDisk(); } setMyMonitor(key); + // eslint-disable-next-line react-hooks/immutability -- eager latest-ref sync (mirrors the ref-sync effect); read by later async steps in this handler myMonitorRef.current = key; if (studio) writeStudioMonitor(key); // sticky across reloads dispatch({ type: 'patch', patch: { selectedId: null, selectedIds: [] } }); @@ -1291,11 +1317,10 @@ export default function Canvas({ studio = false }: Props) { // --- def editor entry points (studio bar) --- // The wrappers (fold-open-def + new/open/clone/preview/rename/delete) live in canvas/useDefEditor; // previewing stays mirrored here too for the canvas-level handlers (context menu / drag / keys). - const previewingRef = useRef(previewing); - previewingRef.current = previewing; - // The live-state mirror (read synchronously by moveNodeToMonitor + the def editor's in-use check). + const previewingRef = useRef(previewing); // mirrored in the commit effect S3 + // The live-state mirror (read by moveNodeToMonitor + the def editor's in-use check, both at event + // time). Mirrored in the commit effect S3. const stateRef = useRef(state); - stateRef.current = state; const { foldOpenDef, startNewWidget, @@ -1355,8 +1380,7 @@ export default function Canvas({ studio = false }: Props) { }, [canvasRef] ); - const panRef = useRef({ panX, panY, zoom }); - panRef.current = { panX, panY, zoom }; + const panRef = useRef({ panX, panY, zoom }); // mirrored in the commit effect S3 const toWorld = useCallback( (x: number, y: number): { x: number; y: number } => { const el = canvasRef.current; @@ -1371,14 +1395,11 @@ export default function Canvas({ studio = false }: Props) { // Latest live values for the drag math (read synchronously — no stale closure). // The combined (measured-flow + solver-floating) map drives drag/drop/hit-test, so targeting // aligns with what the browser actually laid out. + // All mirrored in the commit effect S3 (read only from drag/keyboard/menu event handlers). const solvedRef = useRef(combinedSolved); - solvedRef.current = combinedSolved; const renderablesRef = useRef(renderables); - renderablesRef.current = renderables; const monitorForDragRef = useRef(monitor); - monitorForDragRef.current = monitor; const selectedIdsRef = useRef(selectedIds); - selectedIdsRef.current = selectedIds; const computeDropBar = useCallback( (p: { x: number; y: number }, dragging: string): Rect | null => { @@ -1524,10 +1545,8 @@ export default function Canvas({ studio = false }: Props) { }, [toWorld, toCanvas, computeDropBar, computeDropZone] ); - const dropIntoFlowRef = useRef(dropIntoFlow); - dropIntoFlowRef.current = dropIntoFlow; - const dropIntoCellsRef = useRef(dropIntoCells); - dropIntoCellsRef.current = dropIntoCells; + const dropIntoFlowRef = useRef(dropIntoFlow); // mirrored in the commit effect S3 + const dropIntoCellsRef = useRef(dropIntoCells); // mirrored in the commit effect S3 const onDrop = useCallback( (e: { id: string; x: number; y: number }) => { @@ -1622,24 +1641,12 @@ export default function Canvas({ studio = false }: Props) { ); // ========================================================================================= - // Context menu (5d). + // Context menu (5d). (The `menu` state itself is declared earlier, before switchMonitor.) // ========================================================================================= - // `cellIndex` is set only when opened from an empty grid cell → "Add inside" targets that cell. - const [menu, setMenu] = useState<{ - x: number; - y: number; - id: string; - cellIndex?: number; - } | null>(null); // Context-menu HOVER PREVIEW: the structural op (split / add inside / add beside) under the pointer // or keyboard focus in the menu. A read-only ghost — never mutates the model, undo, or disk (the // preview rects are derived analytically from the measured boxes). Cleared when the menu closes. const [previewOp, setPreviewOp] = useState(null); - // Revert the preview whenever the menu closes — one place covers the backdrop click, Esc/Tab, - // applying an item (menuAct closes the menu), and any programmatic close. - useEffect(() => { - if (!menu) setPreviewOp(null); - }, [menu]); // Ghost rects for the hovered/focused menu item, derived analytically from the measured boxes // (gridPlaceholders supply the empty-cell targets). Purely additive — no model/undo/disk effect. const previewShapes = useMemo( @@ -1651,14 +1658,23 @@ export default function Canvas({ studio = false }: Props) { ); // The menu opens at the cursor but is clamped inside the window so it isn't clipped at the // right/bottom edges. We render at the cursor first, then measure the box and shift it back in a - // layout effect (runs before paint → no visible jump). Reset when the menu closes. + // layout effect (runs before paint → no visible jump). const ctxRef = useRef(null); const [menuPos, setMenuPos] = useState<{ left: number; top: number } | null>(null); - useLayoutEffect(() => { + // When the menu CLOSES, revert the hover preview and clear the clamped position. Done during render + // (store-previous pattern) — these were two menu-keyed effects whose synchronous setState on close + // is exactly what set-state-in-effect flags. Opening/repointing is handled by the layout effect + // below (a DOM measurement, which the rule allows). + const [prevMenu, setPrevMenu] = useState(menu); + if (menu !== prevMenu) { + setPrevMenu(menu); if (!menu) { + setPreviewOp(null); setMenuPos(null); - return; } + } + useLayoutEffect(() => { + if (!menu) return; // closing is handled during render (above) const el = ctxRef.current; if (!el) return; const r = el.getBoundingClientRect(); @@ -1690,28 +1706,12 @@ export default function Canvas({ studio = false }: Props) { } }, [menu]); - const widgetsAt = useCallback((world: { x: number; y: number }): Renderable[] => { - const rs = renderablesRef.current; - const seen = new Set(); - const out: Renderable[] = []; - for (let i = rs.length - 1; i >= 0; i--) { - const r = rs[i]; - const b = r.rect; - if (world.x < b.x || world.x >= b.x + b.w || world.y < b.y || world.y >= b.y + b.h) continue; - if (seen.has(r.selectId)) continue; - seen.add(r.selectId); - out.push(r); - } - return out; - }, []); - const containerAt = useCallback( (world: { x: number; y: number }): string => innermostContainerAt(containerRectsRef.current, world, monitorForDragRef.current.root.id), [] ); - const containerRectsRef = useRef(containerRects); - containerRectsRef.current = containerRects; + const containerRectsRef = useRef(containerRects); // mirrored in the commit effect S3 // menu-derived state. const menuNode = menu @@ -1729,7 +1729,7 @@ export default function Canvas({ studio = false }: Props) { const menuCanDistribute = menuNode !== null && isContainer(menuNode) && menuNode.children.length >= 2; const menuParentId = - menuId && menuId !== '__canvas__' ? findParent(monitor.root, menuId)?.id ?? null : null; + menuId && menuId !== '__canvas__' ? (findParent(monitor.root, menuId)?.id ?? null) : null; // A row/col container can be FLIPPED to the other orientation (context-menu "Convert to …"). const menuConvertKind: Container['kind'] | null = menuNode && isContainer(menuNode) && (menuNode.kind === 'row' || menuNode.kind === 'col') @@ -1741,26 +1741,36 @@ export default function Canvas({ studio = false }: Props) { // widgets first (front-to-back), then the containers/grid cells nesting them (smallest first). // Picking an entry re-points the menu at it, so you can act on a widget OR any container around it. const menuStack = useMemo<{ id: string; label: string }[]>(() => { - if (!menu || !studio) return []; - const world = toWorld(menu.x, menu.y); - const widgets = widgetsAt(world).map((r) => ({ - id: r.selectId, - label: `${r.instance.type} · ${r.selectId}` - })); - const rootId = monitorForDragRef.current.root.id; - const containers = containerRectsRef.current + if (!menu || !studio || menu.wx == null || menu.wy == null) return []; + const wx = menu.wx; + const wy = menu.wy; + // Overlapping widgets first (front-to-back, deduped by selectId), then the containers/grid cells + // nesting them (smallest first). Reads the live renderables/containerRects directly (no refs); + // the opening click's WORLD coords were captured in the handler, so no DOM read is needed here. + const seen = new Set(); + const widgets: { id: string; label: string }[] = []; + for (let i = renderables.length - 1; i >= 0; i--) { + const r = renderables[i]; + const b = r.rect; + if (wx < b.x || wx >= b.x + b.w || wy < b.y || wy >= b.y + b.h) continue; + if (seen.has(r.selectId)) continue; + seen.add(r.selectId); + widgets.push({ id: r.selectId, label: `${r.instance.type} · ${r.selectId}` }); + } + const rootId = monitor.root.id; + const containers = containerRects .filter( (c) => c.id !== rootId && - world.x >= c.rect.x && - world.x < c.rect.x + c.rect.w && - world.y >= c.rect.y && - world.y < c.rect.y + c.rect.h + wx >= c.rect.x && + wx < c.rect.x + c.rect.w && + wy >= c.rect.y && + wy < c.rect.y + c.rect.h ) .sort((a, b) => a.rect.w * a.rect.h - b.rect.w * b.rect.h) .map((c) => ({ id: c.id, label: `▦ ${c.kind} · ${c.id}` })); return [...widgets, ...containers]; - }, [menu, studio, widgetsAt, toWorld]); + }, [menu, studio, renderables, containerRects, monitor]); // A right-button free-move (WidgetHost) arms this so the contextmenu that trails the drag is // swallowed exactly once — by whichever entry point it lands on (the widget's handleContextMenu @@ -1781,15 +1791,23 @@ export default function Canvas({ studio = false }: Props) { return false; }, []); - const onWidgetContextMenu = useCallback((e: { id: string; x: number; y: number }) => { - setMenu({ x: e.x, y: e.y, id: e.id }); - }, []); + const onWidgetContextMenu = useCallback( + (e: { id: string; x: number; y: number }) => { + const w = toWorld(e.x, e.y); + setMenu({ x: e.x, y: e.y, id: e.id, wx: w.x, wy: w.y }); + }, + [toWorld] + ); // Outline rows open the same node menu (the rows name nodes, so no hit-testing needed). The // root row maps to the stage's '__canvas__' sentinel like a bare-canvas right-click would. - const onOutlineContextMenu = useCallback((e: { id: string; x: number; y: number }) => { - const rootId = monitorForDragRef.current.root.id; - setMenu({ x: e.x, y: e.y, id: e.id === rootId ? '__canvas__' : e.id }); - }, []); + const onOutlineContextMenu = useCallback( + (e: { id: string; x: number; y: number }) => { + const rootId = monitorForDragRef.current.root.id; + const w = toWorld(e.x, e.y); + setMenu({ x: e.x, y: e.y, id: e.id === rootId ? '__canvas__' : e.id, wx: w.x, wy: w.y }); + }, + [toWorld] + ); const onCanvasContextMenu = useCallback( (event: React.MouseEvent) => { if (!editModeRef.current || previewingRef.current) return; // read-only while previewing @@ -1804,8 +1822,15 @@ export default function Canvas({ studio = false }: Props) { event.preventDefault(); if (consumeSuppressCtx()) return; // swallow the contextmenu trailing a right-drag free-move const mon = monitorForDragRef.current; - const id = studio ? containerAt(toWorld(event.clientX, event.clientY)) : mon.root.id; - setMenu({ x: event.clientX, y: event.clientY, id: id === mon.root.id ? '__canvas__' : id }); + const world = toWorld(event.clientX, event.clientY); + const id = studio ? containerAt(world) : mon.root.id; + setMenu({ + x: event.clientX, + y: event.clientY, + id: id === mon.root.id ? '__canvas__' : id, + wx: world.x, + wy: world.y + }); }, [studio, navSection, designing, containerAt, toWorld, consumeSuppressCtx] ); @@ -1943,10 +1968,9 @@ export default function Canvas({ studio = false }: Props) { // widget def these stay inert — a nav-rail CLICK instead prompts to finish + leave (navToSection), // but a blocking confirm fired from a keystroke would be jarring. Defined before useKeyboard so its // handler map can reference them. + // Both mirrored in the commit effect S3 (read only from gotoSection/cycleSection at event time). const navSectionRef = useRef(navSection); - navSectionRef.current = navSection; const designingRef = useRef(designing); - designingRef.current = designing; const gotoSection = useCallback((index: number) => { if (designingRef.current) return; // Index the SAME grouped sequence the NavRail renders (main group, then foot), so Ctrl+1..8 @@ -1970,8 +1994,7 @@ export default function Canvas({ studio = false }: Props) { }, [setSelection]); // --- keyboard --- - const dirtyKbRef = useRef(dirty); - dirtyKbRef.current = dirty; + const dirtyKbRef = useRef(dirty); // mirrored in the commit effect S3 const { spaceDownRef, spaceDown } = useKeyboard({ studio, // The plain ControlContext slice; `previewing` folds into the controls' canEdit gate (so @@ -2008,8 +2031,8 @@ export default function Canvas({ studio = false }: Props) { const ids = selectedIdsRef.current.length ? selectedIdsRef.current : selectedIdRef.current - ? [selectedIdRef.current] - : []; + ? [selectedIdRef.current] + : []; const idSet = new Set(ids); if (!idSet.size || (dx === 0 && dy === 0)) return; let changed = false; @@ -2031,9 +2054,42 @@ export default function Canvas({ studio = false }: Props) { } }); const menuRef = useRef(menu); - menuRef.current = menu; const selectedIdRef = useRef(selectedId); - selectedIdRef.current = selectedId; + + // Sync effect S3: mirror the latest render values into the refs that async / event-time consumers + // read (Tauri listeners, the studio-close guard, drag / keyboard / context-menu handlers, persist). + // Runs on every commit — after render, before any of those consumers can fire — so they always see + // current values. The syncRects trio (the only refs read synchronously inside an effect body) is + // handled by the earlier effect S1; none of the refs below are read during render. + // (Some refs below are also read by hooks declared above, so react-hooks/immutability wants the + // write "before the hook" — but a render-time ref write trips react-hooks/refs instead. A latest-ref + // mirror can't satisfy both rules at once, and this project doesn't run the React Compiler; these are + // refs, mutable by design, read only after commit.) + useEffect(() => { + /* eslint-disable react-hooks/immutability */ + myMonitorRef.current = myMonitor; + monitorRef.current = monitor; + pendingExtrasRef.current = pendingExtras; + commitSaveRef.current = commitSave; + savedBaselineRef.current = savedBaseline; + dirtyRef.current = dirty; + dirtyKbRef.current = dirty; + previewingRef.current = previewing; + stateRef.current = state; + panRef.current = { panX, panY, zoom }; + solvedRef.current = combinedSolved; + renderablesRef.current = renderables; + monitorForDragRef.current = monitor; + selectedIdsRef.current = selectedIds; + selectedIdRef.current = selectedId; + dropIntoFlowRef.current = dropIntoFlow; + dropIntoCellsRef.current = dropIntoCells; + containerRectsRef.current = containerRects; + navSectionRef.current = navSection; + designingRef.current = designing; + menuRef.current = menu; + /* eslint-enable react-hooks/immutability */ + }); // --- canvas pointer (marquee + pan) --- const { marquee, panning, onCanvasMouseDown } = useCanvasPointer({ @@ -2257,11 +2313,14 @@ export default function Canvas({ studio = false }: Props) { onContextMenu={(e) => { e.preventDefault(); e.stopPropagation(); + const w = toWorld(e.clientX, e.clientY); setMenu({ x: e.clientX, y: e.clientY, id: cell.gridId === monitor.root.id ? '__canvas__' : cell.gridId, - cellIndex: cell.index + cellIndex: cell.index, + wx: w.x, + wy: w.y }); }} /> @@ -2331,7 +2390,7 @@ export default function Canvas({ studio = false }: Props) { top: `${workArea.y}px`, width: `${workArea.w}px`, height: `${workArea.h}px` - } + } : { position: 'absolute', inset: 0 } } > @@ -3256,8 +3315,8 @@ export default function Canvas({ studio = false }: Props) { {kind === 'row' ? '+ Row inside' : kind === 'col' - ? '+ Column inside' - : '+ Grid inside'} + ? '+ Column inside' + : '+ Grid inside'} ))} {menuCanCollapse && ( @@ -3301,8 +3360,8 @@ export default function Canvas({ studio = false }: Props) { {kind === 'row' ? '+ Row beside' : kind === 'col' - ? '+ Column beside' - : '+ Grid beside'} + ? '+ Column beside' + : '+ Grid beside'} ))} @@ -3391,7 +3450,7 @@ function patchFloatingGroupBox( h: rect.h } } - } + } : l ) } diff --git a/client/src/lib/widgets/ColorField.tsx b/client/src/lib/widgets/ColorField.tsx index 6c6b1d6..7a27a23 100644 --- a/client/src/lib/widgets/ColorField.tsx +++ b/client/src/lib/widgets/ColorField.tsx @@ -3,7 +3,7 @@ // still round-trip. Editing the swatch writes `#rrggbb`; editing the text writes its raw value // (committed on blur, so we don't churn an undo/save per keystroke). The swatch mirrors the current // value (or the inherited placeholder when empty) via toHexColor. A ✕ clears the override. -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { toHexColor } from './colorHex'; import { isValidColor } from './themeTokens'; import './ColorField.css'; @@ -19,7 +19,13 @@ export default function ColorField({ value, placeholder, ariaLabel, onChange }: // Local text state so typing doesn't commit (and re-render the world) on every keystroke; resync // when the external value changes (Clear, theme switch, selecting another widget). const [text, setText] = useState(value); - useEffect(() => setText(value), [value]); + // Resync during render when the external value changes (Clear, theme switch, selecting another + // widget) — the store-previous idiom, so typing (which only touches local `text`) isn't clobbered. + const [prevValue, setPrevValue] = useState(value); + if (value !== prevValue) { + setPrevValue(value); + setText(value); + } const swatch = toHexColor(text || placeholder || '') ?? '#000000'; const invalid = !isValidColor(text); diff --git a/client/src/lib/widgets/CssEditorImpl.tsx b/client/src/lib/widgets/CssEditorImpl.tsx index e435851..8c0ac6f 100644 --- a/client/src/lib/widgets/CssEditorImpl.tsx +++ b/client/src/lib/widgets/CssEditorImpl.tsx @@ -32,8 +32,11 @@ export default function CssEditorImpl({ const hostRef = useRef(null); const viewRef = useRef(null); // Latest callbacks, so the once-created view always calls the current handlers (no stale closures). + // Committed after render (not during it); the view only ever reads them inside CM callbacks, later. const cbRef = useRef({ onChange, onBlur }); - cbRef.current = { onChange, onBlur }; + useEffect(() => { + cbRef.current = { onChange, onBlur }; + }); useEffect(() => { const host = hostRef.current; diff --git a/client/src/lib/widgets/DiagnosticsPanel.tsx b/client/src/lib/widgets/DiagnosticsPanel.tsx index f4b08f6..f5765f1 100644 --- a/client/src/lib/widgets/DiagnosticsPanel.tsx +++ b/client/src/lib/widgets/DiagnosticsPanel.tsx @@ -46,9 +46,13 @@ export default function DiagnosticsPanel() { // this just reflects the control state). const [interactive, setInteractive] = useState>({}); // This (studio) window's per-widget render cost, from the s Canvas wraps each widget in. - const [costs, setCosts] = useState([]); + // Seeded lazily on mount (the interval below keeps it fresh) so render stays free of setState. + const [costs, setCosts] = useState(() => widgetCosts()); // Per-subsystem backend CPU timing (Rust). Demand-gated: enabled only while this panel is open. const [timings, setTimings] = useState([]); + // Wall clock used only for staleness, refreshed on each poll — keeps `performance.now()` (impure) + // out of the render body while giving mergeWindowList a monotonically-advancing "now". + const [now, setNow] = useState(() => performance.now()); useEffect(() => { let alive = true; @@ -78,7 +82,6 @@ export default function DiagnosticsPanel() { requestDiagnostics(); pollProc(); pollLabels(); - setCosts(widgetCosts()); pollTimings(); const poll = window.setInterval(() => { requestDiagnostics(); @@ -86,6 +89,7 @@ export default function DiagnosticsPanel() { pollLabels(); setCosts(widgetCosts()); pollTimings(); + setNow(performance.now()); }, POLL_MS); return () => { alive = false; @@ -95,7 +99,7 @@ export default function DiagnosticsPanel() { }; }, []); - const rows = mergeWindowList(reports, labels, performance.now(), STALE_MS); + const rows = mergeWindowList(reports, labels, now, STALE_MS); const toggleInteractive = (label: string, value: boolean): void => { setInteractive((m) => ({ ...m, [label]: value })); diff --git a/client/src/lib/widgets/DragSnapLayer.css b/client/src/lib/widgets/DragSnapLayer.css index 73cbeac..d6c13a8 100644 --- a/client/src/lib/widgets/DragSnapLayer.css +++ b/client/src/lib/widgets/DragSnapLayer.css @@ -9,6 +9,12 @@ background: rgba(var(--ui-accent-rgb), 0.18); border: 2px solid rgba(var(--ui-accent-rgb), 0.85); border-radius: 6px; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25), 0 8px 30px rgba(0, 0, 0, 0.35); - transition: left 90ms ease, top 90ms ease, width 90ms ease, height 90ms ease; + box-shadow: + 0 0 0 1px rgba(0, 0, 0, 0.25), + 0 8px 30px rgba(0, 0, 0, 0.35); + transition: + left 90ms ease, + top 90ms ease, + width 90ms ease, + height 90ms ease; } diff --git a/client/src/lib/widgets/DragSnapLayer.tsx b/client/src/lib/widgets/DragSnapLayer.tsx index b09c086..bb92d6d 100644 --- a/client/src/lib/widgets/DragSnapLayer.tsx +++ b/client/src/lib/widgets/DragSnapLayer.tsx @@ -145,7 +145,7 @@ export default function DragSnapLayer() { try { const z = armedZone(physRef.current, await pointerProbe()); hoveredRef.current = z; - setHighlight(z ? localRef.current.get(z.id) ?? null : null); + setHighlight(z ? (localRef.current.get(z.id) ?? null) : null); } finally { busyRef.current = false; } diff --git a/client/src/lib/widgets/ImageHost.tsx b/client/src/lib/widgets/ImageHost.tsx index 98aabf1..799efdf 100644 --- a/client/src/lib/widgets/ImageHost.tsx +++ b/client/src/lib/widgets/ImageHost.tsx @@ -10,27 +10,23 @@ import { wallpaperAssetUrl } from '../overlay'; type Props = { src?: string; fit?: string; alt?: string }; export default function ImageHost({ src = '', fit = 'contain', alt = '' }: Props) { - const [url, setUrl] = useState(''); + const s = (src ?? '').trim(); + // The synchronous cases (empty, or a direct URL) resolve during render; `null` means the source is + // a bare filename that needs the async wallpapers/ lookup below. + const direct = !s ? '' : isDirectUrl(s) ? s : null; + const [resolved, setResolved] = useState(''); useEffect(() => { - const s = (src ?? '').trim(); - if (!s) { - setUrl(''); - return; - } - if (isDirectUrl(s)) { - setUrl(s); - return; - } + if (direct !== null) return; // handled during render // A bare filename → resolve against the wallpapers/ folder (best-effort; empty on failure). let alive = true; void wallpaperAssetUrl(s).then((u) => { - if (alive) setUrl(u); + if (alive) setResolved(u); }); return () => { alive = false; }; - }, [src]); + }, [direct, s]); - return ; + return ; } diff --git a/client/src/lib/widgets/Inspector.css b/client/src/lib/widgets/Inspector.css index 176f73f..21bc664 100644 --- a/client/src/lib/widgets/Inspector.css +++ b/client/src/lib/widgets/Inspector.css @@ -218,7 +218,8 @@ padding: var(--space-1) var(--space-2); width: 100%; box-sizing: border-box; - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), box-shadow var(--motion-fast, 100ms) var(--ease-out, ease-out), background var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -246,7 +247,8 @@ background: var(--ui-raised); cursor: pointer; position: relative; - transition: background var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + background var(--motion-fast, 100ms) var(--ease-out, ease-out), border-color var(--motion-fast, 100ms) var(--ease-out, ease-out); } .inspector input[type='checkbox']:hover { @@ -289,7 +291,9 @@ .inspector select:focus { outline: none; border-color: rgb(var(--ui-accent-rgb)); - box-shadow: 0 0 0 1px rgba(var(--ui-accent-rgb), 0.35), 0 0 6px rgba(var(--ui-accent-rgb), 0.15); + box-shadow: + 0 0 0 1px rgba(var(--ui-accent-rgb), 0.35), + 0 0 6px rgba(var(--ui-accent-rgb), 0.15); } .inspector textarea.error { @@ -304,7 +308,8 @@ font-size: var(--text-md); padding: var(--space-1) var(--space-3); cursor: pointer; - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), box-shadow var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -322,7 +327,8 @@ so the affordance feels as tactile as the toolbar. (The keyboard-focus ring comes from the global .canvas :focus-visible baseline.) */ .inspector .palette button { - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), box-shadow var(--motion-fast, 100ms) var(--ease-out, ease-out), transform var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -511,7 +517,8 @@ padding: var(--space-1) var(--space-4); cursor: pointer; /* The active underline slides in + the label brightens when the tab changes. */ - transition: color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + color var(--motion-fast, 100ms) var(--ease-out, ease-out), border-bottom-color var(--motion, 150ms) var(--ease-out, ease-out); } diff --git a/client/src/lib/widgets/Inspector.test.tsx b/client/src/lib/widgets/Inspector.test.tsx index 51870af..3db05ee 100644 --- a/client/src/lib/widgets/Inspector.test.tsx +++ b/client/src/lib/widgets/Inspector.test.tsx @@ -175,7 +175,7 @@ describe('Inspector sensor typeahead options', () => { onOp={vi.fn()} /> ); - fireEvent.click(screen.getByLabelText('Toggle options')); // open the sensor combobox + fireEvent.click(screen.getByRole('combobox', { name: 'sensor' })); // open the sensor combobox via its own input expect(screen.getByText('Temp (°C)')).toBeInTheDocument(); expect( screen.getByText('ha.sensor.temp', { selector: '.np-select-opt-hint' }) diff --git a/client/src/lib/widgets/Inspector.tsx b/client/src/lib/widgets/Inspector.tsx index 3d2e79c..d155834 100644 --- a/client/src/lib/widgets/Inspector.tsx +++ b/client/src/lib/widgets/Inspector.tsx @@ -315,6 +315,14 @@ export default function Inspector({ // still user-toggleable in between, and re-opens when nothing is selected (the primary add affordance). const hasSelection = !!(widget || container || groupUnit); const [addOpen, setAddOpen] = useState(!hasSelection); + // Auto-set on selection change (collapse once something is selected, re-open when nothing is), while + // staying user-toggleable in between — the store-previous idiom, so the reset happens during render + // only when `hasSelection` actually flips, not on every render. + const [prevHasSelection, setPrevHasSelection] = useState(hasSelection); + if (hasSelection !== prevHasSelection) { + setPrevHasSelection(hasSelection); + setAddOpen(!hasSelection); + } // Add-palette hover preview (Tier 2): a floating popover with a live demo render of the hovered // entry — a widget type, OR a library def / template tree. Debounced so a quick pass doesn't spin up @@ -361,9 +369,6 @@ export default function Inspector({ const top = Math.min(palettePreview.top, Math.max(8, window.innerHeight - el.offsetHeight - 8)); el.style.top = `${Math.max(8, top)}px`; }, [palettePreview]); - useEffect(() => { - setAddOpen(!hasSelection); - }, [hasSelection]); // Built-ins + one group per enabled plugin package (re-renders on package toggle). const templateGroups = useTemplateGroups(); @@ -408,16 +413,19 @@ export default function Inspector({ // is an editable buffer applied back via replaceNode; YAML is a read-only mirror. --- const [detailTab, setDetailTab] = useState<'form' | 'data'>('form'); const [dataFormat, setDataFormat] = useState<'json' | 'yaml'>('json'); - const [dataJson, setDataJson] = useState(''); + const [dataJson, setDataJson] = useState(() => (node ? JSON.stringify(node, null, 2) : '')); const [dataError, setDataError] = useState(null); // Re-sync the JSON buffer whenever the selected node changes by identity (selection switch or an // applied edit), mirroring the config-JSON box — so the buffer never goes stale under the agent. - useEffect(() => { + // Store-previous idiom: reset during render on an identity change, not via a set-state effect. + const [prevNode, setPrevNode] = useState(node); + if (node !== prevNode) { + setPrevNode(node); if (node) { setDataJson(JSON.stringify(node, null, 2)); setDataError(null); } - }, [node]); + } function applyNodeJson() { if (!node) return; try { @@ -472,23 +480,27 @@ export default function Inspector({ // The raw-JSON box mirrors the whole config, so it's dirty if any config field changed. const configDirty = [...dirtyKeys].some((k) => k.startsWith('config.')); - const [configText, setConfigText] = useState(''); + const [configText, setConfigText] = useState(() => + widget ? JSON.stringify(widget.config, null, 2) : '' + ); const [configError, setConfigError] = useState(false); // Re-sync the raw-JSON box whenever the config object changes by reference — i.e. on // widget switch AND on every typed-field edit (setConfig makes a new config object). // This keeps the escape-hatch textarea in step with the schema fields, so committing // the JSON can't silently revert a field edit. Typing in the textarea doesn't change - // widget.config until commit, so an in-progress edit is never clobbered. - useEffect(() => { + // widget.config until commit, so an in-progress edit is never clobbered. Store-previous + // idiom keyed on config identity (widget switch + each committed edit), so the reset runs + // during render — never on other widget prop changes, which would clobber in-progress typing. + const widgetConfig = widget?.config; + const [prevConfig, setPrevConfig] = useState(widgetConfig); + if (widgetConfig !== prevConfig) { + setPrevConfig(widgetConfig); if (widget) { setConfigText(JSON.stringify(widget.config, null, 2)); setConfigError(false); } - // Re-sync only on config-object identity (widget switch + each committed edit), never on - // other widget prop changes — that would clobber in-progress typing. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [widget?.config]); + } function patchWidget(patch: Partial) { if (widget) op({ op: 'patchWidget', id: widget.id, patch }); @@ -524,10 +536,10 @@ export default function Inspector({ mode === 'grow' ? { fr: 1 } : mode === 'fixed' - ? typeof container?.basis === 'number' - ? container.basis - : 100 - : undefined + ? typeof container?.basis === 'number' + ? container.basis + : 100 + : undefined }); // Guarded actions. @@ -673,10 +685,10 @@ export default function Inspector({ v === 'grow' ? { fr: 1 } : v === 'fixed' - ? typeof widgetBasis === 'number' - ? widgetBasis - : 100 - : 'content' + ? typeof widgetBasis === 'number' + ? widgetBasis + : 100 + : 'content' }) } aria-label="size in parent" @@ -1095,8 +1107,8 @@ export default function Inspector({ isFrBasis(container.basis) ? 'grow' : typeof container.basis === 'number' - ? 'fixed' - : 'fit' + ? 'fixed' + : 'fit' } options={[ { value: 'fit', label: 'hug — fit children' }, @@ -1247,8 +1259,8 @@ export default function Inspector({ isFrBasis(widgetBasis) ? 'grow' : widgetBasis === 'content' - ? 'content' - : 'fixed' + ? 'content' + : 'fixed' } options={[ { value: 'fixed', label: 'fixed — use the w/h above' }, @@ -1409,18 +1421,18 @@ export default function Inspector({ ? [ { value: '', label: 'System default' }, ...audioOutputs.map((d) => ({ value: d.id, label: d.name })) - ] + ] : f.catalog === 'microphones' - ? [ - { value: '', label: 'System default' }, - ...microphones.map((d) => ({ value: d.id, label: d.name })) - ] - : f.catalog === 'displayNames' - ? [ - { value: '', label: 'Primary monitor' }, - ...displayNames.map((d) => ({ value: d.id, label: d.name })) - ] - : f.options.map((o) => ({ value: o, label: o })) + ? [ + { value: '', label: 'System default' }, + ...microphones.map((d) => ({ value: d.id, label: d.name })) + ] + : f.catalog === 'displayNames' + ? [ + { value: '', label: 'Primary monitor' }, + ...displayNames.map((d) => ({ value: d.id, label: d.name })) + ] + : f.options.map((o) => ({ value: o, label: o })) } onChange={(v) => setConfig(f.key, v)} aria-label={f.label} @@ -1684,7 +1696,7 @@ export default function Inspector({ /> ); - })() + })() : null} ); diff --git a/client/src/lib/widgets/MonitorSwitchHost.tsx b/client/src/lib/widgets/MonitorSwitchHost.tsx index 9ebfe22..eea7bb2 100644 --- a/client/src/lib/widgets/MonitorSwitchHost.tsx +++ b/client/src/lib/widgets/MonitorSwitchHost.tsx @@ -40,16 +40,16 @@ export default function MonitorSwitchHost({ const refresh = useCallback(async (): Promise => { const list = await listMonitorInputs(target || undefined); const found = target - ? list.find((m) => m.gdi === target) ?? null - : list.find((m) => m.primary) ?? list[0] ?? null; + ? (list.find((m) => m.gdi === target) ?? null) + : (list.find((m) => m.primary) ?? list[0] ?? null); setSelected(found); setMissing(Boolean(target) && found === null); }, [target]); useEffect(() => { let alive = true; - void refresh(); const onFocus = (): void => void refresh(); + onFocus(); // initial load (kept off the effect's sync path — refresh setStates after an await) window.addEventListener('focus', onFocus); const timer = window.setInterval(() => { if (alive) void refresh(); @@ -75,7 +75,7 @@ export default function MonitorSwitchHost({ [selected, target, refresh] ); - const current = showCurrent ? selected?.current_input ?? null : null; + const current = showCurrent ? (selected?.current_input ?? null) : null; const rows = useMemo( () => monitorInputRows({ discovered: selected?.supported ?? [], spec: sources, current }), [selected, sources, current] @@ -86,7 +86,7 @@ export default function MonitorSwitchHost({ width: selected.width, height: selected.height, refreshHz: selected.refresh_hz - }) + }) : ''; return ( diff --git a/client/src/lib/widgets/NavRail.css b/client/src/lib/widgets/NavRail.css index 38f05ca..4619934 100644 --- a/client/src/lib/widgets/NavRail.css +++ b/client/src/lib/widgets/NavRail.css @@ -36,7 +36,8 @@ cursor: pointer; /* The active-section indicator slides in (border) and the hover tint eases, so switching sections feels tracked rather than snapping. */ - transition: color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + color var(--motion-fast, 100ms) var(--ease-out, ease-out), background var(--motion-fast, 100ms) var(--ease-out, ease-out), border-left-color var(--motion, 150ms) var(--ease-out, ease-out); } @@ -226,7 +227,8 @@ uncluttered and the destructive ✕ isn't a live target at rest — but the buttons stay in the DOM and tab order for keyboard reach (:focus-within brings them in when tabbed to). */ opacity: 0; - transition: opacity var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + opacity var(--motion-fast, 100ms) var(--ease-out, ease-out), color var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -387,7 +389,8 @@ border-radius: var(--radius-control); padding: var(--space-2) var(--space-3); cursor: pointer; - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), color var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -516,7 +519,8 @@ border-radius: var(--radius-control); padding: var(--space-2) var(--space-3); cursor: pointer; - transition: border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + border-color var(--motion-fast, 100ms) var(--ease-out, ease-out), color var(--motion-fast, 100ms) var(--ease-out, ease-out); } @@ -737,7 +741,8 @@ padding: var(--space-1) var(--space-3); cursor: pointer; opacity: 0; - transition: opacity var(--motion-fast, 100ms) var(--ease-out, ease-out), + transition: + opacity var(--motion-fast, 100ms) var(--ease-out, ease-out), color var(--motion-fast, 100ms) var(--ease-out, ease-out); } diff --git a/client/src/lib/widgets/Outline.tsx b/client/src/lib/widgets/Outline.tsx index 3582342..49418b1 100644 --- a/client/src/lib/widgets/Outline.tsx +++ b/client/src/lib/widgets/Outline.tsx @@ -58,7 +58,7 @@ function Outline({ e.preventDefault(); onNodeContextMenu({ id, x: e.clientX, y: e.clientY }); } - } + } : undefined; const rows = useMemo(() => outlineRows(root), [root]); diff --git a/client/src/lib/widgets/Select.tsx b/client/src/lib/widgets/Select.tsx index b799e6a..4589b71 100644 --- a/client/src/lib/widgets/Select.tsx +++ b/client/src/lib/widgets/Select.tsx @@ -178,8 +178,8 @@ function SelectCombobox({ ? '' : inputValue : inputValue === displayValue(options, value, false) - ? '' - : inputValue; + ? '' + : inputValue; const items = useMemo(() => filterOptions(options, query), [options, query]); const { @@ -217,14 +217,16 @@ function SelectCombobox({ }); const rect = useAnchoredRect(wrapRef, isOpen); - // On close, a non-custom combobox with stray filter text snaps back to the selected label. - useEffect(() => { + // On close, a non-custom combobox with stray filter text snaps back to the selected label. Runs on + // the open→close transition only (store-previous idiom), during render rather than in an effect. + const [prevOpen, setPrevOpen] = useState(isOpen); + if (isOpen !== prevOpen) { + setPrevOpen(isOpen); if (!isOpen && !allowCustom) { const d = displayValue(options, value, false); if (inputValue !== d) setInputValue(d); } - // eslint-disable-next-line react-hooks/exhaustive-deps -- run on open/close transitions only - }, [isOpen]); + } return (
{activity.referenced ? '★' : activity.active ? '●' : '○'} @@ -90,7 +90,7 @@ export default function SensorList({ key={id} hub={hub} id={id} - badge={groupFor ? null : badgeFor?.(id) ?? null} + badge={groupFor ? null : (badgeFor?.(id) ?? null)} activity={activityFor?.(id) ?? null} /> ))} diff --git a/client/src/lib/widgets/ThemePreview.tsx b/client/src/lib/widgets/ThemePreview.tsx index 07b2ba2..d080ee7 100644 --- a/client/src/lib/widgets/ThemePreview.tsx +++ b/client/src/lib/widgets/ThemePreview.tsx @@ -4,7 +4,7 @@ // injects into the studio document, so editing a token (or switching theme) restyles the preview // live, exactly as it will the overlay. Kept dependency-light (no spectrum/now-playing) so it needs // no extra context. Co-located test in ThemePreview.test.tsx. -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { createTelemetryHub, type SensorSample, type TelemetryHub } from '../core/telemetry'; import { createWidget } from '../core/widget'; import type { WidgetInstance } from '../core/layout'; @@ -46,9 +46,10 @@ function build( } export default function ThemePreview() { + // new Date()/Date.now() is fine in a live component (only the screenshot gallery freezes the clock); + // seeded once at mount via lazy state so the render body stays pure. + const [now] = useState(() => Date.now()); const { hub, items } = useMemo(() => { - // new Date() is fine in a live component (only the screenshot gallery freezes the clock). - const now = Date.now(); return { hub: seedHub(now), items: [ @@ -60,7 +61,7 @@ export default function ThemePreview() { build('button', 'tp-btn', 90, 38, undefined, { label: 'tap' }) ] }; - }, []); + }, [now]); return (
diff --git a/client/src/lib/widgets/WidgetHost.tsx b/client/src/lib/widgets/WidgetHost.tsx index e8fbb5c..890f25d 100644 --- a/client/src/lib/widgets/WidgetHost.tsx +++ b/client/src/lib/widgets/WidgetHost.tsx @@ -341,8 +341,8 @@ function WidgetHost({ style={ flow ? // Slot mode (CSS layout): fill the FlowNode slot that owns position/size; only the - // live drag ghost is applied here. - { width: '100%', height: '100%', transform: `translate(${ghost.dx}px, ${ghost.dy}px)` } + // live drag ghost is applied here. + { width: '100%', height: '100%', transform: `translate(${ghost.dx}px, ${ghost.dy}px)` } : { left: `${rect.x}px`, top: `${rect.y}px`, @@ -351,7 +351,7 @@ function WidgetHost({ width: contentSize ? 'max-content' : `${rect.w}px`, height: contentSize ? 'max-content' : `${rect.h}px`, transform: `translate(${ghost.dx}px, ${ghost.dy}px)` - } + } } data-w={domId} data-type={instance.type} diff --git a/client/src/lib/widgets/WidgetPreview.tsx b/client/src/lib/widgets/WidgetPreview.tsx index 779004b..7692bf2 100644 --- a/client/src/lib/widgets/WidgetPreview.tsx +++ b/client/src/lib/widgets/WidgetPreview.tsx @@ -4,7 +4,7 @@ // preview matches how it renders on the canvas, theme tokens and all. A tree is drawn at its native // size and scaled to fit the box. Self-sourcing / bespoke widgets that need the backend (now-playing, // spectrum, HA…) just render their idle state here, which still previews their chrome. -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { createTelemetryHub, type SensorSample, type TelemetryHub } from '../core/telemetry'; import { createWidget } from '../core/widget'; import { leaf, type LayoutNode, type WidgetInstance } from '../core/layoutTree'; @@ -73,7 +73,9 @@ type Props = { }; export default function WidgetPreview({ type, node, size, w = 200, h = 120 }: Props) { - const hub = useMemo(() => seedHub(Date.now()), []); + // Seed the demo clock once at mount via lazy state, keeping Date.now() (impure) out of render. + const [now] = useState(() => Date.now()); + const hub = useMemo(() => seedHub(now), [now]); // Normalise to a (tree, native-size) pair: a type becomes a one-leaf tree at the box size (scale 1); // a def/template tree keeps its authored size and is scaled to fit. const { tree, nat } = useMemo<{ tree: LayoutNode | null; nat: { w: number; h: number } }>(() => { diff --git a/client/src/lib/widgets/canvas/alignControls.ts b/client/src/lib/widgets/canvas/alignControls.ts index a89479b..77db5fe 100644 --- a/client/src/lib/widgets/canvas/alignControls.ts +++ b/client/src/lib/widgets/canvas/alignControls.ts @@ -79,14 +79,14 @@ export function containerAlignControls(c: Container): AlignControl[] { field: 'justify', value: c.justify ?? 'start', options: optionsFor('horizontal', 'justify') - } + } : { axis: 'horizontal', label: 'Horizontal', field: 'align', value: c.align ?? 'stretch', options: optionsFor('horizontal', 'align') - }; + }; const vertical: AlignControl = mainHorizontal ? { axis: 'vertical', @@ -94,14 +94,14 @@ export function containerAlignControls(c: Container): AlignControl[] { field: 'align', value: c.align ?? 'stretch', options: optionsFor('vertical', 'align') - } + } : { axis: 'vertical', label: 'Vertical', field: 'justify', value: c.justify ?? 'start', options: optionsFor('vertical', 'justify') - }; + }; return [horizontal, vertical]; } diff --git a/client/src/lib/widgets/canvas/editorOps.ts b/client/src/lib/widgets/canvas/editorOps.ts index bd35c2f..c782907 100644 --- a/client/src/lib/widgets/canvas/editorOps.ts +++ b/client/src/lib/widgets/canvas/editorOps.ts @@ -294,7 +294,7 @@ export function splitNode( gap: node.gap, pad: node.pad, justify: node.justify - }) + }) : null; let patch: Partial; if (dir === 'grid') { @@ -381,7 +381,7 @@ export function patchContainerOp(s: EditorState, id: string, patch: Partial ({ ...n, children: (n as Container).children.slice(0, cap) } as LayoutNode) + (n) => ({ ...n, children: (n as Container).children.slice(0, cap) }) as LayoutNode ); } } @@ -406,7 +406,7 @@ export function setNodeBasis(s: EditorState, id: string, basis: Length | undefin export function setNodeBases(s: EditorState, entries: { id: string; basis: Length }[]): Patch { let root = s.monitor.root; for (const { id, basis } of entries) { - root = updateNode(root, id, (n) => ({ ...n, basis } as LayoutNode)); + root = updateNode(root, id, (n) => ({ ...n, basis }) as LayoutNode); } return { monitor: { ...s.monitor, root } }; } diff --git a/client/src/lib/widgets/canvas/menuPreview.ts b/client/src/lib/widgets/canvas/menuPreview.ts index 4f9612f..c9856ed 100644 --- a/client/src/lib/widgets/canvas/menuPreview.ts +++ b/client/src/lib/widgets/canvas/menuPreview.ts @@ -49,10 +49,11 @@ function splitRegions( rows, gap, pad, - children: Array.from( - { length: cols * rows }, - (_, i): Container => ({ id: `__pc${i}`, kind: 'col', children: [] }) - ) + children: Array.from({ length: cols * rows }, (_, i): Container => ({ + id: `__pc${i}`, + kind: 'col', + children: [] + })) }; return gridCellRects(synthetic, box); } diff --git a/client/src/lib/widgets/canvas/setTokens.test.ts b/client/src/lib/widgets/canvas/setTokens.test.ts index c1b647a..2363199 100644 --- a/client/src/lib/widgets/canvas/setTokens.test.ts +++ b/client/src/lib/widgets/canvas/setTokens.test.ts @@ -3,7 +3,7 @@ import { setTokens } from './editorOps'; // setTokens only reads `tokenOverrides`, so a minimal partial state suffices. const state = (tokenOverrides: Record = {}) => - ({ tokenOverrides } as unknown as Parameters[0]); + ({ tokenOverrides }) as unknown as Parameters[0]; describe('setTokens op (wallpaper auto-theme)', () => { it('merges a whole map over the existing overrides', () => { diff --git a/client/src/lib/widgets/canvas/useBackground.test.ts b/client/src/lib/widgets/canvas/useBackground.test.ts index 51ef3aa..9e68f18 100644 --- a/client/src/lib/widgets/canvas/useBackground.test.ts +++ b/client/src/lib/widgets/canvas/useBackground.test.ts @@ -16,7 +16,7 @@ vi.mock('../../overlay', () => ({ import { useBackground } from './useBackground'; const monitor = (over: Partial = {}): MonitorLayout => - ({ root: {}, floating: [], ...over } as MonitorLayout); + ({ root: {}, floating: [], ...over }) as MonitorLayout; beforeEach(() => { listWallpapers.mockResolvedValue(['a.png', 'b.mp4']); diff --git a/client/src/lib/widgets/canvas/useCanvasPointer.test.ts b/client/src/lib/widgets/canvas/useCanvasPointer.test.ts index 15efcdd..7b0fb5a 100644 --- a/client/src/lib/widgets/canvas/useCanvasPointer.test.ts +++ b/client/src/lib/widgets/canvas/useCanvasPointer.test.ts @@ -47,7 +47,7 @@ const ev = (o: Over) => target: canvasEl, preventDefault: () => undefined, ...o - } as unknown as React.MouseEvent); + }) as unknown as React.MouseEvent; // Release any window listeners a pan/marquee attached, and reset transient state between cases. function release() { @@ -55,7 +55,7 @@ function release() { } const rend = (selectId: string, rect: { x: number; y: number; w: number; h: number }): Renderable => - ({ selectId, rect } as unknown as Renderable); + ({ selectId, rect }) as unknown as Renderable; afterEach(() => { release(); diff --git a/client/src/lib/widgets/canvas/useCanvasPointer.ts b/client/src/lib/widgets/canvas/useCanvasPointer.ts index 13ea957..0c1d614 100644 --- a/client/src/lib/widgets/canvas/useCanvasPointer.ts +++ b/client/src/lib/widgets/canvas/useCanvasPointer.ts @@ -64,6 +64,9 @@ export function useCanvasPointer(deps: CanvasPointerDeps): CanvasPointer { const marqueeStart = useRef<{ x: number; y: number } | null>(null); const marqueeAdditive = useRef(false); const panStart = useRef<{ x: number; y: number; panX: number; panY: number } | null>(null); + // The live marquee rect, tracked in a ref (written by the mousedown/mousemove handlers alongside + // setMarquee) so onMarqueeUp reads the final rect without touching the ref during render. + const marqueeCurrent = useRef(null); // canvas-relative coords (undo the rail inset). const toCanvas = useCallback( @@ -98,12 +101,18 @@ export function useCanvasPointer(deps: CanvasPointerDeps): CanvasPointer { }, [deps] ); - const onPanUp = useCallback(() => { - window.removeEventListener('mousemove', onPanMove); - window.removeEventListener('mouseup', onPanUp); - panStart.current = null; - setPanning(false); - }, [onPanMove]); + // Named function expression so the removeEventListener can reference the handler via its own + // in-scope name (the same fn object addEventListener registered) instead of the outer const — + // which the compiler would flag as "accessed before it is declared". + const onPanUp = useCallback( + function onPanUp() { + window.removeEventListener('mousemove', onPanMove); + window.removeEventListener('mouseup', onPanUp); + panStart.current = null; + setPanning(false); + }, + [onPanMove] + ); const startPan = useCallback( (event: React.MouseEvent) => { const p = deps.pan(); @@ -121,37 +130,40 @@ export function useCanvasPointer(deps: CanvasPointerDeps): CanvasPointer { const start = marqueeStart.current; if (!start) return; const p = toCanvas(event.clientX, event.clientY); - setMarquee({ + const rect: Rect = { x: Math.min(p.x, start.x), y: Math.min(p.y, start.y), w: Math.abs(p.x - start.x), h: Math.abs(p.y - start.y) - }); + }; + marqueeCurrent.current = rect; // keep the ref in step with state (both set here, off-render) + setMarquee(rect); }, [toCanvas] ); - const onMarqueeUp = useCallback(() => { - window.removeEventListener('mousemove', onMarqueeMove); - window.removeEventListener('mouseup', onMarqueeUp); - const m = marqueeCurrent.current; - setMarquee(null); - marqueeStart.current = null; - if (!m || (m.w < 3 && m.h < 3)) return; // a click, not a drag → leave selection as cleared - const a = canvasToWorld(m.x, m.y); - const b = canvasToWorld(m.x + m.w, m.y + m.h); - const box: Rect = { x: a.x, y: a.y, w: b.x - a.x, h: b.y - a.y }; - const { ids, primary } = marqueeSelection( - deps.renderables(), - box, - marqueeAdditive.current, - deps.selectedIds() - ); - deps.setSelection(ids, primary); - }, [onMarqueeMove, canvasToWorld, deps]); - - // Mirror the live marquee into a ref so onMarqueeUp reads the final rect (it set state async). - const marqueeCurrent = useRef(null); - marqueeCurrent.current = marquee; + // Named function expression (see onPanUp) so removeEventListener can reference the handler itself. + const onMarqueeUp = useCallback( + function onMarqueeUp() { + window.removeEventListener('mousemove', onMarqueeMove); + window.removeEventListener('mouseup', onMarqueeUp); + const m = marqueeCurrent.current; + setMarquee(null); + marqueeStart.current = null; + marqueeCurrent.current = null; + if (!m || (m.w < 3 && m.h < 3)) return; // a click, not a drag → leave selection as cleared + const a = canvasToWorld(m.x, m.y); + const b = canvasToWorld(m.x + m.w, m.y + m.h); + const box: Rect = { x: a.x, y: a.y, w: b.x - a.x, h: b.y - a.y }; + const { ids, primary } = marqueeSelection( + deps.renderables(), + box, + marqueeAdditive.current, + deps.selectedIds() + ); + deps.setSelection(ids, primary); + }, + [onMarqueeMove, canvasToWorld, deps] + ); const onCanvasMouseDown = useCallback( (event: React.MouseEvent) => { @@ -195,7 +207,9 @@ export function useCanvasPointer(deps: CanvasPointerDeps): CanvasPointer { const additive = hit.id === 'studio.marqueeAdd'; const p = toCanvas(event.clientX, event.clientY); marqueeStart.current = p; - setMarquee({ x: p.x, y: p.y, w: 0, h: 0 }); + const rect: Rect = { x: p.x, y: p.y, w: 0, h: 0 }; + marqueeCurrent.current = rect; // seed the ref so a click (no move) reads {w:0,h:0} + setMarquee(rect); marqueeAdditive.current = additive; if (!additive) deps.clearSelection(); window.addEventListener('mousemove', onMarqueeMove); diff --git a/client/src/lib/widgets/canvas/useDefEditor.ts b/client/src/lib/widgets/canvas/useDefEditor.ts index 9e990a9..b1c2bc0 100644 --- a/client/src/lib/widgets/canvas/useDefEditor.ts +++ b/client/src/lib/widgets/canvas/useDefEditor.ts @@ -3,7 +3,7 @@ // blocks switching widgets from the list while one is already open. The def-edit MODE itself // (enterDefEdit / endDefEdit / preview) lives in the editor model's reducer — this hook is just // the studio-bar/list-side wrappers plus the rename/delete prompts around handleOp. -import { useCallback, useRef } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import type { LayoutOp } from '../ops'; import { defInUse, type EditorModel } from './useEditorModel'; import type { EditorState } from './types'; @@ -39,11 +39,14 @@ export function useDefEditor({ dispatch, handleOp }: Deps): DefEditor { - // Latest values for the stable callbacks (read synchronously — no stale closure). + // Latest values for the stable callbacks (read in event handlers — no stale closure). Mirrored in + // a commit effect (not during render); the callbacks only read these later, from user actions. const editingDefIdRef = useRef(editingDefId); - editingDefIdRef.current = editingDefId; const previewingRef = useRef(previewing); - previewingRef.current = previewing; + useEffect(() => { + editingDefIdRef.current = editingDefId; + previewingRef.current = previewing; + }); const foldOpenDef = useCallback(() => { // A read-only preview is discarded (endPreview); a real def edit is folded back (endDefEdit). diff --git a/client/src/lib/widgets/canvas/useEditorModel.ts b/client/src/lib/widgets/canvas/useEditorModel.ts index 9da96d9..5f55d4e 100644 --- a/client/src/lib/widgets/canvas/useEditorModel.ts +++ b/client/src/lib/widgets/canvas/useEditorModel.ts @@ -439,7 +439,7 @@ function reduceDefEdit(state: EditorState, action: DefEditAction): EditorState { ? { ...state.library, defs: state.library.defs.map((d) => (d.id === editingDefId ? { ...d, child } : d)) - } + } : state.library; let next: EditorState = { ...state, diff --git a/client/src/lib/widgets/canvas/useKeyboard.ts b/client/src/lib/widgets/canvas/useKeyboard.ts index 7bb3dc1..9cf313f 100644 --- a/client/src/lib/widgets/canvas/useKeyboard.ts +++ b/client/src/lib/widgets/canvas/useKeyboard.ts @@ -54,8 +54,11 @@ export function useKeyboard(deps: KeyboardDeps): { setSpaceDown(v); }; // Hold deps in a ref so the window listeners stay stable (registered once) but read latest. + // Mirrored in a commit effect (before the mount effect below only reads d.current from listeners). const d = useRef(deps); - d.current = deps; + useEffect(() => { + d.current = deps; + }); useEffect(() => { const onKeydown = (event: KeyboardEvent) => { diff --git a/client/src/lib/widgets/canvas/usePaneSizes.ts b/client/src/lib/widgets/canvas/usePaneSizes.ts index 6448491..652b745 100644 --- a/client/src/lib/widgets/canvas/usePaneSizes.ts +++ b/client/src/lib/widgets/canvas/usePaneSizes.ts @@ -4,7 +4,14 @@ // from localStorage, exposes them as inline vars (overriding the CSS defaults), and drives a divider // drag. Persisted per-machine (a UI pref, not part of the portable widgets.json). The drag math is // pure (clampPane / applyDelta) and unit-tested in usePaneSizes.test.ts. -import { useCallback, useRef, useState, type CSSProperties, type PointerEvent } from 'react'; +import { + useCallback, + useEffect, + useRef, + useState, + type CSSProperties, + type PointerEvent +} from 'react'; import { readJson, writeJson } from '../../../stores/persist'; @@ -50,8 +57,11 @@ export type PaneSizing = { export function usePaneSizes(studio: boolean): PaneSizing { const [sizes, setSizes] = useState(() => (studio ? load() : PANE_DEFAULTS)); + // Mirror the latest sizes for the pointer handlers (startResize / onUp read it later, off-render). const sizesRef = useRef(sizes); - sizesRef.current = sizes; + useEffect(() => { + sizesRef.current = sizes; + }); const startResize = useCallback((edge: Edge, e: PointerEvent) => { e.preventDefault(); @@ -75,7 +85,7 @@ export function usePaneSizes(studio: boolean): PaneSizing { '--rail-l': `${sizes.railL}px`, '--rail-r': `${sizes.railR}px`, '--tree-w': `${sizes.treeW}px` - } as CSSProperties) + } as CSSProperties) : {}; return { vars, startResize }; diff --git a/client/src/lib/widgets/canvas/usePersistence.ts b/client/src/lib/widgets/canvas/usePersistence.ts index 4b8eefa..9148e6e 100644 --- a/client/src/lib/widgets/canvas/usePersistence.ts +++ b/client/src/lib/widgets/canvas/usePersistence.ts @@ -52,17 +52,21 @@ export function usePersistence(state: EditorState, myMonitor: string): Persisten savedMonitor: state.savedMonitor, studio: state.studio }); - view.current = { - myMonitor, - monitor: state.monitor, - library: state.library, - selectedTheme: state.selectedTheme, - themeLock: state.themeLock, - tokenOverrides: state.tokenOverrides, - editingDefId: state.editingDefId, - savedMonitor: state.savedMonitor, - studio: state.studio - }; + // Refresh the mirror in a commit effect (not during render); the debounced writer + Save read + // view.current later (via setTimeout / a button press), never synchronously in this render. + useEffect(() => { + view.current = { + myMonitor, + monitor: state.monitor, + library: state.library, + selectedTheme: state.selectedTheme, + themeLock: state.themeLock, + tokenOverrides: state.tokenOverrides, + editingDefId: state.editingDefId, + savedMonitor: state.savedMonitor, + studio: state.studio + }; + }); // While editing a def we must fold the scoped editing tree back into the library before a // write — but the library set is reducer-owned. The Canvas runs `endDefEdit`/save through the diff --git a/client/src/lib/widgets/canvas/useSacks.test.ts b/client/src/lib/widgets/canvas/useSacks.test.ts index acf0875..194511a 100644 --- a/client/src/lib/widgets/canvas/useSacks.test.ts +++ b/client/src/lib/widgets/canvas/useSacks.test.ts @@ -113,7 +113,7 @@ describe('refreshSacks (section-open peek)', () => { theme: { name: 'Nord', css: 'x' }, tokens: { '--a': '1', '--b': '2' } }) - ) + ) : 'not a sack' ); const { result } = setup({ navSection: 'sacks' }); diff --git a/client/src/lib/widgets/canvas/useSacks.ts b/client/src/lib/widgets/canvas/useSacks.ts index 75fccc0..e3b8fb9 100644 --- a/client/src/lib/widgets/canvas/useSacks.ts +++ b/client/src/lib/widgets/canvas/useSacks.ts @@ -72,9 +72,11 @@ export function useSacks({ // Names + a peek inside each (count of defs, theme name, override count) so the Import list can // say what a sack contains instead of a bare filename. Sacks are small local JSON; reading each // on section-open is cheap. A file that doesn't parse still lists (widgets: null → "unreadable"). - const refreshSacks = useCallback(async () => { + // Pure I/O (no setState) so it can be awaited from an effect's async closure without the compiler + // treating it as a synchronous effect state update. + const loadSackInfos = useCallback(async (): Promise => { const names = await listSacks(); - const infos = await Promise.all( + return Promise.all( names.map(async (name): Promise => { const raw = await readSack(name); const sack = raw ? unpackSack(raw) : null; @@ -87,8 +89,11 @@ export function useSacks({ }; }) ); - setSackInfos(infos); }, []); + // Reload the list into state — used by event handlers (exportSack), not from an effect body. + const refreshSacks = useCallback(async () => { + setSackInfos(await loadSackInfos()); + }, [loadSackInfos]); const exportSack = useCallback(async () => { if (editingDefId != null) { @@ -166,10 +171,19 @@ export function useSacks({ [editingDefId, commitOp, setThemeList, adoptTheme] ); - // Load the saved sacks (+ their summaries) when the Sacks section opens. + // Load the saved sacks (+ their summaries) when the Sacks section opens. setState lives in the + // async .then() (not the effect body), and a cancel guard drops a stale load if the section + // closes / the studio unmounts mid-flight. useEffect(() => { - if (studio && navSection === 'sacks') void refreshSacks(); - }, [studio, navSection, refreshSacks]); + if (!(studio && navSection === 'sacks')) return; + let cancelled = false; + void loadSackInfos().then((infos) => { + if (!cancelled) setSackInfos(infos); + }); + return () => { + cancelled = true; + }; + }, [studio, navSection, loadSackInfos]); return { sackInfos, exportSack, importSack }; } diff --git a/client/src/lib/widgets/canvas/useSplitters.test.ts b/client/src/lib/widgets/canvas/useSplitters.test.ts index d006c94..ffca17b 100644 --- a/client/src/lib/widgets/canvas/useSplitters.test.ts +++ b/client/src/lib/widgets/canvas/useSplitters.test.ts @@ -195,7 +195,7 @@ describe('onSplitReset (double-click → even pair)', () => { describe('onSplitKey (WCAG keyboard nudge)', () => { const key = (k: string, shift = false) => - ({ key: k, shiftKey: shift, preventDefault: vi.fn() } as unknown as React.KeyboardEvent); + ({ key: k, shiftKey: shift, preventDefault: vi.fn() }) as unknown as React.KeyboardEvent; // fr of child A after the n-th commit, run against a real row monitor. const frA = (commitOp: ReturnType['commitOp'], call: number) => { const patch = commitOp.mock.calls[call][0](stateWith(rowMonitor())); diff --git a/client/src/lib/widgets/canvas/useStudioInit.ts b/client/src/lib/widgets/canvas/useStudioInit.ts index c683b7a..9848e7a 100644 --- a/client/src/lib/widgets/canvas/useStudioInit.ts +++ b/client/src/lib/widgets/canvas/useStudioInit.ts @@ -38,9 +38,12 @@ export type StudioInitDeps = { }; export function useStudioInit(deps: StudioInitDeps): void { - // Hold deps in a ref so the mount effect reads the latest callbacks without re-running. + // Hold deps in a ref so the mount effect reads the latest callbacks without re-running. Mirrored in + // a commit effect (before the mount effect below, which only reads d.current from async callbacks). const d = useRef(deps); - d.current = deps; + useEffect(() => { + d.current = deps; + }); useEffect(() => { let cancelled = false; @@ -201,7 +204,7 @@ export function useStudioInit(deps: StudioInitDeps): void { stopDisplayWatch?.(); d.current.clearPreviewWrite(); }; - // Run once on mount (non-idempotent). eslint-disable to keep the empty dep list intentional. - // eslint-disable-next-line react-hooks/exhaustive-deps + // Run once on mount (non-idempotent). The body reads only the stable `d` ref, so the empty dep + // list is intentional and needs no exhaustive-deps suppression. }, []); } diff --git a/client/src/lib/widgets/canvas/useThemes.ts b/client/src/lib/widgets/canvas/useThemes.ts index 60bf527..e244817 100644 --- a/client/src/lib/widgets/canvas/useThemes.ts +++ b/client/src/lib/widgets/canvas/useThemes.ts @@ -63,8 +63,11 @@ export function useThemes({ studio, selectedTheme, dispatch, commitOp }: Deps): const [userThemeSwatches, setUserThemeSwatches] = useState>({}); // applyTheme reads the latest selectedTheme via a ref (it's called from listeners + after sets). + // Mirrored in a commit effect (not during render); every read happens later, off-render. const themeRef = useRef(selectedTheme); - themeRef.current = selectedTheme; + useEffect(() => { + themeRef.current = selectedTheme; + }); const applyTheme = useCallback(async () => { setThemeCss(await resolveThemeCss(themeRef.current)); diff --git a/client/src/lib/widgets/canvas/useZoomFit.test.ts b/client/src/lib/widgets/canvas/useZoomFit.test.ts index 17f145b..2c20470 100644 --- a/client/src/lib/widgets/canvas/useZoomFit.test.ts +++ b/client/src/lib/widgets/canvas/useZoomFit.test.ts @@ -27,7 +27,7 @@ function makeCanvas(left = 0, top = 0): HTMLDivElement { x: left, y: top, toJSON: () => ({}) - } as DOMRect); + }) as DOMRect; document.body.appendChild(el); return el; } diff --git a/client/src/lib/widgets/canvas/useZoomFit.ts b/client/src/lib/widgets/canvas/useZoomFit.ts index 0b62ec3..7347d5d 100644 --- a/client/src/lib/widgets/canvas/useZoomFit.ts +++ b/client/src/lib/widgets/canvas/useZoomFit.ts @@ -33,14 +33,20 @@ export function useZoomFit(opts: { const { studio, myMonitor, monSize, stageW, stageH, canvasRef } = opts; const [pan, setPan] = useState({ panX: 0, panY: 0, zoom: 1 }); // Read the latest overrides without re-subscribing the native wheel listener (its effect deps stay - // [studio, canvasRef]); a new overrides fn each render just updates the ref. + // [studio, canvasRef]); a new overrides fn each render just updates the ref (in a commit effect — + // the wheel listener reads it later). const overridesRef = useRef(opts.overrides ?? NO_OVERRIDES); - overridesRef.current = opts.overrides ?? NO_OVERRIDES; + useEffect(() => { + overridesRef.current = opts.overrides ?? NO_OVERRIDES; + }); // fit() reads the latest sizes via a ref so it's a stable callback (used by the Fit button + the - // auto-fit effect) without re-subscribing. + // auto-fit effect) without re-subscribing. Mirrored in a commit effect declared BEFORE the auto-fit + // effect below, so sizes.current is fresh by the time that effect calls fit(). const sizes = useRef({ monSize, stageW, stageH }); - sizes.current = { monSize, stageW, stageH }; + useEffect(() => { + sizes.current = { monSize, stageW, stageH }; + }); const fit = useCallback(() => { const { monSize: m, stageW: sw, stageH: sh } = sizes.current; diff --git a/client/src/lib/widgets/meters/Countdown.tsx b/client/src/lib/widgets/meters/Countdown.tsx index fe12252..acc55d5 100644 --- a/client/src/lib/widgets/meters/Countdown.tsx +++ b/client/src/lib/widgets/meters/Countdown.tsx @@ -2,7 +2,7 @@ // or runs an auto-cycling Pomodoro rhythm — both driven by the wall clock on a 1s tick, like Clock. // Distinct from the manual Timer widget (which has start/pause controls). The time math is pure // (core/countdown.ts); this just ticks and renders. BARE DOM, styled via --np-* / --cd-* tokens. -import { useEffect, useRef, useState, type CSSProperties } from 'react'; +import { useEffect, useState, type CSSProperties } from 'react'; import { formatCountdown, parseTarget, @@ -34,8 +34,9 @@ export default function Countdown({ }: Props) { const [now, setNow] = useState(() => Date.now()); // Pomodoro anchor: when this widget mounted. The rhythm runs from here (resets on reload — fine for - // a "where am I in the cycle" display; the manual Timer covers precise start/pause). - const startRef = useRef(now); + // a "where am I in the cycle" display; the manual Timer covers precise start/pause). Seeded from the + // initial `now` and held in state so it stays stable across ticks without a during-render ref read. + const [start] = useState(now); useEffect(() => { const timer = setInterval(() => setNow(Date.now()), 1000); @@ -49,7 +50,7 @@ export default function Countdown({ let phase: string; if (mode === 'pomodoro') { - const p = pomodoroAt(now - startRef.current, workMin * 60_000, breakMin * 60_000); + const p = pomodoroAt(now - start, workMin * 60_000, breakMin * 60_000); value = formatCountdown(p.remainingMs, 'ms'); phase = p.phase; // 'work' | 'break' sub = `${p.phase === 'work' ? 'Work' : 'Break'} · #${p.cycle}`; diff --git a/client/src/lib/widgets/meters/CpuCoresCanvas.tsx b/client/src/lib/widgets/meters/CpuCoresCanvas.tsx index f5ce519..07312cb 100644 --- a/client/src/lib/widgets/meters/CpuCoresCanvas.tsx +++ b/client/src/lib/widgets/meters/CpuCoresCanvas.tsx @@ -30,9 +30,12 @@ const DEFAULT_GAP = 4; export default function CpuCoresCanvas(props: Props) { const canvasRef = useRef(null); - // Latest props read by the draw without re-subscribing the ResizeObserver. + // Latest props read by the draw without re-subscribing the ResizeObserver. Written in a commit + // effect (not during render) — the draw only reads it later from the ResizeObserver / telemetry tick. const propsRef = useRef(props); - propsRef.current = props; + useEffect(() => { + propsRef.current = props; + }); const draw = useCallback((): void => { const canvas = canvasRef.current; diff --git a/client/src/lib/widgets/meters/HaInput.tsx b/client/src/lib/widgets/meters/HaInput.tsx index 21aba94..c8b4bf4 100644 --- a/client/src/lib/widgets/meters/HaInput.tsx +++ b/client/src/lib/widgets/meters/HaInput.tsx @@ -84,7 +84,7 @@ export default function HaInput({ value = null, label, onControl }: Props) { min={a.min ?? 0} max={a.max ?? 100} step={a.step ?? 1} - value={Number.isFinite(num) ? num : a.min ?? 0} + value={Number.isFinite(num) ? num : (a.min ?? 0)} aria-label={`${name} value`} onChange={(e) => { const c = inputNumberSetValue(Number(e.currentTarget.value), a); diff --git a/client/src/lib/widgets/meters/Iframe.tsx b/client/src/lib/widgets/meters/Iframe.tsx index 28a39fe..dcc5b5a 100644 Binary files a/client/src/lib/widgets/meters/Iframe.tsx and b/client/src/lib/widgets/meters/Iframe.tsx differ diff --git a/client/src/lib/widgets/meters/MonitorSourcesEditor.tsx b/client/src/lib/widgets/meters/MonitorSourcesEditor.tsx index 1548afb..78a4fdd 100644 --- a/client/src/lib/widgets/meters/MonitorSourcesEditor.tsx +++ b/client/src/lib/widgets/meters/MonitorSourcesEditor.tsx @@ -19,20 +19,50 @@ export default function MonitorSourcesEditor({ value, monitor, onChange }: Props const [detected, setDetected] = useState([]); const [loading, setLoading] = useState(true); - const scan = useCallback(async (): Promise => { - setLoading(true); + // The DDC/CI probe (a Tauri call). Resolves to the chosen monitor's supported inputs — it does NOT + // touch state itself, so callers own when to apply the result (in a `.then` callback, never a + // synchronous setState in the effect body → no cascading setState-in-effect). + const scan = useCallback(async (): Promise => { const list = await listMonitorInputs(monitor || undefined); const target = monitor ? list.find((m) => m.gdi === monitor) - : list.find((m) => m.primary) ?? list[0]; - setDetected(target?.supported ?? []); - setLoading(false); + : (list.find((m) => m.primary) ?? list[0]); + return target?.supported ?? []; }, [monitor]); + // Show the detecting state again when the chosen monitor changes — flagged during render + // (adjust-during-render, so it isn't a setState-in-effect); the effect below runs the probe. + const [prevMonitor, setPrevMonitor] = useState(monitor); + if (monitor !== prevMonitor) { + setPrevMonitor(monitor); + setLoading(true); + } + + // Probe on mount and whenever the monitor (hence `scan`) changes; a stale in-flight probe is + // ignored so a fast monitor switch can't apply the wrong result. setState lives in the `.then` + // callback, keeping the effect body free of a synchronous setState. useEffect(() => { - void scan(); + let cancelled = false; + void scan().then((supported) => { + if (cancelled) return; + setDetected(supported); + setLoading(false); + }); + return () => { + cancelled = true; + }; }, [scan]); + // Manual rescan (button, so setState is a plain event-handler update): re-probe the same monitor, + // showing the detecting state meanwhile. + const rescan = (): void => { + setLoading(true); + void scan().then((supported) => { + setDetected(supported); + setLoading(false); + }); + }; + const rows = sourceEditorRows(detected, value); const emit = (next: SourceEditorRow[]): void => onChange(buildSourceSpec(next)); const toggle = (i: number): void => @@ -47,12 +77,7 @@ export default function MonitorSourcesEditor({ value, monitor, onChange }: Props {loading ? 'detecting inputs…' : `${rows.length} input${rows.length === 1 ? '' : 's'}`} -
diff --git a/client/src/lib/widgets/meters/MonitorSwitch.css b/client/src/lib/widgets/meters/MonitorSwitch.css index f649790..a8cc5f9 100644 --- a/client/src/lib/widgets/meters/MonitorSwitch.css +++ b/client/src/lib/widgets/meters/MonitorSwitch.css @@ -61,7 +61,9 @@ font-size: var(--ms-row-size, 0.95em); text-align: center; cursor: pointer; - transition: background 0.12s ease, border-color 0.12s ease; + transition: + background 0.12s ease, + border-color 0.12s ease; /* Touch ergonomics: no tap flash, no double-tap zoom, no text selection on press. */ -webkit-tap-highlight-color: transparent; touch-action: manipulation; diff --git a/client/src/lib/widgets/meters/NowPlaying.test.tsx b/client/src/lib/widgets/meters/NowPlaying.test.tsx index 79fb009..eb96e06 100644 --- a/client/src/lib/widgets/meters/NowPlaying.test.tsx +++ b/client/src/lib/widgets/meters/NowPlaying.test.tsx @@ -355,7 +355,7 @@ describe('NowPlaying — seek + timeline', () => { expect(bar.getAttribute('data-seekable')).toBe('true'); // happy-dom getBoundingClientRect returns zeros; stub a 200px-wide bar so the fraction is real. bar.getBoundingClientRect = () => - ({ left: 0, width: 200, top: 0, height: 4, right: 200, bottom: 4, x: 0, y: 0 } as DOMRect); + ({ left: 0, width: 200, top: 0, height: 4, right: 200, bottom: 4, x: 0, y: 0 }) as DOMRect; fireEvent.click(bar, { clientX: 100 }); // halfway → 0.5 * 200 = 100 expect(onControl).toHaveBeenCalledWith({ domain: 'media', @@ -371,7 +371,7 @@ describe('NowPlaying — seek + timeline', () => { ); const bar = container.querySelector('[data-part="progress"]') as HTMLElement; bar.getBoundingClientRect = () => - ({ left: 0, width: 200, top: 0, height: 4, right: 200, bottom: 4, x: 0, y: 0 } as DOMRect); + ({ left: 0, width: 200, top: 0, height: 4, right: 200, bottom: 4, x: 0, y: 0 }) as DOMRect; fireEvent.click(bar, { clientX: 9999 }); // past the end → clamped to frac 1 → full duration expect(onControl).toHaveBeenCalledWith({ domain: 'media', diff --git a/client/src/lib/widgets/meters/NowPlaying.tsx b/client/src/lib/widgets/meters/NowPlaying.tsx index 127558c..a263904 100644 Binary files a/client/src/lib/widgets/meters/NowPlaying.tsx and b/client/src/lib/widgets/meters/NowPlaying.tsx differ diff --git a/client/src/lib/widgets/meters/Ping.tsx b/client/src/lib/widgets/meters/Ping.tsx index 50e3857..f9bfdf8 100644 --- a/client/src/lib/widgets/meters/Ping.tsx +++ b/client/src/lib/widgets/meters/Ping.tsx @@ -34,10 +34,10 @@ export default function Ping({ level === 'unknown' ? '—' : level === 'down' - ? 'down' - : ms == null - ? 'up' - : `${Math.round(ms)} ms`; + ? 'down' + : ms == null + ? 'up' + : `${Math.round(ms)} ms`; return (
diff --git a/client/src/lib/widgets/meters/ProcessWatch.tsx b/client/src/lib/widgets/meters/ProcessWatch.tsx index 74f7e1a..d9772d7 100644 --- a/client/src/lib/widgets/meters/ProcessWatch.tsx +++ b/client/src/lib/widgets/meters/ProcessWatch.tsx @@ -37,14 +37,14 @@ export default function ProcessWatch({ sensors = {}, name = 'chrome.exe', label, {state === 'unknown' ? '—' : state === 'stopped' - ? 'not running' - : [ - cpu != null ? `${cpu.toFixed(1)}%` : null, - mem != null ? formatBytes(mem, 0) : null, - count != null && count > 1 ? `×${count}` : null - ] - .filter(Boolean) - .join(' · ') || 'running'} + ? 'not running' + : [ + cpu != null ? `${cpu.toFixed(1)}%` : null, + mem != null ? formatBytes(mem, 0) : null, + count != null && count > 1 ? `×${count}` : null + ] + .filter(Boolean) + .join(' · ') || 'running'}
diff --git a/client/src/lib/widgets/meters/Spectrum.tsx b/client/src/lib/widgets/meters/Spectrum.tsx index 9008212..a13c503 100644 --- a/client/src/lib/widgets/meters/Spectrum.tsx +++ b/client/src/lib/widgets/meters/Spectrum.tsx @@ -48,8 +48,11 @@ export default function Spectrum({ const canvasRef = useRef(null); // Live config read by the draw without re-subscribing the stream. `device`/`scale` are NOT here — // they're effect deps, so changing them re-acquires (the backend re-bins / re-inits accordingly). + // Written in a commit effect (not during render) so the draw callbacks read the latest values. const cfg = useRef({ mode, bars, gap, color, pips }); - cfg.current = { mode, bars, gap, color, pips }; + useEffect(() => { + cfg.current = { mode, bars, gap, color, pips }; + }); useEffect(() => { const canvas = canvasRef.current; @@ -161,7 +164,7 @@ export default function Spectrum({ ? new ResizeObserver(() => { const f = source.latestFrame(); if (f) render(f); - }) + }) : null; ro?.observe(canvas); @@ -171,7 +174,6 @@ export default function Spectrum({ release(); }; // Re-subscribe when the source / device / scale changes; other config is read live (cfg). - // eslint-disable-next-line react-hooks/exhaustive-deps }, [source, device, scale]); return ; diff --git a/client/src/lib/widgets/meters/StickyNote.tsx b/client/src/lib/widgets/meters/StickyNote.tsx index caa5ce4..3119c28 100644 --- a/client/src/lib/widgets/meters/StickyNote.tsx +++ b/client/src/lib/widgets/meters/StickyNote.tsx @@ -29,9 +29,17 @@ export default function StickyNote({ }: Props) { const [text, setText] = useState(() => (widgetId ? load(widgetId) : '')); + // Re-read from storage when the widget id changes — as an adjust-during-render (React re-renders + // before paint) rather than a setState-in-effect. Matches the old effect's `if (!widgetId) return`: + // an empty id keeps whatever is shown. + const [prevId, setPrevId] = useState(widgetId); + if (widgetId !== prevId) { + setPrevId(widgetId); + if (widgetId) setText(load(widgetId)); + } + useEffect(() => { if (!widgetId) return; - setText(load(widgetId)); // Sync edits made in the OTHER window (studio ↔ overlay share the origin → the storage event fires). const onStorage = (e: StorageEvent): void => { if (e.key === keyFor(widgetId)) setText(e.newValue ?? ''); diff --git a/client/src/lib/widgets/meters/Ticker.tsx b/client/src/lib/widgets/meters/Ticker.tsx index e0734d4..0ce1d2a 100644 --- a/client/src/lib/widgets/meters/Ticker.tsx +++ b/client/src/lib/widgets/meters/Ticker.tsx @@ -70,7 +70,7 @@ export default function Ticker({ const seriesValue = sensors.series?.value; const series = seriesValue?.kind === 'series' ? seriesValue.value : []; - const spark = series.length >= 2 ? series : sensors.price?.history ?? []; + const spark = series.length >= 2 ? series : (sensors.price?.history ?? []); return (
Date.now()); const temp = scalar(sensors.temp); const code = scalar(sensors.code); const isDay = scalar(sensors.is_day); @@ -55,7 +58,7 @@ export default function Weather({ low: scalar(sensors[`d${i}low`]) }); } - const forecast = labelForecast(cells, Date.now()).filter( + const forecast = labelForecast(cells, now).filter( (d) => d.high != null || d.low != null || d.code != null ); diff --git a/client/src/lib/widgets/meters/tickerFormat.ts b/client/src/lib/widgets/meters/tickerFormat.ts index 50593fc..4afaa71 100644 --- a/client/src/lib/widgets/meters/tickerFormat.ts +++ b/client/src/lib/widgets/meters/tickerFormat.ts @@ -55,7 +55,7 @@ const CURRENCY_SYMBOLS: Record = { /** A leading symbol for a currency code ($, €, …), or '' for an unknown code (show the bare number). */ export function currencySymbol(code: string | null | undefined): string { - return code ? CURRENCY_SYMBOLS[code.toUpperCase()] ?? '' : ''; + return code ? (CURRENCY_SYMBOLS[code.toUpperCase()] ?? '') : ''; } /** Friendly label for a Yahoo market state, or '' for an open/regular session (nothing to flag). */ diff --git a/client/src/lib/widgets/meters/useTimer.ts b/client/src/lib/widgets/meters/useTimer.ts index ffcfb47..0f56058 100644 --- a/client/src/lib/widgets/meters/useTimer.ts +++ b/client/src/lib/widgets/meters/useTimer.ts @@ -1,7 +1,7 @@ // Stateful tick for the self-sourcing Timer widget (the documented self-sourcing exception, like Clock // drives its own time). Timestamp-anchored so it stays accurate despite interval drift; pure formatting // lives in core/timer.ts. -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; export type TimerMode = 'countdown' | 'stopwatch'; export type TimerConfig = { mode: TimerMode; duration: number; loop?: boolean }; @@ -19,58 +19,61 @@ export type TimerState = { export function useTimer(cfg: TimerConfig): TimerState { const [running, setRunning] = useState(false); - const [, bump] = useState(0); // re-render each tick - const accumRef = useRef(0); // ms accumulated while paused - const startRef = useRef(null); // Date.now() at the last start + const [now, setNow] = useState(() => Date.now()); // advanced by the tick while running + const [accum, setAccum] = useState(0); // ms accumulated while paused + const [startAt, setStartAt] = useState(null); // Date.now() at the last start - const elapsedMs = (): number => - accumRef.current + (running && startRef.current != null ? Date.now() - startRef.current : 0); + // Elapsed ms, derived purely from state — no ref reads and no Date.now() during render. + const elapsedMs = accum + (running && startAt != null ? now - startAt : 0); useEffect(() => { if (!running) return; - const id = setInterval(() => bump((t) => t + 1), 250); + const id = setInterval(() => setNow(Date.now()), 250); return () => clearInterval(id); }, [running]); const start = useCallback(() => { - setRunning((r) => { - if (r) return r; - startRef.current = Date.now(); - return true; - }); - }, []); + if (running) return; + const t = Date.now(); + setStartAt(t); + setNow(t); + setRunning(true); + }, [running]); const pause = useCallback(() => { - setRunning((r) => { - if (!r) return r; - accumRef.current += startRef.current != null ? Date.now() - startRef.current : 0; - startRef.current = null; - return false; - }); - }, []); + if (!running) return; + setAccum((a) => a + (startAt != null ? Date.now() - startAt : 0)); + setStartAt(null); + setRunning(false); + }, [running, startAt]); const reset = useCallback(() => { - accumRef.current = 0; - startRef.current = running ? Date.now() : null; - bump((t) => t + 1); + const t = Date.now(); + setAccum(0); + setStartAt(running ? t : null); + setNow(t); }, [running]); const toggle = useCallback(() => (running ? pause() : start()), [running, pause, start]); - const elapsedSec = elapsedMs() / 1000; + const elapsedSec = elapsedMs / 1000; const seconds = cfg.mode === 'countdown' ? Math.max(0, cfg.duration - elapsedSec) : elapsedSec; const done = cfg.mode === 'countdown' && cfg.duration > 0 && seconds <= 0; - // On a countdown reaching zero: loop (restart) or auto-stop, frozen exactly at 0. - useEffect(() => { - if (!done || !running) return; - if (cfg.loop) { - accumRef.current = 0; - startRef.current = Date.now(); - bump((t) => t + 1); - } else { - startRef.current = null; - accumRef.current = cfg.duration * 1000; - setRunning(false); + // On a countdown reaching zero: loop (re-anchor to now) or auto-stop, frozen exactly at 0. Handled + // as an adjust-during-render (React re-renders before paint) so it isn't a setState-in-effect. The + // loop re-anchors to the state `now` rather than Date.now() (which would be impure during render). + const [prevDone, setPrevDone] = useState(done); + if (done !== prevDone) { + setPrevDone(done); + if (done && running) { + if (cfg.loop) { + setAccum(0); + setStartAt(now); + } else { + setStartAt(null); + setAccum(cfg.duration * 1000); + setRunning(false); + } } - }, [done, running, cfg.loop, cfg.duration]); + } return { seconds, running, done, start, pause, reset, toggle }; } diff --git a/client/src/lib/widgets/meters/useTranscribe.ts b/client/src/lib/widgets/meters/useTranscribe.ts index 318625d..660df17 100644 --- a/client/src/lib/widgets/meters/useTranscribe.ts +++ b/client/src/lib/widgets/meters/useTranscribe.ts @@ -41,7 +41,11 @@ export function useTranscribe(cfg: TranscribeConfig): TranscribeState { const recorderRef = useRef(null); const startingRef = useRef(false); const cfgRef = useRef(cfg); - cfgRef.current = cfg; + // Keep the latest config in a ref, written in a commit effect (not during render), so the async + // `run` below reads the current cfg without re-creating the recorder on every config edit. + useEffect(() => { + cfgRef.current = cfg; + }); // Release the mic if the widget unmounts mid-recording. useEffect( diff --git a/client/src/lib/widgets/plugins/HaMediaPlayerHost.tsx b/client/src/lib/widgets/plugins/HaMediaPlayerHost.tsx index dd338fe..61bf1ba 100644 --- a/client/src/lib/widgets/plugins/HaMediaPlayerHost.tsx +++ b/client/src/lib/widgets/plugins/HaMediaPlayerHost.tsx @@ -21,25 +21,26 @@ type Props = { export default function HaMediaPlayerHost(props: Props) { const pic = ((props.value as HaState | null)?.attributes?.entity_picture as string | undefined) ?? ''; - const [art, setArt] = useState(undefined); + const [decoded, setDecoded] = useState(undefined); useEffect(() => { - if (!pic) { - setArt(undefined); - return; - } + if (!pic) return; let cancelled = false; haMediaArt(pic) .then((url) => { - if (!cancelled) setArt(url); + if (!cancelled) setDecoded(url); }) .catch(() => { - if (!cancelled) setArt(undefined); + if (!cancelled) setDecoded(undefined); }); return () => { cancelled = true; }; }, [pic]); + // No picture → no art (don't linger on a previous track's cover); otherwise the async-decoded url. + // Deriving `art` in render replaces a synchronous `setArt(undefined)` in the effect. + const art = pic ? decoded : undefined; + return ; } diff --git a/client/src/lib/widgets/plugins/LlmSettings.tsx b/client/src/lib/widgets/plugins/LlmSettings.tsx index a0e0c71..cf68211 100644 --- a/client/src/lib/widgets/plugins/LlmSettings.tsx +++ b/client/src/lib/widgets/plugins/LlmSettings.tsx @@ -222,7 +222,19 @@ export default function LlmSettings() { // dropdown populates without a manual "↻ Models" click. Keyed on `provider`/`hasKey` ONLY — a // not-yet-saved key typed char-by-char must not fire a request per keystroke; use ↻ Models for that. useEffect(() => { - if (canListModels) void onLoadModels(); + if (!canListModels) return; + // Defer the auto-load off the synchronous effect body: onLoadModels sets a `loading` status + // immediately, and doing that synchronously inside an effect triggers a cascading render the + // React Compiler flags. A macrotask hop lands the updates after commit (imperceptible); the + // manual ↻ Models button still calls onLoadModels directly from its handler. + let cancelled = false; + const id = setTimeout(() => { + if (!cancelled) void onLoadModels(); + }, 0); + return () => { + cancelled = true; + clearTimeout(id); + }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [provider, hasKey]); diff --git a/client/src/lib/widgets/plugins/NowPlayingSettings.test.tsx b/client/src/lib/widgets/plugins/NowPlayingSettings.test.tsx index b7d99c3..9c50d08 100644 --- a/client/src/lib/widgets/plugins/NowPlayingSettings.test.tsx +++ b/client/src/lib/widgets/plugins/NowPlayingSettings.test.tsx @@ -18,7 +18,7 @@ vi.mock('../../components/NowPlaying/source', () => ({ shuffle: false, repeat: false, seek: true - } + } : null ) ) diff --git a/client/src/lib/widgets/plugins/llm-tts.test.ts b/client/src/lib/widgets/plugins/llm-tts.test.ts index b6602f0..ecf61bd 100644 --- a/client/src/lib/widgets/plugins/llm-tts.test.ts +++ b/client/src/lib/widgets/plugins/llm-tts.test.ts @@ -43,7 +43,10 @@ beforeEach(() => { vi.stubGlobal( 'Blob', class { - constructor(public parts: unknown[], public opts: { type?: string }) {} + constructor( + public parts: unknown[], + public opts: { type?: string } + ) {} } ); let n = 0; diff --git a/client/src/lib/widgets/plugins/packages.ts b/client/src/lib/widgets/plugins/packages.ts index 6130b9e..9ff09cd 100644 --- a/client/src/lib/widgets/plugins/packages.ts +++ b/client/src/lib/widgets/plugins/packages.ts @@ -244,7 +244,7 @@ export async function refreshPackages(): Promise { error: null, warnings: result.pkg.warnings, install - } + } : { id: f.id, manifest: null, error: result.reason, warnings: [], install } ); } diff --git a/client/src/lib/widgets/useAssistant.ts b/client/src/lib/widgets/useAssistant.ts index f56718e..af76020 100644 --- a/client/src/lib/widgets/useAssistant.ts +++ b/client/src/lib/widgets/useAssistant.ts @@ -65,9 +65,12 @@ export function useAssistant(cfg: AssistantConfig): AssistantState { const [text, setText] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); - // Latest config without retriggering the generator's identity on every keystroke. + // Latest config without retriggering the generator's identity on every keystroke. Committed after + // render (not during it); `generate` only reads it later, from timers/handlers. const cfgRef = useRef(cfg); - cfgRef.current = cfg; + useEffect(() => { + cfgRef.current = cfg; + }); const generate = useCallback(async (): Promise => { setBusy(true); diff --git a/client/src/test-setup.ts b/client/src/test-setup.ts index 34f98b9..2aa1a4f 100644 --- a/client/src/test-setup.ts +++ b/client/src/test-setup.ts @@ -2,5 +2,12 @@ import '@testing-library/jest-dom/vitest'; import { cleanup } from '@testing-library/react'; import { afterEach } from 'vitest'; +// happy-dom (bumped to v20) no longer implements the window dialog methods that browsers and the +// previous test env provided. Define no-op defaults so component code that calls them doesn't throw +// and tests can `vi.spyOn(window, 'prompt' | 'confirm' | 'alert')` (spyOn needs the property to exist). +window.prompt ??= () => null; +window.confirm ??= () => false; +window.alert ??= () => {}; + // Unmount React trees + reset jsdom between tests (RTL doesn't auto-cleanup with globals). afterEach(() => cleanup()); diff --git a/client/tsconfig.json b/client/tsconfig.json index 903d536..9da2033 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -15,7 +15,7 @@ "skipLibCheck": true, "sourceMap": true, "noEmit": true, - "types": ["vite/client", "@testing-library/jest-dom", "vitest/globals"] + "types": ["node", "vite/client", "@testing-library/jest-dom", "vitest/globals"] }, "include": ["src"] } diff --git a/widgetsack/Cargo.toml b/widgetsack/Cargo.toml index dbd8f60..2186ede 100644 --- a/widgetsack/Cargo.toml +++ b/widgetsack/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "widgetsack" # Keep in lockstep with tauri.conf.json's version (the bundle/updater source of truth). -version = "0.0.48" +version = "0.0.49" description = "widgetsack desktop widget platform" authors = ["you"] license = "MIT OR Apache-2.0" diff --git a/widgetsack/src/autostart.rs b/widgetsack/src/autostart.rs index 6fa0fab..c707925 100644 --- a/widgetsack/src/autostart.rs +++ b/widgetsack/src/autostart.rs @@ -10,12 +10,80 @@ //! REG_DWORD) — written by both the in-app Settings toggle (`set_autostart_enabled`) and the //! installer's finish-page checkbox — and re-assert the Run key from it on every startup //! (`reconcile`). The preference is the single source of truth; the app owns the Run key. +//! +//! We write the `…\Run` value OURSELVES (`enable_autostart`) instead of via the plugin's +//! `enable()`. `auto-launch` 0.5.0 formats the value as `format!("{} {}", path, args.join(" "))`, +//! which — with our empty args — yields the bare exe path plus a **trailing space** and no quotes +//! (e.g. `C:\…\widgetsack.exe `). Windows' logon Run-key launcher silently refuses to execute that +//! malformed command, so the app never autostarts even though the toggle reports "enabled" (the +//! plugin's `is_enabled()` only checks that the value exists, not its content). We write a clean, +//! quoted, trailing-space-free command instead; the plugin's read/`disable` paths are unaffected. #[cfg(windows)] const PREF_SUBKEY: &str = r"Software\io.github.gyng\widgetsack"; #[cfg(windows)] const PREF_VALUE: &str = "LaunchAtLogin"; +/// HKCU Run key + the value name the autostart plugin registers us under (product name). +#[cfg(windows)] +const RUN_SUBKEY: &str = r"Software\Microsoft\Windows\CurrentVersion\Run"; +#[cfg(windows)] +const RUN_VALUE_NAME: &str = "widgetsack"; +/// Task Manager's per-user startup override list, and the "enabled" marker auto-launch writes there +/// (first byte 0x02, trailing eight bytes zero). We mirror it so a stale "disabled" record can't +/// suppress the entry after we re-enable. +#[cfg(windows)] +const STARTUP_APPROVED_SUBKEY: &str = + r"Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"; +#[cfg(windows)] +const STARTUP_APPROVED_ENABLED: [u8; 12] = [0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + +/// The exact command to register under `…\CurrentVersion\Run`. Quoted (so an install path with +/// spaces still launches) and with **no trailing space** — the two things that make Windows skip +/// the entry at logon when auto-launch writes it. We take no autostart args, so this is just the +/// quoted exe path. +#[cfg_attr(not(windows), allow(dead_code))] +fn run_command(exe: &str) -> String { + format!("\"{exe}\"") +} + +/// Register the app to launch at login by writing the Run value ourselves (clean/quoted), bypassing +/// auto-launch's malformed-value bug. Non-Windows keeps the plugin's cross-platform path. +#[cfg(windows)] +fn enable_autostart(_app: &tauri::AppHandle) -> Result<(), String> { + use winreg::RegKey; + use winreg::RegValue; + use winreg::enums::RegType::REG_BINARY; + use winreg::enums::{HKEY_CURRENT_USER, KEY_SET_VALUE}; + + let exe = std::env::current_exe().map_err(|e| e.to_string())?; + let command = run_command(&exe.to_string_lossy()); + + let hkcu = RegKey::predef(HKEY_CURRENT_USER); + hkcu.open_subkey_with_flags(RUN_SUBKEY, KEY_SET_VALUE) + .map_err(|e| e.to_string())? + .set_value(RUN_VALUE_NAME, &command) + .map_err(|e| e.to_string())?; + + // Best-effort: mark the entry ENABLED in Task Manager's list (the key may not exist yet). + if let Ok(approved) = hkcu.open_subkey_with_flags(STARTUP_APPROVED_SUBKEY, KEY_SET_VALUE) { + let _ = approved.set_raw_value( + RUN_VALUE_NAME, + &RegValue { + vtype: REG_BINARY, + bytes: STARTUP_APPROVED_ENABLED.to_vec(), + }, + ); + } + Ok(()) +} + +#[cfg(not(windows))] +fn enable_autostart(app: &tauri::AppHandle) -> Result<(), String> { + use tauri_plugin_autostart::ManagerExt; + app.autolaunch().enable().map_err(|e| e.to_string()) +} + /// Read the saved launch-at-login preference. `None` = never configured (installer checkbox left /// untouched AND the in-app toggle never used) → leave the OS autostart state alone. #[cfg(windows)] @@ -82,9 +150,9 @@ pub fn reconcile(app: &tauri::AppHandle) { return; }; let result = if want { - manager.enable() + enable_autostart(app) } else { - manager.disable() + manager.disable().map_err(|e| e.to_string()) }; if let Err(err) = result { crate::log::error("startup", "failed to reconcile autostart from preference") @@ -107,18 +175,37 @@ pub fn get_autostart_enabled(app: tauri::AppHandle) -> Result { pub fn set_autostart_enabled(app: tauri::AppHandle, enabled: bool) -> Result { use tauri_plugin_autostart::ManagerExt; write_pref(enabled)?; - let manager = app.autolaunch(); if enabled { - manager.enable().map_err(|e| e.to_string())?; + enable_autostart(&app)?; } else { - manager.disable().map_err(|e| e.to_string())?; + app.autolaunch().disable().map_err(|e| e.to_string())?; } - manager.is_enabled().map_err(|e| e.to_string()) + app.autolaunch().is_enabled().map_err(|e| e.to_string()) } #[cfg(test)] mod tests { - use super::reconcile_action; + use super::{reconcile_action, run_command}; + + #[test] + fn run_command_is_quoted_and_has_no_trailing_space() { + // Regression: auto-launch 0.5.0 writes `format!("{} {}", path, "")` → a bare, unquoted path + // with a trailing space, which Windows' logon Run-key launcher silently skips. Ours must be + // quoted (spaces in the install path still launch) and free of any trailing space. + let cmd = run_command(r"C:\Users\gng\AppData\Local\widgetsack\widgetsack.exe"); + assert_eq!( + cmd, + r#""C:\Users\gng\AppData\Local\widgetsack\widgetsack.exe""# + ); + assert!(cmd.starts_with('"') && cmd.ends_with('"')); + assert!(!cmd.ends_with(' ')); + } + + #[test] + fn run_command_quotes_paths_containing_spaces() { + let cmd = run_command(r"C:\Program Files\widgetsack\widgetsack.exe"); + assert_eq!(cmd, r#""C:\Program Files\widgetsack\widgetsack.exe""#); + } #[test] fn pref_none_is_always_a_noop() { diff --git a/widgetsack/tauri.conf.json b/widgetsack/tauri.conf.json index f2362e6..fe93a8f 100644 --- a/widgetsack/tauri.conf.json +++ b/widgetsack/tauri.conf.json @@ -50,7 +50,7 @@ "createUpdaterArtifacts": false }, "productName": "widgetsack", - "version": "0.0.48", + "version": "0.0.49", "identifier": "io.github.gyng", "plugins": {}, "app": {