Skip to content

Commit

Permalink
Merge branch 'master' into ssr-hooks-sig
Browse files Browse the repository at this point in the history
  • Loading branch information
ranile authored Aug 18, 2023
2 parents 07804c9 + a27076d commit 9ab96a4
Show file tree
Hide file tree
Showing 21 changed files with 268 additions and 102 deletions.
9 changes: 2 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@
## How to Run

The examples are built with [trunk](https://github.com/thedodd/trunk).
You can install it with the following command:

```bash
cargo install --locked trunk
```

Running an example is as easy as running a single command:
Once you have the development envrionment fully set up (see [documentation](https://yew.rs/docs/next/getting-started/introduction)),
running an example is as easy as running a single command:

```bash
# move into the directory of the example you want to run
Expand Down
10 changes: 7 additions & 3 deletions examples/suspense/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ html, body {
.layout {
height: 100vh;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
display: grid;
justify-items: center;
align-items: center;
grid-template-columns: 1fr 1fr;
}

.content {
Expand Down Expand Up @@ -69,3 +69,7 @@ button {

color: rgb(100, 100, 100);
}

h2 {
text-align: center;
}
29 changes: 21 additions & 8 deletions examples/suspense/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use web_sys::HtmlTextAreaElement;
use yew::prelude::*;

mod struct_consumer;
mod use_sleep;

use use_sleep::use_sleep;
pub use use_sleep::use_sleep;

#[derive(Debug, PartialEq, Properties)]
struct PleaseWaitProps {
from: &'static str,
}

#[function_component(PleaseWait)]
fn please_wait() -> Html {
html! {<div class="content-area">{"Please wait 5 Seconds..."}</div>}
fn please_wait(props: &PleaseWaitProps) -> Html {
html! {<div class="content-area">{"Please wait 5 Seconds for "}{props.from}{" component to load..."}</div>}
}

#[function_component(AppContent)]
Expand All @@ -20,7 +26,7 @@ fn app_content() -> HtmlResult {
let value = value.clone();

Callback::from(move |e: InputEvent| {
let input: HtmlTextAreaElement = e.target_unchecked_into();
let input: HtmlTextAreaElement = e.target_unchecked_into::<HtmlTextAreaElement>();

value.set(input.value());
})
Expand All @@ -41,14 +47,21 @@ fn app_content() -> HtmlResult {

#[function_component(App)]
fn app() -> Html {
let fallback = html! {<PleaseWait />};
let fallback_fn = html! {<PleaseWait from="function" />};
let fallback_struct = html! {<PleaseWait from="struct" />};

html! {
<div class="layout">
<div class="content">
<h1>{"Yew Suspense Demo"}</h1>
<Suspense fallback={fallback}>
<AppContent />
<h2>{" Yew Suspense Demo -- function component consumer"}</h2>
<Suspense fallback={fallback_fn}>
<AppContent />
</Suspense>
</div>
<div class="content">
<h2>{"Yew Suspense Demo -- struct component consumer"}</h2>
<Suspense fallback={fallback_struct}>
<struct_consumer::AppContent />
</Suspense>
</div>
</div>
Expand Down
70 changes: 70 additions & 0 deletions examples/suspense/src/struct_consumer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use web_sys::HtmlTextAreaElement;
use yew::prelude::*;

use crate::use_sleep;

#[function_component]
pub fn WithSleep<Comp>() -> HtmlResult
where
Comp: BaseComponent<Properties = AppContentProps>,
{
let sleep = use_sleep()?;
let sleep = Callback::from(move |_| sleep());
Ok(yew::virtual_dom::VChild::<Comp>::new(AppContentProps { resleep: sleep }, None).into())
}

#[derive(Debug, PartialEq, Properties)]
pub struct AppContentProps {
pub resleep: Callback<()>,
}

pub type AppContent = WithSleep<BaseAppContent>;

pub enum Msg {
ValueUpdate(String),
TakeABreak,
}

pub struct BaseAppContent {
value: String,
}

impl Component for BaseAppContent {
type Message = Msg;
type Properties = AppContentProps;

fn create(_ctx: &Context<Self>) -> Self {
Self {
value: "I am writing a long story...".to_string(),
}
}

fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::ValueUpdate(v) => {
self.value = v;
}
Msg::TakeABreak => {
ctx.props().resleep.emit(());
}
};
true
}

fn view(&self, ctx: &Context<Self>) -> Html {
let oninput = ctx.link().callback(|e: InputEvent| {
let input: HtmlTextAreaElement = e.target_unchecked_into::<HtmlTextAreaElement>();
Msg::ValueUpdate(input.value())
});
let on_take_a_break = ctx.link().callback(|_| Msg::TakeABreak);
html! {
<div class="content-area">
<textarea value={self.value.clone()} {oninput}></textarea>
<div class="action-area">
<button onclick={on_take_a_break}>{"Take a break!"}</button>
<div class="hint">{"You can take a break at anytime"}<br />{"and your work will be preserved."}</div>
</div>
</div>
}
}
}
3 changes: 3 additions & 0 deletions packages/yew-macro/src/html_tree/html_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,9 @@ impl Parse for HtmlElementOpen {
if let Some(attr) = props.value.take() {
props.attributes.push(attr);
}
if let Some(attr) = props.checked.take() {
props.attributes.push(attr);
}
}
}
}
Expand Down
31 changes: 23 additions & 8 deletions packages/yew-router/src/components/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ use crate::{utils, Routable};

/// Props for [`Link`]
#[derive(Properties, Clone, PartialEq)]
pub struct LinkProps<R, Q = ()>
pub struct LinkProps<R, Q = (), S = ()>
where
R: Routable,
Q: Clone + PartialEq + Serialize,
S: Clone + PartialEq,
{
/// CSS classes to add to the anchor element (optional).
#[prop_or_default]
Expand All @@ -22,6 +23,9 @@ where
/// Route query data
#[prop_or_default]
pub query: Option<Q>,
/// Route state data
#[prop_or_default]
pub state: Option<S>,
#[prop_or_default]
pub disabled: bool,
/// [`NodeRef`](yew::html::NodeRef) for the `<a>` element.
Expand All @@ -33,18 +37,20 @@ where

/// A wrapper around `<a>` tag to be used with [`Router`](crate::Router)
#[function_component]
pub fn Link<R, Q = ()>(props: &LinkProps<R, Q>) -> Html
pub fn Link<R, Q = (), S = ()>(props: &LinkProps<R, Q, S>) -> Html
where
R: Routable + 'static,
Q: Clone + PartialEq + Serialize + 'static,
S: Clone + PartialEq + 'static,
{
let LinkProps {
classes,
to,
children,
disabled,
query,
state,
disabled,
anchor_ref,
children,
} = props.clone();

let navigator = use_navigator().expect_throw("failed to get navigator");
Expand All @@ -53,21 +59,30 @@ where
let navigator = navigator.clone();
let to = to.clone();
let query = query.clone();
let state = state.clone();

Callback::from(move |e: MouseEvent| {
if e.meta_key() || e.ctrl_key() || e.shift_key() || e.alt_key() {
return;
}
e.prevent_default();
match query {
None => {
match (&state, &query) {
(None, None) => {
navigator.push(&to);
}
Some(ref data) => {
(Some(state), None) => {
navigator.push_with_state(&to, state.clone());
}
(None, Some(query)) => {
navigator
.push_with_query(&to, data)
.push_with_query(&to, query)
.expect_throw("failed push history with query");
}
(Some(state), Some(query)) => {
navigator
.push_with_query_and_state(&to, query, state.clone())
.expect_throw("failed push history with query and state");
}
}
})
};
Expand Down
29 changes: 29 additions & 0 deletions packages/yew/src/dom_bundle/btag/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,7 @@ mod layout_tests {
#[cfg(test)]
mod tests_without_browser {
use crate::html;
use crate::virtual_dom::VNode;

#[test]
fn html_if_bool() {
Expand Down Expand Up @@ -1268,4 +1269,32 @@ mod tests_without_browser {
html! { <div><></></div> },
);
}

#[test]
fn input_checked_stays_there() {
let tag = html! {
<input checked={true} />
};
match tag {
VNode::VTag(tag) => {
assert_eq!(tag.checked(), Some(true));
}
_ => unreachable!(),
}
}
#[test]
fn non_input_checked_stays_there() {
let tag = html! {
<my-el checked="true" />
};
match tag {
VNode::VTag(tag) => {
assert_eq!(
tag.attributes.iter().find(|(k, _)| *k == "checked"),
Some(("checked", "true"))
);
}
_ => unreachable!(),
}
}
}
4 changes: 2 additions & 2 deletions packages/yew/src/suspense/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ where
T: Future<Output = O> + 'static,
O: 'static,
{
use_future_with_deps(move |_| init_f(), ())
use_future_with((), move |_| init_f())
}

/// Use the result of an async computation with dependencies, suspending while waiting.
Expand All @@ -84,7 +84,7 @@ where
///
/// [ready]: std::task::Poll::Ready
#[hook]
pub fn use_future_with_deps<F, D, T, O>(f: F, deps: D) -> SuspensionResult<UseFutureHandle<O>>
pub fn use_future_with<F, D, T, O>(deps: D, f: F) -> SuspensionResult<UseFutureHandle<O>>
where
F: FnOnce(Rc<D>) -> T,
T: Future<Output = O> + 'static,
Expand Down
13 changes: 5 additions & 8 deletions packages/yew/tests/suspense.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use web_sys::{HtmlElement, HtmlTextAreaElement};
use yew::platform::spawn_local;
use yew::platform::time::sleep;
use yew::prelude::*;
use yew::suspense::{use_future, use_future_with_deps, Suspension, SuspensionResult};
use yew::suspense::{use_future, use_future_with, Suspension, SuspensionResult};
use yew::UseStateHandle;

wasm_bindgen_test_configure!(run_in_browser);
Expand Down Expand Up @@ -645,13 +645,10 @@ async fn use_suspending_future_with_deps_works() {

#[function_component(Content)]
fn content(ContentProps { delay_millis }: &ContentProps) -> HtmlResult {
let delayed_result = use_future_with_deps(
|delay_millis| async move {
sleep(Duration::from_millis(*delay_millis)).await;
42
},
*delay_millis,
)?;
let delayed_result = use_future_with(*delay_millis, |delay_millis| async move {
sleep(Duration::from_millis(*delay_millis)).await;
42
})?;

Ok(html! {
<div>
Expand Down
23 changes: 18 additions & 5 deletions tools/changelog/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,38 @@ impl Cli {
let log_lines = create_log_lines(from_ref, to, package_labels, token)?;

// categorize logs
let (fixes, features): (Vec<_>, Vec<_>) = log_lines
let (breaking_changes, filtered_log_lines): (Vec<_>, Vec<_>) = log_lines
.into_iter()
.partition(|log_line| log_line.message.to_lowercase().contains("fix"));
.partition(|log_line| log_line.is_breaking_change);

let (fixes, features): (Vec<_>, Vec<_>) =
filtered_log_lines
.into_iter()
.partition(|filtered_log_line| {
filtered_log_line.message.to_lowercase().contains("fix")
});

// create displayable log lines
let fixes_logs = write_log_lines(fixes)?;
let features_logs = write_log_lines(features)?;
let breaking_changes_logs = write_log_lines(breaking_changes)?;

if !skip_file_write {
// create version changelog
let version_changelog =
write_changelog_file(&fixes_logs, &features_logs, package, next_version)?;
let version_changelog = write_changelog_file(
&fixes_logs,
&features_logs,
&breaking_changes_logs,
package,
next_version,
)?;

// write changelog
write_changelog(&changelog_path, &version_changelog)?;
}

// stdout changelog meant for tag description
stdout_tag_description_changelog(&fixes_logs, &features_logs)?;
stdout_tag_description_changelog(&fixes_logs, &features_logs, &breaking_changes_logs)?;

Ok(())
}
Expand Down
Loading

0 comments on commit 9ab96a4

Please sign in to comment.