Skip to main content

eui_core/
layout.rs

1//! Round 2 (docs/round-2-contract.md §7): the shared layout NUMBERS
2//! (`catalog/layout.json`, generated as `LAYOUT_CONSTANT_NAMES`/`VALUES`):
3//! one place for the core and every painter.
4
5use crate::generated::catalog as g;
6
7/// A layout constant by name (`windowThreshold`, `mediaAspectRatio`, …).
8pub fn layout_constant(name: &str) -> Option<f64> {
9    let i = g::LAYOUT_CONSTANT_NAMES.iter().position(|n| *n == name)?;
10    g::LAYOUT_CONSTANT_VALUES.get(i)?.parse().ok()
11}
12
13/// Items past which List and Table window.
14pub const WINDOW_THRESHOLD: f64 = 50.0;
15/// Items rendered beyond each viewport edge.
16pub const WINDOW_OVERSCAN: f64 = 5.0;
17/// Percentage points per arrow key on a Resizable handle.
18pub const RESIZE_STEP: f64 = 10.0;
19/// A panel's min (percent) when unset.
20pub const PANEL_MIN: f64 = 10.0;
21/// A Resizable handle's hit area across its hairline (px).
22pub const RESIZE_HANDLE_HIT: f64 = 8.0;
23/// The max-content width of a text field (px).
24pub const FIELD_INTRINSIC_WIDTH: f64 = 160.0;
25/// The max-content width of an Image/Video without a width (px).
26pub const MEDIA_INTRINSIC_WIDTH: f64 = 320.0;
27/// Width / height of an Image without `aspectRatio` or a height; Video's default.
28pub const MEDIA_ASPECT_RATIO: f64 = 1.7777778;
29/// One TreeGuides gutter column (px).
30pub const TREE_GUIDE_COLUMN: f64 = 14.0;
31/// The radius of a TreeGuides elbow's corner (px).
32pub const TREE_GUIDE_RADIUS: f64 = 3.0;
33/// How far a TreeGuides vertical overshoots its row's TOP to bridge a
34/// Section divider (px; paint only, never layout).
35pub const TREE_GUIDE_BRIDGE: f64 = 1.0;
36/// EXP-1259: how long a `loading` Button waits before it shows its pending
37/// state (ms).
38pub const PENDING_DELAY_MS: f64 = 150.0;
39/// The Skeleton's ONE opacity pulse (ms, low → high → low, ease-in-out).
40pub const SKELETON_PULSE_MS: f64 = 1600.0;
41pub const SKELETON_OPACITY_LOW: f64 = 0.45;
42pub const SKELETON_OPACITY_HIGH: f64 = 0.9;
43/// The Skeleton's static opacity under reduce motion.
44pub const SKELETON_REDUCED_OPACITY: f64 = 0.6;
45/// The bottom fade over a SearchList's rows while more sit below (px).
46pub const SEARCH_LIST_FADE: f32 = 24.0;
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn the_constants_are_layout_json() {
54        for (name, v) in [("windowThreshold", WINDOW_THRESHOLD), ("windowOverscan", WINDOW_OVERSCAN), ("resizeStep", RESIZE_STEP), ("panelMin", PANEL_MIN), ("resizeHandleHit", RESIZE_HANDLE_HIT), ("fieldIntrinsicWidth", FIELD_INTRINSIC_WIDTH), ("mediaIntrinsicWidth", MEDIA_INTRINSIC_WIDTH), ("mediaAspectRatio", MEDIA_ASPECT_RATIO), ("treeGuideColumn", TREE_GUIDE_COLUMN), ("treeGuideRadius", TREE_GUIDE_RADIUS), ("treeGuideBridge", TREE_GUIDE_BRIDGE), ("pendingDelayMs", PENDING_DELAY_MS), ("skeletonPulseMs", SKELETON_PULSE_MS), ("skeletonOpacityLow", SKELETON_OPACITY_LOW), ("skeletonOpacityHigh", SKELETON_OPACITY_HIGH), ("skeletonReducedOpacity", SKELETON_REDUCED_OPACITY), ("searchListFade", SEARCH_LIST_FADE as f64)] {
55            assert_eq!(layout_constant(name), Some(v), "{name}");
56        }
57        assert_eq!(g::LAYOUT_CONSTANT_NAMES.len(), 17);
58        let json: serde_json::Value = serde_json::from_str(g::LAYOUT_JSON).unwrap();
59        assert_eq!(json["windowThreshold"], 50);
60    }
61}