1use gpui::{AnyElement, App, ElementId, SharedString, Window, div, prelude::*, px};
4use theme::{TextStyle, Theme, Typeset};
5
6pub(crate) const CODE_PADDING_X: f32 = 12.0;
8pub(crate) const CODE_PADDING_Y: f32 = 10.0;
9
10pub fn fence_panel(theme: &Theme) -> gpui::Div {
12 div()
13 .rounded(px(Theme::panel_radius()))
14 .bg(theme.ink(0.035))
15 .border_1()
16 .border_color(theme.border)
17 .overflow_hidden()
18 .relative()
19}
20
21pub const NOTE_SELECTOR: &str = "fence-note";
23
24pub fn fence_note(note: SharedString, theme: &Theme) -> AnyElement {
27 div()
28 .debug_selector(|| NOTE_SELECTOR.into())
29 .flex()
30 .flex_col()
31 .px(px(CODE_PADDING_X))
32 .py(px(CODE_PADDING_Y))
33 .border_t_1()
34 .border_color(theme.border)
35 .text_color(theme.danger)
36 .font_family(theme.font_mono.clone())
37 .text_style(TextStyle::Subheadline)
38 .children(
39 note.lines()
40 .map(|line| SharedString::from(line.to_string()))
41 .collect::<Vec<_>>(),
42 )
43 .into_any_element()
44}
45
46pub fn fence_band(theme: &Theme) -> gpui::Div {
49 div()
50 .relative()
51 .flex()
52 .flex_row()
53 .items_center()
54 .px(px(CODE_PADDING_X))
55 .py(px(5.0))
56 .border_b_1()
57 .border_color(theme.border)
58 .bg(theme.ink(0.02))
59 .text_style(TextStyle::Subheadline)
60}
61
62pub(crate) fn copy_button(
69 code: &str,
70 ix: usize,
71 theme: &Theme,
72 window: &mut Window,
73 cx: &mut App,
74) -> AnyElement {
75 let copied = window.use_keyed_state(ElementId::named_usize("md-copied", ix), cx, |_, _| false);
76 let showing = *copied.read(cx);
77 let text: SharedString = code.to_string().into();
78
79 div()
80 .id(ElementId::named_usize("md-copy", ix))
81 .absolute()
82 .top(px(3.0))
83 .right(px(5.0))
84 .h(px(20.0))
85 .px(px(6.0))
86 .rounded(px(5.0))
87 .flex()
88 .items_center()
89 .cursor_pointer()
90 .text_style(TextStyle::Caption)
91 .text_color(theme.text_muted)
92 .hover(|el| el.bg(theme.element_hover))
93 .child(if showing { "Copied" } else { "Copy" })
94 .on_click({
95 let copied = copied.clone();
96 move |_, _, cx| {
97 cx.write_to_clipboard(gpui::ClipboardItem::new_string(text.to_string()));
98 copied.update(cx, |state, cx| {
99 *state = true;
100 cx.notify();
101 });
102 }
103 })
104 .on_hover(move |hovering, _, cx| {
105 if !*hovering && *copied.read(cx) {
106 copied.update(cx, |state, cx| {
107 *state = false;
108 cx.notify();
109 });
110 }
111 })
112 .into_any_element()
113}