gpui-component 0.7.3

GPUI Component: the styled component library of GPUI Kit, with 60+ desktop UI components for GPUI.
Documentation
use gpui::{Bounds, HighlightStyle, point, px, rgb, size};

use super::{
    DiffSide,
    document::fixture,
    selection::{clip_highlight, line_distance, merge_highlights, word_range},
};

#[test]
fn source_selection_maps_expanded_tabs_and_multibyte_text_without_losing_line_endings() {
    let source = "\tα\tx\r\nnext\n";
    let document = fixture::document(None, Some(("text", source)));
    let first = &document.lines(DiffSide::Modified)[0];
    assert_eq!(first.display().as_ref(), "    α   x");
    // Every painted space generated by a tab maps back to that single byte.
    for ix in 0..4 {
        assert_eq!(first.source_offset(ix), 0);
    }
    for ix in 6..9 {
        assert_eq!(first.source_offset(ix), 3);
    }
    assert_eq!(first.display_range(1..3), 4..6);
    assert_eq!(first.display_range(3..4), 6..9);
    assert_eq!(
        first.source_offset(first.display().len()),
        first.text().len()
    );
    let next = &document.lines(DiffSide::Modified)[1];
    let anchor = first.source().start + first.source_offset(4);
    let cursor = next.source().start + next.source_offset(2);
    assert_eq!(
        &document.source(DiffSide::Modified)[anchor..cursor],
        "α\tx\r\nne"
    );
}

#[test]
fn overlapping_inline_and_selection_highlights_preserve_syntax_and_precedence() {
    let syntax_color = rgb(0x336699).into();
    let inline_color = rgb(0x884422).into();
    let selection_color = rgb(0x225588).into();
    let highlights = merge_highlights(
        8,
        vec![
            (
                0..8,
                HighlightStyle {
                    color: Some(syntax_color),
                    ..Default::default()
                },
            ),
            (
                2..7,
                HighlightStyle {
                    background_color: Some(inline_color),
                    ..Default::default()
                },
            ),
            (
                4..6,
                HighlightStyle {
                    background_color: Some(selection_color),
                    ..Default::default()
                },
            ),
        ],
    );
    assert_eq!(
        highlights
            .iter()
            .map(|(range, _)| range.clone())
            .collect::<Vec<_>>(),
        vec![0..2, 2..4, 4..6, 6..7, 7..8]
    );
    assert!(
        highlights
            .iter()
            .all(|(_, style)| style.color == Some(syntax_color))
    );
    assert_eq!(
        highlights
            .iter()
            .map(|(_, style)| style.background_color)
            .collect::<Vec<_>>(),
        vec![
            None,
            Some(inline_color),
            Some(selection_color),
            Some(inline_color),
            None
        ]
    );
    assert!(merge_highlights(0, vec![]).is_empty());
}

#[test]
fn multi_click_line_top_prefers_current_line_over_previous_bottom() {
    let previous = Bounds::new(point(px(20.), px(30.)), size(px(100.), px(20.)));
    let current = Bounds::new(point(px(20.), px(50.)), size(px(100.), px(20.)));
    let endpoint = point(px(40.), px(50.));
    assert!(line_distance(endpoint, current) < line_distance(endpoint, previous));
    // Horizontal dragging beyond the text keeps the same source line.
    let endpoint = point(px(400.), px(50.));
    assert!(line_distance(endpoint, current) < line_distance(endpoint, previous));
}

#[test]
fn highlight_sweep_restores_lower_precedence_after_edges_and_clamps_invalid_ranges() {
    let layers = vec![
        (
            0..12,
            HighlightStyle {
                fade_out: Some(0.2),
                ..Default::default()
            },
        ),
        (
            4..8,
            HighlightStyle {
                fade_out: Some(0.7),
                ..Default::default()
            },
        ),
        (
            2..6,
            HighlightStyle {
                fade_out: Some(0.9),
                ..Default::default()
            },
        ),
        (
            7..7,
            HighlightStyle {
                fade_out: Some(1.),
                ..Default::default()
            },
        ),
        (
            11..15,
            HighlightStyle {
                fade_out: Some(1.),
                ..Default::default()
            },
        ),
    ];
    let merged = merge_highlights(10, layers);
    assert_eq!(
        merged
            .iter()
            .map(|(range, style)| (range.clone(), style.fade_out))
            .collect::<Vec<_>>(),
        vec![
            (0..2, Some(0.2)),
            (2..4, Some(0.9)),
            (4..6, Some(0.9)),
            (6..8, Some(0.7)),
            (8..10, Some(0.2)),
        ]
    );
}

#[test]
fn highlight_chunks_clip_and_rebase_without_duplicating_adjacent_boundaries() {
    assert_eq!(clip_highlight(4..12, &(8..16)), Some(0..4));
    assert_eq!(clip_highlight(12..20, &(8..16)), Some(4..8));
    assert_eq!(clip_highlight(8..16, &(8..16)), Some(0..8));
    assert_eq!(clip_highlight(4..8, &(8..16)), None);
    assert_eq!(clip_highlight(16..20, &(8..16)), None);
}

#[test]
fn native_word_selection_crosses_render_chunks_and_respects_unicode_and_flank_bounds() {
    let token = "a".repeat(1024);
    assert_eq!(word_range(&token, 512), Some(384..641));
    assert_eq!(word_range("  foo_bar  !", 4), Some(2..9));
    assert_eq!(word_range("  foo_bar  !", 9), Some(9..11));
    assert_eq!(word_range("  foo_bar  !", 11), Some(11..12));
    let text = "éяa\u{0301}界";
    assert_eq!(word_range(text, 2), Some(0..7));
    assert_eq!(word_range(text, 7), Some(7..10));
    assert_eq!(word_range(text, text.len()), None);
}