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