๐Ÿ“ฆ manideepk90 / react-native-hyperswitch-sdk

๐Ÿ“„ Tooltip.res ยท 119 lines
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>
}