mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
set up routing
This commit is contained in:
parent
a3c3478831
commit
c1f4616a31
6 changed files with 196 additions and 0 deletions
|
@ -18,6 +18,7 @@ members = [
|
|||
"leptos_reactive",
|
||||
"leptos_server",
|
||||
"reactive_graph",
|
||||
"routing",
|
||||
"server_fn",
|
||||
"server_fn_macro",
|
||||
"server_fn/server_fn_macro_default",
|
||||
|
@ -55,6 +56,7 @@ leptos_meta = { path = "./meta", version = "0.6.5" }
|
|||
next_tuple = { path = "./next_tuple" }
|
||||
or_poisoned = { path = "./or_poisoned" }
|
||||
reactive_graph = { path = "./reactive_graph" }
|
||||
routing = { path = "./routing" }
|
||||
server_fn = { path = "./server_fn", version = "0.6.5" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.6.5" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.6" }
|
||||
|
|
46
routing/Cargo.toml
Normal file
46
routing/Cargo.toml
Normal file
|
@ -0,0 +1,46 @@
|
|||
[package]
|
||||
name = "router"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
const_str_slice_concat = { workspace = true }
|
||||
next_tuple = { workspace = true }
|
||||
reactive_graph = { workspace = true, optional = true }
|
||||
#paste = "1"
|
||||
thiserror = "1"
|
||||
#tuplestructops = "0.3"
|
||||
url = "2"
|
||||
js-sys = { version = "0.3" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
tracing = { version = "0.1", optional = true }
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
# History/Routing
|
||||
"History",
|
||||
"HtmlAnchorElement",
|
||||
"Location",
|
||||
"MouseEvent",
|
||||
"Url",
|
||||
# Form
|
||||
"FormData",
|
||||
"HtmlButtonElement",
|
||||
"HtmlFormElement",
|
||||
"HtmlInputElement",
|
||||
"SubmitEvent",
|
||||
"Url",
|
||||
"UrlSearchParams",
|
||||
# Fetching in Hydrate Mode
|
||||
"Headers",
|
||||
"Request",
|
||||
"RequestInit",
|
||||
"RequestMode",
|
||||
"Response",
|
||||
"Window",
|
||||
]
|
||||
|
||||
[features]
|
||||
tracing = ["dep:tracing"]
|
||||
reactive_graph = ["dep:reactive_graph"]
|
12
routing/src/lib.rs
Normal file
12
routing/src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
//mod generate_route_list;
|
||||
pub mod location;
|
||||
pub mod params;
|
||||
//pub mod matching;
|
||||
//cfg(feature = "reaccy")]
|
||||
//pub mod reactive;
|
||||
//mod render_mode;
|
||||
//pub mod route;
|
||||
//pub mod router;
|
||||
//mod static_render;
|
||||
//pub use generate_route_list::*;
|
||||
//pub use render_mode::*;
|
78
routing/src/location/mod.rs
Normal file
78
routing/src/location/mod.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use crate::params::Params;
|
||||
use std::fmt::Debug;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
mod server;
|
||||
pub use server::*;
|
||||
|
||||
pub(crate) const BASE: &str = "https://leptos.dev";
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct Url {
|
||||
pub origin: String,
|
||||
pub pathname: String,
|
||||
pub search: String,
|
||||
pub search_params: Params<String>,
|
||||
pub hash: String,
|
||||
}
|
||||
|
||||
/// A description of a navigation.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct LocationChange {
|
||||
/// The new URL.
|
||||
pub value: String,
|
||||
/// If true, the new location will replace the current one in the history stack, i.e.,
|
||||
/// clicking the "back" button will not return to the current location.
|
||||
pub replace: bool,
|
||||
/// If true, the router will scroll to the top of the page at the end of the navigation.
|
||||
pub scroll: bool,
|
||||
/// The [`state`](https://developer.mozilla.org/en-US/docs/Web/API/History/state) that will be added during navigation.
|
||||
pub state: State,
|
||||
}
|
||||
|
||||
impl Default for LocationChange {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
value: Default::default(),
|
||||
replace: true,
|
||||
scroll: true,
|
||||
state: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Location {
|
||||
type Error: Debug;
|
||||
|
||||
/// Sets up any global event listeners or other initialization needed.
|
||||
fn init(&self);
|
||||
|
||||
/// Returns the current URL.
|
||||
fn try_to_url(&self) -> Result<Url, Self::Error>;
|
||||
|
||||
fn set_navigation_hook(&mut self, cb: impl Fn(Url) + 'static);
|
||||
|
||||
/// Navigate to a new location.
|
||||
fn navigate(&self, loc: &LocationChange);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub struct State(pub Option<JsValue>);
|
||||
|
||||
impl State {
|
||||
pub fn to_js_value(&self) -> JsValue {
|
||||
match &self.0 {
|
||||
Some(v) => v.clone(),
|
||||
None => JsValue::UNDEFINED,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for State
|
||||
where
|
||||
T: Into<JsValue>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
State(Some(value.into()))
|
||||
}
|
||||
}
|
57
routing/src/location/server.rs
Normal file
57
routing/src/location/server.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use super::{Location, LocationChange, Url};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RequestUrl(String);
|
||||
|
||||
impl RequestUrl {
|
||||
/// Creates a server-side request URL from a path, with an optional initial slash.
|
||||
pub fn from_path(path: impl AsRef<str>) -> Self {
|
||||
let path = path.as_ref().trim_start_matches('/');
|
||||
let mut string = String::with_capacity(path.len());
|
||||
string.push_str(path);
|
||||
Self(string)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RequestUrl {
|
||||
fn default() -> Self {
|
||||
Self(String::from("/"))
|
||||
}
|
||||
}
|
||||
|
||||
impl Location for RequestUrl {
|
||||
type Error = url::ParseError;
|
||||
|
||||
fn init(&self) {}
|
||||
|
||||
fn try_to_url_with_base(&self, base: &str) -> Result<Url, Self::Error> {
|
||||
let url = String::with_capacity(self.0.len() + 1 + base);
|
||||
let url = url::Url::parse(&self.0)?;
|
||||
let search_params = url
|
||||
.query_pairs()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect();
|
||||
Ok(Url {
|
||||
origin: url.origin().unicode_serialization(),
|
||||
pathname: url.path().to_string(),
|
||||
search: url.query().unwrap_or_default().to_string(),
|
||||
search_params,
|
||||
hash: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn set_navigation_hook(&mut self, _cb: impl FnMut(Url) + 'static) {}
|
||||
|
||||
fn navigate(&self, _loc: &LocationChange) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::RequestUrl;
|
||||
use crate::location::Location;
|
||||
|
||||
pub fn should_parse_url_without_origin() {
|
||||
let req = RequestUrl::from_path("/foo/bar");
|
||||
let url = req.try_to_url().expect("could not parse URL");
|
||||
}
|
||||
}
|
1
routing/src/params.rs
Normal file
1
routing/src/params.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub(crate) type Params<K> = Vec<(K, String)>;
|
Loading…
Reference in a new issue