Reorganize examples and general repo layout (#1092)

* Reorganize crates

* Remove symlink

* Check examples

* Cleanup CI scripts

* nits

* cleanup

* cargo fmt

* Fix yew-stdweb

* cargo clippy --all

* stdweb-examples

* run_emscripten_checks.sh

* Fix typo

* fix typo

* yew-stdweb

* Run tests from yew-stdweb

* fix webgl script
This commit is contained in:
Justin Starry 2020-04-20 22:22:24 +08:00 committed by GitHub
parent 6c16c8c134
commit fa8a1d9f00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
271 changed files with 1073 additions and 2015 deletions

View File

@ -1,2 +0,0 @@
report_todo = "Unnumbered"
report_fixme = "Unnumbered"

View File

@ -36,6 +36,6 @@ install:
- ./ci/install_cargo_web.sh
script:
- ./ci/run_checks.sh
- ./ci/run_stable_checks.sh
- GECKODRIVER=$(pwd)/geckodriver ./ci/run_tests.sh
- ./ci/check_examples.sh
- ./ci/run_emscripten_checks.sh

View File

@ -404,7 +404,7 @@ cloned is when a wrapper component re-renders nested children components.
- #### ⚡️ Features
- `Future` support :tada: A `Component` can update following the completion of a `Future`. Check out [this example](https://github.com/yewstack/yew/tree/master/examples/futures) to see how it works. This approach was borrowed from a fork of Yew called [`plaster`](https://github.com/carlosdp/plaster) created by [@carlosdp]. [[@hgzimmerman], [#717](https://github.com/yewstack/yew/pull/717)]
- `Future` support :tada: A `Component` can update following the completion of a `Future`. Check out [this example](https://github.com/yewstack/yew/tree/v0.14.0/examples/futures) to see how it works. This approach was borrowed from a fork of Yew called [`plaster`](https://github.com/carlosdp/plaster) created by [@carlosdp]. [[@hgzimmerman], [#717](https://github.com/yewstack/yew/pull/717)]
- Added the `agent` and `services` features so that this functionality can be disabled (useful if you are switching to using `Future`s). [[@hgzimmerman], [#684](https://github.com/yewstack/yew/pull/684)]
- Add `ref` keyword for allowing a `Component` to have a direct reference to its rendered elements. For example, you can now easily focus an `<input>` element after mounting. [[@jstarry], [#715](https://github.com/yewstack/yew/pull/715)]

View File

@ -8,31 +8,25 @@
rustup target add wasm32-unknown-unknown
```
#### Install [cargo-web]
#### Build
This is an optional tool that simplifies running the examples:
```bash
cargo build --target wasm32-unknown-unknown
```
#### Examples
TODO: Add more info
##### stdweb
In order to run the examples in `./yew-stdweb`, you may wish to install [cargo-web]:
```bash
cargo install cargo-web
```
> Add `--force` option to ensure you install the latest version.
[cargo-web]: https://github.com/koute/cargo-web
#### Build
Either
```bash
cargo build --target wasm32-unknown-unknown --features web_sys
```
or
```bash
cargo build --target wasm32-unknown-unknown --features std_web
```
See more about features [here](https://docs.rs/yew/0.14.0/yew/#important-notes)
#### Test
##### Web Tests
@ -48,9 +42,9 @@ although more driver support may be added! You can download these at:
* safaridriver - should be preinstalled on OSX
##### Macro Tests
When adding or updating tests, please make sure you have updated the appropriate `stderr` file, which you can find [here](https://github.com/yewstack/yew/tree/master/crates/macro/tests/macro) for the `html!` macro. These files ensure that macro compilation errors are correct and easy to understand.
When adding or updating tests, please make sure you have updated the appropriate `stderr` file, which you can find [here](https://github.com/yewstack/yew/tree/master/yew-macro/tests/macro) for the `html!` macro. These files ensure that macro compilation errors are correct and easy to understand.
To update or generate a new `stderr` file you can run `TRYBUILD=overwrite cargo test --test macro_test` or `TRYBUILD=overwrite cargo test --test derive_props_test` from the `crates/macro` directory.
To update or generate a new `stderr` file you can run `TRYBUILD=overwrite cargo test --test macro_test` or `TRYBUILD=overwrite cargo test --test derive_props_test` from the `yew-macro` directory.
##### Running Tests
@ -60,10 +54,5 @@ To update or generate a new `stderr` file you can run `TRYBUILD=overwrite cargo
or
```bash
cargo test --target wasm32-unknown-unknown --features wasm_test --features web_sys
```
or
```bash
cargo test --target wasm32-unknown-unknown --features wasm_test --features std_web
cargo test --target wasm32-unknown-unknown --features wasm_test
```

View File

@ -1,142 +1,32 @@
[package]
name = "yew"
version = "0.14.3"
edition = "2018"
authors = [
"Denis Kolodin <deniskolodin@gmail.com>",
"Justin Starry <justin@yew.rs>",
]
repository = "https://github.com/yewstack/yew"
homepage = "https://github.com/yewstack/yew"
documentation = "https://docs.rs/yew/"
license = "MIT/Apache-2.0"
readme = "README.md"
keywords = ["web", "asmjs", "webasm", "javascript"]
categories = ["gui", "web-programming"]
description = "A framework for making client-side single-page apps"
[badges]
travis-ci = { repository = "yewstack/yew" }
[dependencies]
anyhow = "1"
anymap = "0.12"
bincode = { version = "~1.2.1", optional = true }
cfg-if = "0.1"
cfg-match = "0.2"
console_error_panic_hook = { version = "0.1", optional = true }
futures = { version = "0.3", optional = true }
gloo = { version = "0.2.1", optional = true }
http = "0.2"
indexmap = "1.0.2"
js-sys = { version = "0.3", optional = true }
log = "0.4"
proc-macro-hack = "0.5"
proc-macro-nested = "0.1"
rmp-serde = { version = "0.14.0", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_cbor = { version = "0.11.1", optional = true }
serde_json = "1.0"
serde_yaml = { version = "0.8.3", optional = true }
slab = "0.4"
stdweb = { version = "0.4.20", optional = true }
thiserror = "1"
toml = { version = "0.5", optional = true }
wasm-bindgen = { version = "0.2.60", optional = true }
wasm-bindgen-futures = { version = "0.4", optional = true }
yew-macro = { version = "0.14.1", path = "crates/macro" }
[dependencies.web-sys]
version = "0.3"
optional = true
features = [
"AbortController",
"AbortSignal",
"BinaryType",
"Blob",
"BlobPropertyBag",
"console",
"DedicatedWorkerGlobalScope",
"Document",
"DomTokenList",
"DragEvent",
"Element",
"Event",
"EventTarget",
"File",
"FileList",
"FileReader",
"FocusEvent",
"Headers",
"HtmlElement",
"HtmlInputElement",
"HtmlSelectElement",
"HtmlTextAreaElement",
"KeyboardEvent",
"Location",
"MessageEvent",
"MouseEvent",
"Node",
"ObserverCallback",
"PointerEvent",
"ReferrerPolicy",
"Request",
"RequestCache",
"RequestCredentials",
"RequestInit",
"RequestMode",
"RequestRedirect",
"Response",
"Storage",
"Text",
"TouchEvent",
"UiEvent",
"Url",
"WebSocket",
"WheelEvent",
"Window",
"Worker",
"WorkerGlobalScope",
"WorkerOptions",
]
# Changes here must be reflected in `build.rs`
[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dependencies]
wasm-bindgen = "0.2.60"
# Changes here must be reflected in `build.rs`
[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dev-dependencies]
wasm-bindgen-test = "0.3.4"
base64 = "0.12.0"
ssri = "5.0.0"
[target.'cfg(target_os = "emscripten")'.dependencies]
ryu = "1.0.2" # 1.0.1 breaks emscripten
[dev-dependencies]
serde_derive = "1"
trybuild = "1.0"
rustversion = "1.0"
rmp-serde = "0.14.0"
bincode = "~1.2.1"
[features]
default = ["services", "agent"]
std_web = ["stdweb"]
web_sys = ["console_error_panic_hook", "futures", "gloo", "js-sys", "web-sys", "wasm-bindgen", "wasm-bindgen-futures"]
doc_test = []
wasm_test = []
services = []
agent = ["bincode"]
yaml = ["serde_yaml"]
msgpack = ["rmp-serde"]
cbor = ["serde_cbor"]
[package.metadata.docs.rs]
features = ["web_sys", "agent", "services", "yaml", "cbor", "toml", "msgpack", "doc_test"]
[workspace]
members = [
"crates/macro",
"crates/functional",
"yew",
"yew-functional",
"yew-macro",
# Examples
"examples/counter",
"examples/crm",
"examples/custom_components",
"examples/dashboard",
"examples/file_upload",
"examples/fragments",
"examples/futures",
"examples/game_of_life",
"examples/inner_html",
"examples/js_callback",
"examples/large_table",
"examples/minimal",
"examples/mount_point",
"examples/multi_thread",
"examples/nested_list",
"examples/node_refs",
"examples/npm_and_rest",
"examples/pub_sub",
"examples/server",
"examples/textarea",
"examples/timer",
"examples/todomvc",
"examples/two_apps",
"examples/webgl",
]

View File

@ -1,38 +0,0 @@
#!/usr/bin/env bash
echo "$(rustup default)" | grep -q "1.39.0"
emscripten_supported=$?
set -euxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
# Some examples are known not to work with some builds, i.e. futures with the
# std_web feature. Other items in the examples/ directory are helpers, i.e.
# pub_sub and server. These block lists allow us to exempt some examples but
# default opt-in any new examples to CI testing.
COMMON_SKIP_EXAMPLES="examples/static examples/pub_sub examples/server \
examples/target examples/web_sys examples/std_web"
STD_WEB_SKIP_EXAMPLES="${COMMON_SKIP_EXAMPLES:?} examples/futures"
WEB_SYS_SKIP_EXAMPLES="${COMMON_SKIP_EXAMPLES:?}"
# Make sure all examples are buildable with stdweb and web-sys.
for ex in $(find examples -maxdepth 1 -mindepth 1 -type d); do
pushd $ex
# TODO Can't build some demos with release, need fix
if [ "$emscripten_supported" == "0" ]; then
if [[ ! " ${STD_WEB_SKIP_EXAMPLES[@]} " =~ " ${ex} " ]]; then
# TODO - Emscripten builds are broken on rustc > 1.39.0
cargo web build --target asmjs-unknown-emscripten --features std_web
cargo web build --target wasm32-unknown-emscripten --features std_web
fi
fi
if [[ ! " ${STD_WEB_SKIP_EXAMPLES[@]} " =~ " ${ex} " ]]; then
cargo web build --target wasm32-unknown-unknown --features std_web
fi
if [[ ! " ${WEB_SYS_SKIP_EXAMPLES[@]} " =~ " ${ex} " ]]; then
cargo build --target wasm32-unknown-unknown --features web_sys
fi
# Reset cwd
popd
done

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
echo "$(rustup default)" | grep -q "stable"
if [ "$?" != "0" ]; then
# only run checks on stable
exit 0
fi
set -euxo pipefail
cargo fmt --all -- --check
cargo clippy --features std_web -- --deny=warnings
cargo clippy --features web_sys -- --deny=warnings

12
ci/run_emscripten_checks.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
echo "$(rustup default)" | grep -q "1.39.0"
emscripten_supported=$?
set -euxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
pushd yew-stdweb
if [ "$emscripten_supported" == "0" ]; then
# TODO - Emscripten builds are broken on rustc > 1.39.0
cargo check --all --target asmjs-unknown-emscripten
cargo check --all --target wasm32-unknown-emscripten
fi
popd

28
ci/run_stable_checks.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
echo "$(rustup default)" | grep -q "stable"
if [ "$?" != "0" ]; then
# only run checks on stable
exit 0
fi
set -euxo pipefail
cargo fmt --all -- --check
cargo clippy --all -- --deny=warnings
cargo check --all
# Enable all optional features
(cd yew \
&& cargo check --features cbor,msgpack,toml,yaml \
&& cargo clippy --features cbor,msgpack,toml,yaml -- --deny=warnings)
# Check stdweb
pushd yew-stdweb
cargo fmt --all -- --check
cargo clippy --all -- --deny=warnings
cargo check --all --target wasm32-unknown-unknown
# webgl_stdweb doesn't play nice with wasm-bindgen
(cd examples/webgl && cargo web check --target wasm32-unknown-unknown)
popd

View File

@ -3,22 +3,25 @@ echo "$(rustup default)" | grep -q "1.39.0"
emscripten_supported=$?
set -euxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
cargo test --target wasm32-unknown-unknown --features wasm_test,std_web
cargo test --target wasm32-unknown-unknown --features wasm_test,web_sys
(cd yew \
&& cargo test --target wasm32-unknown-unknown --features wasm_test \
&& cargo test --doc --features doc_test,wasm_test,yaml,msgpack,cbor,toml \
&& cargo test --doc --features doc_test,wasm_test,yaml,msgpack,cbor,toml \
--features std_web,agent,services --no-default-features)
if [ "$emscripten_supported" == "0" ]; then
# TODO - Emscripten builds are broken on rustc > 1.39.0
cargo web test --target asmjs-unknown-emscripten --features std_web
cargo web test --target wasm32-unknown-emscripten --features std_web
fi
(cd yew-functional \
&& cargo test --target wasm32-unknown-unknown)
cargo test --doc --features doc_test,wasm_test,yaml,msgpack,cbor,std_web
cargo test --doc --features doc_test,wasm_test,yaml,msgpack,cbor,web_sys
(cd crates/macro \
(cd yew-macro \
&& cargo test --test macro_test \
&& cargo test --test derive_props_test \
&& cargo test --doc)
(cd crates/functional \
&& cargo test --features wasm_test --target wasm32-unknown-unknown)
(cd yew-stdweb && cargo test --target wasm32-unknown-unknown --features wasm_test)
# TODO - Emscripten builds are broken on rustc > 1.39.0
if [ "$emscripten_supported" == "0" ]; then
(cd yew-stdweb \
&& cargo web test --target asmjs-unknown-emscripten \
&& cargo web test --target wasm32-unknown-emscripten)
fi

View File

@ -1,375 +0,0 @@
#[cfg(test)]
extern crate wasm_bindgen_test;
#[cfg(test)]
#[cfg(feature = "wasm_test")]
mod test {
use std::ops::Deref;
use std::ops::DerefMut;
use std::rc::Rc;
use wasm_bindgen_test::*;
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
extern crate yew;
use self::yew::NodeRef;
use yew::{html, App, Html, Properties};
use yew_functional::{
use_effect, use_effect_with_deps, use_reducer_with_init, use_ref, use_state,
FunctionComponent, FunctionProvider,
};
#[wasm_bindgen_test]
fn use_state_works() {
struct UseStateFunction {}
impl FunctionProvider for UseStateFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
let (counter, set_counter) = use_state(|| 0);
if *counter < 5 {
set_counter(*counter + 1)
}
return html! {
<div>
{"Test Output: "}
<div id="result">{*counter}</div>
{"\n"}
</div>
};
}
}
type UseComponent = FunctionComponent<UseStateFunction>;
let app: App<UseComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result = obtain_result();
assert_eq!(result.as_str(), "5");
}
#[wasm_bindgen_test]
fn props_are_passed() {
struct PropsPassedFunction {}
#[derive(Properties, Clone, PartialEq)]
struct PropsPassedFunctionProps {
value: String,
}
impl FunctionProvider for PropsPassedFunction {
type TProps = PropsPassedFunctionProps;
fn run(props: &Self::TProps) -> Html {
assert_eq!(&props.value, "props");
return html! {
<div id="result">
{"done"}
</div>
};
}
}
type PropsComponent = FunctionComponent<PropsPassedFunction>;
let app: App<PropsComponent> = yew::App::new();
app.mount_with_props(
yew::utils::document().get_element_by_id("output").unwrap(),
PropsPassedFunctionProps {
value: "props".to_string(),
},
);
let result = obtain_result();
assert_eq!(result.as_str(), "done");
}
#[wasm_bindgen_test]
fn use_ref_works() {
struct UseRefFunction {}
impl FunctionProvider for UseRefFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
let ref_example = use_ref(|| 0);
*ref_example.borrow_mut().deref_mut() += 1;
let (counter, set_counter) = use_state(|| 0);
if *counter < 5 {
set_counter(*counter + 1)
}
return html! {
<div>
{"The test output is: "}
<div id="result">{*ref_example.borrow_mut().deref_mut() > 4}</div>
{"\n"}
</div>
};
}
}
type UseRefComponent = FunctionComponent<UseRefFunction>;
let app: App<UseRefComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result = obtain_result();
assert_eq!(result.as_str(), "true");
}
#[wasm_bindgen_test]
fn use_reducer_works() {
struct UseReducerFunction {}
impl FunctionProvider for UseReducerFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
struct CounterState {
counter: i32,
}
let (counter, dispatch) = use_reducer_with_init(
|prev: std::rc::Rc<CounterState>, action: i32| CounterState {
counter: prev.counter + action,
},
0,
|initial: i32| CounterState {
counter: initial + 10,
},
);
use_effect_with_deps(
move |_| {
dispatch(1);
|| {}
},
(),
);
return html! {
<div>
{"The test result is"}
<div id="result">{counter.counter}</div>
{"\n"}
</div>
};
}
}
type UseReducerComponent = FunctionComponent<UseReducerFunction>;
let app: App<UseReducerComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result = obtain_result();
assert_eq!(result.as_str(), "11");
}
#[wasm_bindgen_test]
fn use_effect_destroys_on_component_drop() {
struct UseEffectFunction {}
struct UseEffectWrapper {}
#[derive(Properties, Clone)]
struct DestroyCalledProps {
destroy_called: Rc<dyn Fn()>,
}
impl PartialEq for DestroyCalledProps {
fn eq(&self, _other: &Self) -> bool {
false
}
}
type UseEffectComponent = FunctionComponent<UseEffectFunction>;
type UseEffectWrapperComponent = FunctionComponent<UseEffectWrapper>;
impl FunctionProvider for UseEffectFunction {
type TProps = DestroyCalledProps;
fn run(props: &Self::TProps) -> Html {
let destroy_called = props.destroy_called.clone();
use_effect_with_deps(
move |_| {
move || {
destroy_called();
}
},
(),
);
return html! {};
}
}
impl FunctionProvider for UseEffectWrapper {
type TProps = DestroyCalledProps;
fn run(props: &Self::TProps) -> Html {
let (should_rerender, set_rerender) = use_state(|| true);
if *should_rerender {
set_rerender(false);
return html! {
<UseEffectComponent destroy_called=props.destroy_called.clone() />
};
} else {
return html! {
<div>{"EMPTY"}</div>
};
}
}
}
let app: App<UseEffectWrapperComponent> = yew::App::new();
let destroy_counter = Rc::new(std::cell::RefCell::new(0));
let destroy_country_c = destroy_counter.clone();
app.mount_with_props(
yew::utils::document().get_element_by_id("output").unwrap(),
DestroyCalledProps {
destroy_called: Rc::new(move || *destroy_country_c.borrow_mut().deref_mut() += 1),
},
);
assert_eq!(1, *destroy_counter.borrow().deref());
}
#[wasm_bindgen_test]
fn use_effect_works_many_times() {
struct UseEffectFunction {}
impl FunctionProvider for UseEffectFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
let (counter, set_counter) = use_state(|| 0);
if *counter < 4 {
set_counter(*counter + 1);
}
let node_ref = NodeRef::default();
let node_ref_c = node_ref.clone();
use_effect(move || {
let text_content = node_ref
.get()
.expect("Should have filled node_ref at this point")
.text_content()
.expect("Text node should have content");
let mut previous = -1;
if *counter == 0 {
assert_eq!("placeholder that should not appear", &text_content);
} else {
previous = text_content
.parse()
.expect("Expected content to be number set last time");
}
assert_eq!(previous, *counter - 1);
node_ref
.get()
.unwrap()
.set_text_content(Some(&format!("{}", counter)));
|| {}
});
return html! {
<div>
{"The test result is"}
<div id="result" ref=node_ref_c>{"placeholder that should not appear"}</div>
{"\n"}
</div>
};
}
}
type UseEffectComponent = FunctionComponent<UseEffectFunction>;
let app: App<UseEffectComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result = obtain_result();
assert_eq!(result.as_str(), "4");
}
#[wasm_bindgen_test]
fn use_effect_works_once() {
struct UseEffectFunction {}
impl FunctionProvider for UseEffectFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
let number_ref = use_ref(|| 0);
let number_ref_c = number_ref.clone();
let initially_true_ref = use_ref(|| false);
let initially_true_ref_c = initially_true_ref.clone();
let node_ref = NodeRef::default();
let node_ref_c = node_ref.clone();
use_effect_with_deps(
move |_| {
if *initially_true_ref.borrow() {
panic!("use_effect should have been called post render!")
}
if *number_ref_c.borrow_mut().deref_mut() == 1 {
panic!("This effect should have been called once only")
}
*number_ref_c.borrow_mut().deref_mut() += 1;
node_ref
.get()
.expect("This NodeRef should point at the result!");
|| panic!("Destructor should not have been called")
},
(),
);
*initially_true_ref_c.borrow_mut() = false;
let (do_rerender, set_rerender) = use_state(|| true);
if *do_rerender {
set_rerender(false);
}
return html! {
<div>
{"The test result is"}
<div id="result" ref=node_ref_c>{*number_ref.borrow_mut().deref_mut()}</div>
{"\n"}
</div>
};
}
}
type UseEffectComponent = FunctionComponent<UseEffectFunction>;
let app: App<UseEffectComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result = obtain_result();
assert_eq!(result.as_str(), "1");
}
#[wasm_bindgen_test]
fn use_effect_refires_on_dependency_change() {
struct UseEffectFunction {}
impl FunctionProvider for UseEffectFunction {
type TProps = ();
fn run(_: &Self::TProps) -> Html {
let number_ref = use_ref(|| 0);
let number_ref_c = number_ref.clone();
let number_ref2 = use_ref(|| 0);
let number_ref2_c = number_ref2.clone();
let arg = *number_ref.borrow_mut().deref_mut();
let (_, set_counter) = use_state(|| 0);
use_effect_with_deps(
move |dep| {
let mut ref_mut = number_ref_c.borrow_mut();
let inner_ref_mut = ref_mut.deref_mut();
if *inner_ref_mut < 1 {
*inner_ref_mut += 1;
assert_eq!(dep, &0);
} else {
assert_eq!(dep, &1);
}
set_counter(10); // we just need to make sure it does not panic
move || {
set_counter(11);
*number_ref2_c.borrow_mut().deref_mut() += 1;
}
},
arg,
);
return html! {
<div>
{"The test result is"}
<div id="result">{*number_ref.borrow_mut().deref_mut()}{*number_ref2.borrow_mut().deref_mut()}</div>
{"\n"}
</div>
};
}
}
type UseEffectComponent = FunctionComponent<UseEffectFunction>;
let app: App<UseEffectComponent> = yew::App::new();
app.mount(yew::utils::document().get_element_by_id("output").unwrap());
let result: String = obtain_result();
assert_eq!(result.as_str(), "11");
}
fn obtain_result() -> String {
return yew::utils::document()
.get_element_by_id("result")
.expect("No result found. Most likely, the application crashed and burned")
.inner_html();
}
}

View File

@ -1,39 +0,0 @@
[workspace]
members = [
"crm",
"custom_components",
"dashboard",
"fragments",
"futures",
"game_of_life",
"large_table",
"minimal",
"nested_list",
"pub_sub",
"server",
"showcase",
"textarea",
"timer",
"std_web/counter",
"std_web/file_upload",
"std_web/inner_html",
"std_web/js_callback",
"std_web/mount_point",
"std_web/multi_thread",
"std_web/node_refs",
"std_web/npm_and_rest",
"std_web/todomvc",
"std_web/two_apps",
"std_web/webgl",
"web_sys/counter",
"web_sys/file_upload",
"web_sys/inner_html",
"web_sys/js_callback",
"web_sys/mount_point",
"web_sys/multi_thread",
"web_sys/node_refs",
"web_sys/npm_and_rest",
"web_sys/todomvc",
"web_sys/two_apps",
"web_sys/webgl",
]

View File

@ -1,140 +0,0 @@
#!/usr/bin/env bash
PID=-1
function ctrl_c() {
echo "** Killing the demo..."
kill $PID
}
function build_std_web() {
for example in */ ; do
if [[ $example == server* ]]; then
continue
fi
if [[ $example == static* ]]; then
continue
fi
if [[ $example == web_sys* ]]; then
continue
fi
if [[ $example == std_web* ]]; then
build_std_web()
else
echo "Building: $example"
cd $example
cargo update
cargo web build --target wasm32-unknown-unknown
cd ..
fi
done
}
function build_web_sys() {
for example in */ ; do
if [[ $example == server* ]]; then
continue
fi
if [[ $example == static* ]]; then
continue
fi
if [[ $example == std_web* ]]; then
continue
fi
if [[ $example == web_sys* ]]; then
build_web_sys()
else
echo "Building: $example"
cd $example
cargo update
cargo build --target wasm32-unknown-unknown
wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm
cd ..
fi
done
}
function run_std_web() {
trap ctrl_c INT
for example in */ ; do
if [[ $example == server* ]]; then
continue
fi
if [[ $example == static* ]]; then
continue
fi
if [[ $example == web_sys* ]]; then
continue
fi
if [[ $example == std_web* ]]; then
run_std_web()
else
echo "Running: $example"
cd $example
cargo web start --target wasm32-unknown-unknown &
PID=$!
wait $PID
cd ..
fi
done
}
function run_web_sys() {
trap ctrl_c INT
for example in */ ; do
if [[ $example == server* ]]; then
continue
fi
if [[ $example == static* ]]; then
continue
fi
if [[ $example == std_web* ]]; then
continue
fi
if [[ $example == web_sys* ]]; then
run_web_sys()
else
echo "Running: $example"
cd $example
cargo build --target wasm32-unknown-unknown
wasm-bindgen --target web --no-typescript --out-dir ../static/ --out-name wasm ../target/wasm32-unknown-unknown/debug/$example.wasm
http -r ../static/
PID=$!
wait $PID
cd ..
fi
done
}
function clean() {
trap ctrl_c INT
for example in */ ; do
echo "Cleaning: $example"
cd $example
cargo clean
PID=$!
wait $PID
cd ..
done
}
case "$1" in
--help)
echo "Available commands: build, run, clean"
;;
build_std_web)
build_std_web
;;
build_web_sys)
build_web_sys
;;
run_std_web)
run_std_web
;;
run_web_sys)
run_web_sys
;;
clean)
clean
;;
esac

View File

@ -1,5 +1,5 @@
[package]
name = "counter_web_sys"
name = "counter"
version = "0.1.1"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
@ -9,4 +9,4 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
js-sys = "0.3"
yew = { path = "../../..", features = ["services", "web_sys"] }
yew = { path = "../../yew" }

View File

@ -31,11 +31,11 @@ impl Component for Model {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Increment => {
self.value = self.value + 1;
self.value += 1;
self.console.log("plus one");
}
Msg::Decrement => {
self.value = self.value - 1;
self.value -= 1;
self.console.log("minus one");
}
Msg::Bulk(list) => {

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<counter::Model>();
}

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
serde = "1"
serde_derive = "1"
yew = { path = "../.." }
yew = { path = "../../yew" }
pulldown-cmark = "0.1.2"
[features]

View File

@ -10,7 +10,7 @@ use yew::services::storage::Area;
use yew::services::{DialogService, StorageService};
use yew::{html, Component, ComponentLink, Html, InputData, Renderable, ShouldRender};
const KEY: &'static str = "yew.crm.database";
const KEY: &str = "yew.crm.database";
#[derive(Serialize, Deserialize)]
struct Database {

View File

@ -34,9 +34,9 @@ pub fn render_markdown(src: &str) -> Html {
top = pre;
} else if let Tag::Table(aligns) = tag {
for r in top.children.iter_mut() {
if let &mut VNode::VTag(ref mut vtag) = r {
if let VNode::VTag(ref mut vtag) = r {
for (i, c) in vtag.children.iter_mut().enumerate() {
if let &mut VNode::VTag(ref mut vtag) = c {
if let VNode::VTag(ref mut vtag) = c {
match aligns[i] {
Alignment::None => {}
Alignment::Left => vtag.add_class("text-left"),
@ -49,7 +49,7 @@ pub fn render_markdown(src: &str) -> Html {
}
} else if let Tag::TableHead = tag {
for c in top.children.iter_mut() {
if let &mut VNode::VTag(ref mut vtag) = c {
if let VNode::VTag(ref mut vtag) = c {
// TODO
// vtag.tag = "th".into();
vtag.add_attribute("scope", &"col");

View File

@ -5,7 +5,7 @@ authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -43,7 +43,7 @@ impl Component for Counter {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Increase => {
self.value = self.value + 1;
self.value += 1;
self.onclick.emit(self.value);
}
}

View File

@ -8,7 +8,7 @@ edition = "2018"
anyhow = "1"
serde = "1"
serde_derive = "1"
yew = { path = "../..", features = ["toml"] }
yew = { path = "../../yew", features = ["toml"] }
[features]
std_web = ["yew/std_web"]

View File

@ -1,5 +1,5 @@
[package]
name = "file_upload_web_sys"
name = "file_upload"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
@ -9,4 +9,4 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
js-sys = "0.3"
yew = { path = "../../..", features = ["web_sys"] }
yew = { path = "../../yew" }

View File

@ -15,7 +15,7 @@ type Chunks = bool;
pub enum Msg {
Loaded(FileData),
Chunk(FileChunk),
Chunk(Option<FileChunk>),
Files(Vec<File>, Chunks),
ToggleByChunks,
}
@ -40,7 +40,7 @@ impl Component for Model {
let info = format!("file: {:?}", file);
self.files.push(info);
}
Msg::Chunk(chunk) => {
Msg::Chunk(Some(chunk)) => {
let info = format!("chunk: {:?}", chunk);
self.files.push(info);
}
@ -61,6 +61,7 @@ impl Component for Model {
Msg::ToggleByChunks => {
self.by_chunks = !self.by_chunks;
}
_ => return false,
}
true
}

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<file_upload::Model>();
}

View File

@ -5,7 +5,7 @@ authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -23,11 +23,11 @@ impl Component for Model {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::More => {
self.counter = self.counter + 1;
self.counter += 1;
}
Msg::Less => {
if self.counter > 0 {
self.counter = self.counter - 1;
self.counter -= 1;
}
}
}

View File

@ -11,7 +11,8 @@ repository = "https://github.com/yewstack/yew"
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
wasm-bindgen = "0.2.60"
wasm-bindgen-futures = "0.4.3"
[dependencies.web-sys]
@ -24,10 +25,3 @@ features = [
'Response',
'Window',
]
[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies]
wasm-bindgen = "0.2.60"
[features]
std_web = ["yew/std_web"]
web_sys = ["yew/web_sys"]

View File

@ -1,13 +1,11 @@
# Futures Example
This example shows off how to make a asynchronous fetch request using web_sys and Yew's futures support.
Because this example uses features not allowed by cargo web, it cannot be included in the showcase, and must be built with a different toolchain instead.
### How to run:
This example requires rustc v1.39.0 or above to compile due to its use of async/.await syntax.
```sh
wasm-pack build --target web --out-dir ../static/ --out-name wasm -- --features (web_sys|std_web) && python -m SimpleHTTPServer 8080
wasm-pack build --target web --out-dir ../static/ --out-name wasm && python -m SimpleHTTPServer 8080
```
This will compile the project, bundle up the compiler output and static assets, and start a http server on port 8080 so you can access the example at localhost:8080.

View File

@ -3,29 +3,23 @@ use std::fmt::{Error, Formatter};
use std::future::Future;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::spawn_local;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response, Window};
use yew::{html, Component, ComponentLink, Html, ShouldRender};
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(cargo_web)))]
/// This method processes a Future that returns a message and sends it back to the component's
/// loop.
///
/// # Panics
/// If the future panics, then the promise will not resolve, and will leak.
pub fn send_future<COMP: Component, F>(link: &ComponentLink<COMP>, future: F)
pub fn send_future<COMP: Component, F>(link: ComponentLink<COMP>, future: F)
where
F: Future<Output = COMP::Message> + 'static,
{
use wasm_bindgen_futures::future_to_promise;
let mut link = link.clone();
let js_future = async move {
spawn_local(async move {
link.send_message(future.await);
Ok(JsValue::NULL)
};
future_to_promise(js_future);
});
}
/// Something wrong has occurred while fetching an external resource.
@ -118,7 +112,7 @@ impl Component for Model {
Err(err) => Msg::SetMarkdownFetchState(FetchState::Failed(err)),
}
};
send_future(&self.link, future);
send_future(self.link.clone(), future);
self.link
.send_message(SetMarkdownFetchState(FetchState::Fetching));
false

View File

@ -10,7 +10,7 @@ edition = "2018"
rand = "0.6.5"
log = "0.4"
web_logger = "0.2"
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["rand/stdweb", "yew/std_web"]

View File

@ -36,7 +36,7 @@ impl Cellule {
self.life_state = LifeState::Dead;
}
pub fn alive(&self) -> bool {
pub fn alive(self) -> bool {
self.life_state == LifeState::Alive
}
@ -97,10 +97,8 @@ impl Model {
if Cellule::alone(&neighbors) || Cellule::overpopulated(&neighbors) {
to_dead.push(current_idx);
}
} else {
if Cellule::can_be_revived(&neighbors) {
to_live.push(current_idx);
}
} else if Cellule::can_be_revived(&neighbors) {
to_live.push(current_idx);
}
}
}

View File

@ -10,4 +10,3 @@
<script src="game_of_life.js"></script>
</body>
</html>

View File

@ -0,0 +1,21 @@
[package]
name = "inner_html"
version = "0.1.0"
authors = ["Garrett Berg <vitiral@gmail.com>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = { path = "../../yew" }
[dependencies.web-sys]
version = "0.3"
features = [
"console",
"Document",
"Element",
"Node",
"Window",
]

View File

@ -1,5 +1,5 @@
[package]
name = "js_callback_web_sys"
name = "js_callback"
version = "0.1.0"
authors = ["Scott Steele <scottlsteele@gmail.com>"]
edition = "2018"
@ -8,7 +8,5 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = { path = "../../..", features = ["web_sys"] }
[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies]
wasm-bindgen = "0.2.60"
yew = { path = "../../yew" }

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<js_callback::Model>();
}

View File

@ -5,7 +5,7 @@ authors = ["qthree <qthree3@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -5,7 +5,7 @@ authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -1,5 +1,5 @@
[package]
name = "mount_point_web_sys"
name = "mount_point"
version = "0.1.0"
authors = ["Ben Berman <ben@standardbots.com>"]
edition = "2018"
@ -9,7 +9,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2"
yew = { path = "../../..", features = ["web_sys"] }
yew = { path = "../../yew" }
[dependencies.web-sys]
version = "0.3"

View File

@ -1,4 +1,4 @@
use mount_point_web_sys::Model;
use mount_point::Model;
use wasm_bindgen::JsValue;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
use yew::App;

View File

@ -1,5 +1,5 @@
[package]
name = "multi_thread_web_sys"
name = "multi_thread"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
@ -20,4 +20,4 @@ log = "0.4"
wasm-logger = "0.2"
serde = "1.0"
serde_derive = "1.0"
yew = { path = "../../..", features = ["agent", "services", "web_sys"]}
yew = { path = "../../yew" }

View File

@ -1,4 +1,4 @@
fn main() {
wasm_logger::init(wasm_logger::Config::default());
yew::start_app::<multi_thread_web_sys::Model>();
yew::start_app::<multi_thread::Model>();
}

View File

@ -2,5 +2,5 @@ use yew::agent::Threaded;
fn main() {
wasm_logger::init(wasm_logger::Config::default());
multi_thread_web_sys::native_worker::Worker::register();
multi_thread::native_worker::Worker::register();
}

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
log = "0.4"
web_logger = "0.2"
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -1,5 +1,5 @@
[package]
name = "node_refs_web_sys"
name = "node_refs"
version = "0.1.0"
authors = ["Justin Starry <justin.starry@icloud.com>"]
edition = "2018"
@ -8,5 +8,5 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = { path = "../../..", features = ["web_sys"] }
yew = { path = "../../yew" }
web-sys = { version = "0.3", features = ["HtmlElement", "HtmlInputElement", "Node"] }

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<node_refs::Model>();
}

View File

@ -1,5 +1,5 @@
[package]
name = "npm_and_rest_web_sys"
name = "npm_and_rest"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
@ -14,4 +14,4 @@ serde = "1"
serde_derive = "1"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["console"] }
yew = { path = "../../..", features = ["web_sys"] }
yew = { path = "../../yew" }

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<npm_and_rest::Model>();
}

View File

@ -9,4 +9,3 @@
<script src="/npm_and_rest.js"></script>
</body>
</html>

26
examples/old.Cargo.toml Normal file
View File

@ -0,0 +1,26 @@
[workspace]
members = [
"counter",
"crm",
"custom_components",
"dashboard",
"file_upload",
"fragments",
"futures",
"game_of_life",
"inner_html",
"js_callback",
"large_table",
"minimal",
"mount_point",
"multi_thread",
"nested_list",
"node_refs",
"npm_and_rest",
"pub_sub",
"textarea",
"timer",
"todomvc",
"two_apps",
"webgl",
]

View File

@ -1,11 +1,14 @@
[package]
name = "event_bus"
name = "pub_sub"
version = "0.1.0"
edition = "2018"
[dependencies]
log = "0.4"
web_logger = "0.1"
web_logger = "0.2"
serde = { version = "1.0", features = ["derive"] }
yew = { path = "../..", features = ["std_web"] }
stdweb = "0.4.20"
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]
web_sys = ["yew/web_sys"]

View File

@ -1,3 +1,3 @@
fn main() {
yew::start_app::<event_bus::Model>();
yew::start_app::<pub_sub::Model>();
}

View File

@ -24,15 +24,15 @@ impl Component for Producer {
Producer { event_bus, link }
}
fn change(&mut self, _: Self::Properties) -> bool {
false
}
fn change(&mut self, _: Self::Properties) -> bool {
false
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Clicked => {
self.event_bus
.send(Request::EventBusMsg(format!("Message received")));
.send(Request::EventBusMsg("Message received".to_string()));
false
}
}

View File

@ -16,10 +16,10 @@ impl Component for Subscriber {
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let callback = link.callback(|s| Msg::NewMessage(s));
let callback = link.callback(Msg::NewMessage);
let _producer = EventBus::bridge(callback);
Subscriber {
message: format!("No message yet."),
message: "No message yet.".to_string(),
_producer,
}
}

View File

@ -1,73 +0,0 @@
[package]
name = "showcase"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>", "Limira"]
edition = "2018"
[dependencies]
cfg-if = "0.1"
log = "0.4"
web_logger = "0.2"
strum = "0.13"
strum_macros = "0.13"
yew = { path = "../.." }
counter_std_web = { path = "../std_web/counter", optional = true }
counter_web_sys = { path = "../web_sys/counter", optional = true }
crm = { path = "../crm" }
custom_components = { path = "../custom_components" }
dashboard = { path = "../dashboard" }
node_refs_std_web = { path = "../std_web/node_refs", optional = true }
node_refs_web_sys = { path = "../web_sys/node_refs", optional = true }
fragments = { path = "../fragments" }
game_of_life = { path = "../game_of_life" }
inner_html_std_web = { path = "../std_web/inner_html", optional = true }
inner_html_web_sys = { path = "../web_sys/inner_html", optional = true }
large_table = { path = "../large_table" }
mount_point_std_web = { path = "../std_web/mount_point", optional = true }
mount_point_web_sys = { path = "../web_sys/mount_point", optional = true }
npm_and_rest_std_web = { path = "../std_web/npm_and_rest", optional = true }
npm_and_rest_web_sys = { path = "../web_sys/npm_and_rest", optional = true }
textarea = { path = "../textarea" }
timer = { path = "../timer" }
todomvc_std_web = { path = "../std_web/todomvc", optional = true }
todomvc_web_sys = { path = "../web_sys/todomvc", optional = true }
two_apps_std_web = { path = "../std_web/two_apps", optional = true }
two_apps_web_sys = { path = "../web_sys/two_apps", optional = true }
[features]
std_web = [
"yew/std_web",
"counter_std_web",
"crm/std_web",
"custom_components/std_web",
"dashboard/std_web",
"node_refs_std_web",
"fragments/std_web",
"game_of_life/std_web",
"inner_html_std_web",
"large_table/std_web",
"mount_point_std_web",
"npm_and_rest_std_web",
"textarea/std_web",
"timer/std_web",
"todomvc_std_web",
"two_apps_std_web",
]
web_sys = [
"yew/web_sys",
"counter_web_sys",
"crm/web_sys",
"custom_components/web_sys",
"dashboard/web_sys",
"node_refs_web_sys",
"fragments/web_sys",
"game_of_life/web_sys",
"inner_html_web_sys",
"large_table/web_sys",
"mount_point_web_sys",
"npm_and_rest_web_sys",
"textarea/web_sys",
"timer/web_sys",
"todomvc_web_sys",
"two_apps_web_sys",
]

View File

@ -1,171 +0,0 @@
#![recursion_limit = "128"]
cfg_if::cfg_if! {
if #[cfg(feature = "std_web")] {
use counter_std_web as counter;
use inner_html_std_web as inner_html;
use mount_point_std_web as mount_point;
use node_refs_std_web as node_refs;
use npm_and_rest_std_web as npm_and_rest;
use todomvc_std_web as todomvc;
use two_apps_std_web as two_apps;
} else if #[cfg(feature = "web_sys")] {
use counter_web_sys as counter;
use inner_html_web_sys as inner_html;
use mount_point_web_sys as mount_point;
use node_refs_web_sys as node_refs;
use npm_and_rest_web_sys as npm_and_rest;
use todomvc_web_sys as todomvc;
use two_apps_web_sys as two_apps;
}
}
use counter::Model as Counter;
use crm::Model as Crm;
use custom_components::Model as CustomComponents;
use dashboard::Model as Dashboard;
use fragments::Model as Fragments;
use game_of_life::Model as GameOfLife;
use inner_html::Model as InnerHtml;
use large_table::Model as LargeTable;
use log::trace;
use mount_point::Model as MountPoint;
use node_refs::Model as NodeRefs;
use npm_and_rest::Model as NpmAndRest;
use strum::IntoEnumIterator;
use strum_macros::{Display, EnumIter, EnumString};
use textarea::Model as Textarea;
use timer::Model as Timer;
use todomvc::Model as Todomvc;
use two_apps::TwoModels as TwoApps;
use yew::components::Select;
use yew::{html, App, Component, ComponentLink, Html, ShouldRender};
#[derive(Clone, Debug, Display, EnumString, EnumIter, PartialEq)]
enum Scene {
Counter,
Crm,
CustomComponents,
Dashboard,
NodeRefs,
Fragments,
GameOfLife,
InnerHtml,
LargeTable,
MountPoint,
NpmAndRest,
Textarea,
Timer,
Todomvc,
TwoApps,
}
struct Model {
scene: Option<Scene>,
link: ComponentLink<Self>,
}
enum Msg {
SwitchTo(Scene),
Reset,
}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
Self { scene: None, link }
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SwitchTo(scene) => {
self.scene = Some(scene);
true
}
Msg::Reset => {
self.scene = None;
true
}
}
}
fn change(&mut self, _: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
html! {
<div id="fullscreen">
<style>{ self.view_style() }</style>
<div id="left_pane">
<h2>{ "Yew showcase" }</h2>
<Select<Scene>
selected=self.scene.clone()
options=Scene::iter().collect::<Vec<_>>()
onchange=self.link.callback(Msg::SwitchTo) />
<button onclick=self.link.callback(|_| Msg::Reset)>
{ "Reset" }
</button>
</div>
<div id="right_pane">
{ self.view_scene() }
</div>
</div>
}
}
}
impl Model {
fn view_scene(&self) -> Html {
if let Some(scene) = self.scene.as_ref() {
match scene {
Scene::Counter => html! { <Counter /> },
Scene::Crm => html! { <Crm /> },
Scene::CustomComponents => html! { <CustomComponents /> },
Scene::Dashboard => html! { <Dashboard /> },
Scene::NodeRefs => html! { <NodeRefs /> },
Scene::Fragments => html! { <Fragments /> },
Scene::GameOfLife => html! { <GameOfLife /> },
Scene::InnerHtml => html! { <InnerHtml /> },
Scene::LargeTable => html! { <LargeTable /> },
Scene::MountPoint => html! { <MountPoint /> },
Scene::NpmAndRest => html! { <NpmAndRest /> },
Scene::Textarea => html! { <Textarea /> },
Scene::Timer => html! { <Timer /> },
Scene::Todomvc => html! { <Todomvc /> },
Scene::TwoApps => html! { <TwoApps /> },
}
} else {
html! {
<p>{ "Select the scene, please." }</p>
}
}
}
fn view_style(&self) -> &str {
if let Some(scene) = self.scene.as_ref() {
match scene {
Scene::GameOfLife => include_str!("../../game_of_life/static/styles.css"),
Scene::LargeTable => include_str!("../../large_table/static/styles.css"),
Scene::Todomvc => include_str!("../static/todomvc.css"),
_ => "",
}
} else {
""
}
}
}
fn main() {
web_logger::init();
trace!("Initializing yew...");
yew::initialize();
trace!("Creating an application instance...");
let app: App<Model> = App::new();
trace!("Mount the App to the body of the page...");
app.mount_to_body();
trace!("Run");
yew::run_loop();
}

View File

@ -1,13 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Yew • Showcase</title>
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<script src="/showcase.js"></script>
</body>
</html>

View File

@ -1,14 +0,0 @@
html, body, #fullscreen {
width: 100%;
display: flex;
flex-direction: row;
}
#left_pane {
display: flex;
flex-direction: column;
}
#right_pane {
display: flex;
}

View File

@ -1,521 +0,0 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 1000px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
}
:focus {
outline: 0;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
.toggle-all {
width: 1px;
height: 1px;
border: none; /* Mobile Safari */
opacity: 0;
position: absolute;
right: 100%;
bottom: 100%;
}
.toggle-all + label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.toggle-all + label:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked + label:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 12px 16px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle {
opacity: 0;
}
.todo-list li .toggle + label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
}
.todo-list li .toggle:checked + label {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
.todo-list li label {
word-break: break-all;
padding: 15px 15px 15px 60px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #c5c5c5;
border-bottom: 1px dashed #f7f7f7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
#issue-count {
display: none;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
padding-left: 300px;
}
.learn-bar > .learn {
left: 8px;
}
}

View File

@ -1,9 +0,0 @@
[package]
name = "counter_std_web"
version = "0.1.1"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
stdweb = "0.4.20"
yew = { path = "../../..", features = ["services", "std_web"] }

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<counter_std_web::Model>();
}

View File

@ -1,8 +0,0 @@
[package]
name = "file_upload_std_web"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../../..", features = ["std_web"] }

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<file_upload_std_web::Model>();
}

View File

@ -1,12 +0,0 @@
[package]
name = "js_callback_std_web"
version = "0.1.0"
authors = ["Scott Steele <scottlsteele@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../../..", features = ["std_web"] }
stdweb = "^0.4.20"
[target.'cfg(all(target_arch = "wasm32", not(cargo_web)))'.dependencies]
wasm-bindgen = "0.2.60"

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<js_callback_std_web::Model>();
}

View File

@ -1,4 +0,0 @@
fn main() {
web_logger::init();
yew::start_app::<multi_thread_std_web::Model>();
}

View File

@ -1 +0,0 @@
../../../target/wasm32-unknown-unknown/release

View File

@ -1,9 +0,0 @@
[package]
name = "node_refs_std_web"
version = "0.1.0"
authors = ["Justin Starry <justin.starry@icloud.com>"]
edition = "2018"
[dependencies]
yew = { path = "../../..", features = ["std_web"] }
stdweb = "0.4.20"

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<node_refs_std_web::Model>();
}

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<npm_and_rest_std_web::Model>();
}

View File

@ -1,12 +0,0 @@
[package]
name = "todomvc_std_web"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
strum = "0.13"
strum_macros = "0.13"
serde = "1"
serde_derive = "1"
yew = { path = "../../..", features = ["std_web"] }

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<todomvc_std_web::Model>();
}

View File

@ -1,9 +0,0 @@
[package]
name = "two_apps_std_web"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
stdweb = "0.4.20"
yew = { path = "../../..", features = ["std_web"] }

View File

@ -1,10 +0,0 @@
[package]
name = "webgl_std_web"
version = "0.1.0"
authors = ["Miklós Tusz <mdtusz@gmail.com>"]
edition = "2018"
[dependencies]
stdweb = "0.4.20"
yew = { path = "../../..", features = [ "std_web" ] }
webgl_stdweb = "0.3.0"

View File

@ -1,3 +0,0 @@
fn main() {
yew::start_app::<webgl_std_web::Model>();
}

View File

@ -5,7 +5,7 @@ authors = ["Andrew Straw <strawman@astraw.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -5,7 +5,7 @@ authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
[dependencies]
yew = { path = "../.." }
yew = { path = "../../yew" }
[features]
std_web = ["yew/std_web"]

View File

@ -1,5 +1,5 @@
[package]
name = "todomvc_web_sys"
name = "todomvc"
version = "0.1.0"
authors = ["Denis Kolodin <deniskolodin@gmail.com>"]
edition = "2018"
@ -12,4 +12,4 @@ strum = "0.13"
strum_macros = "0.13"
serde = "1"
serde_derive = "1"
yew = { path = "../../..", features = ["web_sys"] }
yew = { path = "../../yew" }

View File

@ -8,7 +8,7 @@ use yew::format::Json;
use yew::services::storage::{Area, StorageService};
use yew::{html, Component, ComponentLink, Href, Html, InputData, ShouldRender};
const KEY: &'static str = "yew.todomvc.self";
const KEY: &str = "yew.todomvc.self";
pub struct Model {
link: ComponentLink<Self>,

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<todomvc::Model>();
}

Some files were not shown because too many files have changed in this diff Show More