mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: support equation block (#2903)
This commit is contained in:
parent
7f74fd6149
commit
18ed553296
310
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
310
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
@ -105,7 +105,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||
[[package]]
|
||||
name = "appflowy-integrate"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -145,9 +145,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
@ -168,7 +168,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -179,7 +179,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -203,7 +203,7 @@ dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -600,7 +600,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -827,7 +827,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -837,7 +837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "599aa35200ffff8f04c1925aa1acc92fa2e08874379ef42e210a80e527e60838"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml 0.7.4",
|
||||
"toml 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -886,9 +886,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e70d3ad08698a0568b0562f22710fe6bfc1f4a61a367c77d0398c562eadd453a"
|
||||
checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
@ -935,7 +935,7 @@ checksum = "cf9cc2b23599e6d7479755f3594285efb3f74a1bdca7a7374948bc831e23a552"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz-build 0.1.0",
|
||||
"phf 0.11.1",
|
||||
"phf 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -956,8 +956,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9998fb9f7e9b2111641485bf8beb32f92945f97f92a3d061f744cfef335f751"
|
||||
dependencies = [
|
||||
"parse-zoneinfo",
|
||||
"phf 0.11.1",
|
||||
"phf_codegen 0.11.1",
|
||||
"phf 0.11.2",
|
||||
"phf_codegen 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1030,7 +1030,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -1048,7 +1048,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-client-ws"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"collab-sync",
|
||||
@ -1066,7 +1066,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-database"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1092,7 +1092,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1104,7 +1104,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-document"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -1122,7 +1122,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-folder"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@ -1142,7 +1142,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-persistence"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"chrono",
|
||||
@ -1162,7 +1162,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-plugins"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1193,7 +1193,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-sync"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d1882d#d1882d6784a8863419727be92c29923cd175fd50"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"collab",
|
||||
@ -1292,21 +1292,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
|
||||
checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
|
||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@ -1397,7 +1396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1452,7 +1451,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1463,7 +1462,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1629,7 +1628,7 @@ checksum = "80663502655af01a2902dff3f06869330782267924bf1788410b74edcd93770a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc_version",
|
||||
"toml 0.7.4",
|
||||
"toml 0.7.5",
|
||||
"vswhom",
|
||||
"winreg 0.11.0",
|
||||
]
|
||||
@ -1655,6 +1654,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
@ -1868,7 +1873,7 @@ dependencies = [
|
||||
"flowy-notification",
|
||||
"flowy-task",
|
||||
"futures",
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"lazy_static",
|
||||
"lib-dispatch",
|
||||
"lib-infra",
|
||||
@ -1916,7 +1921,7 @@ dependencies = [
|
||||
"flowy-derive",
|
||||
"flowy-error",
|
||||
"flowy-notification",
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"lib-dispatch",
|
||||
"nanoid",
|
||||
"parking_lot 0.12.1",
|
||||
@ -2213,7 +2218,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2294,7 +2299,7 @@ dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2311,7 +2316,7 @@ dependencies = [
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2325,7 +2330,7 @@ dependencies = [
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2337,15 +2342,15 @@ dependencies = [
|
||||
"gdk-sys",
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
"x11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3e123d9ae7c02966b4d892e550bdc32164f05853cd40ab570650ad600596a8a"
|
||||
checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@ -2400,9 +2405,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
@ -2430,7 +2435,7 @@ dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@ -2476,7 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2517,7 +2522,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2558,7 +2563,7 @@ dependencies = [
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2577,9 +2582,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.19"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
|
||||
checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@ -2587,7 +2592,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@ -2612,6 +2617,12 @@ dependencies = [
|
||||
"ahash 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
@ -2732,9 +2743,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.26"
|
||||
version = "0.14.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@ -2834,17 +2845,6 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
@ -2896,6 +2896,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "infer"
|
||||
version = "0.12.0"
|
||||
@ -2927,9 +2937,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.7.2"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
@ -3145,9 +3155,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lib0"
|
||||
version = "0.16.5"
|
||||
version = "0.16.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daf23122cb1c970b77ea6030eac5e328669415b65d2ab245c99bfb110f9d62dc"
|
||||
checksum = "49d27ae71668a38ad135d463703ce0c5d9cf5a29f9a02add7a0dac6ebb523196"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -3156,9 +3166,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.146"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@ -3631,9 +3641,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.54"
|
||||
version = "0.10.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019"
|
||||
checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@ -3652,7 +3662,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3663,9 +3673,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.88"
|
||||
version = "0.9.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617"
|
||||
checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@ -3717,7 +3727,7 @@ dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3797,9 +3807,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70"
|
||||
checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
@ -3807,9 +3817,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb"
|
||||
checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@ -3817,22 +3827,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e"
|
||||
checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
|
||||
checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
@ -3863,11 +3873,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
|
||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||
dependencies = [
|
||||
"phf_shared 0.11.1",
|
||||
"phf_shared 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3892,12 +3902,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
|
||||
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
|
||||
dependencies = [
|
||||
"phf_generator 0.11.1",
|
||||
"phf_shared 0.11.1",
|
||||
"phf_generator 0.11.2",
|
||||
"phf_shared 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3922,11 +3932,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
|
||||
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
|
||||
dependencies = [
|
||||
"phf_shared 0.11.1",
|
||||
"phf_shared 0.11.2",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
@ -3979,9 +3989,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
|
||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
@ -4003,7 +4013,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4031,7 +4041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"line-wrap",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
@ -4074,12 +4084,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.6"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1"
|
||||
checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4133,9 +4143,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.60"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
|
||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -4582,11 +4592,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.29.1"
|
||||
version = "1.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc"
|
||||
checksum = "d0446843641c69436765a35a5a77088e28c2e6a12da93e84aa3ab1cd4aa5a042"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.3",
|
||||
"arrayvec 0.7.4",
|
||||
"borsh",
|
||||
"bytecheck",
|
||||
"byteorder",
|
||||
@ -4600,9 +4610,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal_macros"
|
||||
version = "1.29.1"
|
||||
version = "1.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e773fd3da1ed42472fdf3cfdb4972948a555bc3d73f5e0bdb99d17e7b54c687"
|
||||
checksum = "7ca5c398d85f83b9a44de754a2048625a8c5eafcf070da7b8f116b685e2f6608"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"rust_decimal",
|
||||
@ -4861,14 +4871,14 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.96"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
|
||||
dependencies = [
|
||||
"itoa 1.0.6",
|
||||
"ryu",
|
||||
@ -4883,14 +4893,14 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
|
||||
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@ -4916,7 +4926,7 @@ dependencies = [
|
||||
"base64 0.21.2",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
@ -4932,7 +4942,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4999,9 +5009,9 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.6"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
|
||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@ -5245,9 +5255,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.18"
|
||||
version = "2.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5269,14 +5279,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.1.0"
|
||||
version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2"
|
||||
checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3"
|
||||
dependencies = [
|
||||
"cfg-expr 0.15.2",
|
||||
"cfg-expr 0.15.3",
|
||||
"heck 0.4.1",
|
||||
"pkg-config",
|
||||
"toml 0.7.4",
|
||||
"toml 0.7.5",
|
||||
"version-compare 0.1.1",
|
||||
]
|
||||
|
||||
@ -5357,15 +5367,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.7"
|
||||
version = "0.12.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5"
|
||||
checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac"
|
||||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "1.4.0"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc35893c7e08d9564a9206bd52182dce031b0d5132dc946b3e166e00d03f8cfe"
|
||||
checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cocoa",
|
||||
@ -5542,7 +5552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb"
|
||||
dependencies = [
|
||||
"embed-resource",
|
||||
"toml 0.7.4",
|
||||
"toml 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5626,7 +5636,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5729,7 +5739,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5836,9 +5846,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
|
||||
checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@ -5848,20 +5858,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
|
||||
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.19.10"
|
||||
version = "0.19.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
|
||||
checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.0.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@ -5922,13 +5932,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.24"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
|
||||
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6189,7 +6199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna 0.4.0",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
@ -6218,11 +6228,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "validator"
|
||||
version = "0.16.0"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ad5bf234c7d3ad1042e5252b7eddb2c4669ee23f32c7dd0e9b7705f07ef591"
|
||||
checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd"
|
||||
dependencies = [
|
||||
"idna 0.2.3",
|
||||
"idna",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
@ -6345,7 +6355,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -6379,7 +6389,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.22",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -6444,7 +6454,7 @@ dependencies = [
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
"soup2-sys",
|
||||
"system-deps 6.1.0",
|
||||
"system-deps 6.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6887,9 +6897,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "yrs"
|
||||
version = "0.16.5"
|
||||
version = "0.16.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c2aef2bf89b4f7c003f9c73f1c8097427ca32e1d006443f3f607f11e79a797b"
|
||||
checksum = "04e5192da97bd1621497ddf66b42475fb0cc44b6ebcf64510f0d3827c0b15cad"
|
||||
dependencies = [
|
||||
"atomic_refcell",
|
||||
"lib0",
|
||||
|
@ -6,6 +6,8 @@ import BlockMenuTurnInto from '$app/components/document/BlockSideToolbar/BlockMe
|
||||
import TextField from '@mui/material/TextField';
|
||||
import { Keyboard } from '$app/constants/document/keyboard';
|
||||
import { selectOptionByUpDown } from '$app/utils/document/menu';
|
||||
import { useSubscribeNode } from '$app/components/document/_shared/SubscribeNode.hooks';
|
||||
import { BlockType } from '$app/interfaces/document';
|
||||
|
||||
enum BlockMenuOption {
|
||||
Duplicate = 'Duplicate',
|
||||
@ -22,6 +24,7 @@ interface Option {
|
||||
|
||||
function BlockMenu({ id, onClose }: { id: string; onClose: () => void }) {
|
||||
const { handleDelete, handleDuplicate } = useBlockMenu(id);
|
||||
const { node } = useSubscribeNode(id);
|
||||
const [subMenuOpened, setSubMenuOpened] = useState(false);
|
||||
const [hovered, setHovered] = useState<BlockMenuOption | null>(null);
|
||||
|
||||
@ -39,29 +42,36 @@ function BlockMenu({ id, onClose }: { id: string; onClose: () => void }) {
|
||||
[onClose]
|
||||
);
|
||||
|
||||
const excludeTurnIntoBlock = useMemo(() => {
|
||||
return [BlockType.DividerBlock].includes(node.type);
|
||||
}, [node.type]);
|
||||
|
||||
const options: Option[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
operate: () => {
|
||||
return handleClick({ operate: handleDelete });
|
||||
() =>
|
||||
[
|
||||
{
|
||||
operate: () => {
|
||||
return handleClick({ operate: handleDelete });
|
||||
},
|
||||
title: 'Delete',
|
||||
icon: <Delete />,
|
||||
key: BlockMenuOption.Delete,
|
||||
},
|
||||
title: 'Delete',
|
||||
icon: <Delete />,
|
||||
key: BlockMenuOption.Delete,
|
||||
},
|
||||
{
|
||||
operate: () => {
|
||||
return handleClick({ operate: handleDuplicate });
|
||||
{
|
||||
operate: () => {
|
||||
return handleClick({ operate: handleDuplicate });
|
||||
},
|
||||
title: 'Duplicate',
|
||||
icon: <ContentCopy />,
|
||||
key: BlockMenuOption.Duplicate,
|
||||
},
|
||||
title: 'Duplicate',
|
||||
icon: <ContentCopy />,
|
||||
key: BlockMenuOption.Duplicate,
|
||||
},
|
||||
{
|
||||
key: BlockMenuOption.TurnInto,
|
||||
},
|
||||
],
|
||||
[handleClick, handleDelete, handleDuplicate]
|
||||
excludeTurnIntoBlock
|
||||
? null
|
||||
: {
|
||||
key: BlockMenuOption.TurnInto,
|
||||
},
|
||||
].filter((item) => item !== null) as Option[],
|
||||
[excludeTurnIntoBlock, handleClick, handleDelete, handleDuplicate]
|
||||
);
|
||||
|
||||
const onKeyDown = useCallback(
|
||||
@ -131,7 +141,10 @@ function BlockMenu({ id, onClose }: { id: string; onClose: () => void }) {
|
||||
}}
|
||||
menuOpened={subMenuOpened}
|
||||
isHovered={hovered === BlockMenuOption.TurnInto}
|
||||
onClose={() => setSubMenuOpened(false)}
|
||||
onClose={() => {
|
||||
setSubMenuOpened(false);
|
||||
onClose();
|
||||
}}
|
||||
id={id}
|
||||
/>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { MouseEvent, useRef } from 'react';
|
||||
import React, { MouseEvent, useEffect, useRef } from 'react';
|
||||
import { ArrowRight, Transform } from '@mui/icons-material';
|
||||
import MenuItem from '$app/components/document/_shared/MenuItem';
|
||||
import TurnIntoPopover from '$app/components/document/_shared/TurnInto';
|
||||
@ -17,8 +17,22 @@ function BlockMenuTurnInto({
|
||||
menuOpened: boolean;
|
||||
}) {
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
const open = isHovered && menuOpened && Boolean(ref.current);
|
||||
const [anchorPosition, setAnchorPosition] = React.useState<{ top: number; left: number }>();
|
||||
const open = Boolean(anchorPosition);
|
||||
|
||||
useEffect(() => {
|
||||
if (isHovered && menuOpened) {
|
||||
const rect = ref.current?.getBoundingClientRect();
|
||||
|
||||
if (!rect) return;
|
||||
setAnchorPosition({
|
||||
top: rect.top + rect.height / 2,
|
||||
left: rect.left + rect.width,
|
||||
});
|
||||
} else {
|
||||
setAnchorPosition(undefined);
|
||||
}
|
||||
}, [isHovered, menuOpened]);
|
||||
return (
|
||||
<>
|
||||
<MenuItem
|
||||
@ -45,11 +59,8 @@ function BlockMenuTurnInto({
|
||||
},
|
||||
}}
|
||||
onClose={onClose}
|
||||
anchorEl={ref.current}
|
||||
anchorOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
anchorReference={'anchorPosition'}
|
||||
anchorPosition={anchorPosition}
|
||||
transformOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'left',
|
||||
|
@ -40,6 +40,10 @@ export function useBlockSideToolbar({ container }: { container: HTMLDivElement }
|
||||
top = headingBlockTopOffset[nodeData.level];
|
||||
}
|
||||
|
||||
if (node.type === BlockType.DividerBlock) {
|
||||
top = -3;
|
||||
}
|
||||
|
||||
setStyle({
|
||||
opacity: '1',
|
||||
pointerEvents: 'auto',
|
||||
@ -99,39 +103,47 @@ function getNodeIdByPoint(x: number, y: number) {
|
||||
: null;
|
||||
}
|
||||
|
||||
const origin: {
|
||||
anchorOrigin: PopoverOrigin;
|
||||
transformOrigin: PopoverOrigin;
|
||||
} = {
|
||||
anchorOrigin: {
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
},
|
||||
transformOrigin: {
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
},
|
||||
const transformOrigin: PopoverOrigin = {
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
};
|
||||
|
||||
export function usePopover() {
|
||||
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
|
||||
const [anchorPosition, setAnchorPosition] = React.useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
}>();
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
setAnchorEl(null);
|
||||
setAnchorPosition(undefined);
|
||||
}, []);
|
||||
|
||||
const handleOpen = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
setAnchorEl(e.currentTarget);
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
|
||||
setAnchorPosition({
|
||||
top: rect.top + rect.height,
|
||||
left: rect.left + rect.width,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const open = Boolean(anchorPosition);
|
||||
|
||||
const onMouseDown = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
anchorEl,
|
||||
anchorPosition,
|
||||
onClose,
|
||||
open,
|
||||
handleOpen,
|
||||
...origin,
|
||||
anchorReference: 'anchorPosition' as const,
|
||||
transformOrigin,
|
||||
onMouseDown,
|
||||
disableRestoreFocus: true,
|
||||
disableAutoFocus: true,
|
||||
disableEnforceFocus: true,
|
||||
};
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { addBlockBelowClickThunk } from '$app_reducers/document/async-actions/menu';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
import { RANGE_NAME, RECT_RANGE_NAME } from '$app/constants/document/name';
|
||||
import { setRectSelectionThunk } from '$app_reducers/document/async-actions/rect_selection';
|
||||
|
||||
export default function BlockSideToolbar({ container }: { container: HTMLDivElement }) {
|
||||
const dispatch = useAppDispatch();
|
||||
@ -22,9 +23,6 @@ export default function BlockSideToolbar({ container }: { container: HTMLDivElem
|
||||
);
|
||||
const { handleOpen, ...popoverProps } = usePopover();
|
||||
|
||||
// prevent popover from showing when anchorEl is not in DOM
|
||||
const showPopover = popoverProps.anchorEl ? document.contains(popoverProps.anchorEl) : true;
|
||||
|
||||
if (!nodeId || isDragging) return null;
|
||||
|
||||
return (
|
||||
@ -65,11 +63,12 @@ export default function BlockSideToolbar({ container }: { container: HTMLDivElem
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (!nodeId) return;
|
||||
dispatch(
|
||||
rectSelectionActions.setSelectionById({
|
||||
setRectSelectionThunk({
|
||||
docId,
|
||||
blockId: nodeId,
|
||||
selection: [nodeId],
|
||||
})
|
||||
);
|
||||
|
||||
handleOpen(e);
|
||||
}}
|
||||
>
|
||||
@ -78,11 +77,9 @@ export default function BlockSideToolbar({ container }: { container: HTMLDivElem
|
||||
</div>
|
||||
</Portal>
|
||||
|
||||
{showPopover && (
|
||||
<Popover {...popoverProps}>
|
||||
<BlockMenu id={nodeId} onClose={popoverProps.onClose} />
|
||||
</Popover>
|
||||
)}
|
||||
<Popover {...popoverProps}>
|
||||
<BlockMenu id={nodeId} onClose={popoverProps.onClose} />
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,10 @@ export function useBlockSlash() {
|
||||
const { docId } = useSubscribeDocument();
|
||||
|
||||
const { blockId, visible, slashText, hoverOption } = useSubscribeSlash();
|
||||
const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null);
|
||||
const [anchorPosition, setAnchorPosition] = React.useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
}>();
|
||||
|
||||
useEffect(() => {
|
||||
if (blockId && visible) {
|
||||
@ -19,11 +22,17 @@ export function useBlockSlash() {
|
||||
const el = blockEl.querySelector(`[role="textbox"]`) as HTMLElement;
|
||||
|
||||
if (el) {
|
||||
setAnchorEl(el);
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
setAnchorPosition({
|
||||
top: rect.top + rect.height,
|
||||
left: rect.left,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
setAnchorEl(null);
|
||||
|
||||
setAnchorPosition(undefined);
|
||||
}, [blockId, visible]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -43,11 +52,11 @@ export function useBlockSlash() {
|
||||
dispatch(slashCommandActions.closeSlashCommand(docId));
|
||||
}, [dispatch, docId]);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const open = Boolean(anchorPosition);
|
||||
|
||||
return {
|
||||
open,
|
||||
anchorEl,
|
||||
anchorPosition,
|
||||
onClose,
|
||||
blockId,
|
||||
searchText,
|
||||
|
@ -5,18 +5,15 @@ import { useBlockSlash } from '$app/components/document/BlockSlash/index.hooks';
|
||||
import { Keyboard } from '$app/constants/document/keyboard';
|
||||
|
||||
function BlockSlash({ container }: { container: HTMLDivElement }) {
|
||||
const { blockId, open, onClose, anchorEl, searchText, hoverOption } = useBlockSlash();
|
||||
const { blockId, open, onClose, anchorPosition, searchText, hoverOption } = useBlockSlash();
|
||||
|
||||
if (!blockId) return null;
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
anchorReference={'anchorPosition'}
|
||||
anchorPosition={anchorPosition}
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'left',
|
||||
|
@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { BlockType, NestedBlock } from '$app/interfaces/document';
|
||||
import KatexMath from '$app/components/document/_shared/KatexMath';
|
||||
import Popover from '@mui/material/Popover';
|
||||
import EquationEditContent from '$app/components/document/_shared/TemporaryInput/EquationEditContent';
|
||||
import { useEquationBlock } from '$app/components/document/EquationBlock/useEquationBlock';
|
||||
import { Functions } from '@mui/icons-material';
|
||||
|
||||
function EquationBlock({ node }: { node: NestedBlock<BlockType.EquationBlock> }) {
|
||||
const { ref, value, onChange, onOpenPopover, open, anchorPosition, onConfirm, onClosePopover } =
|
||||
useEquationBlock(node);
|
||||
|
||||
const formula = open ? value : node.data.formula;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={ref}
|
||||
onClick={onOpenPopover}
|
||||
className={'flex min-h-[59px] cursor-pointer items-center justify-center overflow-hidden hover:bg-main-selector'}
|
||||
>
|
||||
{formula ? (
|
||||
<KatexMath latex={formula} />
|
||||
) : (
|
||||
<span className={'flex text-shade-2'}>
|
||||
<Functions />
|
||||
<span>Add a TeX equation</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Popover
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClose={onClosePopover}
|
||||
open={open}
|
||||
anchorReference={'anchorPosition'}
|
||||
anchorPosition={anchorPosition}
|
||||
>
|
||||
<EquationEditContent
|
||||
placeholder={'c = \\pm\\sqrt{a^2 + b^2\\text{ if }a\\neq 0\\text{ or }b\\neq 0}'}
|
||||
multiline={true}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onConfirm={onConfirm}
|
||||
/>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default EquationBlock;
|
@ -0,0 +1,71 @@
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { BlockType, NestedBlock } from '$app/interfaces/document';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
import { useAppDispatch } from '$app/stores/store';
|
||||
import { updateNodeDataThunk } from '$app_reducers/document/async-actions';
|
||||
import { rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { setRectSelectionThunk } from '$app_reducers/document/async-actions/rect_selection';
|
||||
|
||||
export function useEquationBlock(node: NestedBlock<BlockType.EquationBlock>) {
|
||||
const { controller, docId } = useSubscribeDocument();
|
||||
const id = node.id;
|
||||
const dispatch = useAppDispatch();
|
||||
const formula = node.data.formula;
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [value, setValue] = useState(formula);
|
||||
|
||||
const [anchorPosition, setAnchorPosition] = useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
}>();
|
||||
const open = Boolean(anchorPosition);
|
||||
|
||||
const onChange = useCallback((newVal: string) => {
|
||||
setValue(newVal);
|
||||
}, []);
|
||||
|
||||
const onOpenPopover = useCallback(() => {
|
||||
setValue(formula);
|
||||
const rect = ref.current?.getBoundingClientRect();
|
||||
|
||||
if (!rect) return;
|
||||
setAnchorPosition({
|
||||
top: rect.top + rect.height,
|
||||
left: rect.left + rect.width / 2,
|
||||
});
|
||||
}, [formula]);
|
||||
|
||||
const onClosePopover = useCallback(() => {
|
||||
setAnchorPosition(undefined);
|
||||
dispatch(
|
||||
setRectSelectionThunk({
|
||||
docId,
|
||||
selection: [id],
|
||||
})
|
||||
);
|
||||
}, [dispatch, id, docId]);
|
||||
|
||||
const onConfirm = useCallback(async () => {
|
||||
await dispatch(
|
||||
updateNodeDataThunk({
|
||||
id,
|
||||
data: {
|
||||
formula: value,
|
||||
},
|
||||
controller,
|
||||
})
|
||||
);
|
||||
onClosePopover();
|
||||
}, [dispatch, id, value, controller, onClosePopover]);
|
||||
|
||||
return {
|
||||
open,
|
||||
ref,
|
||||
value,
|
||||
onChange,
|
||||
onOpenPopover,
|
||||
onClosePopover,
|
||||
onConfirm,
|
||||
anchorPosition,
|
||||
};
|
||||
}
|
@ -17,6 +17,7 @@ import CalloutBlock from '$app/components/document/CalloutBlock';
|
||||
import BlockOverlay from '$app/components/document/Overlay/BlockOverlay';
|
||||
import CodeBlock from '$app/components/document/CodeBlock';
|
||||
import { NodeIdContext } from '$app/components/document/_shared/SubscribeNode.hooks';
|
||||
import EquationBlock from '$app/components/document/EquationBlock';
|
||||
|
||||
function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<HTMLDivElement>) {
|
||||
const { node, childIds, isSelected, ref } = useNode(id);
|
||||
@ -26,38 +27,50 @@ function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<H
|
||||
case BlockType.TextBlock: {
|
||||
return <TextBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.HeadingBlock: {
|
||||
return <HeadingBlock node={node} />;
|
||||
}
|
||||
|
||||
case BlockType.TodoListBlock: {
|
||||
return <TodoListBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.QuoteBlock: {
|
||||
return <QuoteBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.BulletedListBlock: {
|
||||
return <BulletedListBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.NumberedListBlock: {
|
||||
return <NumberedListBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.ToggleListBlock: {
|
||||
return <ToggleListBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.DividerBlock: {
|
||||
return <DividerBlock />;
|
||||
}
|
||||
|
||||
case BlockType.CalloutBlock: {
|
||||
return <CalloutBlock node={node} childIds={childIds} />;
|
||||
}
|
||||
|
||||
case BlockType.CodeBlock:
|
||||
return <CodeBlock node={node} />;
|
||||
case BlockType.EquationBlock:
|
||||
return <EquationBlock node={node} />;
|
||||
default:
|
||||
return <UnSupportedBlock />;
|
||||
}
|
||||
}, [node, childIds]);
|
||||
|
||||
const className = props.className ? ` ${props.className}` : '';
|
||||
|
||||
if (!node) return null;
|
||||
|
||||
return (
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { useMenuStyle } from './index.hooks';
|
||||
import TextActionMenuList from '$app/components/document/TextActionMenu/menu';
|
||||
import BlockPortal from '$app/components/document/BlockPortal';
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSubscribeRanges } from '$app/components/document/_shared/SubscribeSelection.hooks';
|
||||
import { debounce } from '$app/utils/tool';
|
||||
import { getBlock } from '$app/components/document/_shared/SubscribeNode.hooks';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
|
||||
const TextActionComponent = ({ container }: { container: HTMLDivElement }) => {
|
||||
const { ref, id } = useMenuStyle(container);
|
||||
@ -30,6 +33,15 @@ const TextActionComponent = ({ container }: { container: HTMLDivElement }) => {
|
||||
|
||||
const TextActionMenu = ({ container }: { container: HTMLDivElement }) => {
|
||||
const range = useSubscribeRanges();
|
||||
const { docId } = useSubscribeDocument();
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const debounceShow = useMemo(() => {
|
||||
return debounce(() => {
|
||||
setShow(true);
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
const canShow = useMemo(() => {
|
||||
const { isDragging, focus, anchor, ranges, caret } = range;
|
||||
|
||||
@ -37,19 +49,38 @@ const TextActionMenu = ({ container }: { container: HTMLDivElement }) => {
|
||||
if (isDragging) return false;
|
||||
// don't show if no focus or anchor
|
||||
if (!caret) return false;
|
||||
const isSameLine = anchor?.id === focus?.id;
|
||||
if (!anchor || !focus) return false;
|
||||
|
||||
const anchorNode = getBlock(docId, anchor.id);
|
||||
const focusNode = getBlock(docId, focus.id);
|
||||
|
||||
// include document title
|
||||
if (!anchorNode.parent || !focusNode.parent) return false;
|
||||
|
||||
const isSameLine = anchor.id === focus.id;
|
||||
|
||||
// show toolbar if range has multiple nodes
|
||||
if (!isSameLine) return true;
|
||||
|
||||
const caretRange = ranges?.[caret.id];
|
||||
|
||||
if (!caretRange) return false;
|
||||
|
||||
// show toolbar if range is not collapsed
|
||||
return caretRange.length > 0;
|
||||
}, [range]);
|
||||
}, [docId, range]);
|
||||
|
||||
if (!canShow) return null;
|
||||
useEffect(() => {
|
||||
if (!canShow) {
|
||||
debounceShow.cancel();
|
||||
setShow(false);
|
||||
return;
|
||||
}
|
||||
|
||||
debounceShow();
|
||||
}, [canShow, debounceShow]);
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return <TextActionComponent container={container} />;
|
||||
};
|
||||
|
@ -6,18 +6,26 @@ import MenuTooltip from './MenuTooltip';
|
||||
import { useSubscribeNode } from '$app/components/document/_shared/SubscribeNode.hooks';
|
||||
|
||||
function TurnIntoSelect({ id }: { id: string }) {
|
||||
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
|
||||
const [anchorPosition, setAnchorPosition] = React.useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
}>();
|
||||
|
||||
const { node } = useSubscribeNode(id);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
const rect = event.currentTarget.getBoundingClientRect();
|
||||
|
||||
setAnchorPosition({
|
||||
top: rect.top + rect.height + 5,
|
||||
left: rect.left,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setAnchorEl(null);
|
||||
setAnchorPosition(undefined);
|
||||
}, []);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const open = Boolean(anchorPosition);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -33,14 +41,11 @@ function TurnIntoSelect({ id }: { id: string }) {
|
||||
id={id}
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
anchorEl={anchorEl}
|
||||
anchorOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
anchorReference={'anchorPosition'}
|
||||
anchorPosition={anchorPosition}
|
||||
transformOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'center',
|
||||
vertical: 'top',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -1,75 +1,64 @@
|
||||
import { Keyboard } from '$app/constants/document/keyboard';
|
||||
import { BlockType } from '$app/interfaces/document';
|
||||
|
||||
export const turnIntoShortcuts = {
|
||||
[Keyboard.keys.SPACE]: [
|
||||
{
|
||||
type: BlockType.HeadingBlock,
|
||||
/**
|
||||
* # or ## or ###
|
||||
*/
|
||||
markdownRegexp: /^(#{1,3})(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.TodoListBlock,
|
||||
/**
|
||||
* -[] or -[x] or -[ ] or [] or [x] or [ ]
|
||||
*/
|
||||
markdownRegexp: /^((-)?\[(x|\s)?\])(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.BulletedListBlock,
|
||||
/**
|
||||
* - or + or *
|
||||
*/
|
||||
markdownRegexp: /^(\s*[-+*])(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.NumberedListBlock,
|
||||
/**
|
||||
* 1. or 2. or 3.
|
||||
* a. or b. or c.
|
||||
*/
|
||||
markdownRegexp: /^(\s*[\d|a-zA-Z]+\.)(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.QuoteBlock,
|
||||
/**
|
||||
* " or “ or ”
|
||||
*/
|
||||
markdownRegexp: /^("|“|”)(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.CalloutBlock,
|
||||
/**
|
||||
* [!TIP] or [!INFO] or [!WARNING] or [!DANGER]
|
||||
*/
|
||||
markdownRegexp: /^(\[!)(TIP|INFO|WARNING|DANGER)(\])(\s)+$/,
|
||||
},
|
||||
{
|
||||
type: BlockType.ToggleListBlock,
|
||||
/**
|
||||
* >
|
||||
*/
|
||||
markdownRegexp: /^(>)(\s)+$/,
|
||||
},
|
||||
],
|
||||
[Keyboard.keys.BACK_QUOTE]: [
|
||||
{
|
||||
type: BlockType.CodeBlock,
|
||||
/**
|
||||
* ```
|
||||
*/
|
||||
markdownRegexp: /^(```)$/,
|
||||
},
|
||||
],
|
||||
[Keyboard.keys.REDUCE]: [
|
||||
{
|
||||
type: BlockType.DividerBlock,
|
||||
/**
|
||||
* ---
|
||||
*/
|
||||
markdownRegexp: /^(-{3,})$/,
|
||||
},
|
||||
],
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
export const turnIntoConfig: Record<
|
||||
BlockType,
|
||||
{
|
||||
type: BlockType;
|
||||
markdownRegexp: RegExp;
|
||||
triggerKey: string;
|
||||
}
|
||||
> = {
|
||||
[BlockType.HeadingBlock]: {
|
||||
type: BlockType.HeadingBlock,
|
||||
markdownRegexp: /^(#{1,3})(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.TodoListBlock]: {
|
||||
type: BlockType.TodoListBlock,
|
||||
markdownRegexp: /^((-)?\[(x|\s)?\])(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.BulletedListBlock]: {
|
||||
type: BlockType.BulletedListBlock,
|
||||
markdownRegexp: /^(\s*[-+*])(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.NumberedListBlock]: {
|
||||
type: BlockType.NumberedListBlock,
|
||||
markdownRegexp: /^(\s*[\d|a-zA-Z]+\.)(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.QuoteBlock]: {
|
||||
type: BlockType.QuoteBlock,
|
||||
markdownRegexp: /^("|“|”)(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.ToggleListBlock]: {
|
||||
type: BlockType.ToggleListBlock,
|
||||
markdownRegexp: /^(>)(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.CalloutBlock]: {
|
||||
type: BlockType.CalloutBlock,
|
||||
markdownRegexp: /^(\[!)(TIP|INFO|WARNING|DANGER)(\])(\s)+$/,
|
||||
triggerKey: Keyboard.keys.SPACE,
|
||||
},
|
||||
[BlockType.EquationBlock]: {
|
||||
type: BlockType.EquationBlock,
|
||||
markdownRegexp: /^(\${2})(\s)*(.+)(\s)*(\${2})$/,
|
||||
triggerKey: Keyboard.keys.DOLLAR,
|
||||
},
|
||||
[BlockType.DividerBlock]: {
|
||||
type: BlockType.DividerBlock,
|
||||
markdownRegexp: /^(-{3,})$/,
|
||||
triggerKey: Keyboard.keys.REDUCE,
|
||||
},
|
||||
[BlockType.CodeBlock]: {
|
||||
type: BlockType.CodeBlock,
|
||||
markdownRegexp: /^(```)$/,
|
||||
triggerKey: Keyboard.keys.BACK_QUOTE,
|
||||
},
|
||||
};
|
||||
|
@ -11,7 +11,7 @@ import isHotkey from 'is-hotkey';
|
||||
import { slashCommandActions } from '$app_reducers/document/slice';
|
||||
import { getDeltaText } from '$app/utils/document/delta';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
import { turnIntoShortcuts } from './shortchut';
|
||||
import { turnIntoConfig } from './shortchut';
|
||||
|
||||
export function useTurnIntoBlockEvents(id: string) {
|
||||
const { docId, controller } = useSubscribeDocument();
|
||||
@ -43,12 +43,11 @@ export function useTurnIntoBlockEvents(id: string) {
|
||||
const canHandle = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>, type: BlockType) => {
|
||||
{
|
||||
const triggerKey = event.key;
|
||||
const shortcutItem = turnIntoShortcuts[triggerKey]?.find((item) => item.type === type);
|
||||
const triggerKey = event.key === turnIntoConfig[type].triggerKey ? event.key : undefined;
|
||||
|
||||
if (!shortcutItem) return false;
|
||||
if (!triggerKey) return false;
|
||||
|
||||
const regex = shortcutItem.markdownRegexp;
|
||||
const regex = turnIntoConfig[type].markdownRegexp;
|
||||
|
||||
// This error will be thrown if the block type is not in the config, and it will happen in development environment
|
||||
if (!regex) {
|
||||
@ -80,6 +79,20 @@ export function useTurnIntoBlockEvents(id: string) {
|
||||
};
|
||||
}, [getDeltaContent]);
|
||||
|
||||
const getAttrs = useCallback(
|
||||
(type: BlockType) => {
|
||||
const flag = getFlag();
|
||||
|
||||
if (!flag) return;
|
||||
const triggerKey = turnIntoConfig[type].triggerKey;
|
||||
const regex = turnIntoConfig[type].markdownRegexp;
|
||||
const match = `${flag}${triggerKey}`.match(regex);
|
||||
|
||||
return match?.[3];
|
||||
},
|
||||
[getFlag]
|
||||
);
|
||||
|
||||
const spaceTriggerMap = useMemo(() => {
|
||||
return {
|
||||
[BlockType.HeadingBlock]: () => {
|
||||
@ -182,6 +195,19 @@ export function useTurnIntoBlockEvents(id: string) {
|
||||
dispatch(turnToBlockThunk({ id, data, type: BlockType.CodeBlock, controller }));
|
||||
},
|
||||
},
|
||||
{
|
||||
canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => canHandle(e, BlockType.EquationBlock),
|
||||
handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
const formula = getAttrs(BlockType.EquationBlock);
|
||||
|
||||
const data = {
|
||||
formula,
|
||||
};
|
||||
|
||||
dispatch(turnToBlockThunk({ id, data, type: BlockType.EquationBlock, controller }));
|
||||
},
|
||||
},
|
||||
{
|
||||
// Here custom slash key event for TextBlock
|
||||
canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
@ -200,7 +226,7 @@ export function useTurnIntoBlockEvents(id: string) {
|
||||
},
|
||||
},
|
||||
];
|
||||
}, [canHandle, controller, dispatch, docId, getDeltaContent, getFlag, id, spaceTriggerMap]);
|
||||
}, [canHandle, controller, dispatch, docId, getAttrs, getDeltaContent, getFlag, id, spaceTriggerMap]);
|
||||
|
||||
return turnIntoBlockEvents;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export default function TodoListBlock({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'flex-1'}>
|
||||
<div className={`flex-1 ${checked ? 'text-shade-2 line-through' : ''}`}>
|
||||
<TextBlock node={node} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,6 @@ import { useAppDispatch } from '$app/stores/store';
|
||||
import { createTemporary } from '$app_reducers/document/async-actions/temporary';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
import KatexMath from '$app/components/document/_shared/KatexMath';
|
||||
import { rangeActions } from '$app_reducers/document/slice';
|
||||
|
||||
const LEFT_CARET_CLASS = 'inline-block-with-cursor-left';
|
||||
const RIGHT_CARET_CLASS = 'inline-block-with-cursor-right';
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
.katex-html {
|
||||
white-space: normal;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import 'katex/dist/katex.min.css';
|
||||
import { BlockMath, InlineMath } from 'react-katex';
|
||||
import './index.css';
|
||||
|
||||
function KatexMath({ latex, isInline = false }: { latex: string; isInline?: boolean }) {
|
||||
return isInline ? <InlineMath math={latex} /> : <BlockMath math={latex} />;
|
||||
|
@ -7,19 +7,25 @@ function EquationEditContent({
|
||||
value,
|
||||
onChange,
|
||||
onConfirm,
|
||||
placeholder = 'E = mc^2',
|
||||
multiline = false,
|
||||
}: {
|
||||
value: string;
|
||||
placeholder?: string;
|
||||
onChange: (newVal: string) => void;
|
||||
onConfirm: () => void;
|
||||
multiline?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div className={'flex p-2'}>
|
||||
<TextField
|
||||
placeholder={'E = mc^2'}
|
||||
placeholder={placeholder}
|
||||
autoFocus={true}
|
||||
multiline={multiline}
|
||||
label='Equation'
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
onConfirm();
|
||||
}
|
||||
}}
|
||||
|
@ -4,11 +4,43 @@ import { BlockData, BlockType, NestedBlock } from '$app/interfaces/document';
|
||||
import { blockConfig } from '$app/constants/document/config';
|
||||
import { turnToBlockThunk } from '$app_reducers/document/async-actions';
|
||||
import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
|
||||
import Delta from 'quill-delta';
|
||||
import { getDeltaText } from '$app/utils/document/delta';
|
||||
import { rangeActions, rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { setRectSelectionThunk } from '$app_reducers/document/async-actions/rect_selection';
|
||||
|
||||
export function useTurnInto({ node, onClose }: { node: NestedBlock; onClose?: () => void }) {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { controller } = useSubscribeDocument();
|
||||
const { controller, docId } = useSubscribeDocument();
|
||||
|
||||
const getTurnIntoData = useCallback(
|
||||
(targetType: BlockType, sourceNode: NestedBlock) => {
|
||||
if (targetType === sourceNode.type) return;
|
||||
const config = blockConfig[targetType];
|
||||
const defaultData = config.defaultData;
|
||||
const data: BlockData<any> = {
|
||||
...defaultData,
|
||||
delta: sourceNode?.data?.delta || [],
|
||||
};
|
||||
|
||||
if (targetType === BlockType.EquationBlock) {
|
||||
data.formula = getDeltaText(new Delta(sourceNode.data.delta));
|
||||
delete data.delta;
|
||||
}
|
||||
|
||||
if (sourceNode.type === BlockType.EquationBlock) {
|
||||
data.delta = [
|
||||
{
|
||||
insert: node.data.formula,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
[node.data.formula]
|
||||
);
|
||||
|
||||
const turnIntoBlock = useCallback(
|
||||
async (type: BlockType, isSelected: boolean, data?: BlockData<any>) => {
|
||||
@ -17,27 +49,34 @@ export function useTurnInto({ node, onClose }: { node: NestedBlock; onClose?: ()
|
||||
return;
|
||||
}
|
||||
|
||||
const config = blockConfig[type];
|
||||
await dispatch(
|
||||
const updateData = {
|
||||
...getTurnIntoData(type, node),
|
||||
...data,
|
||||
};
|
||||
|
||||
const { payload: newBlockId } = await dispatch(
|
||||
turnToBlockThunk({
|
||||
id: node.id,
|
||||
controller,
|
||||
type,
|
||||
data: {
|
||||
...config.defaultData,
|
||||
delta: node?.data?.delta || [],
|
||||
...data,
|
||||
},
|
||||
data: updateData,
|
||||
})
|
||||
);
|
||||
|
||||
onClose?.();
|
||||
dispatch(
|
||||
setRectSelectionThunk({
|
||||
docId,
|
||||
selection: [newBlockId as string],
|
||||
})
|
||||
);
|
||||
},
|
||||
[onClose, controller, dispatch, node]
|
||||
[controller, getTurnIntoData, node, dispatch, onClose, docId]
|
||||
);
|
||||
|
||||
const turnIntoHeading = useCallback(
|
||||
(level: number, isSelected: boolean) => {
|
||||
turnIntoBlock(BlockType.HeadingBlock, isSelected, { level });
|
||||
return turnIntoBlock(BlockType.HeadingBlock, isSelected, { level });
|
||||
},
|
||||
[turnIntoBlock]
|
||||
);
|
||||
|
@ -120,11 +120,12 @@ const TurnIntoPopover = ({
|
||||
title: 'Callout',
|
||||
icon: <Lightbulb />,
|
||||
},
|
||||
// {
|
||||
// type: BlockType.EquationBlock,
|
||||
// title: 'Block KatexMath',
|
||||
// icon: <Functions />,
|
||||
// },
|
||||
{
|
||||
key: SlashCommandOptionKey.EQUATION,
|
||||
type: BlockType.EquationBlock,
|
||||
title: 'Block Equation',
|
||||
icon: <Functions />,
|
||||
},
|
||||
],
|
||||
[node?.data?.level, turnIntoHeading]
|
||||
);
|
||||
|
@ -98,4 +98,10 @@ export const blockConfig: Record<string, BlockConfig> = {
|
||||
[BlockType.DividerBlock]: {
|
||||
canAddChild: false,
|
||||
},
|
||||
[BlockType.EquationBlock]: {
|
||||
canAddChild: false,
|
||||
defaultData: {
|
||||
formula: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -34,6 +34,9 @@ export enum BlockType {
|
||||
ColumnBlock = 'column',
|
||||
}
|
||||
|
||||
export interface EauqtionBlockData {
|
||||
formula: string;
|
||||
}
|
||||
export interface HeadingBlockData extends TextBlockData {
|
||||
level: number;
|
||||
}
|
||||
@ -88,6 +91,8 @@ export type BlockData<Type> = Type extends BlockType.HeadingBlock
|
||||
? DividerBlockData
|
||||
: Type extends BlockType.CalloutBlock
|
||||
? CalloutBlockData
|
||||
: Type extends BlockType.EquationBlock
|
||||
? EauqtionBlockData
|
||||
: Type extends BlockType.TextBlock
|
||||
? TextBlockData
|
||||
: any;
|
||||
|
@ -4,6 +4,7 @@ import { rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { getDuplicateActions } from '$app/utils/document/action';
|
||||
import { RootState } from '$app/stores/store';
|
||||
import { DOCUMENT_NAME } from '$app/constants/document/name';
|
||||
import { setRectSelectionThunk } from '$app_reducers/document/async-actions/rect_selection';
|
||||
|
||||
export const duplicateBelowNodeThunk = createAsyncThunk(
|
||||
'document/duplicateBelowNode',
|
||||
@ -22,7 +23,7 @@ export const duplicateBelowNodeThunk = createAsyncThunk(
|
||||
await controller.applyActions(duplicateActions.actions);
|
||||
|
||||
dispatch(
|
||||
rectSelectionActions.updateSelections({
|
||||
setRectSelectionThunk({
|
||||
docId,
|
||||
selection: [duplicateActions.newNodeId],
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { getNextNodeId, getPrevNodeId } from '$app/utils/document/block';
|
||||
import { rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { rangeActions, rectSelectionActions } from '$app_reducers/document/slice';
|
||||
import { RootState } from '$app/stores/store';
|
||||
|
||||
export const setRectSelectionThunk = createAsyncThunk(
|
||||
@ -16,19 +16,24 @@ export const setRectSelectionThunk = createAsyncThunk(
|
||||
const { docId, selection } = payload;
|
||||
const documentState = (getState() as RootState).document[docId];
|
||||
const selected: Record<string, boolean> = {};
|
||||
|
||||
selection.forEach((id) => {
|
||||
const node = documentState.nodes[id];
|
||||
|
||||
if (!node.parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
selected[id] = selected[id] === undefined ? true : selected[id];
|
||||
selected[node.parent] = false;
|
||||
const nextNodeId = getNextNodeId(documentState, node.parent);
|
||||
const prevNodeId = getPrevNodeId(documentState, node.parent);
|
||||
|
||||
if ((nextNodeId && selection.includes(nextNodeId)) || (prevNodeId && selection.includes(prevNodeId))) {
|
||||
selected[node.parent] = true;
|
||||
}
|
||||
});
|
||||
dispatch(rangeActions.initialState(docId));
|
||||
dispatch(
|
||||
rectSelectionActions.updateSelections({
|
||||
docId,
|
||||
|
@ -23,6 +23,7 @@ export const turnToBlockThunk = createAsyncThunk(
|
||||
const state = (getState() as RootState).document[docId];
|
||||
|
||||
const node = state.nodes[id];
|
||||
|
||||
if (!node.parent) return;
|
||||
|
||||
const parent = state.nodes[node.parent];
|
||||
@ -31,12 +32,15 @@ export const turnToBlockThunk = createAsyncThunk(
|
||||
const block = newBlock<any>(type, parent.id, type === BlockType.DividerBlock ? {} : data);
|
||||
let caretId = block.id;
|
||||
// insert new block after current block
|
||||
let insertActions = [controller.getInsertAction(block, node.id)];
|
||||
const insertActions = [controller.getInsertAction(block, node.id)];
|
||||
|
||||
if (type === BlockType.DividerBlock) {
|
||||
const newTextNode = newBlock<any>(BlockType.TextBlock, parent.id, data);
|
||||
|
||||
insertActions.push(controller.getInsertAction(newTextNode, block.id));
|
||||
caretId = newTextNode.id;
|
||||
}
|
||||
|
||||
// check if prev node is allowed to have children
|
||||
const config = blockConfig[block.type];
|
||||
// if new block is not allowed to have children, move children to parent
|
||||
@ -57,6 +61,7 @@ export const turnToBlockThunk = createAsyncThunk(
|
||||
caret: { id: caretId, index: 0, length: 0 },
|
||||
})
|
||||
);
|
||||
return caretId;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -128,21 +128,6 @@ export const rectSelectionSlice = createSlice({
|
||||
state[docId].selection = selection;
|
||||
},
|
||||
|
||||
// set block selected
|
||||
setSelectionById: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
docId: string;
|
||||
blockId: string;
|
||||
}>
|
||||
) => {
|
||||
const { docId, blockId } = action.payload;
|
||||
const selection = state[docId].selection;
|
||||
|
||||
if (selection.includes(blockId)) return;
|
||||
state[docId].selection = [...selection, blockId];
|
||||
},
|
||||
|
||||
setDragging: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
|
@ -5,11 +5,13 @@ import { nanoid } from 'nanoid';
|
||||
|
||||
export function blockPB2Node(block: BlockPB) {
|
||||
let data = {};
|
||||
|
||||
try {
|
||||
data = JSON.parse(block.data);
|
||||
} catch {
|
||||
Log.error('[Document Open] json parse error', block.data);
|
||||
}
|
||||
|
||||
const node = {
|
||||
id: block.id,
|
||||
type: block.ty as BlockType,
|
||||
@ -17,6 +19,7 @@ export function blockPB2Node(block: BlockPB) {
|
||||
children: block.children_id,
|
||||
data,
|
||||
};
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -26,58 +29,71 @@ export function generateId() {
|
||||
|
||||
export function getPrevLineId(state: DocumentState, id: string) {
|
||||
const node = state.nodes[id];
|
||||
|
||||
if (!node.parent) return;
|
||||
const parent = state.nodes[node.parent];
|
||||
const children = state.children[parent.children];
|
||||
const index = children.indexOf(id);
|
||||
const prevNodeId = children[index - 1];
|
||||
const prevNode = state.nodes[prevNodeId];
|
||||
|
||||
if (!prevNode) {
|
||||
return parent.id;
|
||||
}
|
||||
|
||||
// find prev line
|
||||
let prevLineId = prevNode.id;
|
||||
|
||||
while (prevLineId) {
|
||||
const prevLineChildren = state.children[state.nodes[prevLineId].children];
|
||||
|
||||
if (prevLineChildren.length === 0) break;
|
||||
prevLineId = prevLineChildren[prevLineChildren.length - 1];
|
||||
}
|
||||
|
||||
return prevLineId || parent.id;
|
||||
}
|
||||
|
||||
export function getNextLineId(state: DocumentState, id: string) {
|
||||
const node = state.nodes[id];
|
||||
if (!node.parent) return;
|
||||
|
||||
const firstChild = state.children[node.children][0];
|
||||
|
||||
if (firstChild) return firstChild;
|
||||
|
||||
let nextNodeId = getNextNodeId(state, id);
|
||||
|
||||
if (!node.parent) return;
|
||||
let parent: NestedBlock | null = state.nodes[node.parent];
|
||||
|
||||
while (!nextNodeId && parent) {
|
||||
nextNodeId = getNextNodeId(state, parent.id);
|
||||
parent = parent.parent ? state.nodes[parent.parent] : null;
|
||||
}
|
||||
|
||||
return nextNodeId;
|
||||
}
|
||||
|
||||
export function getNextNodeId(state: DocumentState, id: string) {
|
||||
const node = state.nodes[id];
|
||||
|
||||
if (!node.parent) return;
|
||||
const parent = state.nodes[node.parent];
|
||||
const children = state.children[parent.children];
|
||||
const index = children.indexOf(id);
|
||||
const nextNodeId = children[index + 1];
|
||||
|
||||
return nextNodeId;
|
||||
}
|
||||
|
||||
export function getPrevNodeId(state: DocumentState, id: string) {
|
||||
const node = state.nodes[id];
|
||||
|
||||
if (!node.parent) return;
|
||||
const parent = state.nodes[node.parent];
|
||||
const children = state.children[parent.children];
|
||||
const index = children.indexOf(id);
|
||||
const prevNodeId = children[index - 1];
|
||||
|
||||
return prevNodeId;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user