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