From f913990ef3e62d5f22a95a9d6fd6e7b62aea8cc8 Mon Sep 17 00:00:00 2001 From: Josh Taylor Date: Wed, 11 Jan 2023 21:06:52 +0800 Subject: [PATCH] Add examples for yew showing keymapping and button usage --- examples/Cargo.toml | 2 +- examples/yew_events_external/.gitignore | 3 + examples/yew_events_external/Cargo.toml | 14 +++ examples/yew_events_external/README.md | 7 ++ examples/yew_events_external/index.html | 28 ++++++ examples/yew_events_external/src/main.rs | 87 +++++++++++++++++ examples/yew_events_keymapping/Cargo.toml | 10 ++ examples/yew_events_keymapping/README.md | 8 ++ examples/yew_events_keymapping/index.html | 28 ++++++ examples/yew_events_keymapping/src/main.rs | 107 +++++++++++++++++++++ 10 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 examples/yew_events_external/.gitignore create mode 100644 examples/yew_events_external/Cargo.toml create mode 100644 examples/yew_events_external/README.md create mode 100644 examples/yew_events_external/index.html create mode 100644 examples/yew_events_external/src/main.rs create mode 100644 examples/yew_events_keymapping/Cargo.toml create mode 100644 examples/yew_events_keymapping/README.md create mode 100644 examples/yew_events_keymapping/index.html create mode 100644 examples/yew_events_keymapping/src/main.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d03e6b9..a6f459d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["yew"] +members = ["yew", "yew_events_external", "yew_events_keymapping"] diff --git a/examples/yew_events_external/.gitignore b/examples/yew_events_external/.gitignore new file mode 100644 index 0000000..8f21459 --- /dev/null +++ b/examples/yew_events_external/.gitignore @@ -0,0 +1,3 @@ +target +dist +dist/* diff --git a/examples/yew_events_external/Cargo.toml b/examples/yew_events_external/Cargo.toml new file mode 100644 index 0000000..b02a2de --- /dev/null +++ b/examples/yew_events_external/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "yew_events" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +monaco = { path = "../..", features = ["yew-components"] } +wasm-bindgen = "0.2" +yew = { version = "0.20", features = ["csr"] } + +# Used for the randomess, not needed usually. +getrandom = { version = "0.2", features = ["js"] } +rand = "0.8" diff --git a/examples/yew_events_external/README.md b/examples/yew_events_external/README.md new file mode 100644 index 0000000..771449d --- /dev/null +++ b/examples/yew_events_external/README.md @@ -0,0 +1,7 @@ +# Rust Monaco - Yew Key Mapping Events Example + +This is an example of how to use [Rust Monaco]() with Yew, and using a button to control the editor. + +To use, run `trunk serve`, then access `http://127.0.0.1:8080`. + +Press the button to see the editor change. \ No newline at end of file diff --git a/examples/yew_events_external/index.html b/examples/yew_events_external/index.html new file mode 100644 index 0000000..e2d6737 --- /dev/null +++ b/examples/yew_events_external/index.html @@ -0,0 +1,28 @@ + + + + + + Yew Monaco + + + + + + + diff --git a/examples/yew_events_external/src/main.rs b/examples/yew_events_external/src/main.rs new file mode 100644 index 0000000..b9f89f4 --- /dev/null +++ b/examples/yew_events_external/src/main.rs @@ -0,0 +1,87 @@ +use monaco::{ + api::{CodeEditorOptions, TextModel}, + sys::editor::BuiltinTheme, + yew::CodeEditor, +}; + +use rand::{distributions::Alphanumeric, Rng}; +use yew::prelude::*; + +const CONTENT: &str = include_str!("main.rs"); + +fn get_options() -> CodeEditorOptions { + CodeEditorOptions::default() + .with_language("rust".to_owned()) + .with_value(CONTENT.to_owned()) + .with_builtin_theme(BuiltinTheme::VsDark) + .with_automatic_layout(true) +} + +#[derive(PartialEq, Properties)] +pub struct CustomEditorProps { + text_model: TextModel, +} + +/// This is really just a helper component, so we can pass in props easier. +/// It makes it much easier to use, as we can pass in what we need, and it +/// will only re-render if the props change. +#[function_component(CustomEditor)] +pub fn custom_editor(props: &CustomEditorProps) -> Html { + let CustomEditorProps { text_model } = props; + + html! { + + } +} + +// inefficient and silly, but fine for demo :-) +fn random_string() -> String { + rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(50) + .map(char::from) + .collect() +} + +#[function_component(App)] +fn app() -> Html { + // We need to create a new text model, so we can pass it to Monaco. + // We use use_state_eq, as this allows us to only use it when it changes. + let text_model = + use_state_eq(|| TextModel::create(&random_string(), Some("rust"), None).unwrap()); + + // Here we define what we want to do when we click the button, which is bound to + // the button below. We use the `use_callback` function in Yew to bind the + // function to the button. We can then clone the text model, and use it in + // the callback to set the value to whatever we want. + let on_run_clicked = { + let text_model = text_model.clone(); + use_callback( + move |_, text_model| { + let s: String = random_string(); + // Here we have full access to the text model. We can do whatever we want with + // it. For this example, we'll just set the value to a random + // string. + text_model.set_value(&s); + }, + text_model, + ) + }; + + html! { +
+
+ +
+
+
+ +
+
+
+ } +} + +fn main() { + yew::Renderer::::new().render(); +} diff --git a/examples/yew_events_keymapping/Cargo.toml b/examples/yew_events_keymapping/Cargo.toml new file mode 100644 index 0000000..f33500c --- /dev/null +++ b/examples/yew_events_keymapping/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "yew_events" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +monaco = { path = "../..", features = ["yew-components"] } +wasm-bindgen = "0.2" +yew = { version = "0.20", features = ["csr"] } \ No newline at end of file diff --git a/examples/yew_events_keymapping/README.md b/examples/yew_events_keymapping/README.md new file mode 100644 index 0000000..5d8e90d --- /dev/null +++ b/examples/yew_events_keymapping/README.md @@ -0,0 +1,8 @@ +# Rust Monaco - Yew Key Mapping Events Example + +This is an example of how to use [Rust Monaco]() with Yew, and using `on_editor_created` to add key mappings. + +To use, run `trunk serve`, then access `http://127.0.0.1:8080`. + +Type some code, then press Ctrl+Enter (Linux/Windows) or Cmd+Enter (Mac) to have the code reflect on the right hand +side. \ No newline at end of file diff --git a/examples/yew_events_keymapping/index.html b/examples/yew_events_keymapping/index.html new file mode 100644 index 0000000..e2d6737 --- /dev/null +++ b/examples/yew_events_keymapping/index.html @@ -0,0 +1,28 @@ + + + + + + Yew Monaco + + + + + + + diff --git a/examples/yew_events_keymapping/src/main.rs b/examples/yew_events_keymapping/src/main.rs new file mode 100644 index 0000000..0cb1961 --- /dev/null +++ b/examples/yew_events_keymapping/src/main.rs @@ -0,0 +1,107 @@ +use monaco::{ + api::{CodeEditorOptions, TextModel}, + sys::editor::{BuiltinTheme, IStandaloneCodeEditor}, + yew::{CodeEditor, CodeEditorLink}, +}; +use wasm_bindgen::closure::Closure; +use yew::prelude::*; + +use wasm_bindgen::JsCast; + +const CONTENT: &str = include_str!("main.rs"); + +fn get_options() -> CodeEditorOptions { + CodeEditorOptions::default() + .with_language("rust".to_owned()) + .with_value(CONTENT.to_owned()) + .with_builtin_theme(BuiltinTheme::VsDark) + .with_automatic_layout(true) +} + +#[derive(PartialEq, Properties)] +pub struct CustomEditorProps { + on_editor_created: Callback, + text_model: TextModel, +} + +/// +/// This is really just a helper component, so we can pass in props easier. +/// It makes it much easier to use, as we can pass in what we need, and it +/// will only re-render if the props change. +/// +#[function_component(CustomEditor)] +pub fn custom_editor(props: &CustomEditorProps) -> Html { + let CustomEditorProps { + on_editor_created, + text_model, + } = props; + + html! { + + } +} + +#[function_component(App)] +fn app() -> Html { + // We need to create a new text model, so we can pass it to Monaco. + // We use use_state_eq, as this allows us to only use it when it changes. + let text_model = use_state_eq(|| TextModel::create(CONTENT, Some("rust"), None).unwrap()); + + // This is the current code output. As it's static from the example, we set it to the content. + let code = use_state_eq(|| String::from(CONTENT)); + + // Here we setup the Callback for when the editor is created. + let on_editor_created = { + // We need to clone the text_model/code so we can use them. + let text_model = text_model.clone(); + let code = code.clone(); + + // This is a javascript closure, used to pass to Monaco, using wasm-bindgen. + let js_closure = { + let text_model = text_model.clone(); + + // We update the code state when the Monaco model changes. + // See https://yew.rs/docs/0.20.0/concepts/function-components/pre-defined-hooks + Closure::::new(move || { + code.set(text_model.get_value()); + }) + }; + + // Here we define our callback, we use use_callback as we want to re-render when dependencies change. + // See https://yew.rs/docs/concepts/function-components/state#general-view-of-how-to-store-state + use_callback( + move |editor_link: CodeEditorLink, _text_model| { + editor_link.with_editor(|editor| { + // Registers Ctrl/Cmd + Enter hotkey + let keycode = monaco::sys::KeyCode::Enter.to_value() + | (monaco::sys::KeyMod::ctrl_cmd() as u32); + let raw_editor: &IStandaloneCodeEditor = editor.as_ref(); + + raw_editor.add_command( + keycode.into(), + js_closure.as_ref().unchecked_ref(), + None, + ); + }); + }, + text_model, + ) + }; + html! { +
+
+ +
+
+
+

{"Code (press CTRL+Enter / Command+Enter to view)"}

+
{code.to_string()}
+
+
+
+ } +} + +fn main() { + yew::Renderer::::new().render(); +}