Enum respo::RespoNode

source ·
pub enum RespoNode<T>where
    T: Debug + Clone,
{ Component(StringVec<RespoEffect>, Box<RespoNode<T>>), Element { name: String, attrs: HashMap<String, String>, event: HashMap<String, RespoListenerFn<T>>, style: RespoStyle, children: Vec<(RespoIndexKey, RespoNode<T>)>, }, Referenced(Rc<RespoNode<T>>), }
Expand description

an Element or a Component

Variants§

§

Component(StringVec<RespoEffect>, Box<RespoNode<T>>)

§

Element

Fields

§name: String

tagName

§style: RespoStyle

inlines styles, partially typed. there’s also a macro called static_styles for inserting CSS rules

§children: Vec<(RespoIndexKey, RespoNode<T>)>

each child as a key like a string, by default generated from index, they are used in diffing, so it’s better to be distinct, although not required to be.

corresponding to DOM elements

§

Referenced(Rc<RespoNode<T>>)

Implementations§

create an element node

create a new component

Examples found in repository?
src/dialog/modal.rs (lines 85-134)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (lines 85-134)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (lines 41-97)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (lines 46-104)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (lines 148-224)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

attach styles

element.style(RespoStyle::default().margin(10))
Examples found in repository?
src/respo/primes.rs (line 132)
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  pub fn style(&mut self, more: RespoStyle) -> &mut Self {
    match self {
      RespoNode::Component(_, _, node) => {
        node.style(more);
      }
      RespoNode::Element { ref mut style, .. } => {
        for (k, v) in more.0.into_iter() {
          style.0.push((k.to_owned(), v.to_owned()));
        }
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }
More examples
Hide additional examples
src/respo/alias.rs (lines 58-64)
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
pub fn space<T>(w: Option<i32>, h: Option<i32>) -> RespoNode<T>
where
  T: Clone + Debug,
{
  match (w, h) {
    (Some(wv), Some(hv)) => div()
      .style(
        RespoStyle::default()
          .width(CssSize::Px(wv as f32))
          .height(CssSize::Px(hv as f32))
          .display(crate::CssDisplay::InlineBlock)
          .to_owned(),
      )
      .to_owned(),
    (Some(wv), None) => span()
      .style(
        RespoStyle::default()
          .width(CssSize::Px(wv as f32))
          .display(crate::CssDisplay::InlineBlock)
          .to_owned(),
      )
      .to_owned(),
    (None, Some(hv)) => div()
      .style(
        RespoStyle::default()
          .height(CssSize::Px(hv as f32))
          .width(CssSize::Px(1.0))
          .display(crate::CssDisplay::Block)
          .to_owned(),
      )
      .to_owned(),
    (None, None) => span()
      .style(
        RespoStyle::default()
          .width(CssSize::Px(8.))
          .height(CssSize::Px(8.))
          .display(crate::CssDisplay::InlineBlock)
          .to_owned(),
      )
      .to_owned(),
  }
}
src/dialog/modal.rs (line 88)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/drawer.rs (line 88)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 44)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 49)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

imparative way of updating style

element.modify_style(|s| {
  if data > 1 {
    s.color(CssColor::Red);
  }
});
Examples found in repository?
src/respo/primes.rs (line 159)
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  pub fn modify_style<U>(&mut self, builder: U) -> &mut Self
  where
    U: Fn(&mut RespoStyle),
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.modify_style(builder);
      }
      RespoNode::Element { ref mut style, .. } => {
        builder(style);
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }

set an attribute on element

Examples found in repository?
src/respo/primes.rs (line 178)
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
  pub fn attribute<U, V>(&mut self, property: U, value: V) -> &mut Self
  where
    U: Into<String> + ToOwned,
    V: Display,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.attribute(property, value);
      }
      RespoNode::Element { ref mut attrs, .. } => {
        attrs.insert(property.into(), value.to_string());
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }
  /// set an attribute on element, but using `None` indicates noting
  pub fn maybe_attribute<U, V>(&mut self, property: U, value: Option<V>) -> &mut Self
  where
    U: Into<String> + ToOwned,
    V: Display,
  {
    if let Some(v) = value {
      match self {
        RespoNode::Component(_, _, node) => {
          node.attribute(property, v);
        }
        RespoNode::Element { ref mut attrs, .. } => {
          attrs.insert(property.into(), v.to_string());
        }
        RespoNode::Referenced(_) => {
          unreachable!("should not be called on a referenced node");
        }
      }
    }
    self
  }
  pub fn on_click<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("click", handler);
    self
  }
  pub fn on_input<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("input", handler);
    self
  }
  /// handle keydown event
  pub fn on_keydown<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("keydown", handler);
    self
  }
  /// handle focus event
  pub fn on_focus<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("focus", handler);
    self
  }
  /// handle change event
  pub fn on_change<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("change", handler);
    self
  }
  /// attach a listener by event name(only a small set of events are supported)
  pub fn on_named_event<U>(&mut self, name: &str, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.on_named_event(name, handler);
      }
      RespoNode::Element { ref mut event, .. } => {
        event.insert(name.into(), RespoListenerFn::new(handler));
      }
      RespoNode::Referenced(_) => {
        unreachable!("should attach event on a referenced node");
      }
    }
    self
  }
  /// add children elements,
  /// index key are generated from index number
  pub fn children<U>(&mut self, more: U) -> &mut Self
  where
    U: IntoIterator<Item = RespoNode<T>>,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.children(more);
      }
      RespoNode::Element { ref mut children, .. } => {
        for (idx, v) in more.into_iter().enumerate() {
          children.push((idx.into(), v));
        }
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }
  /// add children elements, with index keys specified
  pub fn children_indexed<U>(&mut self, more: U) -> &mut Self
  where
    U: IntoIterator<Item = (RespoIndexKey, RespoNode<T>)>,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.children_indexed(more);
      }
      RespoNode::Element { ref mut children, .. } => {
        for (idx, v) in more {
          children.push((idx, v));
        }
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }
  /// add an effect on component
  pub fn effect<U, V>(&mut self, args: &[V], handler: U) -> &mut Self
  where
    U: Fn(Vec<RespoEffectArg>, RespoEffectType, &Node) -> Result<(), String> + 'static,
    V: Serialize + Clone,
  {
    match self {
      RespoNode::Component(_, ref mut effects, _) => {
        effects.push(RespoEffect::new(args.to_vec(), handler));
        self
      }
      RespoNode::Element { .. } => unreachable!("effects are on components"),
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
  }
  /// add an empty args effect on component, which does not update
  pub fn stable_effect<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(Vec<RespoEffectArg>, RespoEffectType, &Node) -> Result<(), String> + 'static,
  {
    match self {
      RespoNode::Component(_, ref mut effects, _) => {
        effects.push(RespoEffect::new(vec![] as Vec<()>, handler));
        self
      }
      RespoNode::Element { .. } => unreachable!("effects are on components"),
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
  }
  /// add a list of effects on component
  pub fn effects<U>(&mut self, more: U) -> &mut Self
  where
    U: IntoIterator<Item = RespoEffect>,
  {
    match self {
      RespoNode::Component(_, ref mut effects, _) => {
        effects.extend(more);
        self
      }
      RespoNode::Element { .. } => unreachable!("effects are on components"),
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
  }
  /// attach a class name for adding styles
  pub fn class<U>(&mut self, name: U) -> &mut Self
  where
    U: Into<String>,
  {
    self.attribute("class", name.into())
  }
  /// attach an optional class name for adding styles
  pub fn maybe_class<U>(&mut self, name: Option<U>) -> &mut Self
  where
    U: Into<String>,
  {
    match name {
      Some(name) => self.attribute("class", name.into()),
      None => self,
    }
  }
  /// attach a class name, controlled by a boolean
  pub fn toggle_class<U>(&mut self, name: U, on: bool) -> &mut Self
  where
    U: Into<String>,
  {
    if on {
      self.attribute("class", name.into());
    }
    self
  }
  /// attach a list of class names for adding styles
  pub fn class_list<U>(&mut self, names: &[U]) -> &mut Self
  where
    U: Into<String> + Clone,
  {
    let mut class_name: Vec<String> = vec![];
    for name in names {
      class_name.push((*name).to_owned().into());
    }
    self.attribute("class", class_name.join(" "));
    self
  }
  /// writes `innerText`
  pub fn inner_text<U>(&mut self, content: U) -> &mut Self
  where
    U: Into<String>,
  {
    self.attribute("innerText", content.into());
    self
  }
  /// writes `innerHTML`
  pub fn inner_html<U>(&mut self, content: U) -> &mut Self
  where
    U: Into<String>,
  {
    self.attribute("innerHTML", content.into());
    self
  }
  /// writes `value`
  pub fn value<U>(&mut self, content: U) -> &mut Self
  where
    U: Into<String>,
  {
    self.attribute("value", content.into());
    self
  }
More examples
Hide additional examples
src/dialog/modal.rs (line 131)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/drawer.rs (line 131)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 94)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 101)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 191)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

set an attribute on element, but using None indicates noting

Examples found in repository?
src/dialog/modal.rs (lines 93-100)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (lines 93-100)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (lines 49-56)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (lines 54-61)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (lines 156-167)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
Examples found in repository?
src/dialog/prompt.rs (line 194)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

handle keydown event

handle focus event

handle change event

attach a listener by event name(only a small set of events are supported)

Examples found in repository?
src/respo/primes.rs (line 214)
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  pub fn on_click<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("click", handler);
    self
  }
  pub fn on_input<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("input", handler);
    self
  }
  /// handle keydown event
  pub fn on_keydown<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("keydown", handler);
    self
  }
  /// handle focus event
  pub fn on_focus<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("focus", handler);
    self
  }
  /// handle change event
  pub fn on_change<U>(&mut self, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    self.on_named_event("change", handler);
    self
  }
  /// attach a listener by event name(only a small set of events are supported)
  pub fn on_named_event<U>(&mut self, name: &str, handler: U) -> &mut Self
  where
    U: Fn(RespoEvent, DispatchFn<T>) -> Result<(), String> + 'static,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.on_named_event(name, handler);
      }
      RespoNode::Element { ref mut event, .. } => {
        event.insert(name.into(), RespoListenerFn::new(handler));
      }
      RespoNode::Referenced(_) => {
        unreachable!("should attach event on a referenced node");
      }
    }
    self
  }

add children elements, index key are generated from index number

Examples found in repository?
src/respo/primes.rs (line 274)
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  pub fn children<U>(&mut self, more: U) -> &mut Self
  where
    U: IntoIterator<Item = RespoNode<T>>,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.children(more);
      }
      RespoNode::Element { ref mut children, .. } => {
        for (idx, v) in more.into_iter().enumerate() {
          children.push((idx.into(), v));
        }
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }
More examples
Hide additional examples
src/dialog/modal.rs (lines 89-132)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/drawer.rs (lines 89-132)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (lines 45-95)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (lines 50-102)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (lines 152-222)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

add children elements, with index keys specified

Examples found in repository?
src/respo/primes.rs (line 294)
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  pub fn children_indexed<U>(&mut self, more: U) -> &mut Self
  where
    U: IntoIterator<Item = (RespoIndexKey, RespoNode<T>)>,
  {
    match self {
      RespoNode::Component(_, _, node) => {
        node.children_indexed(more);
      }
      RespoNode::Element { ref mut children, .. } => {
        for (idx, v) in more {
          children.push((idx, v));
        }
      }
      RespoNode::Referenced(_) => {
        unreachable!("should not be called on a referenced node");
      }
    }
    self
  }

add an effect on component

Examples found in repository?
src/dialog/modal.rs (line 136)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (line 136)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 98)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 105)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 226)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

add an empty args effect on component, which does not update

add a list of effects on component

attach a class name for adding styles

Examples found in repository?
src/dialog/modal.rs (line 114)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (line 114)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 74)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 81)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 142)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

attach an optional class name for adding styles

attach a class name, controlled by a boolean

attach a list of class names for adding styles

Examples found in repository?
src/dialog/modal.rs (line 91)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (line 91)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 47)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 52)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 154)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

writes innerText

Examples found in repository?
src/dialog/modal.rs (line 118)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (line 118)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 71)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 77)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 184)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

writes innerHTML

writes value

Examples found in repository?
src/dialog/prompt.rs (line 193)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

wrap with a Rc<RefCell<T>> to enable memory reuse and skipping in diff

Examples found in repository?
src/dialog/modal.rs (line 137)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_modal<T, U>(options: ModalOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Modal".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
More examples
Hide additional examples
src/dialog/drawer.rs (line 137)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
fn comp_drawer<T, U>(options: DrawerOptions<T>, show: bool, on_close: U) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "drawer",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the drawer
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_drawer_card()])
              .style(RespoStyle::default().padding(0.0).line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the drawer
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .class(ui_column())
                .children([
                  div()
                    .class(ui_center())
                    .children([span().inner_text(options.title.unwrap_or_else(|| "Drawer".to_owned())).to_owned()])
                    .to_owned(),
                  space(None, Some(8)),
                  options.render.run(move |dispatch| -> Result<(), String> {
                    let close = close2.clone();
                    close(dispatch)?;
                    Ok(())
                  })?,
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_drawer_fade)
    .share_with_ref(),
  )
}
src/dialog/alert.rs (line 100)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn comp_alert_modal<T, U, V>(options: AlertOptions, show: bool, on_read: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let read = Rc::new(on_read);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "alert-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span().inner_text(options.text.unwrap_or_else(|| "Alert!".to_owned())).to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Read".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          read(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/confirm.rs (line 107)
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
fn comp_confirm_modal<T, U, V>(options: ConfirmOptions, show: bool, on_confirm: U, on_close: V) -> Result<RespoNode<T>, String>
where
  U: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug,
{
  let confirm = Rc::new(on_confirm);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  Ok(
    RespoNode::new_component(
      "confirm-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              close(dispatch)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Need confirmation...".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Confirm".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          let d2 = dispatch.clone();
                          confirm(dispatch)?;
                          close2(d2)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}
src/dialog/prompt.rs (line 227)
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
fn comp_prompt_modal<T, U, V>(
  states: StatesTree,
  options: PromptOptions,
  show: bool,
  on_submit: U,
  on_close: V,
) -> Result<RespoNode<T>, String>
where
  U: Fn(String, DispatchFn<T>) -> Result<(), String> + 'static,
  V: Fn(DispatchFn<T>) -> Result<(), String> + 'static,
  T: Clone + Debug + RespoAction,
{
  let cursor = states.path();
  let cursor2 = cursor.clone();
  let cursor3 = cursor.clone();
  let mut state: InputState = states.data.cast_or_default()?;
  if let Some(text) = &options.initial_value {
    state.draft = text.to_owned();
  }

  // respo::util::log!("State: {:?}", state);

  let state2 = state.clone();

  let submit = Rc::new(on_submit);
  let close = Rc::new(on_close);
  let close2 = close.clone();

  let on_text_input = move |e, dispatch: DispatchFn<_>| -> Result<(), String> {
    if let RespoEvent::Input { value, .. } = e {
      dispatch.run_state(&cursor, InputState { draft: value, error: None })?;
    }
    Ok(())
  };

  let check_submit = move |text: &str, dispatch: DispatchFn<_>| -> Result<(), String> {
    let dispatch2 = dispatch.clone();
    let dispatch3 = dispatch.clone();
    let dispatch4 = dispatch.clone();
    respo::util::log!("validator: {:?}", &options.validator);
    if let Some(validator) = &options.validator {
      // let validator = validator.borrow();
      let result = validator.run(text);
      match result {
        Ok(()) => {
          submit(text.to_owned(), dispatch)?;
          close2(dispatch3)?;
          dispatch4.run_empty_state(&cursor2)?;
        }
        Err(message) => {
          // dispatch.run_state(&cursor2, InputState { draft: text.to_owned() })?;
          dispatch4.run_state(
            &cursor2,
            InputState {
              draft: text.to_owned(),
              error: Some(message),
            },
          )?;
        }
      }
    } else {
      submit(text.to_owned(), dispatch)?;
      close2(dispatch2)?;
      dispatch4.run_empty_state(&cursor2)?;
    }
    Ok(())
  };

  let mut input_el = if options.multilines {
    textarea().class(ui_textarea()).to_owned()
  } else {
    input().class(ui_input()).to_owned()
  };

  Ok(
    RespoNode::new_component(
      "prompt-modal",
      div()
        .style(RespoStyle::default().position(CssPosition::Absolute).to_owned())
        .children([if show {
          div()
            .class_list(&[ui_fullscreen(), ui_center(), css_backdrop()])
            .style(options.backdrop_style)
            .on_click(move |e, dispatch| -> Result<(), String> {
              if let RespoEvent::Click { original_event, .. } = e {
                // stop propagation to prevent closing the modal
                original_event.stop_propagation();
              }
              {
                let dispatch = dispatch.clone();
                close(dispatch)?;
              }
              dispatch.run_empty_state(&cursor3)?;
              Ok(())
            })
            .children([div()
              .class_list(&[ui_column(), ui_global(), css_modal_card()])
              .style(RespoStyle::default().line_height(CssLineHeight::Px(32.0)).to_owned())
              .style(options.card_style)
              .style(options.input_style)
              .on_click(move |e, _dispatch| -> Result<(), String> {
                // nothing to do
                if let RespoEvent::Click { original_event, .. } = e {
                  // stop propagation to prevent closing the modal
                  original_event.stop_propagation();
                }
                Ok(())
              })
              .children([div()
                .children([
                  span()
                    .inner_text(options.text.unwrap_or_else(|| "Input your text:".to_owned()))
                    .to_owned(),
                  space(None, Some(8)),
                  div()
                    .children([input_el
                      .class_list(&[ui_input()])
                      .style(RespoStyle::default().width(CssSize::Percent(100.0)).to_owned())
                      .attribute("placeholder", "Content...")
                      .attribute("autoFocus", "autofocus")
                      .value(state.draft)
                      .on_input(on_text_input)
                      .to_owned()])
                    .to_owned(),
                  match &state.error {
                    Some(message) => div().class_list(&[css_error()]).inner_text(message).to_owned(),
                    None => span(),
                  },
                  space(None, Some(8)),
                  div()
                    .class(ui_row_parted())
                    .children([
                      span(),
                      button()
                        .class_list(&[ui_button(), css_button(), BUTTON_NAME.to_owned()])
                        .inner_text(options.button_text.unwrap_or_else(|| "Submit".to_owned()))
                        .on_click(move |_e, dispatch| -> Result<(), String> {
                          check_submit(&state2.draft, dispatch)?;
                          Ok(())
                        })
                        .to_owned(),
                    ])
                    .to_owned(),
                ])
                .to_owned()])
              .to_owned()])
            .to_owned()
        } else {
          span().attribute("data-name", "placeholder").to_owned()
        }])
        .to_owned(),
    )
    // .effect(&[show], effect_focus)
    .effect(&[show], effect_modal_fade)
    .share_with_ref(),
  )
}

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.