raui_immediate_widgets/
lib.rs

1use raui_immediate::*;
2
3macro_rules! impl_imports {
4    () => {
5        #[allow(unused_imports)]
6        use raui_core::widget::component::{
7            containers::{
8                anchor_box::*, area_box::*, content_box::*, context_box::*, flex_box::*,
9                float_box::*, grid_box::*, hidden_box::*, horizontal_box::*, portal_box::*,
10                responsive_box::*, scroll_box::*, size_box::*, switch_box::*, tabs_box::*,
11                tooltip_box::*, variant_box::*, vertical_box::*, wrap_box::*,
12            },
13            interactive::{
14                button::*, float_view::*, input_field::*, navigation::*, options_view::*,
15                scroll_view::*, slider_view::*,
16            },
17        };
18        #[allow(unused_imports)]
19        use raui_core::widget::{
20            component::{image_box::*, space_box::*, text_box::*},
21            none_widget,
22        };
23        #[allow(unused_imports)]
24        use raui_material::component::{
25            containers::{
26                context_paper::*, flex_paper::*, grid_paper::*, horizontal_paper::*,
27                modal_paper::*, paper::*, scroll_paper::*, text_tooltip_paper::*, tooltip_paper::*,
28                vertical_paper::*, window_paper::*, wrap_paper::*,
29            },
30            interactive::{
31                button_paper::*, icon_button_paper::*, slider_paper::*, switch_button_paper::*,
32                text_button_paper::*, text_field_paper::*,
33            },
34        };
35        #[allow(unused_imports)]
36        use raui_material::component::{icon_paper::*, switch_paper::*, text_paper::*};
37    };
38}
39
40macro_rules! impl_slot_components {
41    ($($name:ident),+ $(,)?) => {
42        $(
43            pub fn $name<R>(
44                props: impl Into<raui_core::props::Props>,
45                f: impl FnMut() -> R,
46            ) -> R {
47                impl_imports!();
48                crate::slot_component(raui_core::make_widget!($name), props, f)
49            }
50        )+
51    };
52}
53
54macro_rules! impl_list_components {
55    ($($name:ident),+ $(,)?) => {
56        $(
57            pub fn $name<R>(
58                props: impl Into<raui_core::props::Props>,
59                f: impl FnMut() -> R,
60            ) -> R {
61                impl_imports!();
62                crate::list_component(raui_core::make_widget!($name), props, f)
63            }
64        )+
65    };
66}
67
68macro_rules! impl_content_components {
69    ($content:literal : $($name:ident),+ $(,)?) => {
70        $(
71            pub fn $name<R>(
72                props: impl Into<raui_core::props::Props>,
73                f: impl FnMut() -> R,
74            ) -> R {
75                impl_imports!();
76                crate::content_component(raui_core::make_widget!($name), $content, props, f)
77            }
78        )+
79    };
80}
81
82macro_rules! impl_components {
83    ($($name:ident),+ $(,)?) => {
84        $(
85            pub fn $name(
86                props: impl Into<raui_core::props::Props>,
87            ) {
88                impl_imports!();
89                crate::component(raui_core::make_widget!($name), props)
90            }
91        )+
92    };
93}
94
95pub mod core {
96    impl_components! {
97        image_box,
98        nav_scroll_box_side_scrollbars,
99        none_widget,
100        space_box,
101        text_box,
102    }
103
104    pub mod containers {
105        impl_content_components! {
106            "content":
107            anchor_box,
108            hidden_box,
109            nav_scroll_box_content,
110            pivot_box,
111            portal_box,
112            responsive_props_box,
113            size_box,
114            wrap_box,
115        }
116
117        impl_slot_components! {
118            context_box,
119            nav_scroll_box,
120            portals_context_box,
121            portals_tooltip_box,
122            tooltip_box,
123            variant_box,
124        }
125
126        impl_list_components! {
127            content_box,
128            flex_box,
129            grid_box,
130            horizontal_box,
131            nav_content_box,
132            nav_flex_box,
133            nav_grid_box,
134            nav_horizontal_box,
135            nav_switch_box,
136            nav_tabs_box,
137            nav_vertical_box,
138            responsive_box,
139            switch_box,
140            vertical_box,
141        }
142    }
143
144    pub mod interactive {
145        use raui_core::{
146            make_widget,
147            props::Props,
148            widget::{
149                component::interactive::{
150                    button::ButtonProps,
151                    input_field::{TextInputProps, TextInputState},
152                    navigation::NavTrackingProps,
153                    options_view::{OptionsViewProps, OptionsViewProxy},
154                    slider_view::{SliderViewProps, SliderViewProxy},
155                },
156                utils::Vec2,
157            },
158        };
159        use raui_immediate::{begin, end, pop, push, use_state};
160        use std::str::FromStr;
161
162        #[derive(Debug, Default, Copy, Clone)]
163        pub struct ImmediateTracking {
164            pub state: NavTrackingProps,
165            pub prev: NavTrackingProps,
166        }
167
168        impl ImmediateTracking {
169            pub fn pointer_delta_factor(&self) -> Vec2 {
170                Vec2 {
171                    x: self.state.factor.x - self.prev.factor.x,
172                    y: self.state.factor.y - self.prev.factor.y,
173                }
174            }
175
176            pub fn pointer_delta_unscaled(&self) -> Vec2 {
177                Vec2 {
178                    x: self.state.unscaled.x - self.prev.unscaled.x,
179                    y: self.state.unscaled.y - self.prev.unscaled.y,
180                }
181            }
182
183            pub fn pointer_delta_ui_space(&self) -> Vec2 {
184                Vec2 {
185                    x: self.state.ui_space.x - self.prev.ui_space.x,
186                    y: self.state.ui_space.y - self.prev.ui_space.y,
187                }
188            }
189
190            pub fn pointer_moved(&self) -> bool {
191                (self.state.factor.x - self.prev.factor.x)
192                    + (self.state.factor.y - self.prev.factor.y)
193                    > 1.0e-6
194            }
195        }
196
197        #[derive(Debug, Default, Copy, Clone)]
198        pub struct ImmediateButton {
199            pub state: ButtonProps,
200            pub prev: ButtonProps,
201        }
202
203        impl ImmediateButton {
204            pub fn select_start(&self) -> bool {
205                !self.prev.selected && self.state.selected
206            }
207
208            pub fn select_stop(&self) -> bool {
209                self.prev.selected && !self.state.selected
210            }
211
212            pub fn select_changed(&self) -> bool {
213                self.prev.selected != self.state.selected
214            }
215
216            pub fn trigger_start(&self) -> bool {
217                !self.prev.trigger && self.state.trigger
218            }
219
220            pub fn trigger_stop(&self) -> bool {
221                self.prev.trigger && !self.state.trigger
222            }
223
224            pub fn trigger_changed(&self) -> bool {
225                self.prev.trigger != self.state.trigger
226            }
227
228            pub fn context_start(&self) -> bool {
229                !self.prev.context && self.state.context
230            }
231
232            pub fn context_stop(&self) -> bool {
233                self.prev.context && !self.state.context
234            }
235
236            pub fn context_changed(&self) -> bool {
237                self.prev.context != self.state.context
238            }
239        }
240
241        impl_content_components! {
242            "content":
243            navigation_barrier,
244        }
245
246        pub fn tracking(
247            props: impl Into<Props>,
248            mut f: impl FnMut(ImmediateTracking),
249        ) -> ImmediateTracking {
250            use crate::internal::*;
251            let state = use_state(ImmediateTracking::default);
252            let result = state.read().unwrap().to_owned();
253            begin();
254            f(result);
255            let node = end().pop().unwrap_or_default();
256            push(
257                make_widget!(immediate_tracking)
258                    .with_props(ImmediateTrackingProps { state: Some(state) })
259                    .merge_props(props.into())
260                    .named_slot("content", node),
261            );
262            result
263        }
264
265        pub fn self_tracking(
266            props: impl Into<Props>,
267            mut f: impl FnMut(ImmediateTracking),
268        ) -> ImmediateTracking {
269            use crate::internal::*;
270            let state = use_state(ImmediateTracking::default);
271            let result = state.read().unwrap().to_owned();
272            begin();
273            f(result);
274            let node = end().pop().unwrap_or_default();
275            push(
276                make_widget!(immediate_self_tracking)
277                    .with_props(ImmediateTrackingProps { state: Some(state) })
278                    .merge_props(props.into())
279                    .named_slot("content", node),
280            );
281            result
282        }
283
284        pub fn button(
285            props: impl Into<Props>,
286            mut f: impl FnMut(ImmediateButton),
287        ) -> ImmediateButton {
288            use crate::internal::*;
289            let state = use_state(ImmediateButton::default);
290            let result = state.read().unwrap().to_owned();
291            begin();
292            f(result);
293            let node = end().pop().unwrap_or_default();
294            push(
295                make_widget!(immediate_button)
296                    .with_props(ImmediateButtonProps { state: Some(state) })
297                    .merge_props(props.into())
298                    .named_slot("content", node),
299            );
300            result
301        }
302
303        pub fn text_input<T: ToString + FromStr + Send + Sync>(
304            value: &T,
305            props: impl Into<Props>,
306            mut f: impl FnMut(&str, TextInputState),
307        ) -> (Option<T>, TextInputState) {
308            use crate::internal::*;
309            let content = use_state(|| value.to_string());
310            let props = props.into();
311            let TextInputProps { allow_new_line, .. } = props.read_cloned_or_default();
312            let text_state = use_state(TextInputState::default);
313            let text_result = text_state.read().unwrap().to_owned();
314            if !text_result.focused {
315                *content.write().unwrap() = value.to_string();
316            }
317            let result = content.read().unwrap().to_string();
318            begin();
319            f(&result, text_result);
320            let node = end().pop().unwrap_or_default();
321            push(
322                make_widget!(immediate_text_input)
323                    .with_props(ImmediateTextInputProps {
324                        state: Some(text_state),
325                    })
326                    .merge_props(props)
327                    .with_props(TextInputProps {
328                        allow_new_line,
329                        text: Some(content.into()),
330                    })
331                    .named_slot("content", node),
332            );
333            (result.parse().ok(), text_result)
334        }
335
336        pub fn input_field<T: ToString + FromStr + Send + Sync>(
337            value: &T,
338            props: impl Into<Props>,
339            mut f: impl FnMut(&str, TextInputState, ImmediateButton),
340        ) -> (Option<T>, TextInputState, ImmediateButton) {
341            use crate::internal::*;
342            let content = use_state(|| value.to_string());
343            let props = props.into();
344            let TextInputProps { allow_new_line, .. } = props.read_cloned_or_default();
345            let text_state = use_state(TextInputState::default);
346            let text_result = text_state.read().unwrap().to_owned();
347            let button_state = use_state(ImmediateButton::default);
348            let button_result = button_state.read().unwrap().to_owned();
349            if !text_result.focused {
350                *content.write().unwrap() = value.to_string();
351            }
352            let result = content.read().unwrap().to_string();
353            begin();
354            f(&result, text_result, button_result);
355            let node = end().pop().unwrap_or_default();
356            push(
357                make_widget!(immediate_input_field)
358                    .with_props(ImmediateTextInputProps {
359                        state: Some(text_state),
360                    })
361                    .with_props(ImmediateButtonProps {
362                        state: Some(button_state),
363                    })
364                    .merge_props(props)
365                    .with_props(TextInputProps {
366                        allow_new_line,
367                        text: Some(content.into()),
368                    })
369                    .named_slot("content", node),
370            );
371            (result.parse().ok(), text_result, button_result)
372        }
373
374        pub fn slider_view<T: SliderViewProxy + Clone + 'static>(
375            value: T,
376            props: impl Into<Props>,
377            mut f: impl FnMut(&T, ImmediateButton),
378        ) -> (T, ImmediateButton) {
379            use crate::internal::*;
380            let content = use_state(|| value.to_owned());
381            let props = props.into();
382            let SliderViewProps {
383                from,
384                to,
385                direction,
386                ..
387            } = props.read_cloned_or_default();
388            let button_state = use_state(ImmediateButton::default);
389            let button_result = button_state.read().unwrap().to_owned();
390            let result = content.read().unwrap().to_owned();
391            begin();
392            f(&result, button_result);
393            let node = end().pop().unwrap_or_default();
394            push(
395                make_widget!(immediate_slider_view)
396                    .with_props(ImmediateButtonProps {
397                        state: Some(button_state),
398                    })
399                    .merge_props(props)
400                    .with_props(SliderViewProps {
401                        input: Some(content.into()),
402                        from,
403                        to,
404                        direction,
405                    })
406                    .named_slot("content", node),
407            );
408            (result, button_result)
409        }
410
411        pub fn options_view<T: OptionsViewProxy + Clone + 'static>(
412            value: T,
413            props: impl Into<Props>,
414            mut f_items: impl FnMut(&T),
415            mut f_content: impl FnMut(),
416        ) -> T {
417            let content = use_state(|| value.to_owned());
418            let props = props.into();
419            let result = content.read().unwrap().to_owned();
420            begin();
421            f_items(&result);
422            let nodes = end();
423            begin();
424            f_content();
425            let node = pop();
426            push(
427                make_widget!(raui_core::widget::component::interactive::options_view::options_view)
428                    .merge_props(props)
429                    .with_props(OptionsViewProps {
430                        input: Some(content.into()),
431                    })
432                    .named_slot("content", node)
433                    .listed_slots(nodes),
434            );
435            result
436        }
437    }
438}
439
440pub mod material {
441    impl_components! {
442        icon_paper,
443        scroll_paper_side_scrollbars,
444        switch_paper,
445        text_paper,
446    }
447
448    pub mod containers {
449        impl_slot_components! {
450            context_paper,
451            scroll_paper,
452            tooltip_paper,
453        }
454
455        impl_content_components! {
456            "content":
457            modal_paper,
458            text_tooltip_paper,
459            wrap_paper,
460        }
461
462        impl_list_components! {
463            flex_paper,
464            grid_paper,
465            horizontal_paper,
466            nav_flex_paper,
467            nav_grid_paper,
468            nav_horizontal_paper,
469            nav_vertical_paper,
470            paper,
471            vertical_paper,
472        }
473    }
474
475    pub mod interactive {
476        use crate::core::interactive::ImmediateButton;
477        use raui_core::{
478            make_widget,
479            props::Props,
480            widget::component::interactive::{
481                input_field::{TextInputProps, TextInputState},
482                slider_view::{SliderViewProps, SliderViewProxy},
483            },
484        };
485        use raui_immediate::{begin, end, push, use_state};
486        use std::str::FromStr;
487
488        pub fn button_paper(
489            props: impl Into<Props>,
490            mut f: impl FnMut(ImmediateButton),
491        ) -> ImmediateButton {
492            use crate::internal::*;
493            let state = use_state(ImmediateButton::default);
494            let result = state.read().unwrap().to_owned();
495            begin();
496            f(result);
497            let node = end().pop().unwrap_or_default();
498            push(
499                make_widget!(immediate_button_paper)
500                    .with_props(ImmediateButtonProps { state: Some(state) })
501                    .merge_props(props.into())
502                    .named_slot("content", node),
503            );
504            result
505        }
506
507        pub fn icon_button_paper(props: impl Into<Props>) -> ImmediateButton {
508            use crate::internal::*;
509            let state = use_state(ImmediateButton::default);
510            let result = state.read().unwrap().to_owned();
511            push(
512                make_widget!(immediate_icon_button_paper)
513                    .with_props(ImmediateButtonProps { state: Some(state) })
514                    .merge_props(props.into()),
515            );
516            result
517        }
518
519        pub fn switch_button_paper(props: impl Into<Props>) -> ImmediateButton {
520            use crate::internal::*;
521            let state = use_state(ImmediateButton::default);
522            let result = state.read().unwrap().to_owned();
523            push(
524                make_widget!(immediate_switch_button_paper)
525                    .with_props(ImmediateButtonProps { state: Some(state) })
526                    .merge_props(props.into()),
527            );
528            result
529        }
530
531        pub fn text_button_paper(props: impl Into<Props>) -> ImmediateButton {
532            use crate::internal::*;
533            let state = use_state(ImmediateButton::default);
534            let result = state.read().unwrap().to_owned();
535            push(
536                make_widget!(immediate_text_button_paper)
537                    .with_props(ImmediateButtonProps { state: Some(state) })
538                    .merge_props(props.into()),
539            );
540            result
541        }
542
543        pub fn text_field_paper<T: ToString + FromStr + Send + Sync>(
544            value: &T,
545            props: impl Into<Props>,
546        ) -> (Option<T>, TextInputState, ImmediateButton) {
547            use crate::internal::*;
548            let content = use_state(|| value.to_string());
549            let props = props.into();
550            let TextInputProps { allow_new_line, .. } =
551                props.read_cloned_or_default::<TextInputProps>();
552            let text_state = use_state(TextInputState::default);
553            let text_result = text_state.read().unwrap().to_owned();
554            let button_state = use_state(ImmediateButton::default);
555            let button_result = button_state.read().unwrap().to_owned();
556            if !text_result.focused {
557                *content.write().unwrap() = value.to_string();
558            }
559            let result = content.read().unwrap().to_string();
560            push(
561                make_widget!(immediate_text_field_paper)
562                    .with_props(ImmediateTextInputProps {
563                        state: Some(text_state),
564                    })
565                    .with_props(ImmediateButtonProps {
566                        state: Some(button_state),
567                    })
568                    .merge_props(props)
569                    .with_props(TextInputProps {
570                        allow_new_line,
571                        text: Some(content.into()),
572                    }),
573            );
574            (result.parse().ok(), text_result, button_result)
575        }
576
577        pub fn slider_paper<T: SliderViewProxy + Clone + 'static>(
578            value: T,
579            props: impl Into<Props>,
580            mut f: impl FnMut(&T, ImmediateButton),
581        ) -> (T, ImmediateButton) {
582            use crate::internal::*;
583            let content = use_state(|| value.to_owned());
584            let props = props.into();
585            let SliderViewProps {
586                from,
587                to,
588                direction,
589                ..
590            } = props.read_cloned_or_default();
591            let button_state = use_state(ImmediateButton::default);
592            let button_result = button_state.read().unwrap().to_owned();
593            let result = content.read().unwrap().to_owned();
594            begin();
595            f(&result, button_result);
596            let node = end().pop().unwrap_or_default();
597            push(
598                make_widget!(immediate_slider_paper)
599                    .with_props(ImmediateButtonProps {
600                        state: Some(button_state),
601                    })
602                    .merge_props(props)
603                    .with_props(SliderViewProps {
604                        input: Some(content.into()),
605                        from,
606                        to,
607                        direction,
608                    })
609                    .named_slot("content", node),
610            );
611            (result, button_result)
612        }
613
614        pub fn numeric_slider_paper<T: SliderViewProxy + Clone + 'static>(
615            value: T,
616            props: impl Into<Props>,
617        ) -> (T, ImmediateButton) {
618            use crate::internal::*;
619            let content = use_state(|| value.to_owned());
620            let props = props.into();
621            let SliderViewProps {
622                from,
623                to,
624                direction,
625                ..
626            } = props.read_cloned_or_default();
627            let button_state = use_state(ImmediateButton::default);
628            let button_result = button_state.read().unwrap().to_owned();
629            let result = content.read().unwrap().to_owned();
630            push(
631                make_widget!(immediate_numeric_slider_paper)
632                    .with_props(ImmediateButtonProps {
633                        state: Some(button_state),
634                    })
635                    .merge_props(props)
636                    .with_props(SliderViewProps {
637                        input: Some(content.into()),
638                        from,
639                        to,
640                        direction,
641                    }),
642            );
643            (result, button_result)
644        }
645    }
646}
647
648mod internal {
649    use crate::core::interactive::{ImmediateButton, ImmediateTracking};
650    use raui_core::{
651        ManagedLazy, Prefab, PropsData, make_widget, pre_hooks,
652        widget::{
653            component::interactive::{
654                button::{ButtonNotifyMessage, ButtonNotifyProps, button},
655                input_field::{TextInputState, input_field, text_input},
656                navigation::{
657                    NavTrackingNotifyMessage, NavTrackingNotifyProps, self_tracking, tracking,
658                    use_nav_tracking_self,
659                },
660                slider_view::slider_view,
661            },
662            context::WidgetContext,
663            node::WidgetNode,
664        },
665    };
666    use raui_material::component::interactive::{
667        button_paper::button_paper_impl,
668        icon_button_paper::icon_button_paper_impl,
669        slider_paper::{numeric_slider_paper_impl, slider_paper_impl},
670        switch_button_paper::switch_button_paper_impl,
671        text_button_paper::text_button_paper_impl,
672        text_field_paper::text_field_paper_impl,
673    };
674    use serde::{Deserialize, Serialize};
675
676    #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
677    #[props_data(raui_core::props::PropsData)]
678    #[prefab(raui_core::Prefab)]
679    pub struct ImmediateTrackingProps {
680        #[serde(default, skip)]
681        pub state: Option<ManagedLazy<ImmediateTracking>>,
682    }
683
684    impl std::fmt::Debug for ImmediateTrackingProps {
685        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
686            f.debug_struct("ImmediateTrackingProps")
687                .field(
688                    "state",
689                    &self
690                        .state
691                        .as_ref()
692                        .and_then(|state| state.read())
693                        .map(|state| *state),
694                )
695                .finish()
696        }
697    }
698
699    #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
700    #[props_data(raui_core::props::PropsData)]
701    #[prefab(raui_core::Prefab)]
702    pub struct ImmediateButtonProps {
703        #[serde(default, skip)]
704        pub state: Option<ManagedLazy<ImmediateButton>>,
705    }
706
707    impl std::fmt::Debug for ImmediateButtonProps {
708        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
709            f.debug_struct("ImmediateButtonProps")
710                .field(
711                    "state",
712                    &self
713                        .state
714                        .as_ref()
715                        .and_then(|state| state.read())
716                        .map(|state| *state),
717                )
718                .finish()
719        }
720    }
721
722    #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
723    #[props_data(raui_core::props::PropsData)]
724    pub struct ImmediateTextInputProps {
725        #[serde(default, skip)]
726        pub state: Option<ManagedLazy<TextInputState>>,
727    }
728
729    impl std::fmt::Debug for ImmediateTextInputProps {
730        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
731            f.debug_struct("ImmediateTextInputProps")
732                .finish_non_exhaustive()
733        }
734    }
735
736    fn use_immediate_tracking(ctx: &mut WidgetContext) {
737        ctx.props
738            .write(NavTrackingNotifyProps(ctx.id.to_owned().into()));
739
740        if let Ok(props) = ctx.props.read::<ImmediateTrackingProps>() {
741            let state = props.state.as_ref().unwrap();
742            let mut state = state.write().unwrap();
743            state.prev = state.state;
744        }
745
746        ctx.life_cycle.change(|ctx| {
747            if let Ok(props) = ctx.props.read::<ImmediateTrackingProps>()
748                && let Some(state) = props.state.as_ref()
749                && let Some(mut state) = state.write()
750            {
751                for msg in ctx.messenger.messages {
752                    if let Some(msg) = msg.as_any().downcast_ref::<NavTrackingNotifyMessage>() {
753                        state.state = msg.state;
754                    }
755                }
756            }
757        });
758    }
759
760    fn use_immediate_button(ctx: &mut WidgetContext) {
761        ctx.props.write(ButtonNotifyProps(ctx.id.to_owned().into()));
762
763        if let Ok(props) = ctx.props.read::<ImmediateButtonProps>() {
764            let state = props.state.as_ref().unwrap();
765            let mut state = state.write().unwrap();
766            state.prev = state.state;
767        }
768
769        ctx.life_cycle.change(|ctx| {
770            if let Ok(props) = ctx.props.read::<ImmediateButtonProps>()
771                && let Some(state) = props.state.as_ref()
772                && let Some(mut state) = state.write()
773            {
774                for msg in ctx.messenger.messages {
775                    if let Some(msg) = msg.as_any().downcast_ref::<ButtonNotifyMessage>() {
776                        state.state = msg.state;
777                    }
778                }
779            }
780        });
781    }
782
783    fn use_immediate_text_input(ctx: &mut WidgetContext) {
784        if let Ok(data) = ctx.state.read_cloned::<TextInputState>()
785            && let Ok(props) = ctx.props.read::<ImmediateTextInputProps>()
786        {
787            let state = props.state.as_ref().unwrap();
788            let mut state = state.write().unwrap();
789            *state = data;
790        }
791    }
792
793    #[pre_hooks(use_immediate_tracking)]
794    pub(crate) fn immediate_tracking(mut ctx: WidgetContext) -> WidgetNode {
795        tracking(ctx)
796    }
797
798    #[pre_hooks(use_immediate_tracking, use_nav_tracking_self)]
799    pub(crate) fn immediate_self_tracking(mut ctx: WidgetContext) -> WidgetNode {
800        self_tracking(ctx)
801    }
802
803    #[pre_hooks(use_immediate_button)]
804    pub(crate) fn immediate_button(mut ctx: WidgetContext) -> WidgetNode {
805        button(ctx)
806    }
807
808    #[pre_hooks(use_immediate_text_input)]
809    pub(crate) fn immediate_text_input(mut ctx: WidgetContext) -> WidgetNode {
810        text_input(ctx)
811    }
812
813    #[pre_hooks(use_immediate_text_input, use_immediate_button)]
814    pub(crate) fn immediate_input_field(mut ctx: WidgetContext) -> WidgetNode {
815        input_field(ctx)
816    }
817
818    #[pre_hooks(use_immediate_button)]
819    pub(crate) fn immediate_slider_view(mut ctx: WidgetContext) -> WidgetNode {
820        slider_view(ctx)
821    }
822
823    pub(crate) fn immediate_button_paper(ctx: WidgetContext) -> WidgetNode {
824        button_paper_impl(make_widget!(immediate_button), ctx)
825    }
826
827    pub(crate) fn immediate_icon_button_paper(ctx: WidgetContext) -> WidgetNode {
828        icon_button_paper_impl(make_widget!(immediate_button_paper), ctx)
829    }
830
831    pub(crate) fn immediate_switch_button_paper(ctx: WidgetContext) -> WidgetNode {
832        switch_button_paper_impl(make_widget!(immediate_button_paper), ctx)
833    }
834
835    pub(crate) fn immediate_text_button_paper(ctx: WidgetContext) -> WidgetNode {
836        text_button_paper_impl(make_widget!(immediate_button_paper), ctx)
837    }
838
839    pub(crate) fn immediate_text_field_paper(ctx: WidgetContext) -> WidgetNode {
840        text_field_paper_impl(make_widget!(immediate_input_field), ctx)
841    }
842
843    pub(crate) fn immediate_slider_paper(ctx: WidgetContext) -> WidgetNode {
844        slider_paper_impl(make_widget!(immediate_slider_view), ctx)
845    }
846
847    pub(crate) fn immediate_numeric_slider_paper(ctx: WidgetContext) -> WidgetNode {
848        numeric_slider_paper_impl(make_widget!(immediate_slider_paper), ctx)
849    }
850}