Skip to main content

telar_ui_core/
lib.rs

1pub mod accessibility;
2#[cfg(feature = "async-assets")]
3mod async_asset;
4mod border;
5mod canvas;
6mod child_host;
7mod container;
8mod context;
9pub mod dismiss;
10mod drag;
11pub mod focus;
12mod image;
13mod input;
14mod input_region;
15mod kept;
16mod keyboard;
17mod keynav;
18mod layout_item;
19mod layout_leaf;
20mod lazy;
21mod line;
22mod line_gutter;
23mod named_overlay;
24pub mod overlay;
25mod path;
26mod pointer;
27mod press;
28mod reactive_list;
29mod rect;
30mod reorder;
31mod rich_text;
32mod scroll_area;
33mod scroll_page;
34pub mod scroll_region;
35mod slots;
36mod styled_container;
37mod surface;
38mod surface_context;
39#[cfg(feature = "svg")]
40mod svg;
41mod text;
42mod text_area;
43mod text_metrics;
44mod virtual_list;
45mod window_root;
46
47#[cfg(feature = "async-assets")]
48pub use async_asset::{AssetSource, AssetState};
49pub use border::{logical_border_radius, logical_border_widths};
50pub use canvas::Canvas;
51pub use child_host::{ChildSlot, fragment, fragment_positional};
52pub use container::Container;
53pub use context::{
54    NodeId, absolute_rect, compute_layout, current_direction, mark_dirty, new_container, new_leaf,
55    overlay_viewport, relayout_if_dirty, remove_node, reset_layout_runtime, set_children,
56    set_direction, set_display, set_min_height, set_overlay_host, track_layout, use_direction,
57};
58pub use dismiss::{dismiss_depth, dismiss_top, use_dismiss_depth};
59pub use drag::{DragStart, drag_start, drag_travel};
60pub use image::Image;
61pub use input::Input;
62pub use input_region::interactive_rects;
63pub use kept::kept;
64pub use keyboard::{
65    end_frame as end_keyboard_frame, key_held, key_pressed, modifiers, observe as observe_keyboard,
66    reset as reset_keyboard,
67};
68pub use keynav::{KeyNav, KeyNavMove, key_nav_apply, key_nav_apply_grid};
69pub use layout_item::{ClipAxis, ClippedItem, Holding, LayoutItem, box_item};
70pub use lazy::Lazy;
71pub use line::Line;
72pub use line_gutter::LineGutter;
73pub use named_overlay::{close as close_overlay, open as open_overlay, state as overlay_state};
74pub use overlay::{Overlay, Placement, anchor_rect};
75pub use path::Path;
76pub use pointer::{
77    PointerButtons, observe_pointer, pointer_buttons, reset_pointer, transform_pointer,
78};
79pub use reactive_list::ReactiveList;
80pub use rect::Rectangle;
81pub use reorder::{Axis, apply_move, insertion_index};
82pub use rich_text::RichText;
83pub use scroll_area::{LayoutScrollArea, ScrollViewport, ScrollbarStyle};
84pub use scroll_page::ScrollPage;
85pub use scroll_region::visible_rect;
86pub use slots::{Children, Slots, use_context};
87pub use styled_container::{StyledContainer, box_transform, style_follows};
88pub use surface::{DEFAULT_SCRIM, Edge, SurfaceScaffold, SurfaceTransition};
89pub use surface_context::{Surface, SurfaceGuard};
90#[cfg(feature = "svg")]
91pub use svg::Svg;
92pub use text::Text;
93pub use text_area::TextArea;
94pub use ui_tree::{Component, ComponentList, EventResult, NodeVec, RenderNode};
95pub use virtual_list::{VirtualList, visible_window};
96pub use window_root::WindowRoot;
97
98/// Routes an event to the overlay layer before the widget tree sees it.
99///
100/// Wraps `ui_tree`'s pointer routing with the keyboard half it cannot do: the dismiss stack and the focus
101/// state both live in this crate, so Escape is resolved here. Every caller (the runner, the plugin bridge)
102/// already goes through `ui_core`, so this is the single choke point either way.
103pub fn dispatch_overlays(event: &platform_core::Event) -> EventResult {
104    // Escape closes the frontmost dialog only when nothing holds focus: a focused editor gets first refusal
105    // and blurs itself (see `Input`'s Escape), so a second press then closes the dialog around it. Dismissing
106    // ahead of the focused widget would make Escape unable to leave a field without also tearing down its form.
107    if let platform_core::Event::KeyPressed {
108        key: platform_core::Key::Named(platform_core::NamedKey::Escape),
109        ..
110    } = event
111        && focus::current().is_none()
112        && dismiss::dismiss_top()
113    {
114        return EventResult::Handled;
115    }
116    ui_tree::dispatch_overlays(event)
117}