Skip to content

Commit 715756e

Browse files
committed
docs: eliminate use of examples symlinks
1 parent 8363b67 commit 715756e

File tree

10 files changed

+271
-17
lines changed

10 files changed

+271
-17
lines changed

packages/iocraft-macros/examples

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/iocraft-macros/src/lib.rs

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,24 @@ impl ToTokens for ParsedComponent {
382382
///
383383
/// Custom components are defined by adding this macro to a function that returns an `Element`:
384384
///
385-
/// ```no_run
386-
#[doc = include_str!("../examples/counter.rs")]
385+
/// ```
386+
/// # use iocraft::prelude::*;
387+
/// # use std::time::Duration;
388+
/// #[component]
389+
/// fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
390+
/// let mut count = hooks.use_state(|| 0);
391+
///
392+
/// hooks.use_future(async move {
393+
/// loop {
394+
/// smol::Timer::after(Duration::from_millis(100)).await;
395+
/// count += 1;
396+
/// }
397+
/// });
398+
///
399+
/// element! {
400+
/// Text(color: Color::Blue, content: format!("counter: {}", count))
401+
/// }
402+
/// }
387403
/// ```
388404
///
389405
/// The function is allowed to take up to two arguments, one named `props`, for the component's
@@ -392,7 +408,60 @@ impl ToTokens for ParsedComponent {
392408
/// Here is an example of a component that takes a reference to a `Vec` of `User` structs via properties:
393409
///
394410
/// ```
395-
#[doc = include_str!("../examples/table.rs")]
411+
/// # use iocraft::prelude::*;
412+
/// # struct User {
413+
/// # id: i32,
414+
/// # name: String,
415+
/// # email: String,
416+
/// # }
417+
/// #[derive(Default, Props)]
418+
/// struct UsersTableProps<'a> {
419+
/// users: Option<&'a Vec<User>>,
420+
/// }
421+
///
422+
/// #[component]
423+
/// fn UsersTable<'a>(props: &UsersTableProps<'a>) -> impl Into<AnyElement<'a>> {
424+
/// element! {
425+
/// Box(
426+
/// margin_top: 1,
427+
/// margin_bottom: 1,
428+
/// flex_direction: FlexDirection::Column,
429+
/// width: 60,
430+
/// border_style: BorderStyle::Round,
431+
/// border_color: Color::Cyan,
432+
/// ) {
433+
/// Box(border_style: BorderStyle::Single, border_edges: Edges::Bottom, border_color: Color::Grey) {
434+
/// Box(width: 10pct, justify_content: JustifyContent::End, padding_right: 2) {
435+
/// Text(content: "Id", weight: Weight::Bold, decoration: TextDecoration::Underline)
436+
/// }
437+
///
438+
/// Box(width: 40pct) {
439+
/// Text(content: "Name", weight: Weight::Bold, decoration: TextDecoration::Underline)
440+
/// }
441+
///
442+
/// Box(width: 50pct) {
443+
/// Text(content: "Email", weight: Weight::Bold, decoration: TextDecoration::Underline)
444+
/// }
445+
/// }
446+
///
447+
/// #(props.users.map(|users| users.iter().enumerate().map(|(i, user)| element! {
448+
/// Box(background_color: if i % 2 == 0 { None } else { Some(Color::DarkGrey) }) {
449+
/// Box(width: 10pct, justify_content: JustifyContent::End, padding_right: 2) {
450+
/// Text(content: user.id.to_string())
451+
/// }
452+
///
453+
/// Box(width: 40pct) {
454+
/// Text(content: user.name.clone())
455+
/// }
456+
///
457+
/// Box(width: 50pct) {
458+
/// Text(content: user.email.clone())
459+
/// }
460+
/// }
461+
/// })).into_iter().flatten())
462+
/// }
463+
/// }
464+
/// }
396465
/// ```
397466
#[proc_macro_attribute]
398467
pub fn component(_attr: TokenStream, item: TokenStream) -> TokenStream {

packages/iocraft/examples

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/iocraft/src/components/context_provider.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,30 @@ pub struct ContextProviderProps<'a> {
1919
/// # Example
2020
///
2121
/// ```
22-
#[doc = include_str!("../../examples/context.rs")]
22+
/// # use iocraft::prelude::*;
23+
/// struct NumberOfTheDay(i32);
24+
///
25+
/// #[component]
26+
/// fn MyContextConsumer(hooks: Hooks) -> impl Into<AnyElement<'static>> {
27+
/// let number = hooks.use_context::<NumberOfTheDay>();
28+
///
29+
/// element! {
30+
/// Box(border_style: BorderStyle::Round, border_color: Color::Cyan) {
31+
/// Text(content: "The number of the day is... ")
32+
/// Text(color: Color::Green, weight: Weight::Bold, content: number.0.to_string())
33+
/// Text(content: "!")
34+
/// }
35+
/// }
36+
/// }
37+
///
38+
/// fn main() {
39+
/// element! {
40+
/// ContextProvider(value: Context::owned(NumberOfTheDay(42))) {
41+
/// MyContextConsumer
42+
/// }
43+
/// }
44+
/// .print();
45+
/// }
2346
/// ```
2447
#[derive(Default)]
2548
pub struct ContextProvider;

packages/iocraft/src/hooks/use_context.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,21 @@ use std::{
1313
/// # Example
1414
///
1515
/// ```
16-
#[doc = include_str!("../../examples/context.rs")]
16+
/// # use iocraft::prelude::*;
17+
/// struct NumberOfTheDay(i32);
18+
///
19+
/// #[component]
20+
/// fn MyContextConsumer(hooks: Hooks) -> impl Into<AnyElement<'static>> {
21+
/// let number = hooks.use_context::<NumberOfTheDay>();
22+
///
23+
/// element! {
24+
/// Box(border_style: BorderStyle::Round, border_color: Color::Cyan) {
25+
/// Text(content: "The number of the day is... ")
26+
/// Text(color: Color::Green, weight: Weight::Bold, content: number.0.to_string())
27+
/// Text(content: "!")
28+
/// }
29+
/// }
30+
/// }
1731
/// ```
1832
pub trait UseContext<'a> {
1933
/// Returns a reference to the context of the given type.

packages/iocraft/src/hooks/use_future.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,24 @@ use std::{
1111
///
1212
/// # Example
1313
///
14-
/// ```no_run
15-
#[doc = include_str!("../../examples/counter.rs")]
14+
/// ```
15+
/// # use iocraft::prelude::*;
16+
/// # use std::time::Duration;
17+
/// #[component]
18+
/// fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
19+
/// let mut count = hooks.use_state(|| 0);
20+
///
21+
/// hooks.use_future(async move {
22+
/// loop {
23+
/// smol::Timer::after(Duration::from_millis(100)).await;
24+
/// count += 1;
25+
/// }
26+
/// });
27+
///
28+
/// element! {
29+
/// Text(color: Color::Blue, content: format!("counter: {}", count))
30+
/// }
31+
/// }
1632
/// ```
1733
pub trait UseFuture {
1834
/// Spawns a future which is bound to the lifetime of the component. When the component is

packages/iocraft/src/hooks/use_output.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,27 @@ use std::{
1010
///
1111
/// # Example
1212
///
13-
/// ```no_run
14-
#[doc = include_str!("../../examples/use_output.rs")]
13+
/// ```
14+
/// # use iocraft::prelude::*;
15+
/// # use std::time::Duration;
16+
/// #[component]
17+
/// fn Example(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
18+
/// let (stdout, stderr) = hooks.use_output();
19+
///
20+
/// hooks.use_future(async move {
21+
/// loop {
22+
/// smol::Timer::after(Duration::from_secs(1)).await;
23+
/// stdout.println("Hello from iocraft to stdout!");
24+
/// stderr.println(" And hello to stderr too!");
25+
/// }
26+
/// });
27+
///
28+
/// element! {
29+
/// Box(border_style: BorderStyle::Round, border_color: Color::Green) {
30+
/// Text(content: "Hello, use_stdio!")
31+
/// }
32+
/// }
33+
/// }
1534
/// ```
1635
pub trait UseOutput {
1736
/// Gets handles which can be used to write to stdout and stderr.

packages/iocraft/src/hooks/use_state.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,24 @@ use std::{
1414
///
1515
/// # Example
1616
///
17-
/// ```no_run
18-
#[doc = include_str!("../../examples/counter.rs")]
17+
/// ```
18+
/// # use iocraft::prelude::*;
19+
/// # use std::time::Duration;
20+
/// #[component]
21+
/// fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
22+
/// let mut count = hooks.use_state(|| 0);
23+
///
24+
/// hooks.use_future(async move {
25+
/// loop {
26+
/// smol::Timer::after(Duration::from_millis(100)).await;
27+
/// count += 1;
28+
/// }
29+
/// });
30+
///
31+
/// element! {
32+
/// Text(color: Color::Blue, content: format!("counter: {}", count))
33+
/// }
34+
/// }
1935
/// ```
2036
pub trait UseState {
2137
/// Creates a new state with its initial value computed by the given function.

packages/iocraft/src/hooks/use_terminal_events.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,78 @@ use std::{
99
///
1010
/// # Example
1111
///
12-
/// ```no_run
13-
#[doc = include_str!("../../examples/use_input.rs")]
12+
/// ```
13+
/// # use iocraft::prelude::*;
14+
/// # use unicode_width::UnicodeWidthStr;
15+
/// const AREA_WIDTH: u32 = 80;
16+
/// const AREA_HEIGHT: u32 = 11;
17+
/// const FACE: &str = "👾";
18+
///
19+
/// #[component]
20+
/// fn Example(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
21+
/// let mut system = hooks.use_context_mut::<SystemContext>();
22+
/// let x = hooks.use_state(|| 0);
23+
/// let y = hooks.use_state(|| 0);
24+
/// let should_exit = hooks.use_state(|| false);
25+
///
26+
/// hooks.use_terminal_events({
27+
/// move |event| match event {
28+
/// TerminalEvent::Key(KeyEvent { code, kind, .. }) if kind != KeyEventKind::Release => {
29+
/// match code {
30+
/// KeyCode::Char('q') => should_exit.set(true),
31+
/// KeyCode::Up => y.set((y.get() as i32 - 1).max(0) as _),
32+
/// KeyCode::Down => y.set((y.get() + 1).min(AREA_HEIGHT - 1)),
33+
/// KeyCode::Left => x.set((x.get() as i32 - 1).max(0) as _),
34+
/// KeyCode::Right => x.set((x.get() + 1).min(AREA_WIDTH - FACE.width() as u32)),
35+
/// _ => {}
36+
/// }
37+
/// }
38+
/// _ => {}
39+
/// }
40+
/// });
41+
///
42+
/// if should_exit.get() {
43+
/// system.exit();
44+
/// }
45+
///
46+
/// element! {
47+
/// Box(
48+
/// flex_direction: FlexDirection::Column,
49+
/// padding: 2,
50+
/// align_items: AlignItems::Center
51+
/// ) {
52+
/// Text(content: "Use arrow keys to move. Press \"q\" to exit.")
53+
/// Box(
54+
/// border_style: BorderStyle::Round,
55+
/// border_color: Color::Green,
56+
/// height: AREA_HEIGHT + 2,
57+
/// width: AREA_WIDTH + 2,
58+
/// ) {
59+
/// #(if should_exit.get() {
60+
/// element! {
61+
/// Box(
62+
/// width: 100pct,
63+
/// height: 100pct,
64+
/// justify_content: JustifyContent::Center,
65+
/// align_items: AlignItems::Center,
66+
/// ) {
67+
/// Text(content: format!("Goodbye! {}", FACE))
68+
/// }
69+
/// }
70+
/// } else {
71+
/// element! {
72+
/// Box(
73+
/// padding_left: x.get(),
74+
/// padding_top: y.get(),
75+
/// ) {
76+
/// Text(content: FACE)
77+
/// }
78+
/// }
79+
/// })
80+
/// }
81+
/// }
82+
/// }
83+
/// }
1484
/// ```
1585
pub trait UseTerminalEvents {
1686
/// Defines a callback to be invoked whenever a terminal event occurs.

packages/iocraft/src/lib.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,19 @@
2121
//! Here's your first `iocraft` program:
2222
//!
2323
//! ```
24-
#![doc = include_str!("../examples/hello_world.rs")]
24+
//! use iocraft::prelude::*;
25+
//!
26+
//! fn main() {
27+
//! element! {
28+
//! Box(
29+
//! border_style: BorderStyle::Round,
30+
//! border_color: Color::Blue,
31+
//! ) {
32+
//! Text(content: "Hello, world!")
33+
//! }
34+
//! }
35+
//! .print();
36+
//! }
2537
//! ```
2638
//!
2739
//! Your UI is composed primarily via the [`element!`] macro, which allows you to declare your UI
@@ -36,7 +48,23 @@
3648
//! which increments every 100ms:
3749
//!
3850
//! ```no_run
39-
#![doc = include_str!("../examples/counter.rs")]
51+
//! # use iocraft::prelude::*;
52+
//! # use std::time::Duration;
53+
//! #[component]
54+
//! fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
55+
//! let mut count = hooks.use_state(|| 0);
56+
//!
57+
//! hooks.use_future(async move {
58+
//! loop {
59+
//! smol::Timer::after(Duration::from_millis(100)).await;
60+
//! count += 1;
61+
//! }
62+
//! });
63+
//!
64+
//! element! {
65+
//! Text(color: Color::Blue, content: format!("counter: {}", count))
66+
//! }
67+
//! }
4068
//! ```
4169
//!
4270
//! ## More Examples
@@ -54,6 +82,7 @@
5482
//! You may also want to check out [Ratatui](https://github.com/ratatui/ratatui), which serves a
5583
//! similar purpose with a less declarative API.
5684
85+
#![allow(clippy::needless_doctest_main)]
5786
#![warn(missing_docs)]
5887

5988
// # Organization

0 commit comments

Comments
 (0)