mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-14 00:27:12 +00:00
chore: clear up... a few warnings
This commit is contained in:
parent
7c526cfa52
commit
8ed8b5605b
74 changed files with 390 additions and 856 deletions
|
@ -28,10 +28,6 @@ sqlx = { version = "0.7", features = [
|
|||
thiserror = "1.0"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
tracing-subscriber-wasm = "0.1"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use crate::errors::TodoAppError;
|
||||
use leptos::prelude::*;
|
||||
#[cfg(feature = "ssr")]
|
||||
use leptos_axum::ResponseOptions;
|
||||
|
||||
// A basic function to display errors served by the error boundaries. Feel free to do more complicated things
|
||||
// here than just displaying them
|
||||
|
|
|
@ -23,7 +23,6 @@ pub async fn file_and_error_handler(
|
|||
let mut errors = Errors::default();
|
||||
errors.insert_with_default_key(TodoAppError::NotFound);
|
||||
let handler = leptos_axum::render_app_to_stream(
|
||||
options.to_owned(),
|
||||
move || view! { <ErrorTemplate outside_errors=errors.clone()/> },
|
||||
);
|
||||
handler(req).await.into_response()
|
||||
|
|
|
@ -8,21 +8,6 @@ pub mod todo;
|
|||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn hydrate() {
|
||||
use crate::todo::TodoApp;
|
||||
/* use tracing_subscriber::fmt;
|
||||
use tracing_subscriber_wasm::MakeConsoleWriter;
|
||||
|
||||
fmt()
|
||||
.with_writer(
|
||||
// To avoide trace events in the browser from showing their
|
||||
// JS backtrace, which is very annoying, in my opinion
|
||||
MakeConsoleWriter::default()
|
||||
.map_trace_level_to(tracing::Level::DEBUG),
|
||||
)
|
||||
// For some reason, if we don't do this in the browser, we get
|
||||
// a runtime error.
|
||||
.without_time()
|
||||
.init();
|
||||
_ = console_log::init_with_level(log::Level::Error);*/
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
leptos::mount::hydrate_body(TodoApp);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{fallback::file_and_error_handler, todo::*};
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::{Path, State},
|
||||
extract::Path,
|
||||
http::Request,
|
||||
response::{IntoResponse, Response},
|
||||
routing::get,
|
||||
|
@ -14,11 +14,9 @@ use todo_app_sqlite_axum::*;
|
|||
//Define a handler to test extractor with state
|
||||
async fn custom_handler(
|
||||
Path(id): Path<String>,
|
||||
State(options): State<LeptosOptions>,
|
||||
req: Request<Body>,
|
||||
) -> Response {
|
||||
let handler = leptos_axum::render_app_to_stream_with_context(
|
||||
options,
|
||||
move || {
|
||||
provide_context(id.clone());
|
||||
},
|
||||
|
|
|
@ -142,7 +142,7 @@ impl SharedContext for HydrateSharedContext {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn seal_errors(&self, boundary_id: &SerializedDataId) {}
|
||||
fn seal_errors(&self, _boundary_id: &SerializedDataId) {}
|
||||
|
||||
fn take_errors(&self) -> Vec<(SerializedDataId, ErrorId, Error)> {
|
||||
self.errors.clone()
|
||||
|
|
|
@ -6,7 +6,7 @@ use futures::{
|
|||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
collections::HashSet,
|
||||
fmt::{Debug, Write},
|
||||
mem,
|
||||
sync::{
|
||||
|
@ -89,7 +89,7 @@ impl SharedContext for SsrSharedContext {
|
|||
|
||||
initial_chunk.push_str("__SERIALIZED_ERRORS=[");
|
||||
for error in mem::take(&mut *self.errors.write().or_poisoned()) {
|
||||
write!(
|
||||
_ = write!(
|
||||
initial_chunk,
|
||||
"[{}, {}, {:?}],",
|
||||
error.0 .0, error.1, error.2
|
||||
|
@ -100,7 +100,7 @@ impl SharedContext for SsrSharedContext {
|
|||
// pending async resources
|
||||
initial_chunk.push_str("__PENDING_RESOURCES=[");
|
||||
for (id, _) in &async_data {
|
||||
write!(&mut initial_chunk, "{},", id.0).unwrap();
|
||||
_ = write!(&mut initial_chunk, "{},", id.0);
|
||||
}
|
||||
initial_chunk.push_str("];");
|
||||
|
||||
|
@ -121,7 +121,7 @@ impl SharedContext for SsrSharedContext {
|
|||
let sealed = sealed.read().or_poisoned();
|
||||
for error in mem::take(&mut *errors.write().or_poisoned()) {
|
||||
if !sealed.contains(&error.0) {
|
||||
write!(
|
||||
_ = write!(
|
||||
val,
|
||||
"__SERIALIZED_ERRORS.push([{}, {}, {:?}]);",
|
||||
error.0 .0,
|
||||
|
|
|
@ -19,9 +19,9 @@ http-body-util = "0.1"
|
|||
leptos = { workspace = true, features = ["nonce", "hydration"] }
|
||||
server_fn = { workspace = true, features = ["axum-no-default"] }
|
||||
leptos_macro = { workspace = true, features = ["axum"] }
|
||||
leptos_meta = { workspace = true }
|
||||
leptos_meta = { workspace = true, features = ["ssr"] }
|
||||
reactive_graph = { workspace = true, features = ["sandboxed-arenas"] }
|
||||
leptos_router = { workspace = true }
|
||||
leptos_router = { workspace = true, features = ["ssr"] }
|
||||
#leptos_integration_utils = { workspace = true }
|
||||
parking_lot = "0.12"
|
||||
serde_json = "1"
|
||||
|
|
|
@ -43,42 +43,24 @@ use axum::{
|
|||
response::{Html, IntoResponse},
|
||||
routing::{delete, get, patch, post, put},
|
||||
};
|
||||
use futures::{
|
||||
channel::mpsc::{Receiver, Sender},
|
||||
stream::once,
|
||||
Future, FutureExt, SinkExt, Stream, StreamExt,
|
||||
};
|
||||
use futures::{stream::once, Future, Stream, StreamExt};
|
||||
use hydration_context::SsrSharedContext;
|
||||
use leptos::{
|
||||
config::LeptosOptions,
|
||||
context::{provide_context, use_context},
|
||||
reactive_graph::{computed::ScopedFuture, owner::Owner},
|
||||
tachys::ssr::StreamBuilder,
|
||||
IntoView,
|
||||
};
|
||||
use leptos_meta::{MetaContext, ServerMetaContext};
|
||||
use leptos_meta::ServerMetaContext;
|
||||
use leptos_router::{
|
||||
location::RequestUrl, PathSegment, RouteList, RouteListing, SsrMode,
|
||||
StaticDataMap, StaticMode,
|
||||
};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::RwLock;
|
||||
use reactive_graph::owner::Sandboxed;
|
||||
use server_fn::{
|
||||
|
||||
error::{NoCustomError, ServerFnErrorSerde},
|
||||
redirect::REDIRECT_HEADER, ServerFnError,
|
||||
,
|
||||
};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fmt::{Debug, Write},
|
||||
io,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
thread::available_parallelism,
|
||||
};
|
||||
use tracing::Instrument;
|
||||
use server_fn::{redirect::REDIRECT_HEADER, ServerFnError};
|
||||
use std::{fmt::Debug, io, pin::Pin, sync::Arc};
|
||||
// use tracing::Instrument; // TODO check tracing span -- was this used in 0.6 for a missing link?
|
||||
|
||||
/// This struct lets you define headers and override the status of the Response from an Element or a Server Function
|
||||
/// Typically contained inside of a ResponseOptions. Setting this is useful for cookies and custom responses.
|
||||
|
@ -251,27 +233,6 @@ fn init_executor() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Leptos pool causes wasm to panic and leptos_reactive::spawn::spawn_local causes native
|
||||
/// to panic so we define a macro to conditionally compile the correct code.
|
||||
macro_rules! spawn_task {
|
||||
($block:expr) => {
|
||||
#[cfg(feature = "wasm")]
|
||||
spawn_local($block);
|
||||
#[cfg(all(not(feature = "wasm"), feature = "default"))]
|
||||
spawn($block);
|
||||
#[cfg(all(not(feature = "wasm"), not(feature = "default")))]
|
||||
{
|
||||
eprintln!(
|
||||
"It appears you have set 'default-features = false' on \
|
||||
'leptos_axum', but are not using the 'wasm' feature. Either \
|
||||
remove 'default-features = false' or, if you are running in \
|
||||
a JS-hosted WASM server environment, add the 'wasm' feature."
|
||||
);
|
||||
spawn_local($block);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// An Axum handlers to listens for a request with Leptos server function arguments in the body,
|
||||
/// run the server function if found, and return the resulting [`Response`].
|
||||
///
|
||||
|
@ -310,9 +271,7 @@ async fn handle_server_fns_inner(
|
|||
let path = req.uri().path().to_string();
|
||||
let (req, parts) = generate_request_and_parts(req);
|
||||
|
||||
let res = if let Some(mut service) =
|
||||
server_fn::axum::get_server_fn_service(&path)
|
||||
{
|
||||
if let Some(mut service) = server_fn::axum::get_server_fn_service(&path) {
|
||||
let owner = Owner::new();
|
||||
owner
|
||||
.with(|| {
|
||||
|
@ -379,25 +338,14 @@ async fn handle_server_fns_inner(
|
|||
function type, somewhere in your `main` function.",
|
||||
)))
|
||||
}
|
||||
.expect("could not build Response");
|
||||
|
||||
res
|
||||
|
||||
/*rx.await.unwrap_or_else(|e| {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ServerFnErrorSerde::ser(
|
||||
&ServerFnError::<NoCustomError>::ServerError(e.to_string()),
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.into_response()
|
||||
})*/
|
||||
.expect("could not build Response")
|
||||
}
|
||||
|
||||
pub type PinnedHtmlStream =
|
||||
Pin<Box<dyn Stream<Item = io::Result<Bytes>> + Send>>;
|
||||
type PinnedStream<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
|
||||
type PinnedFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
|
||||
type BoxedFnOnce<T> = Box<dyn FnOnce() -> T + Send>;
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], serving an HTML stream of your application.
|
||||
|
@ -447,11 +395,10 @@ type PinnedStream<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
Request<Body>,
|
||||
|
@ -462,7 +409,7 @@ pub fn render_app_to_stream<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
render_app_to_stream_with_context(options, || {}, app_fn)
|
||||
render_app_to_stream_with_context(|| {}, app_fn)
|
||||
}
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
|
@ -472,7 +419,6 @@ where
|
|||
/// This is useful if you are using `.leptos_routes_with_handler()`
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_route<IV>(
|
||||
options: LeptosOptions,
|
||||
paths: Vec<AxumRouteListing>,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
|
@ -484,7 +430,7 @@ pub fn render_route<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
render_route_with_context(options, paths, || {}, app_fn)
|
||||
render_route_with_context(paths, || {}, app_fn)
|
||||
}
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
|
@ -538,11 +484,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_in_order<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
Request<Body>,
|
||||
|
@ -553,7 +498,7 @@ pub fn render_app_to_stream_in_order<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
render_app_to_stream_in_order_with_context(options, || {}, app_fn)
|
||||
render_app_to_stream_in_order_with_context(|| {}, app_fn)
|
||||
}
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
|
@ -579,11 +524,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
|
@ -596,7 +540,6 @@ where
|
|||
IV: IntoView + 'static,
|
||||
{
|
||||
render_app_to_stream_with_context_and_replace_blocks(
|
||||
options,
|
||||
additional_context,
|
||||
app_fn,
|
||||
false,
|
||||
|
@ -610,7 +553,6 @@ where
|
|||
/// This is useful if you are using `.leptos_routes_with_handler()`.
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_route_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
paths: Vec<AxumRouteListing>,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
|
@ -624,23 +566,19 @@ where
|
|||
IV: IntoView + 'static,
|
||||
{
|
||||
let ooo = render_app_to_stream_with_context(
|
||||
LeptosOptions::from_ref(&options),
|
||||
additional_context.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
let pb = render_app_to_stream_with_context_and_replace_blocks(
|
||||
LeptosOptions::from_ref(&options),
|
||||
additional_context.clone(),
|
||||
app_fn.clone(),
|
||||
true,
|
||||
);
|
||||
let io = render_app_to_stream_in_order_with_context(
|
||||
LeptosOptions::from_ref(&options),
|
||||
additional_context.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
let asyn = render_app_async_stream_with_context(
|
||||
LeptosOptions::from_ref(&options),
|
||||
additional_context.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
|
@ -690,11 +628,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_with_context_and_replace_blocks<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
replace_blocks: bool,
|
||||
|
@ -707,7 +644,8 @@ pub fn render_app_to_stream_with_context_and_replace_blocks<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
handle_response(options, additional_context, app_fn, |app, chunks| {
|
||||
_ = replace_blocks; // TODO
|
||||
handle_response(additional_context, app_fn, |app, chunks| {
|
||||
Box::pin(async move {
|
||||
Box::pin(app.to_html_stream_out_of_order().chain(chunks()))
|
||||
as PinnedStream<String>
|
||||
|
@ -740,11 +678,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_to_stream_in_order_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
|
@ -756,7 +693,7 @@ pub fn render_app_to_stream_in_order_with_context<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
handle_response(options, additional_context, app_fn, |app, chunks| {
|
||||
handle_response(additional_context, app_fn, |app, chunks| {
|
||||
Box::pin(async move {
|
||||
Box::pin(app.to_html_stream_in_order().chain(chunks()))
|
||||
as PinnedStream<String>
|
||||
|
@ -765,29 +702,17 @@ where
|
|||
}
|
||||
|
||||
fn handle_response<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
stream_builder: fn(
|
||||
IV,
|
||||
Box<dyn FnOnce() -> Pin<Box<dyn Stream<Item = String> + Send>> + Send>,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Pin<Box<dyn Stream<Item = String> + Send>>>
|
||||
+ Send,
|
||||
>,
|
||||
>,
|
||||
) -> impl Fn(
|
||||
Request<Body>,
|
||||
) -> Pin<Box<dyn Future<Output = Response<Body>> + Send + 'static>>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static
|
||||
BoxedFnOnce<PinnedStream<String>>,
|
||||
) -> PinnedFuture<PinnedStream<String>>,
|
||||
) -> impl Fn(Request<Body>) -> PinnedFuture<Response<Body>> + Clone + Send + 'static
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
move |req: Request<Body>| {
|
||||
let options = options.clone();
|
||||
let app_fn = app_fn.clone();
|
||||
let add_context = additional_context.clone();
|
||||
let res_options = ResponseOptions::default();
|
||||
|
@ -941,11 +866,10 @@ fn provide_contexts(
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_async<IV>(
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
Request<Body>,
|
||||
|
@ -956,7 +880,7 @@ pub fn render_app_async<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
render_app_async_with_context(options, || {}, app_fn)
|
||||
render_app_async_with_context(|| {}, app_fn)
|
||||
}
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
|
@ -983,11 +907,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_async_stream_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
|
@ -999,7 +922,7 @@ pub fn render_app_async_stream_with_context<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
handle_response(options, additional_context, app_fn, |app, chunks| {
|
||||
handle_response(additional_context, app_fn, |app, chunks| {
|
||||
Box::pin(async move {
|
||||
let app = app.to_html_stream_in_order().collect::<String>().await;
|
||||
let chunks = chunks();
|
||||
|
@ -1033,11 +956,10 @@ where
|
|||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`MetaContext`](leptos_meta::MetaContext)
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub fn render_app_async_with_context<IV>(
|
||||
options: LeptosOptions,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> impl Fn(
|
||||
|
@ -1049,7 +971,7 @@ pub fn render_app_async_with_context<IV>(
|
|||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
handle_response(options, additional_context, app_fn, |app, chunks| {
|
||||
handle_response(additional_context, app_fn, |app, chunks| {
|
||||
Box::pin(async move {
|
||||
let app = app.to_html_stream_in_order().collect::<String>().await;
|
||||
let chunks = chunks();
|
||||
|
@ -1101,6 +1023,7 @@ where
|
|||
}
|
||||
|
||||
/// TODO docs
|
||||
#[allow(unused)]
|
||||
pub async fn build_static_routes<IV>(
|
||||
options: &LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + 'static + Send + Clone,
|
||||
|
@ -1398,11 +1321,11 @@ where
|
|||
})
|
||||
}*/
|
||||
|
||||
#[allow(unused)] // TODO
|
||||
#[cfg(feature = "default")]
|
||||
fn static_route<IV, S>(
|
||||
router: axum::Router<S>,
|
||||
path: &str,
|
||||
options: LeptosOptions,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
additional_context: impl Fn() + Clone + Send + 'static,
|
||||
method: leptos_router::Method,
|
||||
|
@ -1541,20 +1464,20 @@ where
|
|||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
fn leptos_routes<IV>(
|
||||
self,
|
||||
options: &S,
|
||||
state: &S,
|
||||
paths: Vec<AxumRouteListing>,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
) -> Self
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
self.leptos_routes_with_context(options, paths, || {}, app_fn)
|
||||
self.leptos_routes_with_context(state, paths, || {}, app_fn)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
fn leptos_routes_with_context<IV>(
|
||||
self,
|
||||
options: &S,
|
||||
state: &S,
|
||||
paths: Vec<AxumRouteListing>,
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
app_fn: impl Fn() -> IV + Clone + Send + 'static,
|
||||
|
@ -1566,7 +1489,7 @@ where
|
|||
|
||||
// S represents the router's finished state allowing us to provide
|
||||
// it to the user's server functions.
|
||||
let state = options.clone();
|
||||
let state = state.clone();
|
||||
let cx_with_state = move || {
|
||||
provide_context::<S>(state.clone());
|
||||
additional_context();
|
||||
|
@ -1618,8 +1541,7 @@ where
|
|||
{
|
||||
static_route(
|
||||
router,
|
||||
&path,
|
||||
LeptosOptions::from_ref(options),
|
||||
path,
|
||||
app_fn.clone(),
|
||||
cx_with_state_and_method.clone(),
|
||||
method,
|
||||
|
@ -1636,11 +1558,10 @@ where
|
|||
}
|
||||
} else {
|
||||
router.route(
|
||||
&path,
|
||||
path,
|
||||
match listing.mode() {
|
||||
SsrMode::OutOfOrder => {
|
||||
let s = render_app_to_stream_with_context(
|
||||
LeptosOptions::from_ref(options),
|
||||
cx_with_state_and_method.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
|
@ -1654,7 +1575,6 @@ where
|
|||
}
|
||||
SsrMode::PartiallyBlocked => {
|
||||
let s = render_app_to_stream_with_context_and_replace_blocks(
|
||||
LeptosOptions::from_ref(options),
|
||||
cx_with_state_and_method.clone(),
|
||||
app_fn.clone(),
|
||||
true
|
||||
|
@ -1669,7 +1589,6 @@ where
|
|||
}
|
||||
SsrMode::InOrder => {
|
||||
let s = render_app_to_stream_in_order_with_context(
|
||||
LeptosOptions::from_ref(options),
|
||||
cx_with_state_and_method.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
|
@ -1683,7 +1602,6 @@ where
|
|||
}
|
||||
SsrMode::Async => {
|
||||
let s = render_app_async_with_context(
|
||||
LeptosOptions::from_ref(options),
|
||||
cx_with_state_and_method.clone(),
|
||||
app_fn.clone(),
|
||||
);
|
||||
|
|
|
@ -40,11 +40,6 @@
|
|||
//!
|
||||
//! Use `SyncCallback` when you want the function to be `Sync` and `Send`.
|
||||
|
||||
#![cfg_attr(feature = "nightly", feature(fn_traits))]
|
||||
#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
|
||||
#![cfg_attr(feature = "nightly", feature(auto_traits))]
|
||||
#![cfg_attr(feature = "nightly", feature(negative_impls))]
|
||||
|
||||
use reactive_graph::owner::StoredValue;
|
||||
use std::{fmt, rc::Rc, sync::Arc};
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@ use reactive_graph::{
|
|||
computed::ArcMemo,
|
||||
owner::Owner,
|
||||
signal::ArcRwSignal,
|
||||
traits::{Get, GetUntracked, Update, With, WithUntracked},
|
||||
traits::{Get, Update, With, WithUntracked},
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
use tachys::{
|
||||
html::attribute::Attribute,
|
||||
hydration::Cursor,
|
||||
renderer::{CastFrom, Renderer},
|
||||
renderer::Renderer,
|
||||
ssr::StreamBuilder,
|
||||
view::{
|
||||
add_attr::AddAnyAttr, Mountable, Position, PositionState, Render,
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
use crate::into_view::IntoView;
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::owner::Owner;
|
||||
use std::{hash::Hash, marker::PhantomData};
|
||||
use tachys::{
|
||||
reactive_graph::OwnedView,
|
||||
renderer::Renderer,
|
||||
view::{keyed::keyed, RenderHtml},
|
||||
};
|
||||
use std::hash::Hash;
|
||||
use tachys::{reactive_graph::OwnedView, view::keyed::keyed};
|
||||
|
||||
/// Iterates over children and displays them, keyed by the `key` function given.
|
||||
///
|
||||
|
@ -79,30 +75,6 @@ where
|
|||
move || keyed(each(), key.clone(), children.clone())
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn FlatFor<Rndr, IF, I, T, EF, N, KF, K>(
|
||||
/// Items over which the component should iterate.
|
||||
each: IF,
|
||||
/// A key function that will be applied to each item.
|
||||
key: KF,
|
||||
/// A function that takes the item, and returns the view that will be displayed for each item.
|
||||
children: EF,
|
||||
#[prop(optional)] _rndr: PhantomData<Rndr>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
IF: Fn() -> I + 'static,
|
||||
I: IntoIterator<Item = T>,
|
||||
EF: Fn(T) -> N + Clone + 'static,
|
||||
N: RenderHtml<Rndr> + 'static,
|
||||
KF: Fn(&T) -> K + Clone + 'static,
|
||||
K: Eq + Hash + 'static,
|
||||
T: 'static,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
//move || keyed(each(), key.clone(), children.clone())
|
||||
"bar"
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::For;
|
||||
|
|
|
@ -8,12 +8,10 @@ use server_fn::{
|
|||
use tachys::{
|
||||
either::Either,
|
||||
html::{
|
||||
attribute::any_attribute::AnyAttribute,
|
||||
element::{form, Form},
|
||||
event::submit,
|
||||
},
|
||||
reactive_graph::node_ref::NodeRef,
|
||||
renderer::dom::Dom,
|
||||
};
|
||||
use thiserror::Error;
|
||||
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
|
||||
|
@ -84,9 +82,6 @@ pub fn ActionForm<ServFn>(
|
|||
/// A [`NodeRef`] in which the `<form>` element should be stored.
|
||||
#[prop(optional)]
|
||||
node_ref: Option<NodeRef<Form>>,
|
||||
/// Arbitrary attributes to add to the `<form>`
|
||||
#[prop(attrs, optional)]
|
||||
attributes: Vec<AnyAttribute<Dom>>,
|
||||
/// Component children; should include the HTML of the form elements.
|
||||
children: Children,
|
||||
) -> impl IntoView
|
||||
|
@ -168,9 +163,6 @@ pub fn MultiActionForm<ServFn>(
|
|||
/// A [`NodeRef`] in which the `<form>` element should be stored.
|
||||
#[prop(optional)]
|
||||
node_ref: Option<NodeRef<Form>>,
|
||||
/// Arbitrary attributes to add to the `<form>`
|
||||
#[prop(attrs, optional)]
|
||||
attributes: Vec<AnyAttribute<Dom>>,
|
||||
/// Component children; should include the HTML of the form elements.
|
||||
children: Children,
|
||||
) -> impl IntoView
|
||||
|
|
|
@ -4,10 +4,15 @@ use reactive_graph::owner::Owner;
|
|||
use std::marker::PhantomData;
|
||||
use tachys::{
|
||||
dom::body,
|
||||
hydration::Cursor,
|
||||
renderer::{dom::Dom, Renderer},
|
||||
view::{Mountable, PositionState, Render, RenderHtml},
|
||||
view::{Mountable, Render},
|
||||
};
|
||||
#[cfg(feature = "hydrate")]
|
||||
use tachys::{
|
||||
hydration::Cursor,
|
||||
view::{PositionState, RenderHtml},
|
||||
};
|
||||
#[cfg(feature = "hydrate")]
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::HtmlElement;
|
||||
|
||||
|
@ -36,7 +41,9 @@ where
|
|||
use std::sync::Arc;
|
||||
|
||||
// use wasm-bindgen-futures to drive the reactive system
|
||||
Executor::init_wasm_bindgen();
|
||||
// we ignore the return value because an Err here just means the wasm-bindgen executor is
|
||||
// already initialized, which is not an issue
|
||||
_ = Executor::init_wasm_bindgen();
|
||||
|
||||
// create a new reactive owner and use it as the root node to run the app
|
||||
let owner = Owner::new_root(Some(Arc::new(HydrateSharedContext::new())));
|
||||
|
@ -74,7 +81,9 @@ where
|
|||
N: IntoView,
|
||||
{
|
||||
// use wasm-bindgen-futures to drive the reactive system
|
||||
Executor::init_wasm_bindgen();
|
||||
// we ignore the return value because an Err here just means the wasm-bindgen executor is
|
||||
// already initialized, which is not an issue
|
||||
_ = Executor::init_wasm_bindgen();
|
||||
|
||||
// create a new reactive owner and use it as the root node to run the app
|
||||
let owner = Owner::new();
|
||||
|
@ -105,14 +114,16 @@ where
|
|||
R: Renderer,
|
||||
{
|
||||
// use wasm-bindgen-futures to drive the reactive system
|
||||
Executor::init_wasm_bindgen();
|
||||
// we ignore the return value because an Err here just means the wasm-bindgen executor is
|
||||
// already initialized, which is not an issue
|
||||
_ = Executor::init_wasm_bindgen();
|
||||
|
||||
// create a new reactive owner and use it as the root node to run the app
|
||||
let owner = Owner::new();
|
||||
let mountable = owner.with(move || {
|
||||
let view = f();
|
||||
let mut mountable = view.build();
|
||||
mountable.mount(&parent, None);
|
||||
mountable.mount(parent, None);
|
||||
mountable
|
||||
});
|
||||
|
||||
|
@ -132,7 +143,9 @@ pub fn hydrate_islands() {
|
|||
use std::sync::Arc;
|
||||
|
||||
// use wasm-bindgen-futures to drive the reactive system
|
||||
Executor::init_wasm_bindgen();
|
||||
// we ignore the return value because an Err here just means the wasm-bindgen executor is
|
||||
// already initialized, which is not an issue
|
||||
_ = Executor::init_wasm_bindgen();
|
||||
|
||||
// create a new reactive owner and use it as the root node to run the app
|
||||
let owner = Owner::new_root(Some(Arc::new(HydrateSharedContext::new())));
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use crate::{
|
||||
children::{ChildrenFn, TypedChildrenFn},
|
||||
mount, IntoView,
|
||||
};
|
||||
use cfg_if::cfg_if;
|
||||
use crate::{children::TypedChildrenFn, mount, IntoView};
|
||||
use leptos_dom::helpers::document;
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::{effect::Effect, owner::Owner};
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
};
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::{computed::ArcMemo, traits::Get};
|
||||
use tachys::{either::Either, renderer::dom::Dom, view::RenderHtml};
|
||||
use tachys::either::Either;
|
||||
|
||||
#[component]
|
||||
pub fn Show<W, C>(
|
||||
|
|
|
@ -1,36 +1,27 @@
|
|||
use crate::{
|
||||
children::{TypedChildren, ViewFnOnce},
|
||||
into_view::View,
|
||||
IntoView,
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use futures::{pin_mut, FutureExt};
|
||||
use futures::FutureExt;
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::{
|
||||
computed::{suspense::SuspenseContext, ArcMemo, ScopedFuture},
|
||||
owner::{provide_context, use_context},
|
||||
signal::ArcRwSignal,
|
||||
traits::{Get, Read, Track, Update, With, Writeable},
|
||||
transition::AsyncTransition,
|
||||
traits::{Get, Read, Track, With},
|
||||
};
|
||||
use slotmap::{DefaultKey, SlotMap};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
fmt::Debug,
|
||||
future::{ready, Future},
|
||||
pin::Pin,
|
||||
rc::Rc,
|
||||
};
|
||||
use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc};
|
||||
use tachys::{
|
||||
either::Either,
|
||||
html::attribute::Attribute,
|
||||
hydration::Cursor,
|
||||
reactive_graph::{OwnedView, RenderEffectState},
|
||||
renderer::{dom::Dom, Renderer},
|
||||
renderer::Renderer,
|
||||
ssr::StreamBuilder,
|
||||
view::{
|
||||
add_attr::AddAnyAttr,
|
||||
any_view::AnyView,
|
||||
either::{EitherKeepAlive, EitherKeepAliveState},
|
||||
iterators::OptionState,
|
||||
Mountable, Position, PositionState, Render, RenderHtml,
|
||||
|
@ -46,7 +37,6 @@ pub fn Suspense<Chil>(
|
|||
) -> impl IntoView
|
||||
where
|
||||
Chil: IntoView + Send + 'static,
|
||||
SuspenseBoundary<false, AnyView<Dom>, View<Chil>>: IntoView,
|
||||
{
|
||||
let fallback = fallback.run();
|
||||
let children = children.into_inner()();
|
||||
|
@ -163,7 +153,7 @@ where
|
|||
}
|
||||
|
||||
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
|
||||
mut self,
|
||||
self,
|
||||
buf: &mut StreamBuilder,
|
||||
position: &mut Position,
|
||||
) where
|
||||
|
@ -177,11 +167,13 @@ where
|
|||
|
||||
let mut tx = Some(tx);
|
||||
let eff =
|
||||
reactive_graph::effect::RenderEffect::new_isomorphic(move |prev| {
|
||||
reactive_graph::effect::RenderEffect::new_isomorphic(move |_| {
|
||||
tasks.track();
|
||||
if tasks.read().is_empty() {
|
||||
if let Some(tx) = tx.take() {
|
||||
tx.send(());
|
||||
// If the receiver has dropped, it means the ScopedFuture has already
|
||||
// dropped, so it doesn't matter if we manage to send this.
|
||||
_ = tx.send(());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -427,14 +419,14 @@ where
|
|||
|
||||
const MIN_LENGTH: usize = Fut::Output::MIN_LENGTH;
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
fn to_html_with_buf(self, _buf: &mut String, _position: &mut Position) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
|
||||
self,
|
||||
buf: &mut StreamBuilder,
|
||||
position: &mut Position,
|
||||
_buf: &mut StreamBuilder,
|
||||
_position: &mut Position,
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
use crate::{
|
||||
children::{TypedChildren, ViewFnOnce},
|
||||
into_view::View,
|
||||
suspense_component::SuspenseBoundary,
|
||||
IntoView,
|
||||
};
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::{
|
||||
computed::{suspense::SuspenseContext, ArcMemo},
|
||||
owner::{provide_context, Owner},
|
||||
owner::provide_context,
|
||||
signal::ArcRwSignal,
|
||||
traits::With,
|
||||
};
|
||||
use slotmap::{DefaultKey, SlotMap};
|
||||
use std::future::Future;
|
||||
use tachys::{
|
||||
reactive_graph::OwnedView,
|
||||
renderer::dom::Dom,
|
||||
view::{any_view::AnyView, RenderHtml},
|
||||
};
|
||||
use tachys::reactive_graph::OwnedView;
|
||||
|
||||
/// TODO docs!
|
||||
#[component]
|
||||
|
@ -26,7 +20,7 @@ pub fn Transition<Chil>(
|
|||
children: TypedChildren<Chil>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
SuspenseBoundary<true, AnyView<Dom>, View<Chil>>: IntoView,
|
||||
Chil: IntoView + Send + 'static,
|
||||
{
|
||||
let fallback = fallback.run();
|
||||
let children = children.into_inner()();
|
||||
|
|
|
@ -264,7 +264,7 @@ impl ToTokens for Model {
|
|||
#component_id,
|
||||
#component
|
||||
)
|
||||
// #island_serialized_props
|
||||
#island_serialized_props
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -299,66 +299,6 @@ impl ToTokens for Model {
|
|||
}
|
||||
};
|
||||
|
||||
let count = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.count();
|
||||
|
||||
let dyn_attrs_props = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.enumerate()
|
||||
.map(|(idx, Prop { name, .. })| {
|
||||
let ident = &name.ident;
|
||||
if idx < count - 1 {
|
||||
quote! {
|
||||
self.#ident = v.clone().into();
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
self.#ident = v.into();
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let dyn_binding_props = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.filter_map(
|
||||
|Prop {
|
||||
name,
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| {
|
||||
let ident = &name.ident;
|
||||
|
||||
if *attrs {
|
||||
Some(quote! {
|
||||
::leptos::leptos_dom::html::Binding::Attribute { name, value } => self.#ident.push((name, value)),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let body = quote! {
|
||||
#destructure_props
|
||||
#tracing_span_expr
|
||||
|
|
|
@ -13,7 +13,6 @@ use component::DummyModel;
|
|||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Span, TokenTree};
|
||||
use quote::{quote, ToTokens};
|
||||
use rstml::node::KeyedAttribute;
|
||||
use syn::{parse_macro_input, spanned::Spanned, token::Pub, Visibility};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
|
|
@ -65,10 +65,8 @@ impl ToTokens for Model {
|
|||
body,
|
||||
} = self;
|
||||
|
||||
let (impl_generics, generics, where_clause) =
|
||||
body.generics.split_for_impl();
|
||||
let (_, generics, where_clause) = body.generics.split_for_impl();
|
||||
|
||||
let builder_name = quote::format_ident!("{name}Builder");
|
||||
let prop_builder_fields = prop_builder_fields(vis, props);
|
||||
let prop_docs = generate_prop_docs(props);
|
||||
let builder_name_doc = LitStr::new(
|
||||
|
@ -76,39 +74,6 @@ impl ToTokens for Model {
|
|||
name.span(),
|
||||
);
|
||||
|
||||
let count = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.count();
|
||||
|
||||
let dyn_attrs_props = props
|
||||
.iter()
|
||||
.filter(
|
||||
|Prop {
|
||||
prop_opts: PropOpt { attrs, .. },
|
||||
..
|
||||
}| *attrs,
|
||||
)
|
||||
.enumerate()
|
||||
.map(|(idx, Prop { name, .. })| {
|
||||
let ident = &name;
|
||||
if idx < count - 1 {
|
||||
quote! {
|
||||
self.#ident = v.clone().into();
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
self.#ident = v.into();
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let output = quote! {
|
||||
#[doc = #builder_name_doc]
|
||||
#[doc = ""]
|
||||
|
@ -120,14 +85,13 @@ impl ToTokens for Model {
|
|||
#prop_builder_fields
|
||||
}
|
||||
|
||||
/*
|
||||
impl #generics From<#name #generics> for Vec<#name #generics> #where_clause {
|
||||
fn from(value: #name #generics) -> Self {
|
||||
vec![value]
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics ::leptos::Props for #name #generics #where_clause {
|
||||
/*impl #impl_generics ::leptos::Props for #name #generics #where_clause {
|
||||
type Builder = #builder_name #generics;
|
||||
fn builder() -> Self::Builder {
|
||||
#name::builder()
|
||||
|
@ -139,8 +103,7 @@ impl ToTokens for Model {
|
|||
#dyn_attrs_props
|
||||
self
|
||||
}
|
||||
}
|
||||
*/
|
||||
}*/
|
||||
};
|
||||
|
||||
tokens.append_all(output)
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
use super::{event_to_tokens, fragment_to_tokens, TagType};
|
||||
use crate::view::{
|
||||
attribute_absolute, attribute_to_tokens, attribute_value,
|
||||
event_type_and_handler,
|
||||
};
|
||||
use super::{fragment_to_tokens, TagType};
|
||||
use crate::view::attribute_absolute;
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
use rstml::node::{
|
||||
NodeAttribute, NodeBlock, NodeElement, NodeName, NodeNameFragment,
|
||||
};
|
||||
use rstml::node::{NodeAttribute, NodeBlock, NodeElement};
|
||||
use std::collections::HashMap;
|
||||
use syn::{spanned::Spanned, Expr, ExprRange, RangeLimits, Stmt};
|
||||
|
||||
|
@ -16,6 +11,8 @@ pub(crate) fn component_to_tokens(
|
|||
global_class: Option<&TokenTree>,
|
||||
) -> TokenStream {
|
||||
let name = node.name();
|
||||
|
||||
#[allow(unused)] // TODO this is used by hot-reloading
|
||||
#[cfg(debug_assertions)]
|
||||
let component_name = super::ident_from_tag_name(node.name());
|
||||
|
||||
|
@ -53,30 +50,6 @@ pub(crate) fn component_to_tokens(
|
|||
}
|
||||
});
|
||||
|
||||
let spread_bindings = node.attributes().iter().filter_map(|node| {
|
||||
use rstml::node::NodeBlock;
|
||||
use syn::{Expr, ExprRange, RangeLimits, Stmt};
|
||||
|
||||
if let NodeAttribute::Block(NodeBlock::ValidBlock(block)) = node {
|
||||
match block.stmts.first()? {
|
||||
Stmt::Expr(
|
||||
Expr::Range(ExprRange {
|
||||
start: None,
|
||||
limits: RangeLimits::HalfOpen(_),
|
||||
end: Some(end),
|
||||
..
|
||||
}),
|
||||
_,
|
||||
) => Some(
|
||||
quote! { .dyn_bindings(#[allow(unused_brace)] {#end}) },
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let props = attrs
|
||||
.clone()
|
||||
.enumerate()
|
||||
|
@ -208,6 +181,8 @@ pub(crate) fn component_to_tokens(
|
|||
None,
|
||||
);
|
||||
|
||||
// TODO view marker for hot-reloading
|
||||
/*
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(debug_assertions)] {
|
||||
let marker = format!("<{component_name}/>-children");
|
||||
|
@ -218,6 +193,7 @@ pub(crate) fn component_to_tokens(
|
|||
let view_marker = quote! {};
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if let Some(children) = children {
|
||||
let bindables =
|
||||
|
|
|
@ -13,7 +13,7 @@ use rstml::node::{
|
|||
};
|
||||
use std::collections::HashMap;
|
||||
use syn::{
|
||||
spanned::Spanned, Expr, ExprPath, ExprRange, Lit, LitStr, RangeLimits, Stmt,
|
||||
spanned::Spanned, Expr, ExprRange, Lit, LitStr, RangeLimits, Stmt,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -369,7 +369,8 @@ fn is_spread_marker(node: &NodeElement) -> bool {
|
|||
fn attribute_to_tokens(
|
||||
tag_type: TagType,
|
||||
node: &NodeAttribute,
|
||||
global_class: Option<&TokenTree>,
|
||||
// TODO global_class support
|
||||
_global_class: Option<&TokenTree>,
|
||||
) -> TokenStream {
|
||||
match node {
|
||||
NodeAttribute::Block(node) => {
|
||||
|
@ -979,20 +980,6 @@ pub(crate) fn parse_event_name(name: &str) -> (TokenStream, bool, bool, bool) {
|
|||
(event_type, is_custom, is_force_undelegated, is_targeted)
|
||||
}
|
||||
|
||||
fn expr_to_ident(expr: &syn::Expr) -> Option<&ExprPath> {
|
||||
match expr {
|
||||
syn::Expr::Block(block) => block.block.stmts.last().and_then(|stmt| {
|
||||
if let syn::Stmt::Expr(expr, ..) = stmt {
|
||||
expr_to_ident(expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
syn::Expr::Path(path) => Some(path),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_snake_case(name: String) -> String {
|
||||
if !name.is_case(Snake) {
|
||||
name.to_case(Snake)
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
use reactive_graph::{
|
||||
actions::{Action, ArcAction},
|
||||
owner::StoredValue,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::DefinedAt,
|
||||
unwrap_signal,
|
||||
};
|
||||
use server_fn::{error::ServerFnUrlError, ServerFn, ServerFnError};
|
||||
use server_fn::{ServerFn, ServerFnError};
|
||||
use std::{ops::Deref, panic::Location};
|
||||
|
||||
pub struct ArcServerAction<S>
|
||||
|
|
|
@ -15,10 +15,9 @@ use reactive_graph::{
|
|||
ArcAsyncDerived, ArcAsyncDerivedFuture, ArcMemo, AsyncDerived,
|
||||
AsyncDerivedFuture, AsyncDerivedGuard,
|
||||
},
|
||||
graph::{Source, ToAnySource, ToAnySubscriber},
|
||||
graph::{Source, ToAnySubscriber},
|
||||
owner::Owner,
|
||||
prelude::*,
|
||||
signal::guards::{AsyncPlain, Mapped, ReadGuard},
|
||||
};
|
||||
use std::{future::IntoFuture, ops::Deref};
|
||||
|
||||
|
@ -176,7 +175,7 @@ where
|
|||
.unwrap_or_default();
|
||||
|
||||
let initial = Self::initial_value(&id);
|
||||
let is_ready = matches!(initial, Some(_));
|
||||
let is_ready = initial.is_some();
|
||||
|
||||
let source = ArcMemo::new(move |_| source());
|
||||
let fun = {
|
||||
|
@ -186,7 +185,7 @@ where
|
|||
|
||||
let data = ArcAsyncDerived::new_with_initial(initial, fun);
|
||||
if is_ready {
|
||||
_ = source.with(|_| ());
|
||||
source.with(|_| ());
|
||||
source.add_subscriber(data.to_any_subscriber());
|
||||
}
|
||||
|
||||
|
@ -216,6 +215,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused)]
|
||||
fn initial_value(id: &SerializedDataId) -> Option<T> {
|
||||
#[cfg(feature = "hydration")]
|
||||
{
|
||||
|
@ -225,6 +225,7 @@ where
|
|||
if let Some(value) = value {
|
||||
match T::de(&value) {
|
||||
Ok(value) => return Some(value),
|
||||
#[allow(unused)]
|
||||
Err(e) => {
|
||||
#[cfg(feature = "tracing")]
|
||||
tracing::error!(
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use crate::ServerMetaContext;
|
||||
use indexmap::IndexMap;
|
||||
use leptos::{
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{effect::RenderEffect, owner::use_context},
|
||||
reactive_graph::owner::use_context,
|
||||
tachys::{
|
||||
dom::document,
|
||||
html::{
|
||||
|
@ -17,7 +14,6 @@ use leptos::{
|
|||
class,
|
||||
},
|
||||
hydration::Cursor,
|
||||
reactive_graph::RenderEffectState,
|
||||
renderer::{dom::Dom, Renderer},
|
||||
view::{
|
||||
add_attr::AddAnyAttr, Mountable, Position, PositionState, Render,
|
||||
|
@ -28,14 +24,7 @@ use leptos::{
|
|||
IntoView,
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
future::{ready, Ready},
|
||||
mem,
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use std::mem;
|
||||
use web_sys::HtmlElement;
|
||||
|
||||
/// A component to set metadata on the document’s `<body>` element from
|
||||
|
@ -92,6 +81,7 @@ struct BodyView {
|
|||
attributes: Vec<AnyAttribute<Dom>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // TODO these should be used to rebuild the attributes, I guess
|
||||
struct BodyViewState {
|
||||
el: HtmlElement,
|
||||
attributes: Vec<AnyAttributeState<Dom>>,
|
||||
|
@ -112,8 +102,8 @@ impl Render<Dom> for BodyView {
|
|||
BodyViewState { el, attributes }
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
// TODO rebuilding dynamic things like this
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +111,8 @@ impl AddAnyAttr<Dom> for BodyView {
|
|||
type Output<SomeNewAttr: Attribute<Dom>> = BodyView;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<Dom>>(
|
||||
mut self,
|
||||
attr: NewAttr,
|
||||
self,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<Dom>,
|
||||
|
@ -142,12 +132,12 @@ impl RenderHtml<Dom> for BodyView {
|
|||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {}
|
||||
fn to_html_with_buf(self, _buf: &mut String, _position: &mut Position) {}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
cursor: &Cursor<Dom>,
|
||||
position: &PositionState,
|
||||
_cursor: &Cursor<Dom>,
|
||||
_position: &PositionState,
|
||||
) -> Self::State {
|
||||
let el = document().body().expect("there to be a <body> element");
|
||||
|
||||
|
@ -166,15 +156,15 @@ impl Mountable<Dom> for BodyViewState {
|
|||
|
||||
fn mount(
|
||||
&mut self,
|
||||
parent: &<Dom as Renderer>::Element,
|
||||
marker: Option<&<Dom as Renderer>::Node>,
|
||||
_parent: &<Dom as Renderer>::Element,
|
||||
_marker: Option<&<Dom as Renderer>::Node>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn insert_before_this(
|
||||
&self,
|
||||
parent: &<Dom as Renderer>::Element,
|
||||
child: &mut dyn Mountable<Dom>,
|
||||
_parent: &<Dom as Renderer>::Element,
|
||||
_child: &mut dyn Mountable<Dom>,
|
||||
) -> bool {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use crate::ServerMetaContext;
|
||||
use indexmap::IndexMap;
|
||||
use leptos::{
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{effect::RenderEffect, owner::use_context},
|
||||
reactive_graph::owner::use_context,
|
||||
tachys::{
|
||||
dom::document,
|
||||
html::{
|
||||
|
@ -18,7 +15,6 @@ use leptos::{
|
|||
class,
|
||||
},
|
||||
hydration::Cursor,
|
||||
reactive_graph::RenderEffectState,
|
||||
renderer::{dom::Dom, Renderer},
|
||||
view::{
|
||||
add_attr::AddAnyAttr, Mountable, Position, PositionState, Render,
|
||||
|
@ -29,15 +25,8 @@ use leptos::{
|
|||
IntoView,
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
future::{ready, Ready},
|
||||
mem,
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use web_sys::{Element, HtmlElement};
|
||||
use std::mem;
|
||||
use web_sys::Element;
|
||||
|
||||
/// A component to set metadata on the document’s `<html>` element from
|
||||
/// within the application.
|
||||
|
@ -103,6 +92,7 @@ struct HtmlView {
|
|||
attributes: Vec<AnyAttribute<Dom>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // TODO these should be used to rebuild the attributes, I guess
|
||||
struct HtmlViewState {
|
||||
el: Element,
|
||||
attributes: Vec<AnyAttributeState<Dom>>,
|
||||
|
@ -125,8 +115,8 @@ impl Render<Dom> for HtmlView {
|
|||
HtmlViewState { el, attributes }
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
// TODO rebuilding dynamic things like this
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,8 +124,8 @@ impl AddAnyAttr<Dom> for HtmlView {
|
|||
type Output<SomeNewAttr: Attribute<Dom>> = HtmlView;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<Dom>>(
|
||||
mut self,
|
||||
attr: NewAttr,
|
||||
self,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<Dom>,
|
||||
|
|
|
@ -73,8 +73,6 @@ use or_poisoned::OrPoisoned;
|
|||
use send_wrapper::SendWrapper;
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
future::{ready, Ready},
|
||||
pin::Pin,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use wasm_bindgen::JsCast;
|
||||
|
@ -321,7 +319,7 @@ fn document_head() -> HtmlHeadElement {
|
|||
document.head().unwrap_or_else(|| {
|
||||
let el = document.create_element("head").unwrap();
|
||||
let document = document.document_element().unwrap();
|
||||
document.append_child(&el);
|
||||
_ = document.append_child(&el);
|
||||
el.unchecked_into()
|
||||
})
|
||||
}
|
||||
|
@ -357,7 +355,7 @@ where
|
|||
>;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<Dom>>(
|
||||
mut self,
|
||||
self,
|
||||
attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
|
@ -435,7 +433,7 @@ where
|
|||
|
||||
fn insert_before_this(
|
||||
&self,
|
||||
parent: &<Dom as Renderer>::Element,
|
||||
_parent: &<Dom as Renderer>::Element,
|
||||
child: &mut dyn Mountable<Dom>,
|
||||
) -> bool {
|
||||
self.state.insert_before_this(&document_head(), child)
|
||||
|
@ -447,18 +445,11 @@ where
|
|||
/// being used during server rendering.
|
||||
#[component]
|
||||
pub fn MetaTags() -> impl IntoView {
|
||||
MetaTagsView {
|
||||
context: use_context::<ServerMetaContext>().expect(
|
||||
"before using the <MetaTags/> component, you should make sure to \
|
||||
provide ServerMetaContext via context",
|
||||
),
|
||||
}
|
||||
MetaTagsView
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MetaTagsView {
|
||||
context: ServerMetaContext,
|
||||
}
|
||||
struct MetaTagsView;
|
||||
|
||||
// this implementation doesn't do anything during client-side rendering, it's just for server-side
|
||||
// rendering HTML for all the tags that will be injected into the `<head>`
|
||||
|
@ -469,7 +460,7 @@ impl Render<Dom> for MetaTagsView {
|
|||
|
||||
fn build(self) -> Self::State {}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {}
|
||||
fn rebuild(self, _state: &mut Self::State) {}
|
||||
}
|
||||
|
||||
impl AddAnyAttr<Dom> for MetaTagsView {
|
||||
|
@ -497,14 +488,14 @@ impl RenderHtml<Dom> for MetaTagsView {
|
|||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
fn to_html_with_buf(self, buf: &mut String, _position: &mut Position) {
|
||||
buf.push_str("<!--HEAD-->");
|
||||
}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
cursor: &Cursor<Dom>,
|
||||
position: &PositionState,
|
||||
_cursor: &Cursor<Dom>,
|
||||
_position: &PositionState,
|
||||
) -> Self::State {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
use crate::register;
|
||||
use leptos::{
|
||||
component,
|
||||
oco::Oco,
|
||||
prelude::GlobalAttributes,
|
||||
tachys::{
|
||||
html::{attribute::any_attribute::AnyAttribute, element::link},
|
||||
renderer::dom::Dom,
|
||||
},
|
||||
IntoView,
|
||||
component, oco::Oco, prelude::GlobalAttributes,
|
||||
tachys::html::element::link, IntoView,
|
||||
};
|
||||
|
||||
/// Injects an [`HTMLLinkElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement) into the document
|
||||
|
@ -83,9 +77,6 @@ pub fn Link(
|
|||
/// The [`blocking`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-blocking) attribute.
|
||||
#[prop(optional, into)]
|
||||
blocking: Option<Oco<'static, str>>,
|
||||
/// Custom attributes.
|
||||
#[prop(attrs, optional)]
|
||||
attrs: Vec<AnyAttribute<Dom>>,
|
||||
) -> impl IntoView {
|
||||
// TODO additional attributes
|
||||
register(
|
||||
|
|
|
@ -2,10 +2,7 @@ use crate::register;
|
|||
use leptos::{
|
||||
component,
|
||||
prelude::{CustomAttribute, GlobalAttributes},
|
||||
tachys::{
|
||||
html::{attribute::any_attribute::AnyAttribute, element::meta},
|
||||
renderer::dom::Dom,
|
||||
},
|
||||
tachys::html::element::meta,
|
||||
text_prop::TextProp,
|
||||
IntoView,
|
||||
};
|
||||
|
@ -50,11 +47,7 @@ pub fn Meta(
|
|||
/// The [`content`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#attr-content) attribute.
|
||||
#[prop(optional, into)]
|
||||
content: Option<TextProp>,
|
||||
/// Custom attributes.
|
||||
#[prop(attrs, optional)]
|
||||
attrs: Vec<AnyAttribute<Dom>>,
|
||||
) -> impl IntoView {
|
||||
// TODO other attrs
|
||||
register(
|
||||
meta()
|
||||
.charset(charset.map(|v| move || v.get()))
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
use crate::register;
|
||||
use leptos::{
|
||||
component,
|
||||
oco::Oco,
|
||||
prelude::*,
|
||||
tachys::{
|
||||
html::{attribute::any_attribute::AnyAttribute, element::script},
|
||||
renderer::dom::Dom,
|
||||
view::any_view::AnyView,
|
||||
},
|
||||
IntoView,
|
||||
component, oco::Oco, prelude::*, tachys::html::element::script, IntoView,
|
||||
};
|
||||
|
||||
/// Injects an [`HTMLScriptElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement) into the document
|
||||
|
@ -72,11 +64,7 @@ pub fn Script(
|
|||
/// The content of the `<script>` tag.
|
||||
#[prop(optional)]
|
||||
children: Option<Children>,
|
||||
/// Custom attributes.
|
||||
#[prop(attrs, optional)]
|
||||
attrs: Vec<AnyAttribute<Dom>>,
|
||||
) -> impl IntoView {
|
||||
// TODO other attrs
|
||||
register(
|
||||
script()
|
||||
.id(id)
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
use crate::register;
|
||||
use leptos::{
|
||||
component,
|
||||
oco::Oco,
|
||||
prelude::*,
|
||||
tachys::{
|
||||
html::{attribute::any_attribute::AnyAttribute, element::style},
|
||||
renderer::dom::Dom,
|
||||
view::any_view::AnyView,
|
||||
},
|
||||
IntoView,
|
||||
component, oco::Oco, prelude::*, tachys::html::element::style, IntoView,
|
||||
};
|
||||
|
||||
/// Injects an [`HTMLStyleElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLStyleElement) into the document
|
||||
|
@ -50,12 +42,8 @@ pub fn Style(
|
|||
blocking: Option<Oco<'static, str>>,
|
||||
/// The content of the `<style>` tag.
|
||||
#[prop(optional)]
|
||||
children: Option<Box<dyn FnOnce() -> AnyView<Dom>>>,
|
||||
/// Custom attributes.
|
||||
#[prop(attrs, optional)]
|
||||
attrs: Vec<AnyAttribute<Dom>>,
|
||||
children: Option<Children>,
|
||||
) -> impl IntoView {
|
||||
// TODO other attributes
|
||||
register(
|
||||
style()
|
||||
.id(id)
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use crate::register;
|
||||
use leptos::{
|
||||
component,
|
||||
tachys::{
|
||||
html::{attribute::any_attribute::AnyAttribute, element::link},
|
||||
renderer::dom::Dom,
|
||||
},
|
||||
attr::global::GlobalAttributes, component, tachys::html::element::link,
|
||||
IntoView,
|
||||
};
|
||||
|
||||
|
@ -34,10 +30,7 @@ pub fn Stylesheet(
|
|||
/// An ID for the stylesheet.
|
||||
#[prop(optional, into)]
|
||||
id: Option<String>,
|
||||
/// Custom attributes.
|
||||
#[prop(attrs, optional)]
|
||||
attrs: Vec<AnyAttribute<Dom>>,
|
||||
) -> impl IntoView {
|
||||
// TODO additional attributes
|
||||
register(link().rel("stylesheet").href(href))
|
||||
register(link().id(id).rel("stylesheet").href(href))
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::{use_head, MetaContext, ServerMetaContext};
|
|||
use leptos::{
|
||||
attr::Attribute,
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{
|
||||
effect::RenderEffect,
|
||||
|
@ -22,15 +21,9 @@ use leptos::{
|
|||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
future::{ready, Ready},
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasm_bindgen::{JsCast, UnwrapThrowExt};
|
||||
use web_sys::{Element, HtmlTitleElement};
|
||||
use web_sys::HtmlTitleElement;
|
||||
|
||||
/// Contains the current state of the document's `<title>`.
|
||||
#[derive(Clone, Default)]
|
||||
|
@ -188,6 +181,7 @@ impl TitleView {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // TODO these should be used to rebuild the attributes, I guess
|
||||
struct TitleViewState {
|
||||
el: HtmlTitleElement,
|
||||
formatter: Option<Formatter>,
|
||||
|
@ -231,7 +225,7 @@ impl AddAnyAttr<Dom> for TitleView {
|
|||
|
||||
fn add_any_attr<NewAttr: Attribute<Dom>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<Dom>,
|
||||
|
@ -251,7 +245,7 @@ impl RenderHtml<Dom> for TitleView {
|
|||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
fn to_html_with_buf(self, _buf: &mut String, _position: &mut Position) {
|
||||
// meta tags are rendered into the buffer stored into the context
|
||||
// the value has already been taken out, when we're on the server
|
||||
}
|
||||
|
@ -290,8 +284,8 @@ impl Mountable<Dom> for TitleViewState {
|
|||
|
||||
fn mount(
|
||||
&mut self,
|
||||
parent: &<Dom as Renderer>::Element,
|
||||
marker: Option<&<Dom as Renderer>::Node>,
|
||||
_parent: &<Dom as Renderer>::Element,
|
||||
_marker: Option<&<Dom as Renderer>::Node>,
|
||||
) {
|
||||
// <title> doesn't need to be mounted
|
||||
// TitleView::el() guarantees that there is a <title> in the <head>
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
SubscriberSet, ToAnySource, ToAnySubscriber,
|
||||
},
|
||||
owner::{use_context, Owner},
|
||||
signal::guards::{AsyncPlain, Plain, ReadGuard},
|
||||
signal::guards::{AsyncPlain, ReadGuard},
|
||||
traits::{DefinedAt, ReadUntracked},
|
||||
transition::AsyncTransition,
|
||||
};
|
||||
|
@ -131,9 +131,9 @@ impl<T> DefinedAt for ArcAsyncDerived<T> {
|
|||
// as far as I can tell, require repeating most of the function body.
|
||||
macro_rules! spawn_derived {
|
||||
($spawner:expr, $initial:ident, $fun:ident) => {{
|
||||
let (mut notifier, mut rx) = channel();
|
||||
let (notifier, mut rx) = channel();
|
||||
|
||||
let is_ready = matches!($initial, Some(_));
|
||||
let is_ready = $initial.is_some();
|
||||
|
||||
let owner = Owner::new();
|
||||
let inner = Arc::new(RwLock::new(ArcAsyncDerivedInner {
|
||||
|
@ -234,7 +234,12 @@ macro_rules! spawn_derived {
|
|||
loading.store(false, Ordering::Relaxed);
|
||||
*value.write().await = Some(new_value);
|
||||
inner.write().or_poisoned().dirty = true;
|
||||
ready_tx.send(());
|
||||
|
||||
// if it's an Err, that just means the Receiver was dropped
|
||||
// we don't particularly care about that: the point is to notify if
|
||||
// it still exists, but we don't need to know if Suspense is no
|
||||
// longer listening
|
||||
_ = ready_tx.send(());
|
||||
|
||||
// notify reactive subscribers that we're not loading any more
|
||||
for sub in (&inner.read().or_poisoned().subscribers).into_iter() {
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
use super::{
|
||||
ArcAsyncDerived, ArcAsyncDerivedFuture, ArcAsyncDerivedReadyFuture,
|
||||
};
|
||||
use super::{ArcAsyncDerived, ArcAsyncDerivedReadyFuture};
|
||||
use crate::{
|
||||
graph::{
|
||||
AnySource, AnySubscriber, ReactiveNode, Source, Subscriber,
|
||||
ToAnySource, ToAnySubscriber,
|
||||
},
|
||||
owner::StoredValue,
|
||||
signal::guards::{AsyncPlain, Plain, ReadGuard},
|
||||
signal::guards::{AsyncPlain, ReadGuard},
|
||||
traits::{DefinedAt, Dispose, ReadUntracked},
|
||||
unwrap_signal,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use std::{
|
||||
future::{Future, IntoFuture},
|
||||
panic::Location,
|
||||
};
|
||||
use std::{future::Future, panic::Location};
|
||||
|
||||
pub struct AsyncDerived<T> {
|
||||
#[cfg(debug_assertions)]
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use super::{suspense::SuspenseContext, ArcAsyncDerived, AsyncDerived};
|
||||
use super::{ArcAsyncDerived, AsyncDerived};
|
||||
use crate::{
|
||||
graph::{AnySource, ToAnySource},
|
||||
owner::use_context,
|
||||
signal::guards::{AsyncPlain, Mapped, Plain, ReadGuard},
|
||||
signal::guards::{AsyncPlain, Mapped, ReadGuard},
|
||||
traits::{DefinedAt, Track},
|
||||
unwrap_signal,
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ impl SpecialNonReactiveZone {
|
|||
SpecialNonReactiveZoneGuard
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(all(debug_assertions, feature = "effects"))]
|
||||
#[inline(always)]
|
||||
pub(crate) fn is_inside() -> bool {
|
||||
if cfg!(debug_assertions) {
|
||||
|
|
|
@ -56,30 +56,32 @@ impl Effect {
|
|||
let value = Arc::new(RwLock::new(None::<T>));
|
||||
let mut first_run = true;
|
||||
|
||||
#[cfg(feature = "effects")]
|
||||
Executor::spawn_local({
|
||||
let value = Arc::clone(&value);
|
||||
let subscriber = inner.to_any_subscriber();
|
||||
if cfg!(feature = "effects") {
|
||||
Executor::spawn_local({
|
||||
let value = Arc::clone(&value);
|
||||
let subscriber = inner.to_any_subscriber();
|
||||
|
||||
async move {
|
||||
while rx.next().await.is_some() {
|
||||
if first_run
|
||||
|| subscriber
|
||||
.with_observer(|| subscriber.update_if_necessary())
|
||||
{
|
||||
first_run = false;
|
||||
subscriber.clear_sources(&subscriber);
|
||||
async move {
|
||||
while rx.next().await.is_some() {
|
||||
if first_run
|
||||
|| subscriber.with_observer(|| {
|
||||
subscriber.update_if_necessary()
|
||||
})
|
||||
{
|
||||
first_run = false;
|
||||
subscriber.clear_sources(&subscriber);
|
||||
|
||||
let old_value =
|
||||
mem::take(&mut *value.write().or_poisoned());
|
||||
let new_value = owner.with_cleanup(|| {
|
||||
subscriber.with_observer(|| fun(old_value))
|
||||
});
|
||||
*value.write().or_poisoned() = Some(new_value);
|
||||
let old_value =
|
||||
mem::take(&mut *value.write().or_poisoned());
|
||||
let new_value = owner.with_cleanup(|| {
|
||||
subscriber.with_observer(|| fun(old_value))
|
||||
});
|
||||
*value.write().or_poisoned() = Some(new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
inner: StoredValue::new(Some(inner)),
|
||||
|
@ -96,30 +98,33 @@ impl Effect {
|
|||
let mut first_run = true;
|
||||
let value = Arc::new(RwLock::new(None::<T>));
|
||||
|
||||
#[cfg(feature = "effects")]
|
||||
Executor::spawn({
|
||||
let value = Arc::clone(&value);
|
||||
let subscriber = inner.to_any_subscriber();
|
||||
if cfg!(feature = "effects") {
|
||||
Executor::spawn({
|
||||
let value = Arc::clone(&value);
|
||||
let subscriber = inner.to_any_subscriber();
|
||||
|
||||
async move {
|
||||
while rx.next().await.is_some() {
|
||||
if first_run
|
||||
|| subscriber
|
||||
.with_observer(|| subscriber.update_if_necessary())
|
||||
{
|
||||
first_run = false;
|
||||
subscriber.clear_sources(&subscriber);
|
||||
async move {
|
||||
while rx.next().await.is_some() {
|
||||
if first_run
|
||||
|| subscriber.with_observer(|| {
|
||||
subscriber.update_if_necessary()
|
||||
})
|
||||
{
|
||||
first_run = false;
|
||||
subscriber.clear_sources(&subscriber);
|
||||
|
||||
let old_value =
|
||||
mem::take(&mut *value.write().or_poisoned());
|
||||
let new_value = owner.with_cleanup(|| {
|
||||
subscriber.with_observer(|| fun(old_value))
|
||||
});
|
||||
*value.write().or_poisoned() = Some(new_value);
|
||||
let old_value =
|
||||
mem::take(&mut *value.write().or_poisoned());
|
||||
let new_value = owner.with_cleanup(|| {
|
||||
subscriber.with_observer(|| fun(old_value))
|
||||
});
|
||||
*value.write().or_poisoned() = Some(new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
inner: StoredValue::new(Some(inner)),
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ pub mod prelude {
|
|||
pub use crate::traits::*;
|
||||
}
|
||||
|
||||
// TODO remove this, it's just useful while developing
|
||||
#[allow(unused)]
|
||||
fn log_warning(text: Arguments) {
|
||||
#[cfg(feature = "tracing")]
|
||||
{
|
||||
|
|
|
@ -20,13 +20,18 @@ thread_local! {
|
|||
}
|
||||
|
||||
impl Arena {
|
||||
#[cfg(feature = "hydration")]
|
||||
#[inline(always)]
|
||||
pub fn enter_new() {
|
||||
#[cfg(feature = "sandboxed-arenas")]
|
||||
MAP.with_borrow_mut(|arena| {
|
||||
*arena =
|
||||
Some(Arc::new(RwLock::new(SlotMap::with_capacity_and_key(32))))
|
||||
})
|
||||
{
|
||||
use std::sync::Arc;
|
||||
MAP.with_borrow_mut(|arena| {
|
||||
*arena = Some(Arc::new(RwLock::new(
|
||||
SlotMap::with_capacity_and_key(32),
|
||||
)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
|
@ -51,7 +51,10 @@ impl AsyncTransition {
|
|||
.as_ref()
|
||||
.map(|n| &n.tx)
|
||||
{
|
||||
tx.send(rx);
|
||||
// if it's an Err, that just means the Receiver was dropped
|
||||
// i.e., the transition is no longer listening, in which case it doesn't matter if we
|
||||
// successfully register with it or not
|
||||
_ = tx.send(rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
pub use super::link::*;
|
||||
#[cfg(feature = "ssr")]
|
||||
use crate::location::RequestUrl;
|
||||
use crate::{
|
||||
hooks::use_navigate,
|
||||
location::{
|
||||
BrowserUrl, Location, LocationChange, LocationProvider, RequestUrl,
|
||||
State, Url,
|
||||
BrowserUrl, Location, LocationChange, LocationProvider, State, Url,
|
||||
},
|
||||
navigate::{NavigateOptions, UseNavigate},
|
||||
params::ParamsMap,
|
||||
navigate::NavigateOptions,
|
||||
resolve_path::resolve_path,
|
||||
ChooseView, FlatRoutesView, MatchNestedRoutes, NestedRoute,
|
||||
NestedRoutesView, Routes, SsrMode,
|
||||
};
|
||||
use leptos::prelude::*;
|
||||
use reactive_graph::{
|
||||
computed::ArcMemo,
|
||||
owner::{provide_context, use_context, Owner},
|
||||
signal::{ArcRwSignal, RwSignal},
|
||||
traits::{GetUntracked, Read, ReadUntracked, Set},
|
||||
untrack,
|
||||
signal::ArcRwSignal,
|
||||
traits::{GetUntracked, ReadUntracked, Set},
|
||||
wrappers::write::SignalSetter,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow, fmt::Debug, marker::PhantomData, sync::Arc, time::Duration,
|
||||
};
|
||||
use tachys::renderer::{dom::Dom, Renderer};
|
||||
use tachys::renderer::dom::Dom;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RouteChildren<Children>(Children);
|
||||
|
@ -62,10 +60,6 @@ pub fn Router<Chil>(
|
|||
/// any elements, and should include a [`Routes`](crate::Routes) component somewhere
|
||||
/// to define and display [`Route`](crate::Route)s.
|
||||
children: TypedChildren<Chil>,
|
||||
/// A unique identifier for this router, allowing you to mount multiple Leptos apps with
|
||||
/// different routes from the same server.
|
||||
#[prop(optional)]
|
||||
id: usize,
|
||||
) -> impl IntoView
|
||||
where
|
||||
Chil: IntoView,
|
||||
|
@ -235,7 +229,7 @@ where
|
|||
base: base.clone(),
|
||||
fallback: fallback(),
|
||||
rndr: PhantomData,
|
||||
set_is_routing: set_is_routing.clone(),
|
||||
set_is_routing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,6 +252,9 @@ where
|
|||
..
|
||||
} = use_context()
|
||||
.expect("<FlatRoutes> should be used inside a <Router> component");
|
||||
|
||||
// TODO base
|
||||
#[allow(unused)]
|
||||
let base = base.map(|base| {
|
||||
let mut base = Oco::from(base);
|
||||
base.upgrade_inplace();
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
use crate::{
|
||||
location::{Location, LocationProvider, RequestUrl, Url},
|
||||
location::{LocationProvider, Url},
|
||||
matching::Routes,
|
||||
params::ParamsMap,
|
||||
resolve_path::resolve_path,
|
||||
ChooseView, MatchInterface, MatchNestedRoutes, MatchParams, Method,
|
||||
PathSegment, RouteList, RouteListing, RouteMatchId,
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use either_of::{Either, EitherFuture, EitherOf3};
|
||||
use either_of::{Either, EitherOf3};
|
||||
use futures::FutureExt;
|
||||
use leptos::{component, oco::Oco, IntoView};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo, ScopedFuture},
|
||||
owner::{provide_context, use_context, Owner},
|
||||
signal::{ArcRwSignal, ArcTrigger},
|
||||
traits::{Get, GetUntracked, Read, ReadUntracked, Set, Track, Trigger}, transition::AsyncTransition, wrappers::write::SignalSetter,
|
||||
computed::{ScopedFuture},
|
||||
owner::{provide_context, Owner},
|
||||
signal::{ArcRwSignal},
|
||||
traits::{ReadUntracked, Set},
|
||||
transition::AsyncTransition,
|
||||
wrappers::write::SignalSetter,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
future::Future,
|
||||
iter,
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
rc::Rc,
|
||||
sync::{
|
||||
mpsc::{self, Receiver, Sender},
|
||||
Arc, Mutex,
|
||||
},
|
||||
};
|
||||
use tachys::{
|
||||
hydration::Cursor,
|
||||
|
@ -36,8 +28,6 @@ use tachys::{
|
|||
ssr::StreamBuilder,
|
||||
view::{
|
||||
add_attr::AddAnyAttr,
|
||||
any_view::{AnyView, AnyViewState, IntoAny},
|
||||
either::EitherState,
|
||||
Mountable, Position, PositionState, Render, RenderHtml,
|
||||
},
|
||||
};
|
||||
|
@ -149,6 +139,7 @@ where
|
|||
Fal: Render<R> + 'static,
|
||||
R: Renderer + 'static
|
||||
{
|
||||
#[allow(clippy::type_complexity)]
|
||||
view: <EitherOf3<(), Fal, <Defs::Match as MatchInterface<R>>::View> as Render<R>>::State,
|
||||
id: Option<RouteMatchId>,
|
||||
owner: Owner,
|
||||
|
@ -204,7 +195,7 @@ where
|
|||
let current_url = current_url.read_untracked();
|
||||
|
||||
// we always need to match the new route
|
||||
let new_match = routes.match_route(¤t_url.path());
|
||||
let new_match = routes.match_route(current_url.path());
|
||||
let id = new_match.as_ref().map(|n| n.as_id());
|
||||
|
||||
// create default starting points for owner, url, path, and params
|
||||
|
@ -364,7 +355,7 @@ where
|
|||
|
||||
Executor::spawn_local(owner.with(|| {
|
||||
ScopedFuture::new({
|
||||
let state = Rc::clone(&state);
|
||||
let state = Rc::clone(state);
|
||||
async move {
|
||||
provide_context(url);
|
||||
provide_context(params);
|
||||
|
@ -413,7 +404,7 @@ where
|
|||
|
||||
fn add_any_attr<NewAttr: leptos::attr::Attribute<R>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
@ -433,7 +424,7 @@ where
|
|||
self,
|
||||
) -> Either<Fal, <Defs::Match as MatchInterface<R>>::View> {
|
||||
let current_url = self.current_url.read_untracked();
|
||||
let new_match = self.routes.match_route(¤t_url.path());
|
||||
let new_match = self.routes.match_route(current_url.path());
|
||||
let owner = self.outer_owner.child();
|
||||
let url = ArcRwSignal::new(current_url.to_owned());
|
||||
let params = ArcRwSignal::new(
|
||||
|
@ -487,7 +478,7 @@ where
|
|||
if RouteList::is_generating() {
|
||||
// add routes
|
||||
let (base, routes) = self.routes.generate_routes();
|
||||
let mut routes = routes
|
||||
let routes = routes
|
||||
.into_iter()
|
||||
.map(|data| {
|
||||
let path = base
|
||||
|
@ -557,7 +548,6 @@ where
|
|||
// client-side route component code is not yet loaded
|
||||
let FlatRoutesView {
|
||||
current_url,
|
||||
location,
|
||||
routes,
|
||||
fallback,
|
||||
outer_owner,
|
||||
|
@ -566,7 +556,7 @@ where
|
|||
let current_url = current_url.read_untracked();
|
||||
|
||||
// we always need to match the new route
|
||||
let new_match = routes.match_route(¤t_url.path());
|
||||
let new_match = routes.match_route(current_url.path());
|
||||
let id = new_match.as_ref().map(|n| n.as_id());
|
||||
|
||||
// create default starting points for owner, url, path, and params
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
use crate::{
|
||||
components::RouterContext,
|
||||
location::{Location, Url},
|
||||
navigate::{NavigateOptions, UseNavigate},
|
||||
navigate::NavigateOptions,
|
||||
params::{Params, ParamsError, ParamsMap},
|
||||
RouteContext,
|
||||
};
|
||||
use leptos::{leptos_dom::helpers::window, oco::Oco};
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::use_context,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal},
|
||||
traits::{Get, Read, With},
|
||||
signal::{ArcRwSignal, ReadSignal},
|
||||
traits::{Get, With},
|
||||
};
|
||||
use std::{rc::Rc, str::FromStr};
|
||||
use tachys::renderer::Renderer;
|
||||
/*
|
||||
/// Constructs a signal synchronized with a specific URL query parameter.
|
||||
|
@ -239,6 +237,7 @@ pub(crate) fn use_is_back_navigation() -> ReadSignal<bool> {
|
|||
}
|
||||
*/
|
||||
|
||||
/* TODO check how this is used in 0.6 and use it
|
||||
/// Resolves a redirect location to an (absolute) URL.
|
||||
pub(crate) fn resolve_redirect_url(loc: &str) -> Option<web_sys::Url> {
|
||||
let origin = match window().location().origin() {
|
||||
|
@ -263,3 +262,4 @@ pub(crate) fn resolve_redirect_url(loc: &str) -> Option<web_sys::Url> {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
use crate::{
|
||||
components::RouterContext,
|
||||
hooks::{use_location, use_resolved_path},
|
||||
location::State,
|
||||
components::RouterContext, hooks::use_resolved_path, location::State,
|
||||
};
|
||||
use either_of::Either;
|
||||
use leptos::{
|
||||
children::{Children, TypedChildren},
|
||||
oco::Oco,
|
||||
prelude::*,
|
||||
*,
|
||||
};
|
||||
use reactive_graph::{computed::ArcMemo, effect::Effect, owner::use_context};
|
||||
use leptos::{children::Children, oco::Oco, prelude::*, *};
|
||||
use reactive_graph::{computed::ArcMemo, owner::use_context};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Describes a value that is either a static or a reactive URL, i.e.,
|
||||
|
@ -80,16 +72,6 @@ pub fn A<H>(
|
|||
/// if false, link is marked active if the current route starts with it.
|
||||
#[prop(optional)]
|
||||
exact: bool,
|
||||
/// Provides a class to be added when the link is active. If provided, it will
|
||||
/// be added at the same time that the `aria-current` attribute is set.
|
||||
///
|
||||
/// This supports multiple space-separated class names.
|
||||
///
|
||||
/// **Performance**: If it’s possible to style the link using the CSS with the
|
||||
/// `[aria-current=page]` selector, you should prefer that, as it enables significant
|
||||
/// SSR optimizations.
|
||||
#[prop(optional, into)]
|
||||
active_class: Option<Oco<'static, str>>,
|
||||
/// An object of any type that will be pushed to router state
|
||||
#[prop(optional)]
|
||||
state: Option<State>,
|
||||
|
@ -97,17 +79,6 @@ pub fn A<H>(
|
|||
/// will skip this page.)
|
||||
#[prop(optional)]
|
||||
replace: bool,
|
||||
// TODO arbitrary attributes
|
||||
/*/// Sets the `class` attribute on the underlying `<a>` tag, making it easier to style.
|
||||
#[prop(optional, into)]
|
||||
class: Option<AttributeValue>,
|
||||
/// Sets the `id` attribute on the underlying `<a>` tag, making it easier to target.
|
||||
#[prop(optional, into)]
|
||||
id: Option<Oco<'static, str>>,
|
||||
/// Arbitrary attributes to add to the `<a>`. Attributes can be added with the
|
||||
/// `attr:` syntax in the `view` macro.
|
||||
#[prop(attrs)]
|
||||
attributes: Vec<(&'static str, Attribute)>,*/
|
||||
/// The nodes or elements to be shown inside the link.
|
||||
children: Children,
|
||||
) -> impl IntoView
|
||||
|
@ -120,7 +91,6 @@ where
|
|||
exact: bool,
|
||||
#[allow(unused)] state: Option<State>,
|
||||
#[allow(unused)] replace: bool,
|
||||
#[allow(unused)] active_class: Option<Oco<'static, str>>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
let RouterContext { current_url, .. } =
|
||||
|
@ -143,7 +113,7 @@ where
|
|||
}
|
||||
});
|
||||
|
||||
let mut a = view! {
|
||||
view! {
|
||||
<a
|
||||
href=move || href.get().unwrap_or_default()
|
||||
target=target
|
||||
|
@ -155,31 +125,11 @@ where
|
|||
}
|
||||
>
|
||||
|
||||
// TODO attributes
|
||||
// class=class
|
||||
// id=id
|
||||
{children()}
|
||||
</a>
|
||||
};
|
||||
|
||||
/*if let Some(active_class) = active_class {
|
||||
let classes = active_class
|
||||
.split_ascii_whitespace()
|
||||
.map(|class| Cow::Owned(class.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Either::Left(a.class((classes, move || is_active.get())))
|
||||
} else {
|
||||
Either::Right(a)
|
||||
}*/
|
||||
a
|
||||
|
||||
// TODO attributes
|
||||
/*for (attr_name, attr_value) in attributes {
|
||||
a = a.attr(attr_name, attr_value);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
let href = use_resolved_path::<Dom>(move || href.to_href()());
|
||||
inner(href, target, exact, state, replace, active_class, children)
|
||||
inner(href, target, exact, state, replace, children)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use super::{
|
||||
handle_anchor_click, LocationChange, LocationProvider, State, Url, BASE,
|
||||
};
|
||||
use crate::{navigate::UseNavigate, params::ParamsMap};
|
||||
use super::{handle_anchor_click, LocationChange, LocationProvider, Url};
|
||||
use crate::params::ParamsMap;
|
||||
use core::fmt;
|
||||
use futures::channel::oneshot;
|
||||
use js_sys::{try_iter, Array, JsString, Reflect};
|
||||
use js_sys::{try_iter, Array, JsString};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
signal::ArcRwSignal,
|
||||
|
@ -13,14 +11,12 @@ use reactive_graph::{
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
boxed::Box,
|
||||
cell::RefCell,
|
||||
rc::Rc,
|
||||
string::String,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use tachys::dom::{document, window};
|
||||
use wasm_bindgen::{closure::Closure, JsCast, JsValue};
|
||||
use web_sys::{Event, HtmlAnchorElement, MouseEvent, UrlSearchParams};
|
||||
use web_sys::{Event, UrlSearchParams};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BrowserUrl {
|
||||
|
@ -183,7 +179,7 @@ impl LocationProvider for BrowserUrl {
|
|||
|
||||
fn ready_to_complete(&self) {
|
||||
if let Some(tx) = self.pending_navigation.lock().or_poisoned().take() {
|
||||
tx.send(());
|
||||
_ = tx.send(());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ use core::fmt::Debug;
|
|||
use js_sys::Reflect;
|
||||
use reactive_graph::{
|
||||
computed::Memo,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
signal::{ArcRwSignal, ReadSignal},
|
||||
traits::With,
|
||||
};
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::{borrow::Cow, future::Future, sync::Arc};
|
||||
use std::{borrow::Cow, future::Future};
|
||||
use tachys::dom::window;
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{Event, HtmlAnchorElement, MouseEvent};
|
||||
|
@ -140,7 +140,7 @@ pub trait LocationProvider: Clone + 'static {
|
|||
fn parse_with_base(url: &str, base: &str) -> Result<Url, Self::Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct State(Option<SendWrapper<JsValue>>);
|
||||
|
||||
impl State {
|
||||
|
@ -156,12 +156,6 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for State {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.as_ref().map(|n| n.as_ref())
|
||||
|
|
|
@ -6,13 +6,13 @@ pub use path_segment::*;
|
|||
mod horizontal;
|
||||
mod nested;
|
||||
mod vertical;
|
||||
use crate::{Method, SsrMode};
|
||||
use crate::SsrMode;
|
||||
pub use horizontal::*;
|
||||
pub use nested::*;
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
use tachys::{
|
||||
renderer::Renderer,
|
||||
view::{any_view::IntoAny, Render, RenderHtml},
|
||||
view::{Render, RenderHtml},
|
||||
};
|
||||
pub use vertical::*;
|
||||
|
||||
|
@ -142,7 +142,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct GeneratedRouteData {
|
||||
pub struct GeneratedRouteData {
|
||||
pub segments: Vec<PathSegment>,
|
||||
pub ssr_mode: SsrMode,
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ where
|
|||
params,
|
||||
matched,
|
||||
}| {
|
||||
let (id, inner, remaining) = match &self.children {
|
||||
let (_, inner, remaining) = match &self.children {
|
||||
None => (None, None, remaining),
|
||||
Some(children) => {
|
||||
let (inner, remaining) = children.match_nested(remaining);
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::{MatchInterface, MatchNestedRoutes, PathSegment, RouteMatchId};
|
|||
use crate::{ChooseView, GeneratedRouteData, MatchParams};
|
||||
use core::iter;
|
||||
use either_of::*;
|
||||
use std::{any::Any, borrow::Cow};
|
||||
use std::borrow::Cow;
|
||||
use tachys::renderer::Renderer;
|
||||
|
||||
impl MatchParams for () {
|
||||
|
|
|
@ -60,16 +60,17 @@ fn normalize(path: &str, omit_slash: bool) -> Cow<'_, str> {
|
|||
}
|
||||
}
|
||||
|
||||
fn begins_with_query_or_hash(text: &str) -> bool {
|
||||
matches!(text.chars().next(), Some('#') | Some('?'))
|
||||
}
|
||||
|
||||
/* TODO can remove?
|
||||
#[doc(hidden)]
|
||||
pub fn join_paths<'a>(from: &'a str, to: &'a str) -> String {
|
||||
let from = remove_wildcard(&normalize(from, false));
|
||||
from + normalize(to, false).as_ref()
|
||||
}
|
||||
|
||||
fn begins_with_query_or_hash(text: &str) -> bool {
|
||||
matches!(text.chars().next(), Some('#') | Some('?'))
|
||||
}
|
||||
|
||||
fn remove_wildcard(text: &str) -> String {
|
||||
text.rsplit_once('*')
|
||||
.map(|(prefix, _)| prefix)
|
||||
|
@ -77,6 +78,7 @@ fn remove_wildcard(text: &str) -> String {
|
|||
.trim_end_matches('/')
|
||||
.to_string()
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::location::State;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Options that can be used to configure a navigation. Used with [use_navigate](crate::use_navigate).
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -27,16 +26,3 @@ impl Default for NavigateOptions {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct UseNavigate(
|
||||
pub Arc<dyn Fn(&str, NavigateOptions) + Send + Sync>,
|
||||
);
|
||||
|
||||
impl UseNavigate {
|
||||
pub fn new(
|
||||
fun: impl Fn(&str, NavigateOptions) + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
Self(Arc::new(fun))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
use crate::{
|
||||
location::{Location, LocationProvider, RequestUrl, Url},
|
||||
location::{LocationProvider, Url},
|
||||
matching::Routes,
|
||||
params::ParamsMap,
|
||||
resolve_path::resolve_path,
|
||||
ChooseView, MatchInterface, MatchNestedRoutes, MatchParams, Method,
|
||||
PathSegment, RouteList, RouteListing, RouteMatchId,
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use either_of::{Either, EitherOf3};
|
||||
use futures::future::join_all;
|
||||
use leptos::{component, oco::Oco, IntoView};
|
||||
use leptos::{component, oco::Oco};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo, ScopedFuture},
|
||||
computed::ScopedFuture,
|
||||
owner::{provide_context, use_context, Owner},
|
||||
signal::{ArcRwSignal, ArcTrigger},
|
||||
traits::{Get, Read, ReadUntracked, Set, Track, Trigger},
|
||||
traits::{ReadUntracked, Set, Track, Trigger},
|
||||
wrappers::write::SignalSetter,
|
||||
};
|
||||
use std::{
|
||||
|
@ -37,8 +36,8 @@ use tachys::{
|
|||
ssr::StreamBuilder,
|
||||
view::{
|
||||
add_attr::AddAnyAttr,
|
||||
any_view::{AnyView, AnyViewState, IntoAny},
|
||||
either::{EitherOf3State, EitherState},
|
||||
any_view::{AnyView, IntoAny},
|
||||
either::EitherOf3State,
|
||||
Mountable, Position, PositionState, Render, RenderHtml,
|
||||
},
|
||||
};
|
||||
|
@ -54,6 +53,7 @@ pub(crate) struct NestedRoutesView<Loc, Defs, Fal, R> {
|
|||
pub current_url: ArcRwSignal<Url>,
|
||||
pub base: Option<Oco<'static, str>>,
|
||||
pub fallback: Fal,
|
||||
#[allow(unused)] // TODO
|
||||
pub set_is_routing: Option<SignalSetter<bool>>,
|
||||
pub rndr: PhantomData<R>,
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ where
|
|||
{
|
||||
path: String,
|
||||
current_url: ArcRwSignal<Url>,
|
||||
outer_owner: Owner,
|
||||
outlets: Vec<RouteContext<R>>,
|
||||
// TODO loading fallback
|
||||
#[allow(clippy::type_complexity)]
|
||||
view: Rc<RefCell<EitherOf3State<(), Fal, AnyView<R>, R>>>,
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ where
|
|||
current_url,
|
||||
fallback,
|
||||
base,
|
||||
set_is_routing,
|
||||
..
|
||||
} = self;
|
||||
|
||||
|
@ -97,8 +96,7 @@ where
|
|||
let url = current_url.read_untracked();
|
||||
|
||||
// match the route
|
||||
let new_match = routes.match_route(&url.path());
|
||||
let id = new_match.as_ref().map(|n| n.as_id());
|
||||
let new_match = routes.match_route(url.path());
|
||||
|
||||
// start with an empty view because we'll be loading routes async
|
||||
let view = EitherOf3::A(()).build();
|
||||
|
@ -107,7 +105,7 @@ where
|
|||
None => EitherOf3::B(fallback),
|
||||
Some(route) => {
|
||||
route.build_nested_route(
|
||||
&*url,
|
||||
&url,
|
||||
base,
|
||||
&mut loaders,
|
||||
&mut outlets,
|
||||
|
@ -138,7 +136,6 @@ where
|
|||
current_url,
|
||||
outlets,
|
||||
view,
|
||||
outer_owner,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +154,9 @@ where
|
|||
state.path.clear();
|
||||
state.path.push_str(url_snapshot.path());
|
||||
|
||||
let new_match = self.routes.match_route(&url_snapshot.path());
|
||||
state.current_url.set(url_snapshot.to_owned());
|
||||
|
||||
let new_match = self.routes.match_route(url_snapshot.path());
|
||||
|
||||
match new_match {
|
||||
None => {
|
||||
|
@ -168,7 +167,7 @@ where
|
|||
Some(route) => {
|
||||
let mut loaders = Vec::new();
|
||||
route.rebuild_nested_route(
|
||||
&*self.current_url.read_untracked(),
|
||||
&self.current_url.read_untracked(),
|
||||
self.base,
|
||||
&mut 0,
|
||||
&mut loaders,
|
||||
|
@ -214,7 +213,7 @@ where
|
|||
|
||||
fn add_any_attr<NewAttr: leptos::attr::Attribute<R>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
@ -245,7 +244,7 @@ where
|
|||
if RouteList::is_generating() {
|
||||
// add routes
|
||||
let (base, routes) = self.routes.generate_routes();
|
||||
let mut routes = routes
|
||||
let routes = routes
|
||||
.into_iter()
|
||||
.map(|data| {
|
||||
let path = base
|
||||
|
@ -303,7 +302,7 @@ where
|
|||
None => Either::Left(fallback),
|
||||
Some(route) => {
|
||||
route.build_nested_route(
|
||||
&*current_url,
|
||||
¤t_url,
|
||||
base,
|
||||
&mut Vec::new(),
|
||||
&mut outlets,
|
||||
|
@ -338,12 +337,12 @@ where
|
|||
let current_url = current_url.read_untracked();
|
||||
|
||||
let mut outlets = Vec::new();
|
||||
let new_match = routes.match_route(¤t_url.path());
|
||||
let new_match = routes.match_route(current_url.path());
|
||||
let view = match new_match {
|
||||
None => Either::Left(fallback),
|
||||
Some(route) => {
|
||||
route.build_nested_route(
|
||||
&*current_url,
|
||||
¤t_url,
|
||||
base,
|
||||
&mut Vec::new(),
|
||||
&mut outlets,
|
||||
|
@ -370,7 +369,6 @@ where
|
|||
current_url,
|
||||
fallback,
|
||||
base,
|
||||
set_is_routing,
|
||||
..
|
||||
} = self;
|
||||
|
||||
|
@ -379,8 +377,7 @@ where
|
|||
let url = current_url.read_untracked();
|
||||
|
||||
// match the route
|
||||
let new_match = routes.match_route(&url.path());
|
||||
let id = new_match.as_ref().map(|n| n.as_id());
|
||||
let new_match = routes.match_route(url.path());
|
||||
|
||||
// start with an empty view because we'll be loading routes async
|
||||
let view = Rc::new(RefCell::new(
|
||||
|
@ -388,7 +385,7 @@ where
|
|||
None => EitherOf3::B(fallback),
|
||||
Some(route) => {
|
||||
route.build_nested_route(
|
||||
&*url,
|
||||
&url,
|
||||
base,
|
||||
&mut loaders,
|
||||
&mut outlets,
|
||||
|
@ -409,7 +406,6 @@ where
|
|||
current_url,
|
||||
outlets,
|
||||
view,
|
||||
outer_owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +444,7 @@ where
|
|||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
url: self.url.clone(),
|
||||
id: self.id.clone(),
|
||||
id: self.id,
|
||||
trigger: self.trigger.clone(),
|
||||
params: self.params.clone(),
|
||||
owner: self.owner.clone(),
|
||||
|
@ -555,7 +551,8 @@ where
|
|||
provide_context(url);
|
||||
let view =
|
||||
owner.with(|| ScopedFuture::new(view.choose())).await;
|
||||
tx.send(Box::new(move || owner.with(|| view.into_any())));
|
||||
tx.send(Box::new(move || owner.with(|| view.into_any())))
|
||||
.unwrap();
|
||||
trigger
|
||||
}
|
||||
})
|
||||
|
@ -651,7 +648,8 @@ where
|
|||
.await;
|
||||
tx.send(Box::new(move || {
|
||||
owner.with(|| view.into_any())
|
||||
}));
|
||||
}))
|
||||
.unwrap();
|
||||
drop(old_owner);
|
||||
drop(old_params);
|
||||
drop(old_url);
|
||||
|
@ -728,15 +726,7 @@ where
|
|||
_ = rndr;
|
||||
let ctx = use_context::<RouteContext<R>>()
|
||||
.expect("<Outlet/> used without RouteContext being provided.");
|
||||
let RouteContext {
|
||||
id,
|
||||
trigger,
|
||||
params,
|
||||
owner,
|
||||
tx,
|
||||
rx,
|
||||
..
|
||||
} = ctx;
|
||||
let RouteContext { trigger, rx, .. } = ctx;
|
||||
let rx = rx.lock().or_poisoned().take().expect(
|
||||
"Tried to render <Outlet/> but could not find the view receiver. Are \
|
||||
you using the same <Outlet/> twice?",
|
||||
|
|
|
@ -138,6 +138,9 @@ where
|
|||
// TODO can we support Option<T> and T in a non-nightly way?
|
||||
#[cfg(feature = "nightly")]
|
||||
mod option_param {
|
||||
use super::{IntoParam, ParamsError};
|
||||
use std::{str::FromStr, sync::Arc};
|
||||
|
||||
auto trait NotOption {}
|
||||
impl<T> !NotOption for Option<T> {}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ pub enum StaticMode {
|
|||
pub struct StaticDataMap;
|
||||
|
||||
impl StaticDataMap {
|
||||
#[allow(clippy::new_without_default)] // TODO
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
error, fmt,
|
||||
fmt,
|
||||
fmt::{Display, Write},
|
||||
ops,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
use thiserror::Error;
|
||||
use throw_error::Error;
|
||||
|
|
|
@ -6,11 +6,10 @@ pub use gloo_net::http::Request;
|
|||
use js_sys::{Reflect, Uint8Array};
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use thiserror::Error;
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_streams::ReadableStream;
|
||||
use web_sys::{
|
||||
AbortController, AbortSignal, Event, FormData, Headers, RequestInit,
|
||||
AbortController, AbortSignal, FormData, Headers, RequestInit,
|
||||
UrlSearchParams,
|
||||
};
|
||||
|
||||
|
@ -215,11 +214,12 @@ impl<CustErr> ClientReq<CustErr> for BrowserRequest {
|
|||
body: impl Stream<Item = Bytes> + 'static,
|
||||
) -> Result<Self, ServerFnError<CustErr>> {
|
||||
// TODO abort signal
|
||||
let req = streaming_request(path, accepts, content_type, body)
|
||||
.map_err(|e| ServerFnError::Request(format!("{e:?}")))?;
|
||||
let (request, abort_ctrl) =
|
||||
streaming_request(path, accepts, content_type, body)
|
||||
.map_err(|e| ServerFnError::Request(format!("{e:?}")))?;
|
||||
Ok(Self(SendWrapper::new(RequestInner {
|
||||
request: req,
|
||||
abort_ctrl: None,
|
||||
request,
|
||||
abort_ctrl,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ fn streaming_request(
|
|||
accepts: &str,
|
||||
content_type: &str,
|
||||
body: impl Stream<Item = Bytes> + 'static,
|
||||
) -> Result<Request, JsValue> {
|
||||
) -> Result<(Request, Option<AbortOnDrop>), JsValue> {
|
||||
let (abort_ctrl, abort_signal) = abort_signal();
|
||||
let stream = ReadableStream::from_stream(body.map(|bytes| {
|
||||
let data = Uint8Array::from(bytes.as_ref());
|
||||
|
@ -241,7 +241,10 @@ fn streaming_request(
|
|||
headers.append("Content-Type", content_type)?;
|
||||
headers.append("Accept", accepts)?;
|
||||
let mut init = RequestInit::new();
|
||||
init.headers(&headers).method("POST").body(Some(&stream));
|
||||
init.headers(&headers)
|
||||
.method("POST")
|
||||
.signal(abort_signal.as_ref())
|
||||
.body(Some(&stream));
|
||||
|
||||
// Chrome requires setting `duplex: "half"` on streaming requests
|
||||
Reflect::set(
|
||||
|
@ -250,5 +253,5 @@ fn streaming_request(
|
|||
&JsValue::from_str("half"),
|
||||
)?;
|
||||
let req = web_sys::Request::new_with_str_and_init(path, &init)?;
|
||||
Ok(Request::from(req))
|
||||
Ok((Request::from(req), abort_ctrl))
|
||||
}
|
||||
|
|
|
@ -12,29 +12,7 @@ use any_spawner::Executor;
|
|||
use either_of::Either;
|
||||
use futures::FutureExt;
|
||||
use parking_lot::RwLock;
|
||||
use std::{cell::RefCell, fmt::Debug, future::Future, rc::Rc, sync::Arc};
|
||||
|
||||
pub struct SuspenseBoundary<const TRANSITION: bool, Fal, Chil> {
|
||||
in_fallback: bool,
|
||||
fallback: Option<Fal>,
|
||||
children: Chil,
|
||||
}
|
||||
|
||||
impl<const TRANSITION: bool, Fal, Chil>
|
||||
SuspenseBoundary<TRANSITION, Fal, Chil>
|
||||
{
|
||||
pub fn new(
|
||||
in_fallback: bool,
|
||||
fallback: Option<Fal>,
|
||||
children: Chil,
|
||||
) -> Self {
|
||||
Self {
|
||||
in_fallback,
|
||||
fallback,
|
||||
children,
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::{fmt::Debug, future::Future, sync::Arc};
|
||||
|
||||
pub trait FutureViewExt: Sized {
|
||||
fn suspend(self) -> Suspend<false, (), Self>
|
||||
|
|
|
@ -42,7 +42,7 @@ where
|
|||
Self {
|
||||
key: self.key.clone(),
|
||||
value: self.value.clone(),
|
||||
rndr: self.rndr.clone(),
|
||||
rndr: self.rndr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
renderer::DomRenderer,
|
||||
view::{Position, ToTemplate},
|
||||
};
|
||||
use std::{marker::PhantomData, rc::Rc, sync::Arc};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn class<C, R>(class: C) -> Class<C, R>
|
||||
|
|
|
@ -108,6 +108,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn on_target<E, T, R, F>(
|
||||
event: E,
|
||||
mut cb: F,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use self::attribute::Attribute;
|
||||
use crate::{
|
||||
no_attrs,
|
||||
renderer::Renderer,
|
||||
view::{add_attr::AddAnyAttr, Position, Render, RenderHtml},
|
||||
view::{Position, Render, RenderHtml},
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
|
|
@ -4,10 +4,7 @@ use crate::{
|
|||
no_attrs,
|
||||
prelude::{Mountable, Render, RenderHtml},
|
||||
renderer::{DomRenderer, Renderer},
|
||||
view::{
|
||||
add_attr::AddAnyAttr, strings::StrState, Position, PositionState,
|
||||
ToTemplate,
|
||||
},
|
||||
view::{strings::StrState, Position, PositionState, ToTemplate},
|
||||
};
|
||||
use oco_ref::Oco;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::{
|
|||
RenderHtml, ToTemplate,
|
||||
},
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::effect::RenderEffect;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
@ -454,8 +453,8 @@ mod stable {
|
|||
type Output<SomeNewAttr: Attribute<R>> = $sig<V>;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
mut self,
|
||||
attr: NewAttr,
|
||||
self,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
@ -598,8 +597,8 @@ mod stable {
|
|||
type Output<SomeNewAttr: Attribute<R>> = $sig<V>;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
mut self,
|
||||
attr: NewAttr,
|
||||
self,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
use super::{ReactiveFunction, SharedReactiveFunction};
|
||||
use crate::{html::style::IntoStyle, renderer::DomRenderer};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::effect::RenderEffect;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
impl<F, S, R> IntoStyle<R> for (&'static str, F)
|
||||
where
|
||||
|
|
|
@ -211,7 +211,7 @@ impl SNode {
|
|||
Self(Rc::new(SNodeInner(id)))
|
||||
}
|
||||
|
||||
fn to_node(&self) -> Node {
|
||||
pub fn to_node(&self) -> Node {
|
||||
CHANNEL.with_borrow(|channel| get_node(channel.js_channel(), self.0 .0))
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ fn with(fun: impl FnOnce(&mut Channel)) {
|
|||
flush();
|
||||
}
|
||||
|
||||
#[allow(unused)] // might be handy at some point!
|
||||
fn flush_sync() {
|
||||
FLUSH_PENDING.set(false);
|
||||
CHANNEL.with_borrow_mut(|channel| channel.flush());
|
||||
|
@ -327,9 +328,8 @@ impl Renderer for Sledgehammer {
|
|||
with(|channel| channel.remove(node.0 .0));
|
||||
}
|
||||
|
||||
fn get_parent(node: &Self::Node) -> Option<Self::Node> {
|
||||
todo!()
|
||||
//node.parent_node()
|
||||
fn get_parent(_node: &Self::Node) -> Option<Self::Node> {
|
||||
todo!() // node.parent_node()
|
||||
}
|
||||
|
||||
fn first_child(node: &Self::Node) -> Option<Self::Node> {
|
||||
|
@ -344,7 +344,7 @@ impl Renderer for Sledgehammer {
|
|||
Some(sibling)
|
||||
}
|
||||
|
||||
fn log_node(node: &Self::Node) {
|
||||
fn log_node(_node: &Self::Node) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -357,6 +357,7 @@ impl Renderer for Sledgehammer {
|
|||
pub struct ClassList(SNode);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)] // this will be used, it's just all unimplemented
|
||||
pub struct CssStyle(SNode);
|
||||
|
||||
impl DomRenderer for Sledgehammer {
|
||||
|
@ -365,16 +366,7 @@ impl DomRenderer for Sledgehammer {
|
|||
type CssStyleDeclaration = CssStyle;
|
||||
type TemplateElement = SNode;
|
||||
|
||||
fn set_property(el: &Self::Element, key: &str, value: &JsValue) {
|
||||
/* or_debug!(
|
||||
js_sys::Reflect::set(
|
||||
el,
|
||||
&wasm_bindgen::JsValue::from_str(key),
|
||||
value,
|
||||
),
|
||||
el,
|
||||
"setProperty"
|
||||
);*/
|
||||
fn set_property(_el: &Self::Element, _key: &str, _value: &JsValue) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -391,10 +383,10 @@ impl DomRenderer for Sledgehammer {
|
|||
});
|
||||
|
||||
// return the remover
|
||||
Box::new(move |el| todo!())
|
||||
Box::new(move |_el| todo!())
|
||||
}
|
||||
|
||||
fn event_target<T>(ev: &Self::Event) -> T
|
||||
fn event_target<T>(_ev: &Self::Event) -> T
|
||||
where
|
||||
T: CastFrom<Self::Element>,
|
||||
{
|
||||
|
@ -489,7 +481,7 @@ impl DomRenderer for Sledgehammer {
|
|||
});
|
||||
|
||||
// return the remover
|
||||
Box::new(move |el| todo!())
|
||||
Box::new(move |_el| todo!())
|
||||
}
|
||||
|
||||
fn class_list(el: &Self::Element) -> Self::ClassList {
|
||||
|
@ -506,15 +498,15 @@ impl DomRenderer for Sledgehammer {
|
|||
with(|channel| channel.remove_class(list.0 .0 .0, name));
|
||||
}
|
||||
|
||||
fn style(el: &Self::Element) -> Self::CssStyleDeclaration {
|
||||
fn style(_el: &Self::Element) -> Self::CssStyleDeclaration {
|
||||
todo!()
|
||||
//el.unchecked_ref::<HtmlElement>().style()
|
||||
}
|
||||
|
||||
fn set_css_property(
|
||||
style: &Self::CssStyleDeclaration,
|
||||
name: &str,
|
||||
value: &str,
|
||||
_style: &Self::CssStyleDeclaration,
|
||||
_name: &str,
|
||||
_value: &str,
|
||||
) {
|
||||
todo!()
|
||||
/*or_debug!(
|
||||
|
|
|
@ -25,14 +25,14 @@ where
|
|||
#[macro_export]
|
||||
macro_rules! no_attrs {
|
||||
($ty_name:ty) => {
|
||||
impl<'a, R> crate::view::add_attr::AddAnyAttr<R> for $ty_name
|
||||
impl<'a, R> $crate::view::add_attr::AddAnyAttr<R> for $ty_name
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Output<SomeNewAttr: crate::html::attribute::Attribute<R>> =
|
||||
type Output<SomeNewAttr: $crate::html::attribute::Attribute<R>> =
|
||||
$ty_name;
|
||||
|
||||
fn add_any_attr<NewAttr: crate::html::attribute::Attribute<R>>(
|
||||
fn add_any_attr<NewAttr: $crate::html::attribute::Attribute<R>>(
|
||||
self,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr> {
|
||||
|
|
|
@ -288,7 +288,7 @@ where
|
|||
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
@ -391,6 +391,17 @@ where
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
#[cfg(feature = "ssr")]
|
||||
{
|
||||
self.html_len
|
||||
}
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Mountable<R> for AnyViewState<R>
|
||||
|
|
|
@ -306,8 +306,8 @@ where
|
|||
Rndr: Renderer,
|
||||
{
|
||||
type Output<SomeNewAttr: Attribute<Rndr>> = EitherKeepAlive<
|
||||
<A as AddAnyAttr<Rndr>>::Output<SomeNewAttr>,
|
||||
<B as AddAnyAttr<Rndr>>::Output<SomeNewAttr>,
|
||||
<A as AddAnyAttr<Rndr>>::Output<SomeNewAttr::Cloneable>,
|
||||
<B as AddAnyAttr<Rndr>>::Output<SomeNewAttr::Cloneable>,
|
||||
>;
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute<Rndr>>(
|
||||
|
@ -317,7 +317,13 @@ where
|
|||
where
|
||||
Self::Output<NewAttr>: RenderHtml<Rndr>,
|
||||
{
|
||||
todo!()
|
||||
let EitherKeepAlive { a, b, show_b } = self;
|
||||
let attr = attr.into_cloneable();
|
||||
EitherKeepAlive {
|
||||
a: a.map(|a| a.add_any_attr(attr.clone())),
|
||||
b: b.map(|b| b.add_any_attr(attr.clone())),
|
||||
show_b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ where
|
|||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
{
|
||||
todo!()
|
||||
self.map(|inner| inner.add_any_attr(attr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,9 +144,8 @@ where
|
|||
const MIN_LENGTH: usize = T::MIN_LENGTH;
|
||||
|
||||
fn dry_resolve(&mut self) {
|
||||
match self.as_mut() {
|
||||
Ok(inner) => inner.dry_resolve(),
|
||||
_ => {}
|
||||
if let Ok(inner) = self.as_mut() {
|
||||
inner.dry_resolve()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use self::{add_attr::AddAnyAttr, fragment::Fragment};
|
||||
use self::add_attr::AddAnyAttr;
|
||||
use crate::{hydration::Cursor, renderer::Renderer, ssr::StreamBuilder};
|
||||
use parking_lot::RwLock;
|
||||
use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc};
|
||||
|
|
|
@ -168,8 +168,12 @@ where
|
|||
|
||||
fn dry_resolve(&mut self) {}
|
||||
|
||||
fn resolve(self) -> futures::future::Ready<Self::AsyncOutput> {
|
||||
futures::future::ready(self)
|
||||
// this won't actually compile because if a weird interaction because the const &'static str and
|
||||
// the RPITIT, so we just refine it to a concrete future type; this will never change in any
|
||||
// case
|
||||
#[allow(refining_impl_trait)]
|
||||
fn resolve(self) -> std::future::Ready<Self> {
|
||||
std::future::ready(self)
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
@ -209,7 +213,7 @@ where
|
|||
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
|
|
@ -61,7 +61,7 @@ where
|
|||
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
_attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml<R>,
|
||||
|
|
Loading…
Reference in a new issue