├── .all-contributorsrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile.toml ├── README.md ├── examples ├── demo │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── dist │ │ ├── demo-d350a89f5c90eea4.js │ │ ├── demo-d350a89f5c90eea4_bg.wasm │ │ ├── index.html │ │ ├── output-ca0a674fcde1a78.css │ │ └── vercel.json │ ├── index.html │ ├── input.css │ ├── rust-toolchain.toml │ ├── src │ │ ├── app.rs │ │ └── main.rs │ ├── style │ │ └── output.css │ ├── tailwind.config.js │ └── vercel.json └── ssr-demo │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── public │ └── favicon.ico │ ├── src │ ├── app.rs │ ├── error_template.rs │ ├── fileserv.rs │ ├── lib.rs │ └── main.rs │ └── style │ └── main.scss ├── images └── readme-cover.png ├── leptos_hotkeys ├── Cargo.toml └── src │ ├── context.rs │ ├── hotkey.rs │ ├── lib.rs │ ├── macros.rs │ ├── types.rs │ └── use_hotkeys.rs └── rust-toolchain.toml /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "commitType": "docs", 8 | "commitConvention": "angular", 9 | "contributors": [ 10 | { 11 | "login": "mondeja", 12 | "name": "Álvaro Mondéjar", 13 | "avatar_url": "https://avatars.githubusercontent.com/u/23049315?v=4", 14 | "profile": "https://github.com/mondeja", 15 | "contributions": [ 16 | "code" 17 | ] 18 | }, 19 | { 20 | "login": "JustBobinAround", 21 | "name": "Robert Junkins", 22 | "avatar_url": "https://avatars.githubusercontent.com/u/67753581?v=4", 23 | "profile": "https://github.com/JustBobinAround", 24 | "contributions": [ 25 | "code" 26 | ] 27 | }, 28 | { 29 | "login": "LeoniePhiline", 30 | "name": "LeoniePhiline", 31 | "avatar_url": "https://avatars.githubusercontent.com/u/22329650?v=4", 32 | "profile": "https://github.com/LeoniePhiline", 33 | "contributions": [ 34 | "doc" 35 | ] 36 | }, 37 | { 38 | "login": "szabgab", 39 | "name": "Gábor Szabó", 40 | "avatar_url": "https://avatars.githubusercontent.com/u/48833?v=4", 41 | "profile": "https://szabgab.com/", 42 | "contributions": [ 43 | "doc" 44 | ] 45 | }, 46 | { 47 | "login": "phillipbaird", 48 | "name": "Phillip Baird", 49 | "avatar_url": "https://avatars.githubusercontent.com/u/4003333?v=4", 50 | "profile": "https://github.com/phillipbaird", 51 | "contributions": [ 52 | "bug", 53 | "code" 54 | ] 55 | }, 56 | { 57 | "login": "zakstucke", 58 | "name": "zakstucke", 59 | "avatar_url": "https://avatars.githubusercontent.com/u/44890343?v=4", 60 | "profile": "https://github.com/zakstucke", 61 | "contributions": [ 62 | "bug", 63 | "code" 64 | ] 65 | }, 66 | { 67 | "login": "rkimoakbioinformatics", 68 | "name": "Ryangguk Kim", 69 | "avatar_url": "https://avatars.githubusercontent.com/u/13386712?v=4", 70 | "profile": "http://www.linkedin.com/in/ryangguk-kim", 71 | "contributions": [ 72 | "code" 73 | ] 74 | }, 75 | { 76 | "login": "maxbergmark", 77 | "name": "Max Bergmark", 78 | "avatar_url": "https://avatars.githubusercontent.com/u/1706486?v=4", 79 | "profile": "https://github.com/maxbergmark", 80 | "contributions": [ 81 | "code" 82 | ] 83 | }, 84 | { 85 | "login": "TheBestTvarynka", 86 | "name": "Pavlo Myroniuk", 87 | "avatar_url": "https://avatars.githubusercontent.com/u/43034350?v=4", 88 | "profile": "https://tbt.qkation.com/", 89 | "contributions": [ 90 | "code" 91 | ] 92 | } 93 | ], 94 | "contributorsPerLine": 7, 95 | "skipCi": true, 96 | "repoType": "github", 97 | "repoHost": "https://github.com", 98 | "projectName": "leptos-hotkeys", 99 | "projectOwner": "gaucho-labs" 100 | } 101 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | indent_style = space 7 | trim_trailing_whitespace = true 8 | indent_size = 2 9 | 10 | [*.rs] 11 | indent_size = 4 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | # Don't compute diff for these files 4 | Cargo.lock -diff 5 | dist/** -diff 6 | 7 | # Don't export/archive these files 8 | .github export-ignore 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | /node_modules 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## _July 2nd, 2024_ - [0.2.2] 4 | - Fix bugs related to keycode management 5 | 6 | ## _May 27th, 2024_ - [0.2.1] 7 | - Code movement, change to using keycodes 8 | 9 | 10 | - Fix right/left modifiers not being recognized. 11 | 12 | ### Enhancements 13 | 14 | - Add `FromStr` implementation for `Hotkey` struct. 15 | 16 | ## _April 18th, 2024_ - [0.2.0] 17 | 18 | ### Breaking changes 19 | 20 | - Internal modules are no longer public. 21 | - Remove `prelude` module. 22 | - Make ref nodes listen to `keydown` Keyboard events. 23 | - Remove uneeded features `csr` and `hydrate`. 24 | - Use `code` instead of `key` property for `KeyboardEvent`. 25 | 26 | ### Enhancements 27 | 28 | - Allow to import from root package instead of forcing the usage of `prelude` module. 29 | - Do not depend on `log` if `debug` feature is not enabled. 30 | - Relax dependency versions. 31 | - Add compatibility with Leptos stable. 32 | 33 | ## _February 27th, 2024_ - 0.1.5 34 | 35 | - Clean up macros 36 | 37 | ## _February 23th, 2024_ - 0.1.4 38 | 39 | - Update README 40 | - Add `debug` feature, which produces logs in your browser console upon hotkey fires and scope triggers. 41 | 42 | ## _February 12th, 2024_ - 0.1.3 43 | 44 | - Recognize `meta` key. 45 | - String cleaning. 46 | 47 | ## _February 8th, 2024_ - 0.1.1 48 | 49 | - Elevate `leptos` to v0.6.5 50 | - Added `event.preventDefault()`. 51 | 52 | [0.2.1]: https://github.com/gaucho-labs/leptos-hotkeys/compare/v0.2.0...v0.2.1 53 | [0.2.0]: https://github.com/gaucho-labs/leptos-hotkeys/compare/b83afc96...v0.2.0 -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guide 2 | 3 | ## Setup 4 | 5 | In order to execute development tasks, you need to install [cargo-make](https://github.com/sagiegurari/cargo-make). 6 | 7 | ## Lint 8 | 9 | ```sh 10 | cargo make lint 11 | ``` 12 | 13 | ## Format 14 | 15 | ```sh 16 | cargo make format 17 | ``` 18 | 19 | ## Release 20 | 21 | 1. Update *CHANGELOG.md* and bump version. 22 | 1. Push the changes to the main branch. 23 | 1. Create and push a GIT tag from latest main branch: 24 | 25 | ```sh 26 | git tag v0.1.0 27 | git push upstream v0.1.0 28 | ``` 29 | 30 | > [!NOTE] 31 | > Change `v0.1.0` to the new version number. 32 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 | dependencies = [ 26 | "cfg-if", 27 | "once_cell", 28 | "version_check", 29 | "zerocopy", 30 | ] 31 | 32 | [[package]] 33 | name = "aho-corasick" 34 | version = "1.1.3" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 37 | dependencies = [ 38 | "memchr", 39 | ] 40 | 41 | [[package]] 42 | name = "allocator-api2" 43 | version = "0.2.21" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 46 | 47 | [[package]] 48 | name = "anyhow" 49 | version = "1.0.95" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 52 | 53 | [[package]] 54 | name = "async-recursion" 55 | version = "1.1.1" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" 58 | dependencies = [ 59 | "proc-macro2", 60 | "quote", 61 | "syn 2.0.96", 62 | ] 63 | 64 | [[package]] 65 | name = "async-trait" 66 | version = "0.1.85" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" 69 | dependencies = [ 70 | "proc-macro2", 71 | "quote", 72 | "syn 2.0.96", 73 | ] 74 | 75 | [[package]] 76 | name = "attribute-derive" 77 | version = "0.9.2" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "1f1ee502851995027b06f99f5ffbeffa1406b38d0b318a1ebfa469332c6cbafd" 80 | dependencies = [ 81 | "attribute-derive-macro", 82 | "derive-where", 83 | "manyhow", 84 | "proc-macro2", 85 | "quote", 86 | "syn 2.0.96", 87 | ] 88 | 89 | [[package]] 90 | name = "attribute-derive-macro" 91 | version = "0.9.2" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "3601467f634cfe36c4780ca9c75dea9a5b34529c1f2810676a337e7e0997f954" 94 | dependencies = [ 95 | "collection_literals", 96 | "interpolator", 97 | "manyhow", 98 | "proc-macro-utils 0.8.0", 99 | "proc-macro2", 100 | "quote", 101 | "quote-use", 102 | "syn 2.0.96", 103 | ] 104 | 105 | [[package]] 106 | name = "autocfg" 107 | version = "1.4.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 110 | 111 | [[package]] 112 | name = "axum" 113 | version = "0.7.9" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" 116 | dependencies = [ 117 | "async-trait", 118 | "axum-core", 119 | "bytes", 120 | "futures-util", 121 | "http", 122 | "http-body", 123 | "http-body-util", 124 | "hyper", 125 | "hyper-util", 126 | "itoa", 127 | "matchit", 128 | "memchr", 129 | "mime", 130 | "multer", 131 | "percent-encoding", 132 | "pin-project-lite", 133 | "rustversion", 134 | "serde", 135 | "serde_json", 136 | "serde_path_to_error", 137 | "serde_urlencoded", 138 | "sync_wrapper", 139 | "tokio", 140 | "tower 0.5.2", 141 | "tower-layer", 142 | "tower-service", 143 | "tracing", 144 | ] 145 | 146 | [[package]] 147 | name = "axum-core" 148 | version = "0.4.5" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" 151 | dependencies = [ 152 | "async-trait", 153 | "bytes", 154 | "futures-util", 155 | "http", 156 | "http-body", 157 | "http-body-util", 158 | "mime", 159 | "pin-project-lite", 160 | "rustversion", 161 | "sync_wrapper", 162 | "tower-layer", 163 | "tower-service", 164 | "tracing", 165 | ] 166 | 167 | [[package]] 168 | name = "backtrace" 169 | version = "0.3.74" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 172 | dependencies = [ 173 | "addr2line", 174 | "cfg-if", 175 | "libc", 176 | "miniz_oxide", 177 | "object", 178 | "rustc-demangle", 179 | "windows-targets", 180 | ] 181 | 182 | [[package]] 183 | name = "base64" 184 | version = "0.22.1" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 187 | 188 | [[package]] 189 | name = "bitflags" 190 | version = "2.7.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" 193 | 194 | [[package]] 195 | name = "bumpalo" 196 | version = "3.16.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 199 | 200 | [[package]] 201 | name = "bytes" 202 | version = "1.9.0" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" 205 | 206 | [[package]] 207 | name = "cached" 208 | version = "0.45.1" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "90eb5776f28a149524d1d8623035760b4454ec881e8cf3838fa8d7e1b11254b3" 211 | dependencies = [ 212 | "cached_proc_macro", 213 | "cached_proc_macro_types", 214 | "hashbrown 0.13.2", 215 | "instant", 216 | "once_cell", 217 | "thiserror", 218 | ] 219 | 220 | [[package]] 221 | name = "cached_proc_macro" 222 | version = "0.18.1" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" 225 | dependencies = [ 226 | "darling", 227 | "proc-macro2", 228 | "quote", 229 | "syn 1.0.109", 230 | ] 231 | 232 | [[package]] 233 | name = "cached_proc_macro_types" 234 | version = "0.1.1" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" 237 | 238 | [[package]] 239 | name = "camino" 240 | version = "1.1.9" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" 243 | 244 | [[package]] 245 | name = "cfg-if" 246 | version = "1.0.0" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 249 | 250 | [[package]] 251 | name = "ciborium" 252 | version = "0.2.2" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 255 | dependencies = [ 256 | "ciborium-io", 257 | "ciborium-ll", 258 | "serde", 259 | ] 260 | 261 | [[package]] 262 | name = "ciborium-io" 263 | version = "0.2.2" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 266 | 267 | [[package]] 268 | name = "ciborium-ll" 269 | version = "0.2.2" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 272 | dependencies = [ 273 | "ciborium-io", 274 | "half", 275 | ] 276 | 277 | [[package]] 278 | name = "collection_literals" 279 | version = "1.0.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" 282 | 283 | [[package]] 284 | name = "config" 285 | version = "0.14.1" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" 288 | dependencies = [ 289 | "convert_case", 290 | "nom", 291 | "pathdiff", 292 | "serde", 293 | "toml", 294 | ] 295 | 296 | [[package]] 297 | name = "console_error_panic_hook" 298 | version = "0.1.7" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 301 | dependencies = [ 302 | "cfg-if", 303 | "wasm-bindgen", 304 | ] 305 | 306 | [[package]] 307 | name = "console_log" 308 | version = "1.0.0" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" 311 | dependencies = [ 312 | "log", 313 | "web-sys", 314 | ] 315 | 316 | [[package]] 317 | name = "const_format" 318 | version = "0.2.34" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" 321 | dependencies = [ 322 | "const_format_proc_macros", 323 | ] 324 | 325 | [[package]] 326 | name = "const_format_proc_macros" 327 | version = "0.2.34" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" 330 | dependencies = [ 331 | "proc-macro2", 332 | "quote", 333 | "unicode-xid", 334 | ] 335 | 336 | [[package]] 337 | name = "convert_case" 338 | version = "0.6.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" 341 | dependencies = [ 342 | "unicode-segmentation", 343 | ] 344 | 345 | [[package]] 346 | name = "copy_dir" 347 | version = "0.1.3" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "543d1dd138ef086e2ff05e3a48cf9da045da2033d16f8538fd76b86cd49b2ca3" 350 | dependencies = [ 351 | "walkdir", 352 | ] 353 | 354 | [[package]] 355 | name = "crunchy" 356 | version = "0.2.2" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 359 | 360 | [[package]] 361 | name = "darling" 362 | version = "0.14.4" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" 365 | dependencies = [ 366 | "darling_core", 367 | "darling_macro", 368 | ] 369 | 370 | [[package]] 371 | name = "darling_core" 372 | version = "0.14.4" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" 375 | dependencies = [ 376 | "fnv", 377 | "ident_case", 378 | "proc-macro2", 379 | "quote", 380 | "strsim", 381 | "syn 1.0.109", 382 | ] 383 | 384 | [[package]] 385 | name = "darling_macro" 386 | version = "0.14.4" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" 389 | dependencies = [ 390 | "darling_core", 391 | "quote", 392 | "syn 1.0.109", 393 | ] 394 | 395 | [[package]] 396 | name = "dashmap" 397 | version = "5.5.3" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" 400 | dependencies = [ 401 | "cfg-if", 402 | "hashbrown 0.14.5", 403 | "lock_api", 404 | "once_cell", 405 | "parking_lot_core", 406 | ] 407 | 408 | [[package]] 409 | name = "demo" 410 | version = "0.1.0" 411 | dependencies = [ 412 | "console_error_panic_hook", 413 | "console_log", 414 | "copy_dir", 415 | "leptos", 416 | "leptos_hotkeys", 417 | "leptos_meta", 418 | "leptos_router", 419 | "log", 420 | ] 421 | 422 | [[package]] 423 | name = "derive-where" 424 | version = "1.2.7" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" 427 | dependencies = [ 428 | "proc-macro2", 429 | "quote", 430 | "syn 2.0.96", 431 | ] 432 | 433 | [[package]] 434 | name = "displaydoc" 435 | version = "0.2.5" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 438 | dependencies = [ 439 | "proc-macro2", 440 | "quote", 441 | "syn 2.0.96", 442 | ] 443 | 444 | [[package]] 445 | name = "drain_filter_polyfill" 446 | version = "0.1.3" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" 449 | 450 | [[package]] 451 | name = "either" 452 | version = "1.13.0" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 455 | 456 | [[package]] 457 | name = "encoding_rs" 458 | version = "0.8.35" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 461 | dependencies = [ 462 | "cfg-if", 463 | ] 464 | 465 | [[package]] 466 | name = "equivalent" 467 | version = "1.0.1" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 470 | 471 | [[package]] 472 | name = "fnv" 473 | version = "1.0.7" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 476 | 477 | [[package]] 478 | name = "form_urlencoded" 479 | version = "1.2.1" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 482 | dependencies = [ 483 | "percent-encoding", 484 | ] 485 | 486 | [[package]] 487 | name = "futures" 488 | version = "0.3.31" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 491 | dependencies = [ 492 | "futures-channel", 493 | "futures-core", 494 | "futures-executor", 495 | "futures-io", 496 | "futures-sink", 497 | "futures-task", 498 | "futures-util", 499 | ] 500 | 501 | [[package]] 502 | name = "futures-channel" 503 | version = "0.3.31" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 506 | dependencies = [ 507 | "futures-core", 508 | "futures-sink", 509 | ] 510 | 511 | [[package]] 512 | name = "futures-core" 513 | version = "0.3.31" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 516 | 517 | [[package]] 518 | name = "futures-executor" 519 | version = "0.3.31" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 522 | dependencies = [ 523 | "futures-core", 524 | "futures-task", 525 | "futures-util", 526 | ] 527 | 528 | [[package]] 529 | name = "futures-io" 530 | version = "0.3.31" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 533 | 534 | [[package]] 535 | name = "futures-macro" 536 | version = "0.3.31" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 539 | dependencies = [ 540 | "proc-macro2", 541 | "quote", 542 | "syn 2.0.96", 543 | ] 544 | 545 | [[package]] 546 | name = "futures-sink" 547 | version = "0.3.31" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 550 | 551 | [[package]] 552 | name = "futures-task" 553 | version = "0.3.31" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 556 | 557 | [[package]] 558 | name = "futures-util" 559 | version = "0.3.31" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 562 | dependencies = [ 563 | "futures-channel", 564 | "futures-core", 565 | "futures-io", 566 | "futures-macro", 567 | "futures-sink", 568 | "futures-task", 569 | "memchr", 570 | "pin-project-lite", 571 | "pin-utils", 572 | "slab", 573 | ] 574 | 575 | [[package]] 576 | name = "getrandom" 577 | version = "0.2.15" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 580 | dependencies = [ 581 | "cfg-if", 582 | "js-sys", 583 | "libc", 584 | "wasi", 585 | "wasm-bindgen", 586 | ] 587 | 588 | [[package]] 589 | name = "gimli" 590 | version = "0.31.1" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 593 | 594 | [[package]] 595 | name = "gloo-net" 596 | version = "0.6.0" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" 599 | dependencies = [ 600 | "futures-channel", 601 | "futures-core", 602 | "futures-sink", 603 | "gloo-utils", 604 | "http", 605 | "js-sys", 606 | "pin-project", 607 | "serde", 608 | "serde_json", 609 | "thiserror", 610 | "wasm-bindgen", 611 | "wasm-bindgen-futures", 612 | "web-sys", 613 | ] 614 | 615 | [[package]] 616 | name = "gloo-utils" 617 | version = "0.2.0" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" 620 | dependencies = [ 621 | "js-sys", 622 | "serde", 623 | "serde_json", 624 | "wasm-bindgen", 625 | "web-sys", 626 | ] 627 | 628 | [[package]] 629 | name = "half" 630 | version = "2.4.1" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 633 | dependencies = [ 634 | "cfg-if", 635 | "crunchy", 636 | ] 637 | 638 | [[package]] 639 | name = "hashbrown" 640 | version = "0.13.2" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" 643 | 644 | [[package]] 645 | name = "hashbrown" 646 | version = "0.14.5" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 649 | dependencies = [ 650 | "ahash", 651 | "allocator-api2", 652 | ] 653 | 654 | [[package]] 655 | name = "hashbrown" 656 | version = "0.15.2" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 659 | 660 | [[package]] 661 | name = "html-escape" 662 | version = "0.2.13" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" 665 | dependencies = [ 666 | "utf8-width", 667 | ] 668 | 669 | [[package]] 670 | name = "http" 671 | version = "1.2.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" 674 | dependencies = [ 675 | "bytes", 676 | "fnv", 677 | "itoa", 678 | ] 679 | 680 | [[package]] 681 | name = "http-body" 682 | version = "1.0.1" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 685 | dependencies = [ 686 | "bytes", 687 | "http", 688 | ] 689 | 690 | [[package]] 691 | name = "http-body-util" 692 | version = "0.1.2" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 695 | dependencies = [ 696 | "bytes", 697 | "futures-util", 698 | "http", 699 | "http-body", 700 | "pin-project-lite", 701 | ] 702 | 703 | [[package]] 704 | name = "http-range-header" 705 | version = "0.4.2" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" 708 | 709 | [[package]] 710 | name = "httparse" 711 | version = "1.9.5" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 714 | 715 | [[package]] 716 | name = "httpdate" 717 | version = "1.0.3" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 720 | 721 | [[package]] 722 | name = "hyper" 723 | version = "1.5.2" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" 726 | dependencies = [ 727 | "bytes", 728 | "futures-channel", 729 | "futures-util", 730 | "http", 731 | "http-body", 732 | "httparse", 733 | "httpdate", 734 | "itoa", 735 | "pin-project-lite", 736 | "smallvec", 737 | "tokio", 738 | ] 739 | 740 | [[package]] 741 | name = "hyper-util" 742 | version = "0.1.10" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 745 | dependencies = [ 746 | "bytes", 747 | "futures-util", 748 | "http", 749 | "http-body", 750 | "hyper", 751 | "pin-project-lite", 752 | "tokio", 753 | "tower-service", 754 | ] 755 | 756 | [[package]] 757 | name = "icu_collections" 758 | version = "1.5.0" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 761 | dependencies = [ 762 | "displaydoc", 763 | "yoke", 764 | "zerofrom", 765 | "zerovec", 766 | ] 767 | 768 | [[package]] 769 | name = "icu_locid" 770 | version = "1.5.0" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 773 | dependencies = [ 774 | "displaydoc", 775 | "litemap", 776 | "tinystr", 777 | "writeable", 778 | "zerovec", 779 | ] 780 | 781 | [[package]] 782 | name = "icu_locid_transform" 783 | version = "1.5.0" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 786 | dependencies = [ 787 | "displaydoc", 788 | "icu_locid", 789 | "icu_locid_transform_data", 790 | "icu_provider", 791 | "tinystr", 792 | "zerovec", 793 | ] 794 | 795 | [[package]] 796 | name = "icu_locid_transform_data" 797 | version = "1.5.0" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 800 | 801 | [[package]] 802 | name = "icu_normalizer" 803 | version = "1.5.0" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 806 | dependencies = [ 807 | "displaydoc", 808 | "icu_collections", 809 | "icu_normalizer_data", 810 | "icu_properties", 811 | "icu_provider", 812 | "smallvec", 813 | "utf16_iter", 814 | "utf8_iter", 815 | "write16", 816 | "zerovec", 817 | ] 818 | 819 | [[package]] 820 | name = "icu_normalizer_data" 821 | version = "1.5.0" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 824 | 825 | [[package]] 826 | name = "icu_properties" 827 | version = "1.5.1" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 830 | dependencies = [ 831 | "displaydoc", 832 | "icu_collections", 833 | "icu_locid_transform", 834 | "icu_properties_data", 835 | "icu_provider", 836 | "tinystr", 837 | "zerovec", 838 | ] 839 | 840 | [[package]] 841 | name = "icu_properties_data" 842 | version = "1.5.0" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 845 | 846 | [[package]] 847 | name = "icu_provider" 848 | version = "1.5.0" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 851 | dependencies = [ 852 | "displaydoc", 853 | "icu_locid", 854 | "icu_provider_macros", 855 | "stable_deref_trait", 856 | "tinystr", 857 | "writeable", 858 | "yoke", 859 | "zerofrom", 860 | "zerovec", 861 | ] 862 | 863 | [[package]] 864 | name = "icu_provider_macros" 865 | version = "1.5.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 868 | dependencies = [ 869 | "proc-macro2", 870 | "quote", 871 | "syn 2.0.96", 872 | ] 873 | 874 | [[package]] 875 | name = "ident_case" 876 | version = "1.0.1" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 879 | 880 | [[package]] 881 | name = "idna" 882 | version = "1.0.3" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 885 | dependencies = [ 886 | "idna_adapter", 887 | "smallvec", 888 | "utf8_iter", 889 | ] 890 | 891 | [[package]] 892 | name = "idna_adapter" 893 | version = "1.2.0" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 896 | dependencies = [ 897 | "icu_normalizer", 898 | "icu_properties", 899 | ] 900 | 901 | [[package]] 902 | name = "indexmap" 903 | version = "2.7.0" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" 906 | dependencies = [ 907 | "equivalent", 908 | "hashbrown 0.15.2", 909 | ] 910 | 911 | [[package]] 912 | name = "instant" 913 | version = "0.1.13" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" 916 | dependencies = [ 917 | "cfg-if", 918 | ] 919 | 920 | [[package]] 921 | name = "interpolator" 922 | version = "0.5.0" 923 | source = "registry+https://github.com/rust-lang/crates.io-index" 924 | checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" 925 | 926 | [[package]] 927 | name = "inventory" 928 | version = "0.3.17" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "3b31349d02fe60f80bbbab1a9402364cad7460626d6030494b08ac4a2075bf81" 931 | dependencies = [ 932 | "rustversion", 933 | ] 934 | 935 | [[package]] 936 | name = "itertools" 937 | version = "0.12.1" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 940 | dependencies = [ 941 | "either", 942 | ] 943 | 944 | [[package]] 945 | name = "itoa" 946 | version = "1.0.14" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 949 | 950 | [[package]] 951 | name = "js-sys" 952 | version = "0.3.76" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" 955 | dependencies = [ 956 | "once_cell", 957 | "wasm-bindgen", 958 | ] 959 | 960 | [[package]] 961 | name = "lazy_static" 962 | version = "1.5.0" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 965 | 966 | [[package]] 967 | name = "leptos" 968 | version = "0.6.15" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "0cbb3237c274dadf00dcc27db96c52601b40375117178fb24a991cda073624f0" 971 | dependencies = [ 972 | "cfg-if", 973 | "leptos_config", 974 | "leptos_dom", 975 | "leptos_macro", 976 | "leptos_reactive", 977 | "leptos_server", 978 | "server_fn", 979 | "tracing", 980 | "typed-builder", 981 | "typed-builder-macro", 982 | "wasm-bindgen", 983 | "web-sys", 984 | ] 985 | 986 | [[package]] 987 | name = "leptos_axum" 988 | version = "0.6.15" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "910681b920c48a43508b2bd0261bdb67c4ef9456a0b3613f956a0d30e832e9de" 991 | dependencies = [ 992 | "axum", 993 | "cfg-if", 994 | "futures", 995 | "http-body-util", 996 | "leptos", 997 | "leptos_integration_utils", 998 | "leptos_macro", 999 | "leptos_meta", 1000 | "leptos_router", 1001 | "once_cell", 1002 | "parking_lot", 1003 | "serde_json", 1004 | "server_fn", 1005 | "tokio", 1006 | "tokio-util", 1007 | "tracing", 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "leptos_config" 1012 | version = "0.6.15" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "62ed778611380ddea47568ac6ad6ec5158d39b5bd59e6c4dcd24efc15dc3dc0d" 1015 | dependencies = [ 1016 | "config", 1017 | "regex", 1018 | "serde", 1019 | "thiserror", 1020 | "typed-builder", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "leptos_dom" 1025 | version = "0.6.15" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "8401c46c86c1f4c16dcb7881ed319fcdca9cda9b9e78a6088955cb423afcf119" 1028 | dependencies = [ 1029 | "async-recursion", 1030 | "cfg-if", 1031 | "drain_filter_polyfill", 1032 | "futures", 1033 | "getrandom", 1034 | "html-escape", 1035 | "indexmap", 1036 | "itertools", 1037 | "js-sys", 1038 | "leptos_reactive", 1039 | "once_cell", 1040 | "pad-adapter", 1041 | "paste", 1042 | "rustc-hash", 1043 | "serde", 1044 | "serde_json", 1045 | "server_fn", 1046 | "smallvec", 1047 | "tracing", 1048 | "wasm-bindgen", 1049 | "wasm-bindgen-futures", 1050 | "web-sys", 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "leptos_hot_reload" 1055 | version = "0.6.15" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "6cb53d4794240b684a2f4be224b84bee9e62d2abc498cf2bcd643cd565e01d96" 1058 | dependencies = [ 1059 | "anyhow", 1060 | "camino", 1061 | "indexmap", 1062 | "parking_lot", 1063 | "proc-macro2", 1064 | "quote", 1065 | "rstml", 1066 | "serde", 1067 | "syn 2.0.96", 1068 | "walkdir", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "leptos_hotkeys" 1073 | version = "0.2.2" 1074 | dependencies = [ 1075 | "leptos", 1076 | "log", 1077 | "wasm-bindgen", 1078 | "web-sys", 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "leptos_integration_utils" 1083 | version = "0.6.15" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "5a96976631c2225ec116a7bf9c0ed5bf6999a19fed33f5e3cbcf37af44c384dc" 1086 | dependencies = [ 1087 | "futures", 1088 | "leptos", 1089 | "leptos_config", 1090 | "leptos_hot_reload", 1091 | "leptos_meta", 1092 | "tracing", 1093 | ] 1094 | 1095 | [[package]] 1096 | name = "leptos_macro" 1097 | version = "0.6.15" 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" 1099 | checksum = "4b13bc3db70715cd8218c4535a5af3ae3c0e5fea6f018531fc339377b36bc0e0" 1100 | dependencies = [ 1101 | "attribute-derive", 1102 | "cfg-if", 1103 | "convert_case", 1104 | "html-escape", 1105 | "itertools", 1106 | "leptos_hot_reload", 1107 | "prettyplease", 1108 | "proc-macro-error2", 1109 | "proc-macro2", 1110 | "quote", 1111 | "rstml", 1112 | "server_fn_macro", 1113 | "syn 2.0.96", 1114 | "tracing", 1115 | "uuid", 1116 | ] 1117 | 1118 | [[package]] 1119 | name = "leptos_meta" 1120 | version = "0.6.15" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "25acc2f63cf91932013e400a95bf6e35e5d3dbb44a7b7e25a8e3057d12005b3b" 1123 | dependencies = [ 1124 | "cfg-if", 1125 | "indexmap", 1126 | "leptos", 1127 | "tracing", 1128 | "wasm-bindgen", 1129 | "web-sys", 1130 | ] 1131 | 1132 | [[package]] 1133 | name = "leptos_reactive" 1134 | version = "0.6.15" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "e4161acbf80f59219d8d14182371f57302bc7ff81ee41aba8ba1ff7295727f23" 1137 | dependencies = [ 1138 | "base64", 1139 | "cfg-if", 1140 | "futures", 1141 | "indexmap", 1142 | "js-sys", 1143 | "oco_ref", 1144 | "paste", 1145 | "pin-project", 1146 | "rustc-hash", 1147 | "self_cell", 1148 | "serde", 1149 | "serde-wasm-bindgen", 1150 | "serde_json", 1151 | "slotmap", 1152 | "thiserror", 1153 | "tokio", 1154 | "tracing", 1155 | "wasm-bindgen", 1156 | "wasm-bindgen-futures", 1157 | "web-sys", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "leptos_router" 1162 | version = "0.6.15" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "8d71dea7d42c0d29c40842750232d3425ed1cf10e313a1f898076d20871dad32" 1165 | dependencies = [ 1166 | "cached", 1167 | "cfg-if", 1168 | "gloo-net", 1169 | "itertools", 1170 | "js-sys", 1171 | "lazy_static", 1172 | "leptos", 1173 | "leptos_integration_utils", 1174 | "leptos_meta", 1175 | "linear-map", 1176 | "lru", 1177 | "once_cell", 1178 | "percent-encoding", 1179 | "regex", 1180 | "send_wrapper", 1181 | "serde", 1182 | "serde_json", 1183 | "serde_qs 0.13.0", 1184 | "thiserror", 1185 | "tracing", 1186 | "url", 1187 | "wasm-bindgen", 1188 | "wasm-bindgen-futures", 1189 | "web-sys", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "leptos_server" 1194 | version = "0.6.15" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "4a97eb90a13f71500b831c7119ddd3bdd0d7ae0a6b0487cade4fddeed3b8c03f" 1197 | dependencies = [ 1198 | "inventory", 1199 | "lazy_static", 1200 | "leptos_macro", 1201 | "leptos_reactive", 1202 | "serde", 1203 | "server_fn", 1204 | "thiserror", 1205 | "tracing", 1206 | ] 1207 | 1208 | [[package]] 1209 | name = "libc" 1210 | version = "0.2.169" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 1213 | 1214 | [[package]] 1215 | name = "linear-map" 1216 | version = "1.2.0" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" 1219 | dependencies = [ 1220 | "serde", 1221 | "serde_test", 1222 | ] 1223 | 1224 | [[package]] 1225 | name = "litemap" 1226 | version = "0.7.4" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" 1229 | 1230 | [[package]] 1231 | name = "lock_api" 1232 | version = "0.4.12" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1235 | dependencies = [ 1236 | "autocfg", 1237 | "scopeguard", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "log" 1242 | version = "0.4.22" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1245 | 1246 | [[package]] 1247 | name = "lru" 1248 | version = "0.11.1" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" 1251 | dependencies = [ 1252 | "hashbrown 0.14.5", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "manyhow" 1257 | version = "0.10.4" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "f91ea592d76c0b6471965708ccff7e6a5d277f676b90ab31f4d3f3fc77fade64" 1260 | dependencies = [ 1261 | "manyhow-macros", 1262 | "proc-macro2", 1263 | "quote", 1264 | "syn 2.0.96", 1265 | ] 1266 | 1267 | [[package]] 1268 | name = "manyhow-macros" 1269 | version = "0.10.4" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "c64621e2c08f2576e4194ea8be11daf24ac01249a4f53cd8befcbb7077120ead" 1272 | dependencies = [ 1273 | "proc-macro-utils 0.8.0", 1274 | "proc-macro2", 1275 | "quote", 1276 | ] 1277 | 1278 | [[package]] 1279 | name = "matchit" 1280 | version = "0.7.3" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 1283 | 1284 | [[package]] 1285 | name = "memchr" 1286 | version = "2.7.4" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1289 | 1290 | [[package]] 1291 | name = "mime" 1292 | version = "0.3.17" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1295 | 1296 | [[package]] 1297 | name = "mime_guess" 1298 | version = "2.0.5" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 1301 | dependencies = [ 1302 | "mime", 1303 | "unicase", 1304 | ] 1305 | 1306 | [[package]] 1307 | name = "minimal-lexical" 1308 | version = "0.2.1" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1311 | 1312 | [[package]] 1313 | name = "miniz_oxide" 1314 | version = "0.8.2" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" 1317 | dependencies = [ 1318 | "adler2", 1319 | ] 1320 | 1321 | [[package]] 1322 | name = "mio" 1323 | version = "1.0.3" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 1326 | dependencies = [ 1327 | "libc", 1328 | "wasi", 1329 | "windows-sys 0.52.0", 1330 | ] 1331 | 1332 | [[package]] 1333 | name = "multer" 1334 | version = "3.1.0" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" 1337 | dependencies = [ 1338 | "bytes", 1339 | "encoding_rs", 1340 | "futures-util", 1341 | "http", 1342 | "httparse", 1343 | "memchr", 1344 | "mime", 1345 | "spin", 1346 | "version_check", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "nom" 1351 | version = "7.1.3" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1354 | dependencies = [ 1355 | "memchr", 1356 | "minimal-lexical", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "object" 1361 | version = "0.36.7" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1364 | dependencies = [ 1365 | "memchr", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "oco_ref" 1370 | version = "0.1.1" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "c51ebcefb2f0b9a5e0bea115532c8ae4215d1b01eff176d0f4ba4192895c2708" 1373 | dependencies = [ 1374 | "serde", 1375 | "thiserror", 1376 | ] 1377 | 1378 | [[package]] 1379 | name = "once_cell" 1380 | version = "1.20.2" 1381 | source = "registry+https://github.com/rust-lang/crates.io-index" 1382 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1383 | 1384 | [[package]] 1385 | name = "pad-adapter" 1386 | version = "0.1.1" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "56d80efc4b6721e8be2a10a5df21a30fa0b470f1539e53d8b4e6e75faf938b63" 1389 | 1390 | [[package]] 1391 | name = "parking_lot" 1392 | version = "0.12.3" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1395 | dependencies = [ 1396 | "lock_api", 1397 | "parking_lot_core", 1398 | ] 1399 | 1400 | [[package]] 1401 | name = "parking_lot_core" 1402 | version = "0.9.10" 1403 | source = "registry+https://github.com/rust-lang/crates.io-index" 1404 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1405 | dependencies = [ 1406 | "cfg-if", 1407 | "libc", 1408 | "redox_syscall", 1409 | "smallvec", 1410 | "windows-targets", 1411 | ] 1412 | 1413 | [[package]] 1414 | name = "paste" 1415 | version = "1.0.15" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1418 | 1419 | [[package]] 1420 | name = "pathdiff" 1421 | version = "0.2.3" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" 1424 | 1425 | [[package]] 1426 | name = "percent-encoding" 1427 | version = "2.3.1" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1430 | 1431 | [[package]] 1432 | name = "pin-project" 1433 | version = "1.1.8" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" 1436 | dependencies = [ 1437 | "pin-project-internal", 1438 | ] 1439 | 1440 | [[package]] 1441 | name = "pin-project-internal" 1442 | version = "1.1.8" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" 1445 | dependencies = [ 1446 | "proc-macro2", 1447 | "quote", 1448 | "syn 2.0.96", 1449 | ] 1450 | 1451 | [[package]] 1452 | name = "pin-project-lite" 1453 | version = "0.2.16" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1456 | 1457 | [[package]] 1458 | name = "pin-utils" 1459 | version = "0.1.0" 1460 | source = "registry+https://github.com/rust-lang/crates.io-index" 1461 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1462 | 1463 | [[package]] 1464 | name = "prettyplease" 1465 | version = "0.2.28" 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" 1467 | checksum = "924b9a625d6df5b74b0b3cfbb5669b3f62ddf3d46a677ce12b1945471b4ae5c3" 1468 | dependencies = [ 1469 | "proc-macro2", 1470 | "syn 2.0.96", 1471 | ] 1472 | 1473 | [[package]] 1474 | name = "proc-macro-error" 1475 | version = "1.0.4" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1478 | dependencies = [ 1479 | "proc-macro-error-attr", 1480 | "proc-macro2", 1481 | "quote", 1482 | "version_check", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "proc-macro-error-attr" 1487 | version = "1.0.4" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1490 | dependencies = [ 1491 | "proc-macro2", 1492 | "quote", 1493 | "version_check", 1494 | ] 1495 | 1496 | [[package]] 1497 | name = "proc-macro-error-attr2" 1498 | version = "2.0.0" 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" 1500 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 1501 | dependencies = [ 1502 | "proc-macro2", 1503 | "quote", 1504 | ] 1505 | 1506 | [[package]] 1507 | name = "proc-macro-error2" 1508 | version = "2.0.1" 1509 | source = "registry+https://github.com/rust-lang/crates.io-index" 1510 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 1511 | dependencies = [ 1512 | "proc-macro-error-attr2", 1513 | "proc-macro2", 1514 | "quote", 1515 | ] 1516 | 1517 | [[package]] 1518 | name = "proc-macro-utils" 1519 | version = "0.8.0" 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" 1521 | checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8" 1522 | dependencies = [ 1523 | "proc-macro2", 1524 | "quote", 1525 | "smallvec", 1526 | ] 1527 | 1528 | [[package]] 1529 | name = "proc-macro-utils" 1530 | version = "0.10.0" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" 1533 | dependencies = [ 1534 | "proc-macro2", 1535 | "quote", 1536 | "smallvec", 1537 | ] 1538 | 1539 | [[package]] 1540 | name = "proc-macro2" 1541 | version = "1.0.93" 1542 | source = "registry+https://github.com/rust-lang/crates.io-index" 1543 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 1544 | dependencies = [ 1545 | "unicode-ident", 1546 | ] 1547 | 1548 | [[package]] 1549 | name = "proc-macro2-diagnostics" 1550 | version = "0.10.1" 1551 | source = "registry+https://github.com/rust-lang/crates.io-index" 1552 | checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" 1553 | dependencies = [ 1554 | "proc-macro2", 1555 | "quote", 1556 | "syn 2.0.96", 1557 | "version_check", 1558 | "yansi", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "quote" 1563 | version = "1.0.38" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 1566 | dependencies = [ 1567 | "proc-macro2", 1568 | ] 1569 | 1570 | [[package]] 1571 | name = "quote-use" 1572 | version = "0.8.4" 1573 | source = "registry+https://github.com/rust-lang/crates.io-index" 1574 | checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" 1575 | dependencies = [ 1576 | "quote", 1577 | "quote-use-macros", 1578 | ] 1579 | 1580 | [[package]] 1581 | name = "quote-use-macros" 1582 | version = "0.8.4" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" 1585 | dependencies = [ 1586 | "proc-macro-utils 0.10.0", 1587 | "proc-macro2", 1588 | "quote", 1589 | "syn 2.0.96", 1590 | ] 1591 | 1592 | [[package]] 1593 | name = "redox_syscall" 1594 | version = "0.5.8" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" 1597 | dependencies = [ 1598 | "bitflags", 1599 | ] 1600 | 1601 | [[package]] 1602 | name = "regex" 1603 | version = "1.11.1" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1606 | dependencies = [ 1607 | "aho-corasick", 1608 | "memchr", 1609 | "regex-automata", 1610 | "regex-syntax", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "regex-automata" 1615 | version = "0.4.9" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1618 | dependencies = [ 1619 | "aho-corasick", 1620 | "memchr", 1621 | "regex-syntax", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "regex-syntax" 1626 | version = "0.8.5" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1629 | 1630 | [[package]] 1631 | name = "rstml" 1632 | version = "0.11.2" 1633 | source = "registry+https://github.com/rust-lang/crates.io-index" 1634 | checksum = "fe542870b8f59dd45ad11d382e5339c9a1047cde059be136a7016095bbdefa77" 1635 | dependencies = [ 1636 | "proc-macro2", 1637 | "proc-macro2-diagnostics", 1638 | "quote", 1639 | "syn 2.0.96", 1640 | "syn_derive", 1641 | "thiserror", 1642 | ] 1643 | 1644 | [[package]] 1645 | name = "rustc-demangle" 1646 | version = "0.1.24" 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" 1648 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1649 | 1650 | [[package]] 1651 | name = "rustc-hash" 1652 | version = "1.1.0" 1653 | source = "registry+https://github.com/rust-lang/crates.io-index" 1654 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1655 | 1656 | [[package]] 1657 | name = "rustversion" 1658 | version = "1.0.19" 1659 | source = "registry+https://github.com/rust-lang/crates.io-index" 1660 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 1661 | 1662 | [[package]] 1663 | name = "ryu" 1664 | version = "1.0.18" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 1667 | 1668 | [[package]] 1669 | name = "same-file" 1670 | version = "1.0.6" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1673 | dependencies = [ 1674 | "winapi-util", 1675 | ] 1676 | 1677 | [[package]] 1678 | name = "scopeguard" 1679 | version = "1.2.0" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1682 | 1683 | [[package]] 1684 | name = "self_cell" 1685 | version = "1.1.0" 1686 | source = "registry+https://github.com/rust-lang/crates.io-index" 1687 | checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" 1688 | 1689 | [[package]] 1690 | name = "send_wrapper" 1691 | version = "0.6.0" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" 1694 | dependencies = [ 1695 | "futures-core", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "serde" 1700 | version = "1.0.217" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 1703 | dependencies = [ 1704 | "serde_derive", 1705 | ] 1706 | 1707 | [[package]] 1708 | name = "serde-wasm-bindgen" 1709 | version = "0.6.5" 1710 | source = "registry+https://github.com/rust-lang/crates.io-index" 1711 | checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" 1712 | dependencies = [ 1713 | "js-sys", 1714 | "serde", 1715 | "wasm-bindgen", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "serde_derive" 1720 | version = "1.0.217" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 1723 | dependencies = [ 1724 | "proc-macro2", 1725 | "quote", 1726 | "syn 2.0.96", 1727 | ] 1728 | 1729 | [[package]] 1730 | name = "serde_json" 1731 | version = "1.0.135" 1732 | source = "registry+https://github.com/rust-lang/crates.io-index" 1733 | checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" 1734 | dependencies = [ 1735 | "itoa", 1736 | "memchr", 1737 | "ryu", 1738 | "serde", 1739 | ] 1740 | 1741 | [[package]] 1742 | name = "serde_path_to_error" 1743 | version = "0.1.16" 1744 | source = "registry+https://github.com/rust-lang/crates.io-index" 1745 | checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" 1746 | dependencies = [ 1747 | "itoa", 1748 | "serde", 1749 | ] 1750 | 1751 | [[package]] 1752 | name = "serde_qs" 1753 | version = "0.12.0" 1754 | source = "registry+https://github.com/rust-lang/crates.io-index" 1755 | checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" 1756 | dependencies = [ 1757 | "percent-encoding", 1758 | "serde", 1759 | "thiserror", 1760 | ] 1761 | 1762 | [[package]] 1763 | name = "serde_qs" 1764 | version = "0.13.0" 1765 | source = "registry+https://github.com/rust-lang/crates.io-index" 1766 | checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" 1767 | dependencies = [ 1768 | "percent-encoding", 1769 | "serde", 1770 | "thiserror", 1771 | ] 1772 | 1773 | [[package]] 1774 | name = "serde_spanned" 1775 | version = "0.6.8" 1776 | source = "registry+https://github.com/rust-lang/crates.io-index" 1777 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 1778 | dependencies = [ 1779 | "serde", 1780 | ] 1781 | 1782 | [[package]] 1783 | name = "serde_test" 1784 | version = "1.0.177" 1785 | source = "registry+https://github.com/rust-lang/crates.io-index" 1786 | checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" 1787 | dependencies = [ 1788 | "serde", 1789 | ] 1790 | 1791 | [[package]] 1792 | name = "serde_urlencoded" 1793 | version = "0.7.1" 1794 | source = "registry+https://github.com/rust-lang/crates.io-index" 1795 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1796 | dependencies = [ 1797 | "form_urlencoded", 1798 | "itoa", 1799 | "ryu", 1800 | "serde", 1801 | ] 1802 | 1803 | [[package]] 1804 | name = "server_fn" 1805 | version = "0.6.15" 1806 | source = "registry+https://github.com/rust-lang/crates.io-index" 1807 | checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" 1808 | dependencies = [ 1809 | "axum", 1810 | "bytes", 1811 | "ciborium", 1812 | "const_format", 1813 | "dashmap", 1814 | "futures", 1815 | "gloo-net", 1816 | "http", 1817 | "http-body-util", 1818 | "hyper", 1819 | "inventory", 1820 | "js-sys", 1821 | "once_cell", 1822 | "send_wrapper", 1823 | "serde", 1824 | "serde_json", 1825 | "serde_qs 0.12.0", 1826 | "server_fn_macro_default", 1827 | "thiserror", 1828 | "tower 0.4.13", 1829 | "tower-layer", 1830 | "url", 1831 | "wasm-bindgen", 1832 | "wasm-bindgen-futures", 1833 | "wasm-streams", 1834 | "web-sys", 1835 | "xxhash-rust", 1836 | ] 1837 | 1838 | [[package]] 1839 | name = "server_fn_macro" 1840 | version = "0.6.15" 1841 | source = "registry+https://github.com/rust-lang/crates.io-index" 1842 | checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" 1843 | dependencies = [ 1844 | "const_format", 1845 | "convert_case", 1846 | "proc-macro2", 1847 | "quote", 1848 | "syn 2.0.96", 1849 | "xxhash-rust", 1850 | ] 1851 | 1852 | [[package]] 1853 | name = "server_fn_macro_default" 1854 | version = "0.6.15" 1855 | source = "registry+https://github.com/rust-lang/crates.io-index" 1856 | checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" 1857 | dependencies = [ 1858 | "server_fn_macro", 1859 | "syn 2.0.96", 1860 | ] 1861 | 1862 | [[package]] 1863 | name = "slab" 1864 | version = "0.4.9" 1865 | source = "registry+https://github.com/rust-lang/crates.io-index" 1866 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1867 | dependencies = [ 1868 | "autocfg", 1869 | ] 1870 | 1871 | [[package]] 1872 | name = "slotmap" 1873 | version = "1.0.7" 1874 | source = "registry+https://github.com/rust-lang/crates.io-index" 1875 | checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" 1876 | dependencies = [ 1877 | "serde", 1878 | "version_check", 1879 | ] 1880 | 1881 | [[package]] 1882 | name = "smallvec" 1883 | version = "1.13.2" 1884 | source = "registry+https://github.com/rust-lang/crates.io-index" 1885 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1886 | 1887 | [[package]] 1888 | name = "socket2" 1889 | version = "0.5.8" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 1892 | dependencies = [ 1893 | "libc", 1894 | "windows-sys 0.52.0", 1895 | ] 1896 | 1897 | [[package]] 1898 | name = "spin" 1899 | version = "0.9.8" 1900 | source = "registry+https://github.com/rust-lang/crates.io-index" 1901 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1902 | 1903 | [[package]] 1904 | name = "ssr-demo" 1905 | version = "0.1.0" 1906 | dependencies = [ 1907 | "axum", 1908 | "console_error_panic_hook", 1909 | "http", 1910 | "leptos", 1911 | "leptos_axum", 1912 | "leptos_hotkeys", 1913 | "leptos_meta", 1914 | "leptos_router", 1915 | "thiserror", 1916 | "tokio", 1917 | "tower 0.4.13", 1918 | "tower-http", 1919 | "tracing", 1920 | "wasm-bindgen", 1921 | ] 1922 | 1923 | [[package]] 1924 | name = "stable_deref_trait" 1925 | version = "1.2.0" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1928 | 1929 | [[package]] 1930 | name = "strsim" 1931 | version = "0.10.0" 1932 | source = "registry+https://github.com/rust-lang/crates.io-index" 1933 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1934 | 1935 | [[package]] 1936 | name = "syn" 1937 | version = "1.0.109" 1938 | source = "registry+https://github.com/rust-lang/crates.io-index" 1939 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1940 | dependencies = [ 1941 | "proc-macro2", 1942 | "quote", 1943 | "unicode-ident", 1944 | ] 1945 | 1946 | [[package]] 1947 | name = "syn" 1948 | version = "2.0.96" 1949 | source = "registry+https://github.com/rust-lang/crates.io-index" 1950 | checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" 1951 | dependencies = [ 1952 | "proc-macro2", 1953 | "quote", 1954 | "unicode-ident", 1955 | ] 1956 | 1957 | [[package]] 1958 | name = "syn_derive" 1959 | version = "0.1.8" 1960 | source = "registry+https://github.com/rust-lang/crates.io-index" 1961 | checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" 1962 | dependencies = [ 1963 | "proc-macro-error", 1964 | "proc-macro2", 1965 | "quote", 1966 | "syn 2.0.96", 1967 | ] 1968 | 1969 | [[package]] 1970 | name = "sync_wrapper" 1971 | version = "1.0.2" 1972 | source = "registry+https://github.com/rust-lang/crates.io-index" 1973 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1974 | 1975 | [[package]] 1976 | name = "synstructure" 1977 | version = "0.13.1" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1980 | dependencies = [ 1981 | "proc-macro2", 1982 | "quote", 1983 | "syn 2.0.96", 1984 | ] 1985 | 1986 | [[package]] 1987 | name = "thiserror" 1988 | version = "1.0.69" 1989 | source = "registry+https://github.com/rust-lang/crates.io-index" 1990 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1991 | dependencies = [ 1992 | "thiserror-impl", 1993 | ] 1994 | 1995 | [[package]] 1996 | name = "thiserror-impl" 1997 | version = "1.0.69" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2000 | dependencies = [ 2001 | "proc-macro2", 2002 | "quote", 2003 | "syn 2.0.96", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "tinystr" 2008 | version = "0.7.6" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 2011 | dependencies = [ 2012 | "displaydoc", 2013 | "zerovec", 2014 | ] 2015 | 2016 | [[package]] 2017 | name = "tokio" 2018 | version = "1.43.0" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 2021 | dependencies = [ 2022 | "backtrace", 2023 | "bytes", 2024 | "libc", 2025 | "mio", 2026 | "pin-project-lite", 2027 | "socket2", 2028 | "tokio-macros", 2029 | "windows-sys 0.52.0", 2030 | ] 2031 | 2032 | [[package]] 2033 | name = "tokio-macros" 2034 | version = "2.5.0" 2035 | source = "registry+https://github.com/rust-lang/crates.io-index" 2036 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 2037 | dependencies = [ 2038 | "proc-macro2", 2039 | "quote", 2040 | "syn 2.0.96", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "tokio-util" 2045 | version = "0.7.13" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" 2048 | dependencies = [ 2049 | "bytes", 2050 | "futures-core", 2051 | "futures-sink", 2052 | "futures-util", 2053 | "hashbrown 0.14.5", 2054 | "pin-project-lite", 2055 | "tokio", 2056 | ] 2057 | 2058 | [[package]] 2059 | name = "toml" 2060 | version = "0.8.19" 2061 | source = "registry+https://github.com/rust-lang/crates.io-index" 2062 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 2063 | dependencies = [ 2064 | "serde", 2065 | "serde_spanned", 2066 | "toml_datetime", 2067 | "toml_edit", 2068 | ] 2069 | 2070 | [[package]] 2071 | name = "toml_datetime" 2072 | version = "0.6.8" 2073 | source = "registry+https://github.com/rust-lang/crates.io-index" 2074 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 2075 | dependencies = [ 2076 | "serde", 2077 | ] 2078 | 2079 | [[package]] 2080 | name = "toml_edit" 2081 | version = "0.22.22" 2082 | source = "registry+https://github.com/rust-lang/crates.io-index" 2083 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 2084 | dependencies = [ 2085 | "indexmap", 2086 | "serde", 2087 | "serde_spanned", 2088 | "toml_datetime", 2089 | "winnow", 2090 | ] 2091 | 2092 | [[package]] 2093 | name = "tower" 2094 | version = "0.4.13" 2095 | source = "registry+https://github.com/rust-lang/crates.io-index" 2096 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 2097 | dependencies = [ 2098 | "futures-core", 2099 | "futures-util", 2100 | "pin-project", 2101 | "pin-project-lite", 2102 | "tower-layer", 2103 | "tower-service", 2104 | "tracing", 2105 | ] 2106 | 2107 | [[package]] 2108 | name = "tower" 2109 | version = "0.5.2" 2110 | source = "registry+https://github.com/rust-lang/crates.io-index" 2111 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 2112 | dependencies = [ 2113 | "futures-core", 2114 | "futures-util", 2115 | "pin-project-lite", 2116 | "sync_wrapper", 2117 | "tokio", 2118 | "tower-layer", 2119 | "tower-service", 2120 | "tracing", 2121 | ] 2122 | 2123 | [[package]] 2124 | name = "tower-http" 2125 | version = "0.5.2" 2126 | source = "registry+https://github.com/rust-lang/crates.io-index" 2127 | checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" 2128 | dependencies = [ 2129 | "bitflags", 2130 | "bytes", 2131 | "futures-util", 2132 | "http", 2133 | "http-body", 2134 | "http-body-util", 2135 | "http-range-header", 2136 | "httpdate", 2137 | "mime", 2138 | "mime_guess", 2139 | "percent-encoding", 2140 | "pin-project-lite", 2141 | "tokio", 2142 | "tokio-util", 2143 | "tower-layer", 2144 | "tower-service", 2145 | "tracing", 2146 | ] 2147 | 2148 | [[package]] 2149 | name = "tower-layer" 2150 | version = "0.3.3" 2151 | source = "registry+https://github.com/rust-lang/crates.io-index" 2152 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 2153 | 2154 | [[package]] 2155 | name = "tower-service" 2156 | version = "0.3.3" 2157 | source = "registry+https://github.com/rust-lang/crates.io-index" 2158 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2159 | 2160 | [[package]] 2161 | name = "tracing" 2162 | version = "0.1.41" 2163 | source = "registry+https://github.com/rust-lang/crates.io-index" 2164 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2165 | dependencies = [ 2166 | "log", 2167 | "pin-project-lite", 2168 | "tracing-attributes", 2169 | "tracing-core", 2170 | ] 2171 | 2172 | [[package]] 2173 | name = "tracing-attributes" 2174 | version = "0.1.28" 2175 | source = "registry+https://github.com/rust-lang/crates.io-index" 2176 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 2177 | dependencies = [ 2178 | "proc-macro2", 2179 | "quote", 2180 | "syn 2.0.96", 2181 | ] 2182 | 2183 | [[package]] 2184 | name = "tracing-core" 2185 | version = "0.1.33" 2186 | source = "registry+https://github.com/rust-lang/crates.io-index" 2187 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 2188 | dependencies = [ 2189 | "once_cell", 2190 | ] 2191 | 2192 | [[package]] 2193 | name = "typed-builder" 2194 | version = "0.18.2" 2195 | source = "registry+https://github.com/rust-lang/crates.io-index" 2196 | checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" 2197 | dependencies = [ 2198 | "typed-builder-macro", 2199 | ] 2200 | 2201 | [[package]] 2202 | name = "typed-builder-macro" 2203 | version = "0.18.2" 2204 | source = "registry+https://github.com/rust-lang/crates.io-index" 2205 | checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" 2206 | dependencies = [ 2207 | "proc-macro2", 2208 | "quote", 2209 | "syn 2.0.96", 2210 | ] 2211 | 2212 | [[package]] 2213 | name = "unicase" 2214 | version = "2.8.1" 2215 | source = "registry+https://github.com/rust-lang/crates.io-index" 2216 | checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 2217 | 2218 | [[package]] 2219 | name = "unicode-ident" 2220 | version = "1.0.14" 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" 2222 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 2223 | 2224 | [[package]] 2225 | name = "unicode-segmentation" 2226 | version = "1.12.0" 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" 2228 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 2229 | 2230 | [[package]] 2231 | name = "unicode-xid" 2232 | version = "0.2.6" 2233 | source = "registry+https://github.com/rust-lang/crates.io-index" 2234 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 2235 | 2236 | [[package]] 2237 | name = "url" 2238 | version = "2.5.4" 2239 | source = "registry+https://github.com/rust-lang/crates.io-index" 2240 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2241 | dependencies = [ 2242 | "form_urlencoded", 2243 | "idna", 2244 | "percent-encoding", 2245 | ] 2246 | 2247 | [[package]] 2248 | name = "utf16_iter" 2249 | version = "1.0.5" 2250 | source = "registry+https://github.com/rust-lang/crates.io-index" 2251 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 2252 | 2253 | [[package]] 2254 | name = "utf8-width" 2255 | version = "0.1.7" 2256 | source = "registry+https://github.com/rust-lang/crates.io-index" 2257 | checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" 2258 | 2259 | [[package]] 2260 | name = "utf8_iter" 2261 | version = "1.0.4" 2262 | source = "registry+https://github.com/rust-lang/crates.io-index" 2263 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2264 | 2265 | [[package]] 2266 | name = "uuid" 2267 | version = "1.11.1" 2268 | source = "registry+https://github.com/rust-lang/crates.io-index" 2269 | checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4" 2270 | dependencies = [ 2271 | "getrandom", 2272 | ] 2273 | 2274 | [[package]] 2275 | name = "version_check" 2276 | version = "0.9.5" 2277 | source = "registry+https://github.com/rust-lang/crates.io-index" 2278 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2279 | 2280 | [[package]] 2281 | name = "walkdir" 2282 | version = "2.5.0" 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" 2284 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 2285 | dependencies = [ 2286 | "same-file", 2287 | "winapi-util", 2288 | ] 2289 | 2290 | [[package]] 2291 | name = "wasi" 2292 | version = "0.11.0+wasi-snapshot-preview1" 2293 | source = "registry+https://github.com/rust-lang/crates.io-index" 2294 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2295 | 2296 | [[package]] 2297 | name = "wasm-bindgen" 2298 | version = "0.2.99" 2299 | source = "registry+https://github.com/rust-lang/crates.io-index" 2300 | checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" 2301 | dependencies = [ 2302 | "cfg-if", 2303 | "once_cell", 2304 | "wasm-bindgen-macro", 2305 | ] 2306 | 2307 | [[package]] 2308 | name = "wasm-bindgen-backend" 2309 | version = "0.2.99" 2310 | source = "registry+https://github.com/rust-lang/crates.io-index" 2311 | checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" 2312 | dependencies = [ 2313 | "bumpalo", 2314 | "log", 2315 | "proc-macro2", 2316 | "quote", 2317 | "syn 2.0.96", 2318 | "wasm-bindgen-shared", 2319 | ] 2320 | 2321 | [[package]] 2322 | name = "wasm-bindgen-futures" 2323 | version = "0.4.49" 2324 | source = "registry+https://github.com/rust-lang/crates.io-index" 2325 | checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" 2326 | dependencies = [ 2327 | "cfg-if", 2328 | "js-sys", 2329 | "once_cell", 2330 | "wasm-bindgen", 2331 | "web-sys", 2332 | ] 2333 | 2334 | [[package]] 2335 | name = "wasm-bindgen-macro" 2336 | version = "0.2.99" 2337 | source = "registry+https://github.com/rust-lang/crates.io-index" 2338 | checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" 2339 | dependencies = [ 2340 | "quote", 2341 | "wasm-bindgen-macro-support", 2342 | ] 2343 | 2344 | [[package]] 2345 | name = "wasm-bindgen-macro-support" 2346 | version = "0.2.99" 2347 | source = "registry+https://github.com/rust-lang/crates.io-index" 2348 | checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" 2349 | dependencies = [ 2350 | "proc-macro2", 2351 | "quote", 2352 | "syn 2.0.96", 2353 | "wasm-bindgen-backend", 2354 | "wasm-bindgen-shared", 2355 | ] 2356 | 2357 | [[package]] 2358 | name = "wasm-bindgen-shared" 2359 | version = "0.2.99" 2360 | source = "registry+https://github.com/rust-lang/crates.io-index" 2361 | checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" 2362 | 2363 | [[package]] 2364 | name = "wasm-streams" 2365 | version = "0.4.2" 2366 | source = "registry+https://github.com/rust-lang/crates.io-index" 2367 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 2368 | dependencies = [ 2369 | "futures-util", 2370 | "js-sys", 2371 | "wasm-bindgen", 2372 | "wasm-bindgen-futures", 2373 | "web-sys", 2374 | ] 2375 | 2376 | [[package]] 2377 | name = "web-sys" 2378 | version = "0.3.76" 2379 | source = "registry+https://github.com/rust-lang/crates.io-index" 2380 | checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" 2381 | dependencies = [ 2382 | "js-sys", 2383 | "wasm-bindgen", 2384 | ] 2385 | 2386 | [[package]] 2387 | name = "winapi-util" 2388 | version = "0.1.9" 2389 | source = "registry+https://github.com/rust-lang/crates.io-index" 2390 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 2391 | dependencies = [ 2392 | "windows-sys 0.59.0", 2393 | ] 2394 | 2395 | [[package]] 2396 | name = "windows-sys" 2397 | version = "0.52.0" 2398 | source = "registry+https://github.com/rust-lang/crates.io-index" 2399 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2400 | dependencies = [ 2401 | "windows-targets", 2402 | ] 2403 | 2404 | [[package]] 2405 | name = "windows-sys" 2406 | version = "0.59.0" 2407 | source = "registry+https://github.com/rust-lang/crates.io-index" 2408 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2409 | dependencies = [ 2410 | "windows-targets", 2411 | ] 2412 | 2413 | [[package]] 2414 | name = "windows-targets" 2415 | version = "0.52.6" 2416 | source = "registry+https://github.com/rust-lang/crates.io-index" 2417 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2418 | dependencies = [ 2419 | "windows_aarch64_gnullvm", 2420 | "windows_aarch64_msvc", 2421 | "windows_i686_gnu", 2422 | "windows_i686_gnullvm", 2423 | "windows_i686_msvc", 2424 | "windows_x86_64_gnu", 2425 | "windows_x86_64_gnullvm", 2426 | "windows_x86_64_msvc", 2427 | ] 2428 | 2429 | [[package]] 2430 | name = "windows_aarch64_gnullvm" 2431 | version = "0.52.6" 2432 | source = "registry+https://github.com/rust-lang/crates.io-index" 2433 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2434 | 2435 | [[package]] 2436 | name = "windows_aarch64_msvc" 2437 | version = "0.52.6" 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" 2439 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2440 | 2441 | [[package]] 2442 | name = "windows_i686_gnu" 2443 | version = "0.52.6" 2444 | source = "registry+https://github.com/rust-lang/crates.io-index" 2445 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2446 | 2447 | [[package]] 2448 | name = "windows_i686_gnullvm" 2449 | version = "0.52.6" 2450 | source = "registry+https://github.com/rust-lang/crates.io-index" 2451 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2452 | 2453 | [[package]] 2454 | name = "windows_i686_msvc" 2455 | version = "0.52.6" 2456 | source = "registry+https://github.com/rust-lang/crates.io-index" 2457 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2458 | 2459 | [[package]] 2460 | name = "windows_x86_64_gnu" 2461 | version = "0.52.6" 2462 | source = "registry+https://github.com/rust-lang/crates.io-index" 2463 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2464 | 2465 | [[package]] 2466 | name = "windows_x86_64_gnullvm" 2467 | version = "0.52.6" 2468 | source = "registry+https://github.com/rust-lang/crates.io-index" 2469 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2470 | 2471 | [[package]] 2472 | name = "windows_x86_64_msvc" 2473 | version = "0.52.6" 2474 | source = "registry+https://github.com/rust-lang/crates.io-index" 2475 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2476 | 2477 | [[package]] 2478 | name = "winnow" 2479 | version = "0.6.24" 2480 | source = "registry+https://github.com/rust-lang/crates.io-index" 2481 | checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" 2482 | dependencies = [ 2483 | "memchr", 2484 | ] 2485 | 2486 | [[package]] 2487 | name = "write16" 2488 | version = "1.0.0" 2489 | source = "registry+https://github.com/rust-lang/crates.io-index" 2490 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 2491 | 2492 | [[package]] 2493 | name = "writeable" 2494 | version = "0.5.5" 2495 | source = "registry+https://github.com/rust-lang/crates.io-index" 2496 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 2497 | 2498 | [[package]] 2499 | name = "xxhash-rust" 2500 | version = "0.8.15" 2501 | source = "registry+https://github.com/rust-lang/crates.io-index" 2502 | checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" 2503 | 2504 | [[package]] 2505 | name = "yansi" 2506 | version = "1.0.1" 2507 | source = "registry+https://github.com/rust-lang/crates.io-index" 2508 | checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" 2509 | 2510 | [[package]] 2511 | name = "yoke" 2512 | version = "0.7.5" 2513 | source = "registry+https://github.com/rust-lang/crates.io-index" 2514 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 2515 | dependencies = [ 2516 | "serde", 2517 | "stable_deref_trait", 2518 | "yoke-derive", 2519 | "zerofrom", 2520 | ] 2521 | 2522 | [[package]] 2523 | name = "yoke-derive" 2524 | version = "0.7.5" 2525 | source = "registry+https://github.com/rust-lang/crates.io-index" 2526 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 2527 | dependencies = [ 2528 | "proc-macro2", 2529 | "quote", 2530 | "syn 2.0.96", 2531 | "synstructure", 2532 | ] 2533 | 2534 | [[package]] 2535 | name = "zerocopy" 2536 | version = "0.7.35" 2537 | source = "registry+https://github.com/rust-lang/crates.io-index" 2538 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 2539 | dependencies = [ 2540 | "zerocopy-derive", 2541 | ] 2542 | 2543 | [[package]] 2544 | name = "zerocopy-derive" 2545 | version = "0.7.35" 2546 | source = "registry+https://github.com/rust-lang/crates.io-index" 2547 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 2548 | dependencies = [ 2549 | "proc-macro2", 2550 | "quote", 2551 | "syn 2.0.96", 2552 | ] 2553 | 2554 | [[package]] 2555 | name = "zerofrom" 2556 | version = "0.1.5" 2557 | source = "registry+https://github.com/rust-lang/crates.io-index" 2558 | checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" 2559 | dependencies = [ 2560 | "zerofrom-derive", 2561 | ] 2562 | 2563 | [[package]] 2564 | name = "zerofrom-derive" 2565 | version = "0.1.5" 2566 | source = "registry+https://github.com/rust-lang/crates.io-index" 2567 | checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" 2568 | dependencies = [ 2569 | "proc-macro2", 2570 | "quote", 2571 | "syn 2.0.96", 2572 | "synstructure", 2573 | ] 2574 | 2575 | [[package]] 2576 | name = "zerovec" 2577 | version = "0.10.4" 2578 | source = "registry+https://github.com/rust-lang/crates.io-index" 2579 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 2580 | dependencies = [ 2581 | "yoke", 2582 | "zerofrom", 2583 | "zerovec-derive", 2584 | ] 2585 | 2586 | [[package]] 2587 | name = "zerovec-derive" 2588 | version = "0.10.3" 2589 | source = "registry+https://github.com/rust-lang/crates.io-index" 2590 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 2591 | dependencies = [ 2592 | "proc-macro2", 2593 | "quote", 2594 | "syn 2.0.96", 2595 | ] 2596 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["leptos_hotkeys", "examples/demo", "examples/ssr-demo"] 3 | resolver = "2" 4 | 5 | [workspace.dependencies] 6 | wasm-bindgen = "0.2" 7 | web-sys = "0.3" 8 | 9 | [profile.wasm-release] 10 | inherits = "release" 11 | opt-level = "z" 12 | lto = true 13 | codegen-units = 1 14 | panic = "abort" 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Matthew Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.toml: -------------------------------------------------------------------------------- 1 | [config] 2 | default_to_workspace = false 3 | 4 | [tasks.lint] 5 | description = "Check format of files and run linters" 6 | run_task = { name = ["lint-rs"] } 7 | 8 | [tasks.lint-rs] 9 | description = "Lint Rust code" 10 | run_task = { name = ["clippy", "cargo-check", "format-check"] } 11 | 12 | [tasks.clippy] 13 | description = "Run clippy" 14 | clear = true 15 | install_crate = "cargo-hack" 16 | command = "cargo" 17 | # TODO: Remove ["-A", "clippy::empty-docs"] when the next issue is resolved: 18 | # https://github.com/leptos-rs/leptos/issues/2406 19 | args = [ 20 | "hack", 21 | "clippy", 22 | "--all", 23 | "--each-feature", 24 | "--no-dev-deps", 25 | "--", 26 | "-A", 27 | "clippy::empty-docs", 28 | "-D", 29 | "clippy::print_stdout" 30 | ] 31 | 32 | [tasks.cargo-check] 33 | description = "Run cargo-check" 34 | clear = true 35 | install_crate = "cargo-hack" 36 | command = "cargo" 37 | args = [ 38 | "hack", 39 | "check", 40 | "--all", 41 | "--each-feature", 42 | "--no-dev-deps", 43 | ] 44 | 45 | [tasks.format-check] 46 | description = "Check Rust code formatting with rustfmt" 47 | install_crate = "rustfmt" 48 | command = "cargo" 49 | args = ["fmt", "--all", "--check"] 50 | 51 | [tasks.format] 52 | clear = true 53 | description = "Format files" 54 | run_task = { name = ["format-rs"] } 55 | 56 | [tasks.format-rs] 57 | description = "Format Rust code with rustfmt" 58 | install_crate = "rustfmt" 59 | command = "cargo" 60 | args = ["fmt", "--all"] 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [_leptos-hotkeys_](https://github.com/gaucho-labs/leptos-hotkeys) 2 | 3 | 4 | [![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-) 5 | 6 | 7 | 8 | Declaratively create and pair keybindings with callbacks for Leptos applications. 9 | 10 | [![Crates.io](https://img.shields.io/crates/v/leptos_hotkeys)](https://crates.io/crates/leptos_hotkeys) 11 | [![discord](https://img.shields.io/badge/Join-Discord-%235865F2.svg)](https://discord.gg/XhVbKk38ux) 12 | 13 | 14 | 15 | A person playing a burning piano at a sandy beach under a cloudy sky 18 | 19 | 20 | 21 | Leptos-hotkeys creates and manages keyboard shortcuts. It provides macros and functions that simplify the definition of 22 | keybindings, since the management of event lifecycle associated with keyboard interactions has been done for you! 23 | 24 | ## Live example 25 | 26 | Curious to see how it works? [See the demo](https://leptos-hotkeys.vercel.app). 27 | 28 | To get started, follow the [Quick Start](#quick-start) section. 29 | 30 | ## Features 31 | 32 | > [!NOTE] 33 | > This crate has three types of hotkeys: global, scoped, and focus-trapped. 34 | 35 | 36 | ### The `use_hotkeys!` Macro 37 | 38 | Use this macro to declare global and scoped hotkeys. This macro has js idioms while preserving Leptos standards. [More about the macro.](](#macro-api).) 39 | 40 | ### Global Hotkeys 41 | 42 | This example creates two global hotkeys: `W` and `F`. 43 | 44 | ```rust 45 | use leptos_hotkeys::use_hotkeys; 46 | 47 | #[component] 48 | pub fn SomeComponent() -> impl IntoView { 49 | let (count, set_count) = create_signal(0); 50 | 51 | // creating a global scope for the W key 52 | use_hotkeys!(("keyw") => move |_| { 53 | logging::log!("w has been pressed"); 54 | set_count.update(|c| *c += 1); 55 | }); 56 | 57 | // this is also a global scope for the F key! 58 | use_hotkeys!(("keyf", "*") => move |_| { 59 | logging::log!("f has been pressed"); 60 | set_count.update(|c| *c -= 1); 61 | }); 62 | 63 | view! {

Num Respects: {count}

} 64 | } 65 | ``` 66 | 67 | > [!TIP] 68 | > How do I write certain keys? See [Key Grammar](#keybinding-grammar). 69 | 70 | > [!NOTE] 71 | > The `*` symbol is reserved for the global scope_. 72 | > 73 | > The `W` hotkey omitted the scope parameter, implicitly making it global. 74 | 75 | ### Scoped Hotkeys 76 | Scopes provide context behind hotkeys. This context can be chained to a component, a state, or logic. 77 | 78 | This example shows an inner and outer scope and hotkeys that toggle scopes. 79 | 80 | ```rust 81 | use leptos_hotkeys::{use_hotkeys, use_hotkeys_context, HotkeysContext}; 82 | 83 | #[component] 84 | pub fn SomeComponent() -> impl IntoView { 85 | 86 | let HotkeysContext { enable_scope, disable_scope, .. } = use_hotkeys_context(); 87 | 88 | // switch into the inner scope 89 | use_hotkeys!(("keyi", "outer") => move |_| { 90 | disable_scope.call("outer".to_string()); 91 | enable_scope.call("inner".to_string()); 92 | }); 93 | 94 | // switch into the outer scope 95 | use_hotkeys!(("keyo", "inner") => move |_| { 96 | disable_scope.call("inner".to_string()); 97 | enable_scope.call("outer".to_string()); 98 | }); 99 | 100 | view! { 101 |
102 | // outer logic residing... 103 |
104 | // inner logic 105 |
106 |
107 | } 108 | } 109 | ``` 110 | 111 | > [!NOTE] 112 | > Scopes are case-insensitive. That means `my_scope` and `mY_sCoPe` are considered the same scope. 113 | 114 | ### Focus trapped Hotkeys (the `use_hotkeys_ref!` macro) 115 | 116 | This example embeds a hotkey to a `

` tag. This hotkey will fire iff the element is focused and the scope is correct. 117 | 118 | ```rust 119 | use leptos_hotkeys::use_hotkeys_ref; 120 | 121 | #[component] 122 | pub fn SomeComponent() -> impl IntoView { 123 | 124 | let p_ref = use_hotkeys_ref!(("keyk", "*") => move |_| { 125 | // some logic 126 | }); 127 | 128 | view! { 129 |

130 | p tag with node ref 131 |

132 | } 133 | } 134 | ``` 135 | 136 | ## Quick Start 137 | 138 | ### Installation 139 | 140 | ```shell 141 | cargo add leptos_hotkeys 142 | ``` 143 | 144 | We also offer other feature flags that enhance developer experience, see [features](#features). 145 | 146 | ### `provide_hotkeys_context()` 147 | 148 | Call `provide_hotkeys_context()` in the `App()` component. This will provide the `HotkeysContext` for the current reactive node and all of its descendents. This function takes three parameters, the `node_ref`, a flag to disable blur events and a list of `initially_active_scopes`. 149 | `provide_hotkeys_context()` returns a `HotkeyContext`. To manage hotkeys, you can pull necessary signals out of `HotkeysContext`. 150 | 151 | ```rust 152 | use leptos_hotkeys::{provide_hotkeys_context, HotkeysContext, scopes}; 153 | 154 | #[component] 155 | pub fn App() -> impl IntoView { 156 | provide_meta_context(); 157 | 158 | let main_ref = create_node_ref::(); 159 | let HotkeysContext { .. } = provide_hotkeys_context(main_ref, false, scopes!()); 160 | 161 | view! { 162 | 163 |
// <-- attach main ref here! 164 | 165 | 166 | 167 | 168 |
169 |
170 | } 171 | } 172 | ``` 173 | 174 | > [!NOTE] 175 | > If you're using [scopes](#scoped-hotkeys), you can initialize with a specific scope. 176 | 177 | ## That's it! [You can create global, scoped, and focus-trapped hotkeys!](#features) 178 | 179 | ### Keybinding Grammar 180 | 181 | `leptos_hotkeys` matches code values from [KeyboardEvent's](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) `code` property. For reference, here's a list of [all code values for keyboard events](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values). 182 | 183 | You can bind multiple hotkeys to a callback. For example: 184 | 185 | ```txt 186 | "KeyG+KeyR,MetaLeft+KeyO,ControlLeft+keyK" 187 | ``` 188 | 189 | Keys are case-agnostic and whitspace-agnostic. For a hotkey with multiple keys, use the `,` as a delimiter in a sequence of keys. 190 | 191 | ### `scopes!()` 192 | 193 | Maybe you want to initialize a certain scope upon load, that's where the prop `initially_active_scopes` comes into play. 194 | Instead of having to create a `vec!["scope_name".to_string()]`, use the `scopes!()` macro. 195 | 196 | ```rust 197 | use leptos_hotkeys::{provide_hotkeys_context, scopes}; 198 | 199 | #[component] 200 | pub fn App() -> impl IntoView { 201 | let main_ref = create_node_ref::(); 202 | provide_hotkeys_context(main_ref, false, scopes!("scope_a", "settings_scope")); 203 | 204 | view! { 205 | 206 |
207 | 208 | // ... routes 209 | 210 |
211 |
212 | } 213 | } 214 | ``` 215 | 216 | ## The `debug` feature flag 217 | 218 | Improve developer experience by introducing the `debug` flag which adds logging to your console in CSR. It logs the current pressed key `code` values, hotkeys fires, and scopes toggling. 219 | 220 | Just simply: 221 | 222 | ```toml 223 | leptos_hotkeys = { path = "0.2.1", features = ["debug"] } 224 | ``` 225 | 226 | ## Contributors 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 |
Álvaro Mondéjar
Álvaro Mondéjar

💻
Robert Junkins
Robert Junkins

💻
LeoniePhiline
LeoniePhiline

📖
Gábor Szabó
Gábor Szabó

📖
Phillip Baird
Phillip Baird

🐛 💻
zakstucke
zakstucke

🐛 💻
Ryangguk Kim
Ryangguk Kim

💻
Max Bergmark
Max Bergmark

💻
Pavlo Myroniuk
Pavlo Myroniuk

💻
247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /examples/demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock/ -------------------------------------------------------------------------------- /examples/demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "demo" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | leptos = { version = "0.6", features = ["csr", "nightly"] } 8 | console_error_panic_hook = "0.1" 9 | console_log = "1" 10 | copy_dir = "0.1" 11 | leptos_meta = "0.6" 12 | leptos_router = { version = "0.6", features = ["csr"] } 13 | log = "0.4" 14 | leptos_hotkeys = { path = "../../leptos_hotkeys", features = [ 15 | "debug", 16 | "use_key", 17 | ] } 18 | -------------------------------------------------------------------------------- /examples/demo/README.md: -------------------------------------------------------------------------------- 1 | # leptos-hotkeys CSR demo 2 | 3 | ```sh 4 | trunk serve --open 5 | ``` 6 | -------------------------------------------------------------------------------- /examples/demo/dist/demo-d350a89f5c90eea4.js: -------------------------------------------------------------------------------- 1 | let wasm; 2 | 3 | const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); 4 | 5 | if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; 6 | 7 | let cachedUint8ArrayMemory0 = null; 8 | 9 | function getUint8ArrayMemory0() { 10 | if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { 11 | cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); 12 | } 13 | return cachedUint8ArrayMemory0; 14 | } 15 | 16 | function getStringFromWasm0(ptr, len) { 17 | ptr = ptr >>> 0; 18 | return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); 19 | } 20 | 21 | const heap = new Array(128).fill(undefined); 22 | 23 | heap.push(undefined, null, true, false); 24 | 25 | let heap_next = heap.length; 26 | 27 | function addHeapObject(obj) { 28 | if (heap_next === heap.length) heap.push(heap.length + 1); 29 | const idx = heap_next; 30 | heap_next = heap[idx]; 31 | 32 | heap[idx] = obj; 33 | return idx; 34 | } 35 | 36 | function getObject(idx) { return heap[idx]; } 37 | 38 | function dropObject(idx) { 39 | if (idx < 132) return; 40 | heap[idx] = heap_next; 41 | heap_next = idx; 42 | } 43 | 44 | function takeObject(idx) { 45 | const ret = getObject(idx); 46 | dropObject(idx); 47 | return ret; 48 | } 49 | 50 | function isLikeNone(x) { 51 | return x === undefined || x === null; 52 | } 53 | 54 | let cachedDataViewMemory0 = null; 55 | 56 | function getDataViewMemory0() { 57 | if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { 58 | cachedDataViewMemory0 = new DataView(wasm.memory.buffer); 59 | } 60 | return cachedDataViewMemory0; 61 | } 62 | 63 | let WASM_VECTOR_LEN = 0; 64 | 65 | const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); 66 | 67 | const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' 68 | ? function (arg, view) { 69 | return cachedTextEncoder.encodeInto(arg, view); 70 | } 71 | : function (arg, view) { 72 | const buf = cachedTextEncoder.encode(arg); 73 | view.set(buf); 74 | return { 75 | read: arg.length, 76 | written: buf.length 77 | }; 78 | }); 79 | 80 | function passStringToWasm0(arg, malloc, realloc) { 81 | 82 | if (realloc === undefined) { 83 | const buf = cachedTextEncoder.encode(arg); 84 | const ptr = malloc(buf.length, 1) >>> 0; 85 | getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); 86 | WASM_VECTOR_LEN = buf.length; 87 | return ptr; 88 | } 89 | 90 | let len = arg.length; 91 | let ptr = malloc(len, 1) >>> 0; 92 | 93 | const mem = getUint8ArrayMemory0(); 94 | 95 | let offset = 0; 96 | 97 | for (; offset < len; offset++) { 98 | const code = arg.charCodeAt(offset); 99 | if (code > 0x7F) break; 100 | mem[ptr + offset] = code; 101 | } 102 | 103 | if (offset !== len) { 104 | if (offset !== 0) { 105 | arg = arg.slice(offset); 106 | } 107 | ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; 108 | const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); 109 | const ret = encodeString(arg, view); 110 | 111 | offset += ret.written; 112 | ptr = realloc(ptr, len, offset, 1) >>> 0; 113 | } 114 | 115 | WASM_VECTOR_LEN = offset; 116 | return ptr; 117 | } 118 | 119 | function debugString(val) { 120 | // primitive types 121 | const type = typeof val; 122 | if (type == 'number' || type == 'boolean' || val == null) { 123 | return `${val}`; 124 | } 125 | if (type == 'string') { 126 | return `"${val}"`; 127 | } 128 | if (type == 'symbol') { 129 | const description = val.description; 130 | if (description == null) { 131 | return 'Symbol'; 132 | } else { 133 | return `Symbol(${description})`; 134 | } 135 | } 136 | if (type == 'function') { 137 | const name = val.name; 138 | if (typeof name == 'string' && name.length > 0) { 139 | return `Function(${name})`; 140 | } else { 141 | return 'Function'; 142 | } 143 | } 144 | // objects 145 | if (Array.isArray(val)) { 146 | const length = val.length; 147 | let debug = '['; 148 | if (length > 0) { 149 | debug += debugString(val[0]); 150 | } 151 | for(let i = 1; i < length; i++) { 152 | debug += ', ' + debugString(val[i]); 153 | } 154 | debug += ']'; 155 | return debug; 156 | } 157 | // Test for built-in 158 | const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); 159 | let className; 160 | if (builtInMatches.length > 1) { 161 | className = builtInMatches[1]; 162 | } else { 163 | // Failed to match the standard '[object ClassName]' 164 | return toString.call(val); 165 | } 166 | if (className == 'Object') { 167 | // we're a user defined class or Object 168 | // JSON.stringify avoids problems with cycles, and is generally much 169 | // easier than looping through ownProperties of `val`. 170 | try { 171 | return 'Object(' + JSON.stringify(val) + ')'; 172 | } catch (_) { 173 | return 'Object'; 174 | } 175 | } 176 | // errors 177 | if (val instanceof Error) { 178 | return `${val.name}: ${val.message}\n${val.stack}`; 179 | } 180 | // TODO we could test for more things here, like `Set`s and `Map`s. 181 | return className; 182 | } 183 | 184 | const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') 185 | ? { register: () => {}, unregister: () => {} } 186 | : new FinalizationRegistry(state => { 187 | wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b) 188 | }); 189 | 190 | function makeMutClosure(arg0, arg1, dtor, f) { 191 | const state = { a: arg0, b: arg1, cnt: 1, dtor }; 192 | const real = (...args) => { 193 | // First up with a closure we increment the internal reference 194 | // count. This ensures that the Rust closure environment won't 195 | // be deallocated while we're invoking it. 196 | state.cnt++; 197 | const a = state.a; 198 | state.a = 0; 199 | try { 200 | return f(a, state.b, ...args); 201 | } finally { 202 | if (--state.cnt === 0) { 203 | wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); 204 | CLOSURE_DTORS.unregister(state); 205 | } else { 206 | state.a = a; 207 | } 208 | } 209 | }; 210 | real.original = state; 211 | CLOSURE_DTORS.register(real, state, state); 212 | return real; 213 | } 214 | function __wbg_adapter_38(arg0, arg1, arg2) { 215 | wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hdda730a5c18a7d7f(arg0, arg1, addHeapObject(arg2)); 216 | } 217 | 218 | function makeClosure(arg0, arg1, dtor, f) { 219 | const state = { a: arg0, b: arg1, cnt: 1, dtor }; 220 | const real = (...args) => { 221 | // First up with a closure we increment the internal reference 222 | // count. This ensures that the Rust closure environment won't 223 | // be deallocated while we're invoking it. 224 | state.cnt++; 225 | try { 226 | return f(state.a, state.b, ...args); 227 | } finally { 228 | if (--state.cnt === 0) { 229 | wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b); 230 | state.a = 0; 231 | CLOSURE_DTORS.unregister(state); 232 | } 233 | } 234 | }; 235 | real.original = state; 236 | CLOSURE_DTORS.register(real, state, state); 237 | return real; 238 | } 239 | function __wbg_adapter_41(arg0, arg1, arg2) { 240 | wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h64e8acc7146d060c(arg0, arg1, addHeapObject(arg2)); 241 | } 242 | 243 | function __wbg_adapter_44(arg0, arg1) { 244 | wasm._dyn_core__ops__function__Fn_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h2ba0875584c37f8b(arg0, arg1); 245 | } 246 | 247 | function __wbg_adapter_47(arg0, arg1, arg2) { 248 | wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__he2572c33aea36833(arg0, arg1, addHeapObject(arg2)); 249 | } 250 | 251 | function __wbg_adapter_50(arg0, arg1) { 252 | wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb99ea04cec5f73e1(arg0, arg1); 253 | } 254 | 255 | function __wbg_adapter_53(arg0, arg1, arg2) { 256 | wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h06e8f121564574c4(arg0, arg1, addHeapObject(arg2)); 257 | } 258 | 259 | function getCachedStringFromWasm0(ptr, len) { 260 | if (ptr === 0) { 261 | return getObject(len); 262 | } else { 263 | return getStringFromWasm0(ptr, len); 264 | } 265 | } 266 | 267 | function handleError(f, args) { 268 | try { 269 | return f.apply(this, args); 270 | } catch (e) { 271 | wasm.__wbindgen_exn_store(addHeapObject(e)); 272 | } 273 | } 274 | function __wbg_adapter_270(arg0, arg1, arg2, arg3) { 275 | wasm.wasm_bindgen__convert__closures__invoke2_mut__h1b8e136d78587ed3(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); 276 | } 277 | 278 | const IntoUnderlyingByteSourceFinalization = (typeof FinalizationRegistry === 'undefined') 279 | ? { register: () => {}, unregister: () => {} } 280 | : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingbytesource_free(ptr >>> 0, 1)); 281 | /** 282 | */ 283 | export class IntoUnderlyingByteSource { 284 | 285 | __destroy_into_raw() { 286 | const ptr = this.__wbg_ptr; 287 | this.__wbg_ptr = 0; 288 | IntoUnderlyingByteSourceFinalization.unregister(this); 289 | return ptr; 290 | } 291 | 292 | free() { 293 | const ptr = this.__destroy_into_raw(); 294 | wasm.__wbg_intounderlyingbytesource_free(ptr, 0); 295 | } 296 | /** 297 | * @returns {string} 298 | */ 299 | get type() { 300 | try { 301 | const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); 302 | wasm.intounderlyingbytesource_type(retptr, this.__wbg_ptr); 303 | var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); 304 | var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); 305 | var v1 = getCachedStringFromWasm0(r0, r1); 306 | if (r0 !== 0) { wasm.__wbindgen_free(r0, r1, 1); } 307 | return v1; 308 | } finally { 309 | wasm.__wbindgen_add_to_stack_pointer(16); 310 | } 311 | } 312 | /** 313 | * @returns {number} 314 | */ 315 | get autoAllocateChunkSize() { 316 | const ret = wasm.intounderlyingbytesource_autoAllocateChunkSize(this.__wbg_ptr); 317 | return ret >>> 0; 318 | } 319 | /** 320 | * @param {ReadableByteStreamController} controller 321 | */ 322 | start(controller) { 323 | wasm.intounderlyingbytesource_start(this.__wbg_ptr, addHeapObject(controller)); 324 | } 325 | /** 326 | * @param {ReadableByteStreamController} controller 327 | * @returns {Promise} 328 | */ 329 | pull(controller) { 330 | const ret = wasm.intounderlyingbytesource_pull(this.__wbg_ptr, addHeapObject(controller)); 331 | return takeObject(ret); 332 | } 333 | /** 334 | */ 335 | cancel() { 336 | const ptr = this.__destroy_into_raw(); 337 | wasm.intounderlyingbytesource_cancel(ptr); 338 | } 339 | } 340 | 341 | const IntoUnderlyingSinkFinalization = (typeof FinalizationRegistry === 'undefined') 342 | ? { register: () => {}, unregister: () => {} } 343 | : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingsink_free(ptr >>> 0, 1)); 344 | /** 345 | */ 346 | export class IntoUnderlyingSink { 347 | 348 | __destroy_into_raw() { 349 | const ptr = this.__wbg_ptr; 350 | this.__wbg_ptr = 0; 351 | IntoUnderlyingSinkFinalization.unregister(this); 352 | return ptr; 353 | } 354 | 355 | free() { 356 | const ptr = this.__destroy_into_raw(); 357 | wasm.__wbg_intounderlyingsink_free(ptr, 0); 358 | } 359 | /** 360 | * @param {any} chunk 361 | * @returns {Promise} 362 | */ 363 | write(chunk) { 364 | const ret = wasm.intounderlyingsink_write(this.__wbg_ptr, addHeapObject(chunk)); 365 | return takeObject(ret); 366 | } 367 | /** 368 | * @returns {Promise} 369 | */ 370 | close() { 371 | const ptr = this.__destroy_into_raw(); 372 | const ret = wasm.intounderlyingsink_close(ptr); 373 | return takeObject(ret); 374 | } 375 | /** 376 | * @param {any} reason 377 | * @returns {Promise} 378 | */ 379 | abort(reason) { 380 | const ptr = this.__destroy_into_raw(); 381 | const ret = wasm.intounderlyingsink_abort(ptr, addHeapObject(reason)); 382 | return takeObject(ret); 383 | } 384 | } 385 | 386 | const IntoUnderlyingSourceFinalization = (typeof FinalizationRegistry === 'undefined') 387 | ? { register: () => {}, unregister: () => {} } 388 | : new FinalizationRegistry(ptr => wasm.__wbg_intounderlyingsource_free(ptr >>> 0, 1)); 389 | /** 390 | */ 391 | export class IntoUnderlyingSource { 392 | 393 | __destroy_into_raw() { 394 | const ptr = this.__wbg_ptr; 395 | this.__wbg_ptr = 0; 396 | IntoUnderlyingSourceFinalization.unregister(this); 397 | return ptr; 398 | } 399 | 400 | free() { 401 | const ptr = this.__destroy_into_raw(); 402 | wasm.__wbg_intounderlyingsource_free(ptr, 0); 403 | } 404 | /** 405 | * @param {ReadableStreamDefaultController} controller 406 | * @returns {Promise} 407 | */ 408 | pull(controller) { 409 | const ret = wasm.intounderlyingsource_pull(this.__wbg_ptr, addHeapObject(controller)); 410 | return takeObject(ret); 411 | } 412 | /** 413 | */ 414 | cancel() { 415 | const ptr = this.__destroy_into_raw(); 416 | wasm.intounderlyingsource_cancel(ptr); 417 | } 418 | } 419 | 420 | async function __wbg_load(module, imports) { 421 | if (typeof Response === 'function' && module instanceof Response) { 422 | if (typeof WebAssembly.instantiateStreaming === 'function') { 423 | try { 424 | return await WebAssembly.instantiateStreaming(module, imports); 425 | 426 | } catch (e) { 427 | if (module.headers.get('Content-Type') != 'application/wasm') { 428 | console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); 429 | 430 | } else { 431 | throw e; 432 | } 433 | } 434 | } 435 | 436 | const bytes = await module.arrayBuffer(); 437 | return await WebAssembly.instantiate(bytes, imports); 438 | 439 | } else { 440 | const instance = await WebAssembly.instantiate(module, imports); 441 | 442 | if (instance instanceof WebAssembly.Instance) { 443 | return { instance, module }; 444 | 445 | } else { 446 | return instance; 447 | } 448 | } 449 | } 450 | 451 | function __wbg_get_imports() { 452 | const imports = {}; 453 | imports.wbg = {}; 454 | imports.wbg.__wbindgen_string_new = function(arg0, arg1) { 455 | const ret = getStringFromWasm0(arg0, arg1); 456 | return addHeapObject(ret); 457 | }; 458 | imports.wbg.__wbindgen_object_clone_ref = function(arg0) { 459 | const ret = getObject(arg0); 460 | return addHeapObject(ret); 461 | }; 462 | imports.wbg.__wbindgen_cb_drop = function(arg0) { 463 | const obj = takeObject(arg0).original; 464 | if (obj.cnt-- == 1) { 465 | obj.a = 0; 466 | return true; 467 | } 468 | const ret = false; 469 | return ret; 470 | }; 471 | imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { 472 | var v0 = getCachedStringFromWasm0(arg0, arg1); 473 | if (arg0 !== 0) { wasm.__wbindgen_free(arg0, arg1, 1); } 474 | console.error(v0); 475 | }; 476 | imports.wbg.__wbg_new_abda76e883ba8a5f = function() { 477 | const ret = new Error(); 478 | return addHeapObject(ret); 479 | }; 480 | imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { 481 | const ret = getObject(arg1).stack; 482 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 483 | const len1 = WASM_VECTOR_LEN; 484 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 485 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 486 | }; 487 | imports.wbg.__wbindgen_is_undefined = function(arg0) { 488 | const ret = getObject(arg0) === undefined; 489 | return ret; 490 | }; 491 | imports.wbg.__wbindgen_number_get = function(arg0, arg1) { 492 | const obj = getObject(arg1); 493 | const ret = typeof(obj) === 'number' ? obj : undefined; 494 | getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true); 495 | getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true); 496 | }; 497 | imports.wbg.__wbindgen_boolean_get = function(arg0) { 498 | const v = getObject(arg0); 499 | const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; 500 | return ret; 501 | }; 502 | imports.wbg.__wbindgen_is_null = function(arg0) { 503 | const ret = getObject(arg0) === null; 504 | return ret; 505 | }; 506 | imports.wbg.__wbindgen_string_get = function(arg0, arg1) { 507 | const obj = getObject(arg1); 508 | const ret = typeof(obj) === 'string' ? obj : undefined; 509 | var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 510 | var len1 = WASM_VECTOR_LEN; 511 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 512 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 513 | }; 514 | imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) { 515 | const ret = getObject(arg0) === getObject(arg1); 516 | return ret; 517 | }; 518 | imports.wbg.__wbindgen_is_falsy = function(arg0) { 519 | const ret = !getObject(arg0); 520 | return ret; 521 | }; 522 | imports.wbg.__wbg_instanceof_Window_5012736c80a01584 = function(arg0) { 523 | let result; 524 | try { 525 | result = getObject(arg0) instanceof Window; 526 | } catch (_) { 527 | result = false; 528 | } 529 | const ret = result; 530 | return ret; 531 | }; 532 | imports.wbg.__wbg_document_8554450897a855b9 = function(arg0) { 533 | const ret = getObject(arg0).document; 534 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 535 | }; 536 | imports.wbg.__wbg_location_af118da6c50d4c3f = function(arg0) { 537 | const ret = getObject(arg0).location; 538 | return addHeapObject(ret); 539 | }; 540 | imports.wbg.__wbg_history_489e13d0b625263c = function() { return handleError(function (arg0) { 541 | const ret = getObject(arg0).history; 542 | return addHeapObject(ret); 543 | }, arguments) }; 544 | imports.wbg.__wbg_scrollTo_19dc1dbbc8c19fa8 = function(arg0, arg1, arg2) { 545 | getObject(arg0).scrollTo(arg1, arg2); 546 | }; 547 | imports.wbg.__wbg_requestAnimationFrame_b4b782250b9c2c88 = function() { return handleError(function (arg0, arg1) { 548 | const ret = getObject(arg0).requestAnimationFrame(getObject(arg1)); 549 | return ret; 550 | }, arguments) }; 551 | imports.wbg.__wbg_body_b3bb488e8e54bf4b = function(arg0) { 552 | const ret = getObject(arg0).body; 553 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 554 | }; 555 | imports.wbg.__wbg_createComment_7a1d9856e50567bb = function(arg0, arg1, arg2) { 556 | var v0 = getCachedStringFromWasm0(arg1, arg2); 557 | const ret = getObject(arg0).createComment(v0); 558 | return addHeapObject(ret); 559 | }; 560 | imports.wbg.__wbg_createDocumentFragment_5d919bd9d2e05b55 = function(arg0) { 561 | const ret = getObject(arg0).createDocumentFragment(); 562 | return addHeapObject(ret); 563 | }; 564 | imports.wbg.__wbg_createElement_5921e9eb06b9ec89 = function() { return handleError(function (arg0, arg1, arg2) { 565 | var v0 = getCachedStringFromWasm0(arg1, arg2); 566 | const ret = getObject(arg0).createElement(v0); 567 | return addHeapObject(ret); 568 | }, arguments) }; 569 | imports.wbg.__wbg_createTextNode_8bce33cf33bf8f6e = function(arg0, arg1, arg2) { 570 | var v0 = getCachedStringFromWasm0(arg1, arg2); 571 | const ret = getObject(arg0).createTextNode(v0); 572 | return addHeapObject(ret); 573 | }; 574 | imports.wbg.__wbg_getElementById_f56c8e6a15a6926d = function(arg0, arg1, arg2) { 575 | var v0 = getCachedStringFromWasm0(arg1, arg2); 576 | const ret = getObject(arg0).getElementById(v0); 577 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 578 | }; 579 | imports.wbg.__wbg_namespaceURI_d27c7f3638dd2926 = function(arg0, arg1) { 580 | const ret = getObject(arg1).namespaceURI; 581 | var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 582 | var len1 = WASM_VECTOR_LEN; 583 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 584 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 585 | }; 586 | imports.wbg.__wbg_classList_d725bcb3b32c27b5 = function(arg0) { 587 | const ret = getObject(arg0).classList; 588 | return addHeapObject(ret); 589 | }; 590 | imports.wbg.__wbg_setinnerHTML_ea7e3c6a3c4790c6 = function(arg0, arg1, arg2) { 591 | var v0 = getCachedStringFromWasm0(arg1, arg2); 592 | getObject(arg0).innerHTML = v0; 593 | }; 594 | imports.wbg.__wbg_outerHTML_463e1461b3d153ca = function(arg0, arg1) { 595 | const ret = getObject(arg1).outerHTML; 596 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 597 | const len1 = WASM_VECTOR_LEN; 598 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 599 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 600 | }; 601 | imports.wbg.__wbg_getAttribute_e867e037f066c410 = function(arg0, arg1, arg2, arg3) { 602 | var v0 = getCachedStringFromWasm0(arg2, arg3); 603 | const ret = getObject(arg1).getAttribute(v0); 604 | var ptr2 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 605 | var len2 = WASM_VECTOR_LEN; 606 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len2, true); 607 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr2, true); 608 | }; 609 | imports.wbg.__wbg_hasAttribute_a17d49194d050f19 = function(arg0, arg1, arg2) { 610 | var v0 = getCachedStringFromWasm0(arg1, arg2); 611 | const ret = getObject(arg0).hasAttribute(v0); 612 | return ret; 613 | }; 614 | imports.wbg.__wbg_removeAttribute_c80e298b60689065 = function() { return handleError(function (arg0, arg1, arg2) { 615 | var v0 = getCachedStringFromWasm0(arg1, arg2); 616 | getObject(arg0).removeAttribute(v0); 617 | }, arguments) }; 618 | imports.wbg.__wbg_scrollIntoView_4b805e2532108e71 = function(arg0) { 619 | getObject(arg0).scrollIntoView(); 620 | }; 621 | imports.wbg.__wbg_setAttribute_d5540a19be09f8dc = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { 622 | var v0 = getCachedStringFromWasm0(arg1, arg2); 623 | var v1 = getCachedStringFromWasm0(arg3, arg4); 624 | getObject(arg0).setAttribute(v0, v1); 625 | }, arguments) }; 626 | imports.wbg.__wbg_before_ac3792b457802cbf = function() { return handleError(function (arg0, arg1) { 627 | getObject(arg0).before(getObject(arg1)); 628 | }, arguments) }; 629 | imports.wbg.__wbg_remove_5b68b70c39041e2a = function(arg0) { 630 | getObject(arg0).remove(); 631 | }; 632 | imports.wbg.__wbg_append_22299f1011b1f9d7 = function() { return handleError(function (arg0, arg1, arg2) { 633 | getObject(arg0).append(getObject(arg1), getObject(arg2)); 634 | }, arguments) }; 635 | imports.wbg.__wbg_view_2a901bda0727aeb3 = function(arg0) { 636 | const ret = getObject(arg0).view; 637 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 638 | }; 639 | imports.wbg.__wbg_respond_a799bab31a44f2d7 = function() { return handleError(function (arg0, arg1) { 640 | getObject(arg0).respond(arg1 >>> 0); 641 | }, arguments) }; 642 | imports.wbg.__wbg_instanceof_ShadowRoot_72d8e783f8e0093c = function(arg0) { 643 | let result; 644 | try { 645 | result = getObject(arg0) instanceof ShadowRoot; 646 | } catch (_) { 647 | result = false; 648 | } 649 | const ret = result; 650 | return ret; 651 | }; 652 | imports.wbg.__wbg_host_fdfe1258b06fe937 = function(arg0) { 653 | const ret = getObject(arg0).host; 654 | return addHeapObject(ret); 655 | }; 656 | imports.wbg.__wbg_state_b863826253700666 = function() { return handleError(function (arg0) { 657 | const ret = getObject(arg0).state; 658 | return addHeapObject(ret); 659 | }, arguments) }; 660 | imports.wbg.__wbg_pushState_fc8b2d0c45854901 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { 661 | var v0 = getCachedStringFromWasm0(arg2, arg3); 662 | var v1 = getCachedStringFromWasm0(arg4, arg5); 663 | getObject(arg0).pushState(getObject(arg1), v0, v1); 664 | }, arguments) }; 665 | imports.wbg.__wbg_replaceState_c3213575ed65bac2 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { 666 | var v0 = getCachedStringFromWasm0(arg2, arg3); 667 | var v1 = getCachedStringFromWasm0(arg4, arg5); 668 | getObject(arg0).replaceState(getObject(arg1), v0, v1); 669 | }, arguments) }; 670 | imports.wbg.__wbg_instanceof_HtmlAnchorElement_7a88f0b97085fa30 = function(arg0) { 671 | let result; 672 | try { 673 | result = getObject(arg0) instanceof HTMLAnchorElement; 674 | } catch (_) { 675 | result = false; 676 | } 677 | const ret = result; 678 | return ret; 679 | }; 680 | imports.wbg.__wbg_target_fed794e9a6ed73fe = function(arg0, arg1) { 681 | const ret = getObject(arg1).target; 682 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 683 | const len1 = WASM_VECTOR_LEN; 684 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 685 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 686 | }; 687 | imports.wbg.__wbg_href_31456ceb26f92368 = function(arg0, arg1) { 688 | const ret = getObject(arg1).href; 689 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 690 | const len1 = WASM_VECTOR_LEN; 691 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 692 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 693 | }; 694 | imports.wbg.__wbg_close_cef2400b120c9c73 = function() { return handleError(function (arg0) { 695 | getObject(arg0).close(); 696 | }, arguments) }; 697 | imports.wbg.__wbg_enqueue_6f3d433b5e457aea = function() { return handleError(function (arg0, arg1) { 698 | getObject(arg0).enqueue(getObject(arg1)); 699 | }, arguments) }; 700 | imports.wbg.__wbg_debug_5a33c41aeac15ee6 = function(arg0) { 701 | console.debug(getObject(arg0)); 702 | }; 703 | imports.wbg.__wbg_error_09480e4aadca50ad = function(arg0) { 704 | console.error(getObject(arg0)); 705 | }; 706 | imports.wbg.__wbg_info_c261acb2deacd903 = function(arg0) { 707 | console.info(getObject(arg0)); 708 | }; 709 | imports.wbg.__wbg_log_b103404cc5920657 = function(arg0) { 710 | console.log(getObject(arg0)); 711 | }; 712 | imports.wbg.__wbg_log_59354cb765a05b18 = function(arg0, arg1) { 713 | console.log(getObject(arg0), getObject(arg1)); 714 | }; 715 | imports.wbg.__wbg_warn_2b3adb99ce26c314 = function(arg0) { 716 | console.warn(getObject(arg0)); 717 | }; 718 | imports.wbg.__wbg_byobRequest_b32c77640da946ac = function(arg0) { 719 | const ret = getObject(arg0).byobRequest; 720 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 721 | }; 722 | imports.wbg.__wbg_close_aca7442e6619206b = function() { return handleError(function (arg0) { 723 | getObject(arg0).close(); 724 | }, arguments) }; 725 | imports.wbg.__wbg_sethref_9d76f6c9356e9638 = function() { return handleError(function (arg0, arg1, arg2) { 726 | var v0 = getCachedStringFromWasm0(arg1, arg2); 727 | getObject(arg0).href = v0; 728 | }, arguments) }; 729 | imports.wbg.__wbg_origin_648082c4831a5be8 = function() { return handleError(function (arg0, arg1) { 730 | const ret = getObject(arg1).origin; 731 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 732 | const len1 = WASM_VECTOR_LEN; 733 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 734 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 735 | }, arguments) }; 736 | imports.wbg.__wbg_pathname_6e6871539b48a0e5 = function() { return handleError(function (arg0, arg1) { 737 | const ret = getObject(arg1).pathname; 738 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 739 | const len1 = WASM_VECTOR_LEN; 740 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 741 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 742 | }, arguments) }; 743 | imports.wbg.__wbg_search_20c15d493b8602c5 = function() { return handleError(function (arg0, arg1) { 744 | const ret = getObject(arg1).search; 745 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 746 | const len1 = WASM_VECTOR_LEN; 747 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 748 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 749 | }, arguments) }; 750 | imports.wbg.__wbg_hash_313d7fdf42f6e7d3 = function() { return handleError(function (arg0, arg1) { 751 | const ret = getObject(arg1).hash; 752 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 753 | const len1 = WASM_VECTOR_LEN; 754 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 755 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 756 | }, arguments) }; 757 | imports.wbg.__wbg_ctrlKey_957c6c31b62b4550 = function(arg0) { 758 | const ret = getObject(arg0).ctrlKey; 759 | return ret; 760 | }; 761 | imports.wbg.__wbg_shiftKey_8c0f9a5ca3ff8f93 = function(arg0) { 762 | const ret = getObject(arg0).shiftKey; 763 | return ret; 764 | }; 765 | imports.wbg.__wbg_altKey_d3fbce7596aac8cf = function(arg0) { 766 | const ret = getObject(arg0).altKey; 767 | return ret; 768 | }; 769 | imports.wbg.__wbg_metaKey_be0158b14b1cef4a = function(arg0) { 770 | const ret = getObject(arg0).metaKey; 771 | return ret; 772 | }; 773 | imports.wbg.__wbg_button_460cdec9f2512a91 = function(arg0) { 774 | const ret = getObject(arg0).button; 775 | return ret; 776 | }; 777 | imports.wbg.__wbg_href_f1d20018a97415a0 = function(arg0, arg1) { 778 | const ret = getObject(arg1).href; 779 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 780 | const len1 = WASM_VECTOR_LEN; 781 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 782 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 783 | }; 784 | imports.wbg.__wbg_origin_b1cdab9cfa04b734 = function(arg0, arg1) { 785 | const ret = getObject(arg1).origin; 786 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 787 | const len1 = WASM_VECTOR_LEN; 788 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 789 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 790 | }; 791 | imports.wbg.__wbg_pathname_adec1eb7f76356a8 = function(arg0, arg1) { 792 | const ret = getObject(arg1).pathname; 793 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 794 | const len1 = WASM_VECTOR_LEN; 795 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 796 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 797 | }; 798 | imports.wbg.__wbg_search_f384756d8e27fd66 = function(arg0, arg1) { 799 | const ret = getObject(arg1).search; 800 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 801 | const len1 = WASM_VECTOR_LEN; 802 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 803 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 804 | }; 805 | imports.wbg.__wbg_searchParams_8b40e0942f870b44 = function(arg0) { 806 | const ret = getObject(arg0).searchParams; 807 | return addHeapObject(ret); 808 | }; 809 | imports.wbg.__wbg_hash_50828fbc16613897 = function(arg0, arg1) { 810 | const ret = getObject(arg1).hash; 811 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 812 | const len1 = WASM_VECTOR_LEN; 813 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 814 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 815 | }; 816 | imports.wbg.__wbg_newwithbase_ba5e3790a41efd02 = function() { return handleError(function (arg0, arg1, arg2, arg3) { 817 | var v0 = getCachedStringFromWasm0(arg0, arg1); 818 | var v1 = getCachedStringFromWasm0(arg2, arg3); 819 | const ret = new URL(v0, v1); 820 | return addHeapObject(ret); 821 | }, arguments) }; 822 | imports.wbg.__wbg_setdata_27c6828c5a5a5ce4 = function(arg0, arg1, arg2) { 823 | var v0 = getCachedStringFromWasm0(arg1, arg2); 824 | getObject(arg0).data = v0; 825 | }; 826 | imports.wbg.__wbg_parentNode_3e06cf96d7693d57 = function(arg0) { 827 | const ret = getObject(arg0).parentNode; 828 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 829 | }; 830 | imports.wbg.__wbg_childNodes_031aa96d5e3d21b0 = function(arg0) { 831 | const ret = getObject(arg0).childNodes; 832 | return addHeapObject(ret); 833 | }; 834 | imports.wbg.__wbg_previousSibling_076df2178284ef97 = function(arg0) { 835 | const ret = getObject(arg0).previousSibling; 836 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 837 | }; 838 | imports.wbg.__wbg_nextSibling_f6396d6fd0b97830 = function(arg0) { 839 | const ret = getObject(arg0).nextSibling; 840 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 841 | }; 842 | imports.wbg.__wbg_textContent_a049d1ce093c3d21 = function(arg0, arg1) { 843 | const ret = getObject(arg1).textContent; 844 | var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 845 | var len1 = WASM_VECTOR_LEN; 846 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 847 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 848 | }; 849 | imports.wbg.__wbg_settextContent_cd38ea7d4e0f7260 = function(arg0, arg1, arg2) { 850 | var v0 = getCachedStringFromWasm0(arg1, arg2); 851 | getObject(arg0).textContent = v0; 852 | }; 853 | imports.wbg.__wbg_appendChild_ac45d1abddf1b89b = function() { return handleError(function (arg0, arg1) { 854 | const ret = getObject(arg0).appendChild(getObject(arg1)); 855 | return addHeapObject(ret); 856 | }, arguments) }; 857 | imports.wbg.__wbg_cloneNode_629a1b180e91c467 = function() { return handleError(function (arg0) { 858 | const ret = getObject(arg0).cloneNode(); 859 | return addHeapObject(ret); 860 | }, arguments) }; 861 | imports.wbg.__wbg_length_4919f4a62b9b1e94 = function(arg0) { 862 | const ret = getObject(arg0).length; 863 | return ret; 864 | }; 865 | imports.wbg.__wbg_key_a626396efbca2b95 = function(arg0, arg1) { 866 | const ret = getObject(arg1).key; 867 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 868 | const len1 = WASM_VECTOR_LEN; 869 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 870 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 871 | }; 872 | imports.wbg.__wbg_add_e210e3b838bff57f = function() { return handleError(function (arg0, arg1, arg2) { 873 | var v0 = getCachedStringFromWasm0(arg1, arg2); 874 | getObject(arg0).add(v0); 875 | }, arguments) }; 876 | imports.wbg.__wbg_remove_0dd2beafdaa4d9ba = function() { return handleError(function (arg0, arg1, arg2) { 877 | var v0 = getCachedStringFromWasm0(arg1, arg2); 878 | getObject(arg0).remove(v0); 879 | }, arguments) }; 880 | imports.wbg.__wbg_target_b7cb1739bee70928 = function(arg0) { 881 | const ret = getObject(arg0).target; 882 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 883 | }; 884 | imports.wbg.__wbg_defaultPrevented_9e2309e82258aee7 = function(arg0) { 885 | const ret = getObject(arg0).defaultPrevented; 886 | return ret; 887 | }; 888 | imports.wbg.__wbg_cancelBubble_0374b329f66f59b5 = function(arg0) { 889 | const ret = getObject(arg0).cancelBubble; 890 | return ret; 891 | }; 892 | imports.wbg.__wbg_composedPath_d1052062308beae5 = function(arg0) { 893 | const ret = getObject(arg0).composedPath(); 894 | return addHeapObject(ret); 895 | }; 896 | imports.wbg.__wbg_preventDefault_c55d86c27b2dfa6e = function(arg0) { 897 | getObject(arg0).preventDefault(); 898 | }; 899 | imports.wbg.__wbg_addEventListener_e167f012cbedfa4e = function() { return handleError(function (arg0, arg1, arg2, arg3) { 900 | var v0 = getCachedStringFromWasm0(arg1, arg2); 901 | getObject(arg0).addEventListener(v0, getObject(arg3)); 902 | }, arguments) }; 903 | imports.wbg.__wbg_addEventListener_14b036ff7cb8747c = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { 904 | var v0 = getCachedStringFromWasm0(arg1, arg2); 905 | getObject(arg0).addEventListener(v0, getObject(arg3), getObject(arg4)); 906 | }, arguments) }; 907 | imports.wbg.__wbg_removeEventListener_b6cef5ad085bea8f = function() { return handleError(function (arg0, arg1, arg2, arg3) { 908 | var v0 = getCachedStringFromWasm0(arg1, arg2); 909 | getObject(arg0).removeEventListener(v0, getObject(arg3)); 910 | }, arguments) }; 911 | imports.wbg.__wbindgen_is_function = function(arg0) { 912 | const ret = typeof(getObject(arg0)) === 'function'; 913 | return ret; 914 | }; 915 | imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4 = function(arg0) { 916 | queueMicrotask(getObject(arg0)); 917 | }; 918 | imports.wbg.__wbg_queueMicrotask_3cbae2ec6b6cd3d6 = function(arg0) { 919 | const ret = getObject(arg0).queueMicrotask; 920 | return addHeapObject(ret); 921 | }; 922 | imports.wbg.__wbg_decodeURI_27d956972029c70b = function() { return handleError(function (arg0, arg1) { 923 | var v0 = getCachedStringFromWasm0(arg0, arg1); 924 | const ret = decodeURI(v0); 925 | return addHeapObject(ret); 926 | }, arguments) }; 927 | imports.wbg.__wbg_get_3baa728f9d58d3f6 = function(arg0, arg1) { 928 | const ret = getObject(arg0)[arg1 >>> 0]; 929 | return addHeapObject(ret); 930 | }; 931 | imports.wbg.__wbg_isArray_8364a5371e9737d8 = function(arg0) { 932 | const ret = Array.isArray(getObject(arg0)); 933 | return ret; 934 | }; 935 | imports.wbg.__wbg_length_ae22078168b726f5 = function(arg0) { 936 | const ret = getObject(arg0).length; 937 | return ret; 938 | }; 939 | imports.wbg.__wbg_new_796382978dfd4fb0 = function(arg0, arg1) { 940 | var v0 = getCachedStringFromWasm0(arg0, arg1); 941 | const ret = new Error(v0); 942 | return addHeapObject(ret); 943 | }; 944 | imports.wbg.__wbg_newnoargs_76313bd6ff35d0f2 = function(arg0, arg1) { 945 | var v0 = getCachedStringFromWasm0(arg0, arg1); 946 | const ret = new Function(v0); 947 | return addHeapObject(ret); 948 | }; 949 | imports.wbg.__wbg_call_1084a111329e68ce = function() { return handleError(function (arg0, arg1) { 950 | const ret = getObject(arg0).call(getObject(arg1)); 951 | return addHeapObject(ret); 952 | }, arguments) }; 953 | imports.wbg.__wbg_call_89af060b4e1523f2 = function() { return handleError(function (arg0, arg1, arg2) { 954 | const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); 955 | return addHeapObject(ret); 956 | }, arguments) }; 957 | imports.wbg.__wbg_next_f9cb570345655b9a = function() { return handleError(function (arg0) { 958 | const ret = getObject(arg0).next(); 959 | return addHeapObject(ret); 960 | }, arguments) }; 961 | imports.wbg.__wbg_next_de3e9db4440638b2 = function(arg0) { 962 | const ret = getObject(arg0).next; 963 | return addHeapObject(ret); 964 | }; 965 | imports.wbg.__wbg_done_bfda7aa8f252b39f = function(arg0) { 966 | const ret = getObject(arg0).done; 967 | return ret; 968 | }; 969 | imports.wbg.__wbg_value_6d39332ab4788d86 = function(arg0) { 970 | const ret = getObject(arg0).value; 971 | return addHeapObject(ret); 972 | }; 973 | imports.wbg.__wbg_is_009b1ef508712fda = function(arg0, arg1) { 974 | const ret = Object.is(getObject(arg0), getObject(arg1)); 975 | return ret; 976 | }; 977 | imports.wbg.__wbg_exec_a29a4ce5544bd3be = function(arg0, arg1, arg2) { 978 | var v0 = getCachedStringFromWasm0(arg1, arg2); 979 | const ret = getObject(arg0).exec(v0); 980 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 981 | }; 982 | imports.wbg.__wbg_new_13847c66f41dda63 = function(arg0, arg1, arg2, arg3) { 983 | var v0 = getCachedStringFromWasm0(arg0, arg1); 984 | var v1 = getCachedStringFromWasm0(arg2, arg3); 985 | const ret = new RegExp(v0, v1); 986 | return addHeapObject(ret); 987 | }; 988 | imports.wbg.__wbg_iterator_888179a48810a9fe = function() { 989 | const ret = Symbol.iterator; 990 | return addHeapObject(ret); 991 | }; 992 | imports.wbg.__wbg_new_b85e72ed1bfd57f9 = function(arg0, arg1) { 993 | try { 994 | var state0 = {a: arg0, b: arg1}; 995 | var cb0 = (arg0, arg1) => { 996 | const a = state0.a; 997 | state0.a = 0; 998 | try { 999 | return __wbg_adapter_270(a, state0.b, arg0, arg1); 1000 | } finally { 1001 | state0.a = a; 1002 | } 1003 | }; 1004 | const ret = new Promise(cb0); 1005 | return addHeapObject(ret); 1006 | } finally { 1007 | state0.a = state0.b = 0; 1008 | } 1009 | }; 1010 | imports.wbg.__wbg_resolve_570458cb99d56a43 = function(arg0) { 1011 | const ret = Promise.resolve(getObject(arg0)); 1012 | return addHeapObject(ret); 1013 | }; 1014 | imports.wbg.__wbg_then_95e6edc0f89b73b1 = function(arg0, arg1) { 1015 | const ret = getObject(arg0).then(getObject(arg1)); 1016 | return addHeapObject(ret); 1017 | }; 1018 | imports.wbg.__wbg_globalThis_86b222e13bdf32ed = function() { return handleError(function () { 1019 | const ret = globalThis.globalThis; 1020 | return addHeapObject(ret); 1021 | }, arguments) }; 1022 | imports.wbg.__wbg_self_3093d5d1f7bcb682 = function() { return handleError(function () { 1023 | const ret = self.self; 1024 | return addHeapObject(ret); 1025 | }, arguments) }; 1026 | imports.wbg.__wbg_window_3bcfc4d31bc012f8 = function() { return handleError(function () { 1027 | const ret = window.window; 1028 | return addHeapObject(ret); 1029 | }, arguments) }; 1030 | imports.wbg.__wbg_global_e5a3fe56f8be9485 = function() { return handleError(function () { 1031 | const ret = global.global; 1032 | return addHeapObject(ret); 1033 | }, arguments) }; 1034 | imports.wbg.__wbg_newwithbyteoffsetandlength_8a2cb9ca96b27ec9 = function(arg0, arg1, arg2) { 1035 | const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); 1036 | return addHeapObject(ret); 1037 | }; 1038 | imports.wbg.__wbg_buffer_0710d1b9dbe2eea6 = function(arg0) { 1039 | const ret = getObject(arg0).buffer; 1040 | return addHeapObject(ret); 1041 | }; 1042 | imports.wbg.__wbg_length_8339fcf5d8ecd12e = function(arg0) { 1043 | const ret = getObject(arg0).length; 1044 | return ret; 1045 | }; 1046 | imports.wbg.__wbg_byteLength_850664ef28f3e42f = function(arg0) { 1047 | const ret = getObject(arg0).byteLength; 1048 | return ret; 1049 | }; 1050 | imports.wbg.__wbg_byteOffset_ea14c35fa6de38cc = function(arg0) { 1051 | const ret = getObject(arg0).byteOffset; 1052 | return ret; 1053 | }; 1054 | imports.wbg.__wbg_set_d1e79e2388520f18 = function(arg0, arg1, arg2) { 1055 | getObject(arg0).set(getObject(arg1), arg2 >>> 0); 1056 | }; 1057 | imports.wbg.__wbindgen_is_object = function(arg0) { 1058 | const val = getObject(arg0); 1059 | const ret = typeof(val) === 'object' && val !== null; 1060 | return ret; 1061 | }; 1062 | imports.wbg.__wbindgen_is_string = function(arg0) { 1063 | const ret = typeof(getObject(arg0)) === 'string'; 1064 | return ret; 1065 | }; 1066 | imports.wbg.__wbg_get_224d16597dbbfd96 = function() { return handleError(function (arg0, arg1) { 1067 | const ret = Reflect.get(getObject(arg0), getObject(arg1)); 1068 | return addHeapObject(ret); 1069 | }, arguments) }; 1070 | imports.wbg.__wbg_has_4bfbc01db38743f7 = function() { return handleError(function (arg0, arg1) { 1071 | const ret = Reflect.has(getObject(arg0), getObject(arg1)); 1072 | return ret; 1073 | }, arguments) }; 1074 | imports.wbg.__wbg_set_eacc7d73fefaafdf = function() { return handleError(function (arg0, arg1, arg2) { 1075 | const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); 1076 | return ret; 1077 | }, arguments) }; 1078 | imports.wbg.__wbg_buffer_b7b08af79b0b0974 = function(arg0) { 1079 | const ret = getObject(arg0).buffer; 1080 | return addHeapObject(ret); 1081 | }; 1082 | imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { 1083 | const ret = debugString(getObject(arg1)); 1084 | const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 1085 | const len1 = WASM_VECTOR_LEN; 1086 | getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); 1087 | getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); 1088 | }; 1089 | imports.wbg.__wbindgen_object_drop_ref = function(arg0) { 1090 | takeObject(arg0); 1091 | }; 1092 | imports.wbg.__wbindgen_throw = function(arg0, arg1) { 1093 | throw new Error(getStringFromWasm0(arg0, arg1)); 1094 | }; 1095 | imports.wbg.__wbindgen_rethrow = function(arg0) { 1096 | throw takeObject(arg0); 1097 | }; 1098 | imports.wbg.__wbindgen_memory = function() { 1099 | const ret = wasm.memory; 1100 | return addHeapObject(ret); 1101 | }; 1102 | imports.wbg.__wbindgen_closure_wrapper654 = function(arg0, arg1, arg2) { 1103 | const ret = makeMutClosure(arg0, arg1, 41, __wbg_adapter_38); 1104 | return addHeapObject(ret); 1105 | }; 1106 | imports.wbg.__wbindgen_closure_wrapper656 = function(arg0, arg1, arg2) { 1107 | const ret = makeClosure(arg0, arg1, 39, __wbg_adapter_41); 1108 | return addHeapObject(ret); 1109 | }; 1110 | imports.wbg.__wbindgen_closure_wrapper5123 = function(arg0, arg1, arg2) { 1111 | const ret = makeClosure(arg0, arg1, 392, __wbg_adapter_44); 1112 | return addHeapObject(ret); 1113 | }; 1114 | imports.wbg.__wbindgen_closure_wrapper6149 = function(arg0, arg1, arg2) { 1115 | const ret = makeMutClosure(arg0, arg1, 463, __wbg_adapter_47); 1116 | return addHeapObject(ret); 1117 | }; 1118 | imports.wbg.__wbindgen_closure_wrapper6855 = function(arg0, arg1, arg2) { 1119 | const ret = makeMutClosure(arg0, arg1, 519, __wbg_adapter_50); 1120 | return addHeapObject(ret); 1121 | }; 1122 | imports.wbg.__wbindgen_closure_wrapper11850 = function(arg0, arg1, arg2) { 1123 | const ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_53); 1124 | return addHeapObject(ret); 1125 | }; 1126 | 1127 | return imports; 1128 | } 1129 | 1130 | function __wbg_init_memory(imports, memory) { 1131 | 1132 | } 1133 | 1134 | function __wbg_finalize_init(instance, module) { 1135 | wasm = instance.exports; 1136 | __wbg_init.__wbindgen_wasm_module = module; 1137 | cachedDataViewMemory0 = null; 1138 | cachedUint8ArrayMemory0 = null; 1139 | 1140 | 1141 | wasm.__wbindgen_start(); 1142 | return wasm; 1143 | } 1144 | 1145 | function initSync(module) { 1146 | if (wasm !== undefined) return wasm; 1147 | 1148 | 1149 | if (typeof module !== 'undefined' && Object.getPrototypeOf(module) === Object.prototype) 1150 | ({module} = module) 1151 | else 1152 | console.warn('using deprecated parameters for `initSync()`; pass a single object instead') 1153 | 1154 | const imports = __wbg_get_imports(); 1155 | 1156 | __wbg_init_memory(imports); 1157 | 1158 | if (!(module instanceof WebAssembly.Module)) { 1159 | module = new WebAssembly.Module(module); 1160 | } 1161 | 1162 | const instance = new WebAssembly.Instance(module, imports); 1163 | 1164 | return __wbg_finalize_init(instance, module); 1165 | } 1166 | 1167 | async function __wbg_init(module_or_path) { 1168 | if (wasm !== undefined) return wasm; 1169 | 1170 | 1171 | if (typeof module_or_path !== 'undefined' && Object.getPrototypeOf(module_or_path) === Object.prototype) 1172 | ({module_or_path} = module_or_path) 1173 | else 1174 | console.warn('using deprecated parameters for the initialization function; pass a single object instead') 1175 | 1176 | if (typeof module_or_path === 'undefined') { 1177 | module_or_path = new URL('demo_bg.wasm', import.meta.url); 1178 | } 1179 | const imports = __wbg_get_imports(); 1180 | 1181 | if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { 1182 | module_or_path = fetch(module_or_path); 1183 | } 1184 | 1185 | __wbg_init_memory(imports); 1186 | 1187 | const { instance, module } = await __wbg_load(await module_or_path, imports); 1188 | 1189 | return __wbg_finalize_init(instance, module); 1190 | } 1191 | 1192 | export { initSync }; 1193 | export default __wbg_init; 1194 | -------------------------------------------------------------------------------- /examples/demo/dist/demo-d350a89f5c90eea4_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaucho-labs/leptos-hotkeys/1a3cebb7fcba3c609e09167002dd58a510ec2032/examples/demo/dist/demo-d350a89f5c90eea4_bg.wasm -------------------------------------------------------------------------------- /examples/demo/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | demo 7 | 8 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 71 | 72 | 73 | 74 | 75 | 205 | 206 | -------------------------------------------------------------------------------- /examples/demo/dist/output-ca0a674fcde1a78.css: -------------------------------------------------------------------------------- 1 | /*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}body,html{background-color:rgb(253 253 253/var(--tw-bg-opacity));color:rgb(0 0 0/var(--tw-text-opacity))}body,body.dark,html,html.dark{--tw-bg-opacity:1;--tw-text-opacity:1}body.dark,html.dark{background-color:rgb(26 26 26/var(--tw-bg-opacity));color:rgb(255 255 255/var(--tw-text-opacity))}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.static{position:static}.absolute{position:absolute}.flex{display:flex}.grid{display:grid}.h-full{height:100%}.h-screen{height:100vh}.w-10\/12{width:83.333333%}.w-full{width:100%}.flex-1{flex:1 1 0%}.flex-col{flex-direction:column}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(2rem*var(--tw-space-x-reverse));margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-20>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.border{border-width:1px}.border-\[\#1a1a1a\]{--tw-border-opacity:1;border-color:rgb(26 26 26/var(--tw-border-opacity))}.bg-\[\#1a1a1a\]{--tw-bg-opacity:1;background-color:rgb(26 26 26/var(--tw-bg-opacity))}.bg-\[\#fdfdfd\]{--tw-bg-opacity:1;background-color:rgb(253 253 253/var(--tw-bg-opacity))}.p-8{padding:2rem}.py-20{padding-top:5rem;padding-bottom:5rem}.font-robotomono{font-family:Roboto Mono,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.outline{outline-style:solid}:is(.dark .dark\:border-\[\#fdfdfd\]){--tw-border-opacity:1;border-color:rgb(253 253 253/var(--tw-border-opacity))}:is(.dark .dark\:bg-\[\#1a1a1a\]){--tw-bg-opacity:1;background-color:rgb(26 26 26/var(--tw-bg-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}} -------------------------------------------------------------------------------- /examples/demo/dist/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/index.html" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /examples/demo/input.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | 6 | @layer base { 7 | html, 8 | body { 9 | @apply bg-[#fdfdfd] text-black; 10 | } 11 | 12 | html.dark, 13 | body.dark { 14 | @apply bg-[#1a1a1a] text-white; 15 | } 16 | } -------------------------------------------------------------------------------- /examples/demo/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | -------------------------------------------------------------------------------- /examples/demo/src/app.rs: -------------------------------------------------------------------------------- 1 | use leptos::*; 2 | use leptos_hotkeys::{ 3 | provide_hotkeys_context, scopes, use_hotkeys, use_hotkeys_context, use_hotkeys_ref, 4 | HotkeysContext, 5 | }; 6 | use leptos_meta::*; 7 | use leptos_router::*; 8 | 9 | #[component] 10 | pub fn Button(href: &'static str, children: Children) -> impl IntoView { 11 | view! { 12 | 13 | {children()} 14 | 15 | } 16 | } 17 | 18 | #[component] 19 | pub fn App() -> impl IntoView { 20 | provide_meta_context(); 21 | let main_ref = create_node_ref::(); 22 | provide_hotkeys_context(main_ref, false, scopes!("scope_a")); 23 | 24 | view! { 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | } 35 | } 36 | 37 | #[component] 38 | fn HomePage() -> impl IntoView { 39 | const SCOPE_BORDER: &str = 40 | "border border-1 border-[#1a1a1a] dark:border-[#fdfdfd] p-8 space-y-20 h-full"; 41 | let current_scope = create_rw_signal("scope_a"); 42 | let is_green = create_rw_signal(true); 43 | 44 | // leptos_hotkey specific logic 45 | fn go_to_link(key: &'static str, link: String, scope: &'static str) { 46 | use_hotkeys!((*key, scope) => move |_| { 47 | window().location().set_href(&link).expect("Failed to navigate"); 48 | }) 49 | } 50 | 51 | let (count, set_count) = create_signal(0); 52 | 53 | let HotkeysContext { toggle_scope, .. } = use_hotkeys_context(); 54 | 55 | // global hotkeys 56 | use_hotkeys!(("s") => move |_| { 57 | toggle_scope("scope_a".to_string()); 58 | toggle_scope("scope_b".to_string()); 59 | 60 | if current_scope.get() == "scope_a" { 61 | current_scope.set("scope_b") 62 | } else { 63 | current_scope.set("scope_a") 64 | } 65 | }); 66 | 67 | go_to_link( 68 | "controlleft+r,controlright+r", 69 | "https://github.com/gaucho-labs/leptos_hotkeys".to_string(), 70 | "*", 71 | ); 72 | 73 | // scope_a related hotkeys 74 | use_hotkeys!(("arrowup,arrowright", "scope_a") => move |_| { 75 | set_count.update(|count| { 76 | *count += 1; 77 | }) 78 | }); 79 | 80 | use_hotkeys!(("arrowdown,arrowleft", "scope_a") => move |_| { 81 | set_count.update(|count| { 82 | *count -= 1; 83 | }) 84 | }); 85 | 86 | use_hotkeys!(("escape", "scope_a") => move |_| { 87 | set_count.set(0); 88 | }); 89 | 90 | let a_ref = create_node_ref::(); 91 | use_hotkeys_ref!((a_ref, "6", "scope_a") => move |_| { 92 | if is_green.get() { 93 | is_green.set(false) 94 | } else { 95 | is_green.set(true) 96 | } 97 | }); 98 | 99 | const BANANA: &str = "https://www.youtube.com/watch?v=N982sQcjsZI"; 100 | 101 | go_to_link("b+meta", BANANA.to_string(), "scope_b"); 102 | 103 | view! { 104 |
105 | 106 |
107 |
108 |
109 | 112 |

press ctrl+R to go to repository

113 |
114 |

a library designed to declaratively pair your keybindings with callbacks.

115 |
116 |
117 |
118 | 119 |
120 |

Press 's' to toggle between scopes a and b

121 |

Current scope: {move || { current_scope.get() }}

122 |
123 |
124 |
125 |
130 |
131 |

scope_a

132 |
133 |

Current count: {count}

134 |
135 |

"press 'Arrow Up' to increase the count"

136 |

"press 'Arrow Down' to decrease the count"

137 |

"press 'Escape' to reset the count"

138 |
139 |
140 |
146 |

click on me and press 6

147 |
148 |
149 |
150 |
155 |
156 |

scope_b

157 |
158 |

press "Cmd/Super/Win"+ 'B'

159 |
160 | 161 |
162 |
163 |
164 |
165 |
166 | 169 | 172 | 175 |
176 | 177 |
178 |
179 | } 180 | } 181 | 182 | #[component] 183 | fn ErrorPage() -> impl IntoView { 184 | let params = use_params_map(); 185 | let p_unknown = move || params.with(|p| p.get("else").cloned().unwrap_or_default()); 186 | 187 | let unknown = p_unknown(); 188 | 189 | view! { 190 |
192 |

Unknown command: {unknown}

193 |
194 | } 195 | } 196 | -------------------------------------------------------------------------------- /examples/demo/src/main.rs: -------------------------------------------------------------------------------- 1 | use app::*; 2 | use leptos::*; 3 | mod app; 4 | 5 | pub fn main() { 6 | _ = console_log::init_with_level(log::Level::Debug); 7 | console_error_panic_hook::set_once(); 8 | 9 | logging::log!("csr mode - mounting to body"); 10 | 11 | mount_to_body(|| { 12 | view! { } 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /examples/demo/style/output.css: -------------------------------------------------------------------------------- 1 | /*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}body,html{background-color:rgb(253 253 253/var(--tw-bg-opacity));color:rgb(0 0 0/var(--tw-text-opacity))}body,body.dark,html,html.dark{--tw-bg-opacity:1;--tw-text-opacity:1}body.dark,html.dark{background-color:rgb(26 26 26/var(--tw-bg-opacity));color:rgb(255 255 255/var(--tw-text-opacity))}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.static{position:static}.absolute{position:absolute}.flex{display:flex}.grid{display:grid}.h-full{height:100%}.h-screen{height:100vh}.w-10\/12{width:83.333333%}.w-full{width:100%}.flex-1{flex:1 1 0%}.flex-col{flex-direction:column}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(2rem*var(--tw-space-x-reverse));margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-20>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.border{border-width:1px}.border-\[\#1a1a1a\]{--tw-border-opacity:1;border-color:rgb(26 26 26/var(--tw-border-opacity))}.bg-\[\#1a1a1a\]{--tw-bg-opacity:1;background-color:rgb(26 26 26/var(--tw-bg-opacity))}.bg-\[\#fdfdfd\]{--tw-bg-opacity:1;background-color:rgb(253 253 253/var(--tw-bg-opacity))}.p-8{padding:2rem}.py-20{padding-top:5rem;padding-bottom:5rem}.font-robotomono{font-family:Roboto Mono,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.outline{outline-style:solid}:is(.dark .dark\:border-\[\#fdfdfd\]){--tw-border-opacity:1;border-color:rgb(253 253 253/var(--tw-border-opacity))}:is(.dark .dark\:bg-\[\#1a1a1a\]){--tw-bg-opacity:1;background-color:rgb(26 26 26/var(--tw-bg-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}} -------------------------------------------------------------------------------- /examples/demo/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: { 4 | files: ["*.html", "./src/**/*.rs", "./input.css"], 5 | }, 6 | theme: { 7 | extend: { 8 | fontFamily: { 9 | 'opensans': ['Open Sans', 'sans-serif'], 10 | 'robotomono': ['Roboto Mono', 'monospace'], 11 | } 12 | }, 13 | }, 14 | plugins: [], 15 | darkMode: 'class', 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/demo/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/index.html" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/ssr-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock/ -------------------------------------------------------------------------------- /examples/ssr-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ssr-demo" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | [dependencies] 10 | axum = { version = "0.7", optional = true } 11 | console_error_panic_hook = "0.1" 12 | leptos = { version = "0.6", features = ["nightly"] } 13 | leptos_axum = { version = "0.6", optional = true } 14 | leptos_meta = { version = "0.6", features = ["nightly"] } 15 | leptos_router = { version = "0.6", features = ["nightly"] } 16 | tokio = { version = "1", features = ["rt-multi-thread"], optional = true } 17 | tower = { version = "0.4", features = ["util"], optional = true } 18 | tower-http = { version = "0.5", features = ["fs"], optional = true } 19 | wasm-bindgen.workspace = true 20 | thiserror = "1" 21 | tracing = { version = "0.1", optional = true } 22 | http = "1" 23 | leptos_hotkeys = { path = "../../leptos_hotkeys", features = [ 24 | "debug", 25 | "use_key", 26 | ] } 27 | 28 | [features] 29 | hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"] 30 | ssr = [ 31 | "dep:axum", 32 | "dep:tokio", 33 | "dep:tower", 34 | "dep:tower-http", 35 | "dep:leptos_axum", 36 | "leptos/ssr", 37 | "leptos_meta/ssr", 38 | "leptos_router/ssr", 39 | "dep:tracing", 40 | ] 41 | 42 | [package.metadata.leptos] 43 | # The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name 44 | output-name = "ssr-demo" 45 | # The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup. 46 | site-root = "target/site" 47 | # The site-root relative folder where all compiled output (JS, WASM and CSS) is written 48 | # Defaults to pkg 49 | site-pkg-dir = "pkg" 50 | # [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to //app.css 51 | style-file = "style/main.scss" 52 | # Assets source dir. All files found here will be copied and synchronized to site-root. 53 | # The assets-dir cannot have a sub directory with the same name/path as site-pkg-dir. 54 | # 55 | # Optional. Env: LEPTOS_ASSETS_DIR. 56 | assets-dir = "public" 57 | # The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup. 58 | site-addr = "127.0.0.1:3000" 59 | # The port to use for automatic reload monitoring 60 | reload-port = 3001 61 | # [Optional] Command to use when running end2end tests. It will run in the end2end dir. 62 | # [Windows] for non-WSL use "npx.cmd playwright test" 63 | # This binary name can be checked in Powershell with Get-Command npx 64 | end2end-cmd = "npx playwright test" 65 | end2end-dir = "end2end" 66 | # The browserlist query used for optimizing the CSS. 67 | browserquery = "defaults" 68 | # The features to use when compiling the bin target 69 | # 70 | # Optional. Can be over-ridden with the command line parameter --bin-features 71 | bin-features = ["ssr"] 72 | # If the --no-default-features flag should be used when compiling the bin target 73 | # 74 | # Optional. Defaults to false. 75 | bin-default-features = false 76 | # The features to use when compiling the lib target 77 | # 78 | # Optional. Can be over-ridden with the command line parameter --lib-features 79 | lib-features = ["hydrate"] 80 | # If the --no-default-features flag should be used when compiling the lib target 81 | # 82 | # Optional. Defaults to false. 83 | lib-default-features = false 84 | # The profile to use for the lib target when compiling for release 85 | # 86 | # Optional. Defaults to "release". 87 | lib-profile-release = "wasm-release" 88 | -------------------------------------------------------------------------------- /examples/ssr-demo/README.md: -------------------------------------------------------------------------------- 1 | # leptos-hotkeys SSR demo 2 | 3 | ```sh 4 | cargo install cargo-leptos 5 | cargo leptos watch 6 | ``` 7 | -------------------------------------------------------------------------------- /examples/ssr-demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaucho-labs/leptos-hotkeys/1a3cebb7fcba3c609e09167002dd58a510ec2032/examples/ssr-demo/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr-demo/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::error_template::{AppError, ErrorTemplate}; 2 | use leptos::*; 3 | use leptos_hotkeys::{ 4 | provide_hotkeys_context, scopes, use_hotkeys, use_hotkeys_ref, HotkeysContext, 5 | }; 6 | use leptos_meta::*; 7 | use leptos_router::*; 8 | 9 | #[component] 10 | pub fn App() -> impl IntoView { 11 | // Provides context that manages stylesheets, titles, meta tags, etc. 12 | provide_meta_context(); 13 | 14 | let main_ref = create_node_ref::(); 15 | 16 | let HotkeysContext { .. } = provide_hotkeys_context(main_ref, false, scopes!()); 17 | 18 | view! { 19 | 20 | 21 | // sets the document title 22 | 23 | 24 | // content for this welcome page 25 | <Router fallback=|| { 26 | let mut outside_errors = Errors::default(); 27 | outside_errors.insert_with_default_key(AppError::NotFound); 28 | view! { <ErrorTemplate outside_errors /> }.into_view() 29 | }> 30 | <main _ref=main_ref> 31 | <Routes> 32 | <Route path="" view=HomePage /> 33 | </Routes> 34 | </main> 35 | </Router> 36 | } 37 | } 38 | 39 | /// Renders the home page of your application. 40 | #[component] 41 | fn HomePage() -> impl IntoView { 42 | // Creates a reactive value to update the button 43 | let (count, set_count) = create_signal(0); 44 | 45 | use_hotkeys!(("arrowup") => move |_| { 46 | set_count.update(|c| *c += 1); 47 | }); 48 | 49 | use_hotkeys!(("arrowdown") => move |_| { 50 | set_count.update(|c| *c -= 1); 51 | }); 52 | 53 | use_hotkeys!(("space") => move |_| { 54 | logging::log!("hola") 55 | }); 56 | 57 | let div_ref = create_node_ref::<html::Div>(); 58 | 59 | use_hotkeys_ref!((div_ref, "5") => move |_| { 60 | logging::log!("howdy") 61 | }); 62 | 63 | use_hotkeys!(("controlleft") => move |_| { 64 | logging::log!("works either using control left or control right!") 65 | }); 66 | 67 | let giraffe_signal = create_rw_signal(false); 68 | 69 | use_hotkeys!(("space + l") => move |_| { 70 | giraffe_signal.set(!giraffe_signal.get()); 71 | logging::log!("i'm a giraffe"); 72 | }); 73 | 74 | view! { 75 | <h1>"Welcome to Leptos!"</h1> 76 | <div>"Press arrow up and arrow down: " {count}</div> 77 | <div tabIndex=-1 _ref=div_ref> 78 | howdy 79 | </div> 80 | <Show when=move || giraffe_signal.get()>"I'm a giraffe!"</Show> 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/ssr-demo/src/error_template.rs: -------------------------------------------------------------------------------- 1 | use http::status::StatusCode; 2 | use leptos::*; 3 | use thiserror::Error; 4 | 5 | #[derive(Clone, Debug, Error)] 6 | pub enum AppError { 7 | #[error("Not Found")] 8 | NotFound, 9 | } 10 | 11 | impl AppError { 12 | pub fn status_code(&self) -> StatusCode { 13 | match self { 14 | AppError::NotFound => StatusCode::NOT_FOUND, 15 | } 16 | } 17 | } 18 | 19 | // A basic function to display errors served by the error boundaries. 20 | // Feel free to do more complicated things here than just displaying the error. 21 | #[component] 22 | pub fn ErrorTemplate( 23 | #[prop(optional)] outside_errors: Option<Errors>, 24 | #[prop(optional)] errors: Option<RwSignal<Errors>>, 25 | ) -> impl IntoView { 26 | let errors = match outside_errors { 27 | Some(e) => create_rw_signal(e), 28 | None => match errors { 29 | Some(e) => e, 30 | None => panic!("No Errors found and we expected errors!"), 31 | }, 32 | }; 33 | // Get Errors from Signal 34 | let errors = errors.get_untracked(); 35 | 36 | // Downcast lets us take a type that implements `std::error::Error` 37 | let errors: Vec<AppError> = errors 38 | .into_iter() 39 | .filter_map(|(_k, v)| v.downcast_ref::<AppError>().cloned()) 40 | .collect(); 41 | #[allow(clippy::print_stdout)] 42 | { 43 | println!("Errors: {errors:#?}"); 44 | } 45 | 46 | // Only the response code for the first error is actually sent from the server 47 | // this may be customized by the specific application 48 | #[cfg(feature = "ssr")] 49 | { 50 | use leptos_axum::ResponseOptions; 51 | let response = use_context::<ResponseOptions>(); 52 | if let Some(response) = response { 53 | response.set_status(errors[0].status_code()); 54 | } 55 | } 56 | 57 | view! { 58 | <h1>{if errors.len() > 1 { "Errors" } else { "Error" }}</h1> 59 | <For 60 | // a function that returns the items we're iterating over; a signal is fine 61 | each=move || { errors.clone().into_iter().enumerate() } 62 | // a unique key for each item as a reference 63 | key=|(index, _error)| *index 64 | // renders each item to a view 65 | children=move |error| { 66 | let error_string = error.1.to_string(); 67 | let error_code = error.1.status_code(); 68 | view! { 69 | <h2>{error_code.to_string()}</h2> 70 | <p>"Error: " {error_string}</p> 71 | } 72 | } 73 | /> 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/ssr-demo/src/fileserv.rs: -------------------------------------------------------------------------------- 1 | use crate::app::App; 2 | use axum::response::Response as AxumResponse; 3 | use axum::{ 4 | body::Body, 5 | extract::State, 6 | http::{Request, Response, StatusCode}, 7 | response::IntoResponse, 8 | }; 9 | use leptos::*; 10 | use std::convert::Infallible; 11 | use tower::ServiceExt; 12 | use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir}; 13 | 14 | pub async fn file_and_error_handler( 15 | State(options): State<LeptosOptions>, 16 | req: Request<Body>, 17 | ) -> AxumResponse { 18 | let root = options.site_root.clone(); 19 | let (parts, body) = req.into_parts(); 20 | 21 | let mut static_parts = parts.clone(); 22 | static_parts.headers.clear(); 23 | if let Some(encodings) = parts.headers.get("accept-encoding") { 24 | static_parts 25 | .headers 26 | .insert("accept-encoding", encodings.clone()); 27 | } 28 | 29 | let res = get_static_file(Request::from_parts(static_parts, Body::empty()), &root) 30 | .await 31 | .unwrap(); 32 | 33 | if res.status() == StatusCode::OK { 34 | res.into_response() 35 | } else { 36 | let handler = leptos_axum::render_app_to_stream(options.to_owned(), App); 37 | handler(Request::from_parts(parts, body)) 38 | .await 39 | .into_response() 40 | } 41 | } 42 | 43 | async fn get_static_file( 44 | request: Request<Body>, 45 | root: &str, 46 | ) -> Result<Response<ServeFileSystemResponseBody>, Infallible> { 47 | // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` 48 | // This path is relative to the cargo root 49 | ServeDir::new(root) 50 | .precompressed_gzip() 51 | .precompressed_br() 52 | .oneshot(request) 53 | .await 54 | } 55 | -------------------------------------------------------------------------------- /examples/ssr-demo/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod app; 2 | pub mod error_template; 3 | #[cfg(feature = "ssr")] 4 | pub mod fileserv; 5 | 6 | #[cfg(feature = "hydrate")] 7 | #[wasm_bindgen::prelude::wasm_bindgen] 8 | pub fn hydrate() { 9 | use crate::app::*; 10 | console_error_panic_hook::set_once(); 11 | leptos::mount_to_body(App); 12 | } 13 | -------------------------------------------------------------------------------- /examples/ssr-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "ssr")] 2 | #[tokio::main] 3 | async fn main() { 4 | use axum::Router; 5 | use leptos::*; 6 | use leptos_axum::{generate_route_list, LeptosRoutes}; 7 | use ssr_demo::app::*; 8 | use ssr_demo::fileserv::file_and_error_handler; 9 | 10 | // Setting get_configuration(None) means we'll be using cargo-leptos's env values 11 | // For deployment these variables are: 12 | // <https://github.com/leptos-rs/start-axum#executing-a-server-on-a-remote-machine-without-the-toolchain> 13 | // Alternately a file can be specified such as Some("Cargo.toml") 14 | // The file would need to be included with the executable when moved to deployment 15 | let conf = get_configuration(None).await.unwrap(); 16 | let leptos_options = conf.leptos_options; 17 | let addr = leptos_options.site_addr; 18 | let routes = generate_route_list(App); 19 | 20 | // build our application with a route 21 | let app = Router::new() 22 | .leptos_routes(&leptos_options, routes, App) 23 | .fallback(file_and_error_handler) 24 | .with_state(leptos_options); 25 | 26 | let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); 27 | logging::log!("listening on http://{}", &addr); 28 | axum::serve(listener, app.into_make_service()) 29 | .await 30 | .unwrap(); 31 | } 32 | 33 | #[cfg(not(feature = "ssr"))] 34 | pub fn main() { 35 | // no client-side main function 36 | // unless we want this to work with e.g., Trunk for a purely client-side app 37 | // see lib.rs for hydration function instead 38 | } 39 | -------------------------------------------------------------------------------- /examples/ssr-demo/style/main.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } -------------------------------------------------------------------------------- /images/readme-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaucho-labs/leptos-hotkeys/1a3cebb7fcba3c609e09167002dd58a510ec2032/images/readme-cover.png -------------------------------------------------------------------------------- /leptos_hotkeys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leptos_hotkeys" 3 | version = "0.2.2" 4 | edition = "2021" 5 | description = "A library that declaratively pairs keybindings with callbacks for Leptos applications." 6 | license = "MIT" 7 | repository = "https://github.com/gaucho-labs/leptos-hotkeys" 8 | readme = "../README.md" 9 | authors = ["Matthew Kim", "Álvaro Mondéjar Rubio", "Robert Junkins", "Zak Stucke"] 10 | keywords = ["leptos", "hotkeys", "wasm"] 11 | 12 | [dependencies] 13 | leptos = "0.6" 14 | log = { version = "0.4", optional = true } 15 | wasm-bindgen.workspace = true 16 | web-sys.workspace = true 17 | 18 | [features] 19 | debug = ["dep:log"] 20 | ssr = [] 21 | use_key = [] -------------------------------------------------------------------------------- /leptos_hotkeys/src/context.rs: -------------------------------------------------------------------------------- 1 | use leptos::html::ElementDescriptor; 2 | use leptos::*; 3 | use std::collections::{BTreeMap, HashSet}; 4 | #[cfg(not(feature = "ssr"))] 5 | use wasm_bindgen::JsCast; 6 | 7 | #[derive(Clone, Copy)] 8 | pub struct HotkeysContext { 9 | #[cfg(not(feature = "ssr"))] 10 | pub(crate) keys_pressed: RwSignal<KeyPresses>, 11 | 12 | #[cfg(not(feature = "ssr"))] 13 | pub active_ref_target: RwSignal<Option<web_sys::EventTarget>>, 14 | 15 | #[cfg(not(feature = "ssr"))] 16 | pub set_ref_target: Callback<Option<web_sys::EventTarget>>, 17 | 18 | pub active_scopes: RwSignal<HashSet<String>>, 19 | pub enable_scope: Callback<String>, 20 | pub disable_scope: Callback<String>, 21 | pub toggle_scope: Callback<String>, 22 | } 23 | #[derive(Debug, Default, Clone)] 24 | #[cfg_attr(feature = "ssr", allow(dead_code))] 25 | pub struct KeyPresses { 26 | pub key_map: BTreeMap<String, web_sys::KeyboardEvent>, 27 | pub last_key: Option<String>, 28 | } 29 | 30 | pub fn provide_hotkeys_context<T>( 31 | #[cfg_attr(feature = "ssr", allow(unused_variables))] node_ref: NodeRef<T>, 32 | #[cfg_attr(feature = "ssr", allow(unused_variables))] allow_blur_event: bool, 33 | initially_active_scopes: HashSet<String>, 34 | ) -> HotkeysContext 35 | where 36 | T: ElementDescriptor + 'static + Clone, 37 | { 38 | #[cfg(not(feature = "ssr"))] 39 | let active_ref_target: RwSignal<Option<web_sys::EventTarget>> = RwSignal::new(None); 40 | 41 | #[cfg(not(feature = "ssr"))] 42 | let set_ref_target = Callback::new(move |target: Option<web_sys::EventTarget>| { 43 | active_ref_target.set(target); 44 | }); 45 | 46 | #[cfg(not(feature = "ssr"))] 47 | let keys_pressed: RwSignal<KeyPresses> = RwSignal::new(KeyPresses::default()); 48 | 49 | let active_scopes: RwSignal<HashSet<String>> = RwSignal::new(initially_active_scopes); 50 | 51 | let enable_scope = Callback::new(move |scope: String| { 52 | active_scopes.update(|scopes| { 53 | if !scopes.contains(&scope) { 54 | if cfg!(feature = "debug") { 55 | logging::log!("inserting scope {}", &scope); 56 | } 57 | scopes.insert(scope); 58 | } 59 | }); 60 | }); 61 | 62 | let disable_scope = Callback::new(move |scope: String| { 63 | active_scopes.update(|scopes| { 64 | if cfg!(feature = "debug") { 65 | logging::log!("removing scope {}", &scope); 66 | } 67 | scopes.remove(&scope); 68 | }) 69 | }); 70 | 71 | let toggle_scope = Callback::new(move |scope: String| { 72 | active_scopes.update(|scopes| { 73 | if scopes.contains(&scope) { 74 | if cfg!(feature = "debug") { 75 | logging::log!("removing scope {}", &scope); 76 | } 77 | scopes.remove(&scope); 78 | } else { 79 | if cfg!(feature = "debug") { 80 | logging::log!("inserting scope {}", &scope); 81 | } 82 | scopes.insert(scope); 83 | } 84 | }) 85 | }); 86 | 87 | #[cfg(all(feature = "debug", not(feature = "ssr")))] 88 | create_effect(move |_| { 89 | let keys_pressed_list = move || { 90 | keys_pressed 91 | .get() 92 | .key_map 93 | .keys() 94 | .cloned() 95 | .collect::<Vec<String>>() 96 | }; 97 | logging::log!("keys pressed: {:?}", keys_pressed_list()); 98 | }); 99 | 100 | #[cfg(not(feature = "ssr"))] 101 | node_ref.on_load(move |_| { 102 | let blur_listener = wasm_bindgen::closure::Closure::wrap(Box::new(move || { 103 | if cfg!(feature = "debug") { 104 | logging::log!("Window lost focus"); 105 | } 106 | keys_pressed.set_untracked(KeyPresses::default()); 107 | }) as Box<dyn Fn()>); 108 | 109 | let keydown_listener = 110 | wasm_bindgen::closure::Closure::wrap(Box::new(move |event: web_sys::KeyboardEvent| { 111 | keys_pressed.update(|keys| { 112 | let key = clean_key(&event); 113 | keys.key_map.insert(key.clone(), event); 114 | keys.last_key = Some(key); 115 | }); 116 | }) as Box<dyn Fn(_)>); 117 | let keyup_listener = 118 | wasm_bindgen::closure::Closure::wrap(Box::new(move |event: web_sys::KeyboardEvent| { 119 | keys_pressed.update(|keys| { 120 | let key = clean_key(&event); 121 | keys.key_map.remove(&key); 122 | keys.last_key = None; 123 | }); 124 | }) as Box<dyn Fn(_)>); 125 | 126 | if !allow_blur_event { 127 | window() 128 | .add_event_listener_with_callback("blur", blur_listener.as_ref().unchecked_ref()) 129 | .expect("Failed to add blur event listener"); 130 | } 131 | 132 | document() 133 | .add_event_listener_with_callback("keydown", keydown_listener.as_ref().unchecked_ref()) 134 | .expect("Failed to add keydown event listener"); 135 | document() 136 | .add_event_listener_with_callback("keyup", keyup_listener.as_ref().unchecked_ref()) 137 | .expect("Failed to add keyup event listener"); 138 | 139 | on_cleanup(move || { 140 | if !allow_blur_event { 141 | window() 142 | .remove_event_listener_with_callback( 143 | "blur", 144 | blur_listener.as_ref().unchecked_ref(), 145 | ) 146 | .expect("Failed to remove blur event listener"); 147 | blur_listener.forget(); 148 | } 149 | 150 | document() 151 | .remove_event_listener_with_callback( 152 | "keydown", 153 | keydown_listener.as_ref().unchecked_ref(), 154 | ) 155 | .expect("Failed to remove keydown event listener"); 156 | document() 157 | .remove_event_listener_with_callback( 158 | "keyup", 159 | keyup_listener.as_ref().unchecked_ref(), 160 | ) 161 | .expect("Failed to remove keyup event listener"); 162 | keydown_listener.forget(); 163 | keyup_listener.forget(); 164 | }); 165 | }); 166 | 167 | let hotkeys_context = HotkeysContext { 168 | #[cfg(not(feature = "ssr"))] 169 | keys_pressed, 170 | 171 | #[cfg(not(feature = "ssr"))] 172 | active_ref_target, 173 | 174 | #[cfg(not(feature = "ssr"))] 175 | set_ref_target, 176 | 177 | active_scopes, 178 | enable_scope, 179 | disable_scope, 180 | toggle_scope, 181 | }; 182 | 183 | provide_context(hotkeys_context); 184 | hotkeys_context 185 | } 186 | 187 | pub fn use_hotkeys_context() -> HotkeysContext { 188 | use_context::<HotkeysContext>().expect("expected hotkeys context") 189 | } 190 | 191 | #[cfg(not(feature = "ssr"))] 192 | fn clean_key(event: &web_sys::KeyboardEvent) -> String { 193 | if cfg!(feature = "use_key") { 194 | match event.key().as_str() { 195 | " " => "spacebar".to_string(), 196 | key => key.to_lowercase(), 197 | } 198 | } else { 199 | event.code().to_lowercase() 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /leptos_hotkeys/src/hotkey.rs: -------------------------------------------------------------------------------- 1 | use crate::KeyboardModifiers; 2 | use crate::{context::KeyPresses, types::Keys}; 3 | use core::str::FromStr; 4 | use std::collections::HashSet; 5 | use std::fmt::{Display, Formatter}; 6 | 7 | #[derive(Debug, PartialEq, Hash, Eq)] 8 | pub struct Hotkey { 9 | pub(crate) modifiers: KeyboardModifiers, 10 | pub(crate) keys: Keys, 11 | } 12 | 13 | impl Display for Hotkey { 14 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 15 | let keys = self 16 | .keys 17 | .iter() 18 | .map(|k| k.as_str()) 19 | .collect::<Vec<&str>>() 20 | .join("+"); 21 | 22 | match keys.is_empty() { 23 | true => write!(f, "{}", self.modifiers), 24 | false => write!(f, "{}{}", keys, self.modifiers), 25 | } 26 | } 27 | } 28 | 29 | impl Hotkey { 30 | pub fn new(key_combination: &str) -> Self { 31 | key_combination.parse().unwrap() 32 | } 33 | 34 | fn includes_key(&self, key: &String) -> bool { 35 | self.keys.iter().any(|k| k == key) 36 | } 37 | } 38 | 39 | impl FromStr for Hotkey { 40 | type Err = (); 41 | 42 | fn from_str(key_combination: &str) -> Result<Self, Self::Err> { 43 | let parts = key_combination 44 | .split('+') 45 | .map(|v| if v == " " { "spacebar" } else { v.trim() }) 46 | .collect::<Vec<&str>>(); 47 | 48 | let mut modifiers = KeyboardModifiers::default(); 49 | let mut keys = Vec::new(); 50 | 51 | for part in parts { 52 | match part.to_lowercase().as_str() { 53 | "controlleft" => modifiers.ctrl = true, 54 | "controlright" => modifiers.ctrl = true, 55 | "ctrl" => modifiers.ctrl = true, 56 | "control" => modifiers.ctrl = true, 57 | 58 | "alt" => modifiers.alt = true, 59 | "altleft" => modifiers.alt = true, 60 | "altright" => modifiers.alt = true, 61 | "option" => modifiers.alt = true, // macos variant 62 | 63 | "metaleft" => modifiers.meta = true, 64 | "metaright" => modifiers.meta = true, 65 | "meta" => modifiers.meta = true, 66 | "command" => modifiers.meta = true, // macos variant 67 | "cmd" => modifiers.meta = true, // macos variant 68 | "super" => modifiers.meta = true, // linux variant 69 | "win" => modifiers.meta = true, // windows variant 70 | 71 | "shiftleft" => modifiers.shift = true, 72 | "shiftright" => modifiers.shift = true, 73 | "shift" => modifiers.shift = true, 74 | 75 | "spacebar" | "space" | " " => keys.push("spacebar".to_string()), // spacebar key is " " 76 | 77 | key => keys.push(key.to_lowercase().to_string()), 78 | } 79 | } 80 | 81 | Ok(Hotkey { modifiers, keys }) 82 | } 83 | } 84 | 85 | #[cfg_attr(feature = "ssr", allow(dead_code))] 86 | pub(crate) fn is_last_key_match(parsed_keys: &HashSet<Hotkey>, pressed_keys: &KeyPresses) -> bool { 87 | pressed_keys.last_key.as_ref().is_some_and(|last_key| { 88 | parsed_keys 89 | .iter() 90 | .any(|hotkey| hotkey.includes_key(last_key)) 91 | }) 92 | } 93 | 94 | #[cfg_attr(feature = "ssr", allow(dead_code))] 95 | pub(crate) fn is_hotkey_match( 96 | hotkey: &Hotkey, 97 | pressed_keyset: &mut std::collections::BTreeMap<String, web_sys::KeyboardEvent>, 98 | ) -> bool { 99 | let mut modifiers_match = true; 100 | 101 | let is_ctrl_pressed = pressed_keyset.contains_key("controlleft") 102 | || pressed_keyset.contains_key("controlright") 103 | || pressed_keyset.contains_key("control"); 104 | if hotkey.modifiers.ctrl { 105 | modifiers_match &= is_ctrl_pressed; 106 | } else { 107 | modifiers_match &= !is_ctrl_pressed; 108 | } 109 | 110 | let is_shift_pressed = pressed_keyset.contains_key("shiftleft") 111 | || pressed_keyset.contains_key("shiftright") 112 | || pressed_keyset.contains_key("shift"); 113 | if hotkey.modifiers.shift { 114 | modifiers_match &= is_shift_pressed; 115 | } else { 116 | modifiers_match &= !is_shift_pressed; 117 | } 118 | 119 | let is_meta_pressed = pressed_keyset.contains_key("metaleft") 120 | || pressed_keyset.contains_key("metaright") 121 | || pressed_keyset.contains_key("meta") 122 | || pressed_keyset.contains_key("command") 123 | || pressed_keyset.contains_key("cmd") 124 | || pressed_keyset.contains_key("super") 125 | || pressed_keyset.contains_key("win"); 126 | if hotkey.modifiers.meta { 127 | modifiers_match &= is_meta_pressed; 128 | } else { 129 | modifiers_match &= !is_meta_pressed; 130 | } 131 | 132 | let is_alt_pressed = pressed_keyset.contains_key("altleft") 133 | || pressed_keyset.contains_key("altright") 134 | || pressed_keyset.contains_key("alt"); 135 | if hotkey.modifiers.alt { 136 | modifiers_match &= is_alt_pressed; 137 | } else { 138 | modifiers_match &= !is_alt_pressed; 139 | } 140 | 141 | if modifiers_match { 142 | let keys_match = hotkey.keys.iter().all(|key| { 143 | if let Some(event) = pressed_keyset.get_mut(key) { 144 | event.prevent_default(); 145 | true 146 | } else { 147 | false 148 | } 149 | }); 150 | 151 | modifiers_match && keys_match 152 | } else { 153 | false 154 | } 155 | } 156 | 157 | #[cfg(test)] 158 | mod tests { 159 | use super::*; 160 | 161 | fn from_string_test_cases() -> Vec<(String, Hotkey)> { 162 | vec![ 163 | ( 164 | "shift+r+meta".to_string(), 165 | Hotkey { 166 | modifiers: KeyboardModifiers { 167 | shift: true, 168 | ctrl: false, 169 | alt: false, 170 | meta: true, 171 | }, 172 | keys: vec!["r".into()], 173 | }, 174 | ), 175 | ( 176 | "alt + o + T".to_string(), 177 | Hotkey { 178 | modifiers: KeyboardModifiers { 179 | shift: false, 180 | ctrl: false, 181 | alt: true, 182 | meta: false, 183 | }, 184 | keys: vec!["o".into(), "t".into()], 185 | }, 186 | ), 187 | ( 188 | "control+L+ 8 + 8".to_string(), 189 | Hotkey { 190 | modifiers: KeyboardModifiers { 191 | shift: false, 192 | ctrl: true, 193 | alt: false, 194 | meta: false, 195 | }, 196 | keys: vec!["l".into(), "8".into(), "8".into()], 197 | }, 198 | ), 199 | ( 200 | "shift+ctrl+alt+t".to_string(), 201 | Hotkey { 202 | modifiers: KeyboardModifiers { 203 | shift: true, 204 | ctrl: true, 205 | alt: true, 206 | meta: false, 207 | }, 208 | keys: vec!["t".into()], 209 | }, 210 | ), 211 | ( 212 | "command+k".to_string(), 213 | Hotkey { 214 | modifiers: KeyboardModifiers { 215 | shift: false, 216 | ctrl: false, 217 | alt: false, 218 | meta: true, 219 | }, 220 | keys: vec!["k".into()], 221 | }, 222 | ), 223 | ( 224 | "cmd+k".to_string(), 225 | Hotkey { 226 | modifiers: KeyboardModifiers { 227 | shift: false, 228 | ctrl: false, 229 | alt: false, 230 | meta: true, 231 | }, 232 | keys: vec!["k".into()], 233 | }, 234 | ), 235 | ] 236 | } 237 | 238 | #[test] 239 | fn hotkey_constructor() { 240 | for (input, expected) in from_string_test_cases() { 241 | let hotkey = Hotkey::new(&input); 242 | assert_eq!(hotkey, expected); 243 | 244 | let hotkey: Hotkey = input.parse().unwrap(); 245 | assert_eq!(hotkey, expected); 246 | } 247 | } 248 | 249 | #[test] 250 | fn hotkey_from_string() { 251 | for (input, expected) in from_string_test_cases() { 252 | let hotkey: Hotkey = input.parse().unwrap(); 253 | assert_eq!(hotkey, expected); 254 | } 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /leptos_hotkeys/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod context; 2 | mod hotkey; 3 | mod macros; 4 | mod types; 5 | mod use_hotkeys; 6 | 7 | pub use context::{provide_hotkeys_context, use_hotkeys_context, HotkeysContext}; 8 | pub use hotkey::Hotkey; 9 | pub use types::KeyboardModifiers; 10 | pub use use_hotkeys::{use_hotkeys_ref, use_hotkeys_scoped}; 11 | -------------------------------------------------------------------------------- /leptos_hotkeys/src/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! scopes { 3 | () => { 4 | { 5 | let mut set = std::collections::HashSet::<String>::new(); 6 | set.insert("*".to_string()); 7 | set 8 | } 9 | }; 10 | 11 | ($($lit:literal),+ $(,)?) => { 12 | { 13 | let mut temp_set = std::collections::HashSet::<String>::new(); 14 | temp_set.insert("*".to_string()); 15 | $( 16 | temp_set.insert($lit.to_string()); 17 | )+ 18 | temp_set 19 | } 20 | }; 21 | 22 | ($($expr:expr),+ $(,)?) => { 23 | { 24 | let mut temp_set = std::collections::HashSet::<String>::new(); 25 | temp_set.insert("*".to_string()); 26 | $( 27 | temp_set.insert($expr); 28 | )+ 29 | temp_set 30 | } 31 | }; 32 | } 33 | 34 | #[macro_export] 35 | macro_rules! use_hotkeys { 36 | (($key_combo:literal) => $($code:tt)*) => { 37 | { 38 | $crate::use_hotkeys_scoped( 39 | $key_combo.to_string(), 40 | ::leptos::Callback::new( 41 | $($code)* 42 | ), 43 | vec!["*".to_string()] 44 | ); 45 | } 46 | }; 47 | 48 | (($key_combo:expr) => $($code:tt)*) => { 49 | { 50 | use_hotkeys_scoped( 51 | $key_combo.to_string(), 52 | ::leptos::Callback::new( 53 | $($code)* 54 | ), 55 | vec!["*".to_string()] 56 | ); 57 | } 58 | }; 59 | 60 | (($key_combo:expr $(, $scopes:literal)*) => $($code:tt)*) => { 61 | { 62 | $crate::use_hotkeys_scoped( 63 | $key_combo.to_string(), 64 | ::leptos::Callback::new( 65 | $($code)* 66 | ), 67 | vec![$($scopes.to_string(),)*] 68 | ); 69 | } 70 | }; 71 | 72 | (($key_combo:literal $(, $scopes:literal)*) => $($code:tt)*) => { 73 | { 74 | $crate::use_hotkeys_scoped( 75 | $key_combo.to_string(), 76 | ::leptos::Callback::new( 77 | $($code)* 78 | ), 79 | vec![$($scopes.to_string(),)*] 80 | ); 81 | } 82 | }; 83 | 84 | (($key_combo:literal $(, $scopes:expr)*) => $($code:tt)*) => { 85 | { 86 | $crate::use_hotkeys_scoped( 87 | $key_combo.to_string(), 88 | ::leptos::Callback::new( 89 | $($code)* 90 | ), 91 | vec![$($scopes.to_string(),)*] 92 | ); 93 | } 94 | }; 95 | 96 | (($key_combo:expr $(, $scopes:expr)*) => $($code:tt)*) => { 97 | { 98 | $crate::use_hotkeys_scoped( 99 | $key_combo.to_string(), 100 | ::leptos::Callback::new( 101 | $($code)* 102 | ), 103 | vec![$($scopes.to_string(),)*] 104 | ); 105 | } 106 | }; 107 | } 108 | 109 | #[macro_export] 110 | macro_rules! use_hotkeys_ref { 111 | (($node_ref:expr, $key_combo:literal) => $($code:tt)*) => { 112 | { 113 | $crate::use_hotkeys_ref( 114 | $node_ref, 115 | $key_combo.to_string(), 116 | ::leptos::Callback::new( 117 | $($code)* 118 | ), 119 | vec!["*".to_string()] 120 | ) 121 | } 122 | }; 123 | 124 | (($node_ref:expr, $key_combo:expr) => $($code:tt)*) => { 125 | { 126 | $crate::use_hotkeys_ref( 127 | $node_ref, 128 | $key_combo.to_string(), 129 | ::leptos::Callback::new( 130 | $($code)* 131 | ), 132 | vec!["*".to_string()] 133 | ) 134 | } 135 | }; 136 | 137 | (($node_ref:expr, $key_combo:expr $(, $scopes:literal)*) => $($code:tt)*) => { 138 | { 139 | $crate::use_hotkeys_ref( 140 | $node_ref, 141 | $key_combo.to_string(), 142 | ::leptos::Callback::new( 143 | $($code)* 144 | ), 145 | vec![$($scopes.to_string(),)*] 146 | ) 147 | } 148 | }; 149 | 150 | (($node_ref:expr, $key_combo:literal $(, $scopes:literal)*) => $($code:tt)*) => { 151 | { 152 | $crate::use_hotkeys_ref( 153 | $node_ref, 154 | $key_combo.to_string(), 155 | ::leptos::Callback::new( 156 | $($code)* 157 | ), 158 | vec![$($scopes.to_string(),)*] 159 | ) 160 | } 161 | }; 162 | 163 | (($key_combo:literal $(, $scopes:expr)*) => $($code:tt)*) => { 164 | { 165 | $crate::use_hotkeys_ref( 166 | $key_combo.to_string(), 167 | ::leptos::Callback::new( 168 | $($code)* 169 | ), 170 | vec![$($scopes.to_string(),)*] 171 | ) 172 | } 173 | }; 174 | 175 | (($key_combo:expr $(, $scopes:expr)*) => $($code:tt)*) => { 176 | { 177 | $crate::use_hotkeys_ref( 178 | $key_combo.to_string(), 179 | ::leptos::Callback::new( 180 | $($code)* 181 | ), 182 | vec![$($scopes.to_string(),)*] 183 | ) 184 | } 185 | }; 186 | } 187 | -------------------------------------------------------------------------------- /leptos_hotkeys/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Display, Formatter, Result}; 2 | 3 | pub type Keys = Vec<String>; 4 | 5 | #[derive(Debug, PartialEq, Hash, Eq, Default)] 6 | pub struct KeyboardModifiers { 7 | pub(crate) alt: bool, 8 | pub(crate) ctrl: bool, 9 | pub(crate) meta: bool, 10 | pub(crate) shift: bool, 11 | } 12 | 13 | impl Display for KeyboardModifiers { 14 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 15 | let mut modifiers = Vec::new(); 16 | 17 | if self.alt { 18 | modifiers.push("Alt"); 19 | } 20 | if self.ctrl { 21 | modifiers.push("Ctrl"); 22 | } 23 | if self.meta { 24 | modifiers.push("Meta"); 25 | } 26 | if self.shift { 27 | modifiers.push("Shift"); 28 | } 29 | 30 | match modifiers.is_empty() { 31 | true => write!(f, ""), 32 | false => write!(f, "+{}", modifiers.join("+")), 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leptos_hotkeys/src/use_hotkeys.rs: -------------------------------------------------------------------------------- 1 | use leptos::{html::ElementDescriptor, *}; 2 | 3 | pub fn use_hotkeys_scoped( 4 | #[cfg_attr(feature = "ssr", allow(unused_variables))] key_combination: String, 5 | #[cfg_attr(feature = "ssr", allow(unused_variables))] on_triggered: Callback<()>, 6 | #[cfg_attr(feature = "ssr", allow(unused_variables))] scopes: Vec<String>, 7 | ) { 8 | #[cfg(not(feature = "ssr"))] 9 | { 10 | use crate::hotkey::{is_hotkey_match, is_last_key_match}; 11 | use crate::{use_hotkeys_context, Hotkey}; 12 | use std::collections::HashSet; 13 | 14 | let parsed_keys: HashSet<Hotkey> = key_combination.split(',').map(Hotkey::new).collect(); 15 | 16 | let hotkeys_context = use_hotkeys_context(); 17 | 18 | create_effect(move |_| { 19 | let active_scopes = hotkeys_context.active_scopes.get(); 20 | let within_scope = scopes.iter().any(|scope| active_scopes.contains(scope)); 21 | 22 | if !within_scope { 23 | return; 24 | } 25 | 26 | let mut keys_pressed = hotkeys_context.keys_pressed.get(); 27 | if !is_last_key_match(&parsed_keys, &keys_pressed) { 28 | return; 29 | } 30 | 31 | if let Some(matching_hotkey) = parsed_keys 32 | .iter() 33 | .find(|hotkey| is_hotkey_match(hotkey, &mut keys_pressed.key_map)) 34 | { 35 | if cfg!(feature = "debug") { 36 | let message = format!("%cfiring hotkey: {}", &matching_hotkey); 37 | web_sys::console::log_2( 38 | &wasm_bindgen::JsValue::from_str(&message), 39 | &wasm_bindgen::JsValue::from_str("color: #39FF14;"), 40 | ); 41 | } 42 | Callable::call(&on_triggered, ()); 43 | } 44 | }); 45 | } 46 | } 47 | 48 | pub fn use_hotkeys_ref<T>( 49 | #[cfg_attr(feature = "ssr", allow(unused_variables))] node_ref: NodeRef<T>, 50 | #[cfg_attr(feature = "ssr", allow(unused_variables))] key_combination: String, 51 | #[cfg_attr(feature = "ssr", allow(unused_variables))] on_triggered: Callback<()>, 52 | #[cfg_attr(feature = "ssr", allow(unused_variables))] scopes: Vec<String>, 53 | ) where 54 | T: ElementDescriptor + 'static + Clone, 55 | { 56 | #[cfg(not(feature = "ssr"))] 57 | create_effect(move |_| { 58 | use crate::hotkey::{is_hotkey_match, is_last_key_match}; 59 | use crate::{use_hotkeys_context, Hotkey}; 60 | use leptos::ev::DOMEventResponder; 61 | use std::collections::HashSet; 62 | 63 | let parsed_keys: HashSet<Hotkey> = key_combination.split(',').map(Hotkey::new).collect(); 64 | let scopes = scopes.clone(); 65 | if let Some(element) = node_ref.get() { 66 | let keydown_closure = move |_event: web_sys::KeyboardEvent| { 67 | let hotkeys_context = use_hotkeys_context(); 68 | let active_scopes = hotkeys_context.active_scopes.get(); 69 | let mut pressed_keys = hotkeys_context.keys_pressed.get(); 70 | let within_scope = scopes.iter().any(|scope| active_scopes.contains(scope)); 71 | 72 | if !within_scope { 73 | return; 74 | } 75 | 76 | if !is_last_key_match(&parsed_keys, &pressed_keys) { 77 | return; 78 | } 79 | 80 | if let Some(matching_hotkey) = parsed_keys 81 | .iter() 82 | .find(|hotkey| is_hotkey_match(hotkey, &mut pressed_keys.key_map)) 83 | { 84 | if cfg!(feature = "debug") { 85 | let message = format!("%cfiring hotkey: {}", &matching_hotkey); 86 | web_sys::console::log_2( 87 | &wasm_bindgen::JsValue::from_str(&message), 88 | &wasm_bindgen::JsValue::from_str("color: #39FF14;"), 89 | ); 90 | } 91 | Callable::call(&on_triggered, ()); 92 | } 93 | }; 94 | 95 | // needs `leptos::ev::DOMEventResponder` 96 | let _ = element.add(ev::keydown, keydown_closure); 97 | } 98 | }); 99 | } 100 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | --------------------------------------------------------------------------------