1use freya_core::prelude::*;
2use freya_router::prelude::{
3 NavigationTarget,
4 Navigator,
5};
6
7use crate::{
8 get_theme,
9 theming::component_themes::LinkThemePartial,
10 tooltip::{
11 Tooltip,
12 TooltipContainer,
13 },
14};
15
16#[derive(Clone, PartialEq)]
18pub enum LinkTooltip {
19 None,
21 Default,
26 Custom(String),
28}
29
30#[derive(PartialEq)]
31pub struct Link {
32 pub(crate) theme: Option<LinkThemePartial>,
34 to: NavigationTarget,
36 children: Vec<Element>,
38 tooltip: LinkTooltip,
40}
41
42impl ChildrenExt for Link {
43 fn get_children(&mut self) -> &mut Vec<Element> {
44 &mut self.children
45 }
46}
47
48impl Link {
49 pub fn new(to: impl Into<NavigationTarget>) -> Self {
50 Self {
51 to: to.into(),
52 children: Vec::new(),
53 tooltip: LinkTooltip::Default,
54 theme: None,
55 }
56 }
57
58 pub fn tooltip(mut self, tooltip: impl Into<LinkTooltip>) -> Self {
59 self.tooltip = tooltip.into();
60 self
61 }
62}
63
64impl Render for Link {
65 fn render(&self) -> impl IntoElement {
66 let theme = get_theme!(&self.theme, link);
67 let mut is_hovering = use_state(|| false);
68
69 let url = if let NavigationTarget::External(ref url) = self.to {
70 Some(url.clone())
71 } else {
72 None
73 };
74
75 let on_pointer_enter = move |_| {
76 is_hovering.set(true);
77 };
78
79 let on_pointer_leave = move |_| {
80 is_hovering.set(false);
81 };
82
83 let on_press = {
84 let to = self.to.clone();
85 let url = url.clone();
86 move |_| {
87 if let Some(url) = &url {
90 let _ = open::that(url);
91 } else {
92 Navigator::get().push(to.clone());
93 }
94 }
95 };
96
97 let color = if *is_hovering.read() {
98 Some(theme.color)
99 } else {
100 None
101 };
102
103 let tooltip_text = match &self.tooltip {
104 LinkTooltip::Default => url.clone(),
105 LinkTooltip::None => None,
106 LinkTooltip::Custom(str) => Some(str.clone()),
107 };
108
109 let link = rect()
110 .on_press(on_press)
111 .on_pointer_enter(on_pointer_enter)
112 .on_pointer_leave(on_pointer_leave)
113 .map(color, |rect, color| rect.color(color))
114 .children(self.children.clone());
115
116 if let Some(tooltip_text) = tooltip_text {
117 TooltipContainer::new(Tooltip::new(tooltip_text))
118 .child(link)
119 .into_element()
120 } else {
121 link.into()
122 }
123 }
124}