Skip to main content

cranpose_ui/
lib.rs

1//! High level UI primitives built on top of the Compose core runtime.
2
3use cranpose_core::{location_key, MemoryApplier};
4pub use cranpose_core::{Composition, Key};
5pub use cranpose_macros::composable;
6
7mod cursor_animation;
8mod debug;
9mod draw;
10pub mod fling_animation;
11mod focus_dispatch;
12mod key_event;
13pub mod layout;
14mod modifier;
15mod modifier_nodes;
16mod pointer_dispatch;
17mod primitives;
18mod render_state;
19mod renderer;
20pub mod scroll;
21mod subcompose_layout;
22pub mod text;
23pub mod text_field_focus;
24mod text_field_handler;
25mod text_field_input;
26mod text_field_modifier_node;
27pub mod text_layout_result;
28mod text_modifier_node;
29pub mod widgets;
30mod word_boundaries;
31
32// Export for cursor blink animation - AppShell checks this to continuously redraw
33pub use text_field_focus::has_focused_field;
34// Export cursor blink timing for WaitUntil scheduling
35pub use cursor_animation::{
36    is_cursor_visible, next_cursor_blink_time, reset_cursor_blink, start_cursor_blink,
37    stop_cursor_blink, tick_cursor_blink,
38};
39
40pub use cranpose_ui_graphics::{BlurredEdgeTreatment, ColorFilter, Dp, ImageBitmap};
41pub use cranpose_ui_layout::IntrinsicSize;
42pub use draw::{execute_draw_commands, DrawCacheBuilder, DrawCommand};
43pub use focus_dispatch::{
44    active_focus_target, clear_focus_invalidations, has_pending_focus_invalidations,
45    process_focus_invalidations, schedule_focus_invalidation, set_active_focus_target,
46};
47// Re-export FocusManager from cranpose-foundation to avoid duplication
48pub use cranpose_foundation::nodes::input::focus::FocusManager;
49pub use layout::{
50    core::{
51        Alignment, Arrangement, HorizontalAlignment, LinearArrangement, Measurable, Placeable,
52        VerticalAlignment,
53    },
54    measure_layout, tree_needs_layout, LayoutBox, LayoutEngine, LayoutMeasurements, LayoutNodeData,
55    LayoutNodeKind, LayoutTree, SemanticsAction, SemanticsCallback, SemanticsNode, SemanticsRole,
56    SemanticsTree,
57};
58pub use modifier::{
59    collect_modifier_slices, collect_slices_from_modifier, BlendMode, Brush, Color,
60    CompositingStrategy, CornerRadii, DpOffset, EdgeInsets, GraphicsLayer, LayerShape, Modifier,
61    ModifierNodeSlices, Point, PointerEvent, PointerEventKind, PointerInputScope, Rect,
62    RenderEffect, ResolvedBackground, ResolvedModifiers, RoundedCornerShape, RuntimeShader, Shadow,
63    ShadowScope, Size, TransformOrigin,
64};
65pub use modifier_nodes::{
66    AlphaElement, AlphaNode, BackgroundElement, BackgroundNode, ClickableElement, ClickableNode,
67    CornerShapeElement, CornerShapeNode, FillDirection, FillElement, FillNode, OffsetElement,
68    OffsetNode, PaddingElement, PaddingNode, SizeElement, SizeNode,
69};
70pub use pointer_dispatch::{
71    clear_pointer_repasses, has_pending_pointer_repasses, process_pointer_repasses,
72    schedule_pointer_repass,
73};
74pub use primitives::{
75    BasicTextField, BasicTextFieldOptions, BitmapPainter, Box, BoxScope, BoxSpec,
76    BoxWithConstraints, BoxWithConstraintsScope, BoxWithConstraintsScopeImpl, Button, Canvas,
77    Column, ColumnSpec, ContentScale, ForEach, Image, Layout, LayoutNode, Painter, Row, RowSpec,
78    Spacer, SubcomposeLayout, Text, DEFAULT_ALPHA,
79};
80// Lazy list exports - single source from cranpose-foundation
81pub use cranpose_foundation::lazy::{LazyListItemInfo, LazyListLayoutInfo, LazyListState};
82pub use key_event::{KeyCode, KeyEvent, KeyEventType, Modifiers};
83pub use render_state::{
84    current_density, has_pending_draw_repasses, has_pending_layout_repasses,
85    peek_focus_invalidation, peek_layout_invalidation, peek_pointer_invalidation,
86    peek_render_invalidation, request_focus_invalidation, request_layout_invalidation,
87    request_pointer_invalidation, request_render_invalidation, schedule_draw_repass,
88    schedule_layout_repass, set_density, take_draw_repass_nodes, take_focus_invalidation,
89    take_layout_invalidation, take_layout_repass_nodes, take_pointer_invalidation,
90    take_render_invalidation,
91};
92pub use renderer::{HeadlessRenderer, PaintLayer, RecordedRenderScene, RenderOp};
93pub use scroll::{ScrollElement, ScrollNode, ScrollState};
94// Test utilities for fling velocity verification (only with test-helpers feature)
95#[cfg(feature = "test-helpers")]
96pub use modifier::{last_fling_velocity, reset_last_fling_velocity};
97pub use subcompose_layout::{
98    Constraints, MeasureResult, Placement, SubcomposeLayoutNode, SubcomposeLayoutScope,
99    SubcomposeMeasureScope, SubcomposeMeasureScopeImpl,
100};
101pub use text::{
102    get_cursor_x_for_offset, get_offset_for_position, layout_text, measure_text, set_text_measurer,
103    TextMeasurer, TextMetrics, TextStyle,
104};
105pub use text_field_modifier_node::{TextFieldElement, TextFieldModifierNode};
106pub use text_modifier_node::{TextModifierElement, TextModifierNode};
107pub use widgets::lazy_list::{LazyColumn, LazyColumnSpec, LazyRow, LazyRowSpec};
108
109// Debug utilities
110pub use debug::{
111    format_layout_tree, format_modifier_chain, format_render_scene, install_modifier_chain_trace,
112    log_layout_tree, log_modifier_chain, log_render_scene, log_screen_summary,
113    ModifierChainTraceGuard,
114};
115
116/// Convenience alias used in examples and tests.
117pub type TestComposition = Composition<MemoryApplier>;
118
119/// Build a composition with a simple in-memory applier and run the provided closure once.
120pub fn run_test_composition(build: impl FnMut()) -> TestComposition {
121    let mut composition = Composition::new(MemoryApplier::new());
122    composition
123        .render(location_key(file!(), line!(), column!()), build)
124        .expect("initial render succeeds");
125    composition
126}
127
128pub use cranpose_core::MutableState as SnapshotState;
129
130#[cfg(test)]
131#[path = "tests/anchor_async_tests.rs"]
132mod anchor_async_tests;
133
134#[cfg(test)]
135#[path = "tests/async_runtime_full_layout_test.rs"]
136mod async_runtime_full_layout_test;
137
138#[cfg(test)]
139#[path = "tests/cursor_position_tests.rs"]
140mod cursor_position_tests;
141
142#[cfg(test)]
143#[path = "tests/tab_switching_tests.rs"]
144mod tab_switching_tests;
145
146#[cfg(test)]
147#[path = "tests/lazy_list_viewport_tests.rs"]
148mod lazy_list_viewport_tests;
149
150#[cfg(test)]
151#[path = "tests/lazy_list_recompose_tests.rs"]
152mod lazy_list_recompose_tests;