1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119open ReactNative
open Style
@react.component
let make = (
~children: React.element,
~renderContent: (_ => unit) => React.element,
~maxHeight=200.,
~maxWidth=200.,
~adjustment=2.,
~containerStyle=?,
~backgroundColor=?,
~disabled=false,
~keyboardShouldPersistTaps=false,
) => {
let {
component,
borderWidth,
borderRadius,
boxBorderColor,
shadowColor,
shadowIntensity,
sheetContentPadding,
} = ThemebasedStyle.useThemeBasedStyle()
let shadowStyle = ShadowHook.useGetShadowStyle(~shadowIntensity, ~shadowColor, ())
let (viewPortContants, _) = React.useContext(ViewportContext.viewPortContext)
let maxHeight = min(viewPortContants.screenHeight -. sheetContentPadding *. 2., maxHeight)
let maxWidth = min(
viewPortContants.screenWidth -. sheetContentPadding *. 2. -. adjustment *. 2.,
maxWidth,
)
let renderedElement = React.useRef(Nullable.null)
let (tooltipPosition, setTooltipPosition) = React.useState(_ => None)
let (isVisible, setIsVisible) = React.useState(_ => false)
let toggleVisibility = () => {
setIsVisible(val => !val)
}
let calculateTooltipPosition = _ => {
setTooltipPosition(_ => None)
toggleVisibility()
switch renderedElement.current->Nullable.toOption {
| Some(element) =>
element->View.measure((~x as _, ~y as _, ~width as _, ~height, ~pageX, ~pageY) => {
let x: TooltipTypes.positionX = if viewPortContants.screenWidth -. pageX < maxWidth {
Right(sheetContentPadding -. adjustment)
} else {
Left(pageX)
}
let y: TooltipTypes.positionY = if viewPortContants.screenHeight -. pageY < maxHeight {
Bottom(viewPortContants.screenHeight -. pageY)
} else {
Top(pageY +. height)
}
setTooltipPosition(_ => Some(({x, y}: TooltipTypes.tooltipPosition)))
})
| None => ()
}
}
let onPress = _ => {
!keyboardShouldPersistTaps && Keyboard.isVisible()
? Keyboard.dismiss()
: calculateTooltipPosition()
}
let getPositionStyle = (position: option<TooltipTypes.tooltipPosition>) => {
switch position {
| None => empty
| Some(pos) => {
let xStyle = switch pos.x {
| Left(x) => s({left: x->dp})
| Right(x) => s({right: x->dp})
}
let yStyle = switch pos.y {
| Top(y) => s({top: y->dp})
| Bottom(y) => s({bottom: y->dp})
}
StyleSheet.flatten([xStyle, yStyle])
}
}
}
let tooltipBaseStyle = {
let baseStyle = s({
position: #absolute,
paddingHorizontal: 20.->dp,
paddingVertical: 10.->dp,
maxWidth: maxWidth->dp,
maxHeight: maxHeight->dp,
backgroundColor: backgroundColor->Option.getOr(component.background),
borderRadius,
borderWidth,
})
StyleSheet.flatten([baseStyle, boxBorderColor, shadowStyle, getPositionStyle(tooltipPosition)])
}
let tooltipStyle = switch containerStyle {
| Some(customStyle) => [tooltipBaseStyle, customStyle]->StyleSheet.flatten
| None => [tooltipBaseStyle]->StyleSheet.flatten
}
<View ref={Ref.value(renderedElement)} onLayout={_ => ()}>
<CustomPressable onPress disabled> children </CustomPressable>
<UIUtils.RenderIf condition={isVisible && tooltipPosition->Option.isSome}>
<Portal>
<CustomPressable onPress={_ => toggleVisibility()} style={s({flex: 1.})}>
<View style={tooltipStyle}> {renderContent(toggleVisibility)} </View>
</CustomPressable>
</Portal>
</UIUtils.RenderIf>
</View>
}