use dioxus::prelude::*;
use dioxus_nox_markdown::markdown;
use dioxus_nox_markdown::prelude::{
LivePreviewVariant, MarkdownHandle, Mode, use_heading_index, use_markdown_handle,
};
fn main() {
dioxus::launch(App);
}
const SAMPLE: &str = "\
# Inline Live Preview
This editor uses **Obsidian-style** inline live preview.
## How It Works
- All blocks render as formatted HTML
- Click a block to edit it as raw markdown
- Move away to re-render as formatted HTML
## Try It
Edit this *paragraph* directly. Notice that `**bold**` and `_italic_` markers
appear only when the cursor is inside this block.
### Code Block
```rust
fn hello() {
println!(\"Hello, inline preview!\");
}
```
### Quote
> Inline preview collapses the editor/preview split into a single surface.
## More Content
Add more paragraphs to see each block independently switch between rendered
and raw modes as you move your cursor around the document.
";
#[component]
fn App() -> Element {
let mut current_mode = use_signal(|| Mode::LivePreview);
rsx! {
document::Link { rel: "stylesheet", href: asset!("/assets/examples.css") }
markdown::Root {
mode: current_mode,
on_mode_change: move |m: Mode| current_mode.set(m),
default_value: SAMPLE,
live_preview_variant: LivePreviewVariant::Inline,
markdown::ModeBar {
markdown::ModeTab { mode: Mode::Read, "Read" }
markdown::ModeTab { mode: Mode::Source, "Source" }
markdown::ModeTab { mode: Mode::LivePreview, "Inline Preview" }
}
markdown::Toolbar {
FormatToolbar {}
}
markdown::Editor {
placeholder: "Type markdown here...",
}
HeadingSidebar {}
}
}
}
#[component]
fn FormatToolbar() -> Element {
let handle: MarkdownHandle = use_markdown_handle();
rsx! {
markdown::ToolbarButton {
onclick: move |_| {
spawn(async move {
handle.wrap_selection("**", "**").await;
});
},
"Bold"
}
markdown::ToolbarSeparator {}
markdown::ToolbarButton {
onclick: move |_| {
spawn(async move {
handle.wrap_selection("_", "_").await;
});
},
"Italic"
}
markdown::ToolbarSeparator {}
markdown::ToolbarButton {
onclick: move |_| {
spawn(async move {
handle.wrap_selection("[", "](url)").await;
});
},
"Link"
}
}
}
#[component]
fn HeadingSidebar() -> Element {
let headings = use_heading_index();
rsx! {
aside {
h3 { "Contents" }
ul {
for h in headings() {
li { "H{h.level} {h.text}" }
}
}
}
}
}