@neko-os/ui 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/dist/DynamicStyleTag.js +5 -0
  2. package/dist/DynamicStyleTag.native.js +1 -0
  3. package/dist/NekoUI.js +1 -1
  4. package/dist/abstractions/ActivityIndicator.native.js +1 -1
  5. package/dist/abstractions/ActivityIndicator.web.js +1 -0
  6. package/dist/abstractions/AnimatedView.web.js +1 -0
  7. package/dist/abstractions/BlurView.web.js +1 -0
  8. package/dist/abstractions/FlatList.js +1 -0
  9. package/dist/abstractions/FlatList.native.js +1 -0
  10. package/dist/abstractions/FlatList.web.js +1 -0
  11. package/dist/abstractions/ScrollView.web.js +1 -0
  12. package/dist/abstractions/StaticList.js +1 -0
  13. package/dist/abstractions/helpers/storage.js +1 -0
  14. package/dist/abstractions/helpers/storage.native.js +1 -0
  15. package/dist/abstractions/helpers/useSafeAreaInsets.js +1 -0
  16. package/dist/abstractions/helpers/useSafeAreaInsets.native.js +1 -0
  17. package/dist/components/actions/Button.js +1 -1
  18. package/dist/components/actions/Dropdown.js +1 -1
  19. package/dist/components/actions/FloatingButton.js +1 -0
  20. package/dist/components/actions/index.js +1 -1
  21. package/dist/components/actions/menu/VerticalMenu.js +1 -1
  22. package/dist/components/calendar/_helpers/calendarDays.js +1 -1
  23. package/dist/components/feedback/alerter.js +1 -1
  24. package/dist/components/feedback/confirmer.js +1 -1
  25. package/dist/components/helpers/ConditionalLazyRender.js +1 -0
  26. package/dist/components/helpers/LazyAction.js +1 -0
  27. package/dist/components/helpers/LazyRender.js +1 -1
  28. package/dist/components/helpers/LazyRender.native.js +1 -1
  29. package/dist/components/helpers/index.js +1 -1
  30. package/dist/components/index.js +1 -1
  31. package/dist/components/inputs/DateInput.js +1 -1
  32. package/dist/components/inputs/InputWrapper.js +1 -1
  33. package/dist/components/inputs/LinkInput.js +1 -1
  34. package/dist/components/inputs/NumberInput.js +1 -0
  35. package/dist/components/inputs/Picker.js +1 -1
  36. package/dist/components/inputs/Radio.js +1 -1
  37. package/dist/components/inputs/RateInput.js +1 -0
  38. package/dist/components/inputs/SegmentedPicker.js +1 -0
  39. package/dist/components/inputs/Select.js +1 -0
  40. package/dist/components/inputs/datePicker/DayPicker.js +1 -1
  41. package/dist/components/inputs/datePicker/MonthPicker.js +1 -1
  42. package/dist/components/inputs/datePicker/QuarterPicker.js +1 -1
  43. package/dist/components/inputs/datePicker/WeekPicker.js +1 -1
  44. package/dist/components/inputs/datePicker/YearPicker.js +1 -1
  45. package/dist/components/inputs/index.js +1 -1
  46. package/dist/components/layout/Layout.js +1 -1
  47. package/dist/components/list/FlatList.js +1 -0
  48. package/dist/components/list/index.js +1 -1
  49. package/dist/components/presentation/Rate.js +1 -0
  50. package/dist/components/presentation/RateTag.js +1 -0
  51. package/dist/components/presentation/Result.js +1 -1
  52. package/dist/components/presentation/Tooltip.js +1 -1
  53. package/dist/components/presentation/index.js +1 -1
  54. package/dist/components/state/LoadingView.js +1 -1
  55. package/dist/components/structure/Accordion.js +1 -1
  56. package/dist/components/structure/Row.js +1 -1
  57. package/dist/components/structure/Segment.js +1 -0
  58. package/dist/components/structure/View.js +1 -1
  59. package/dist/components/structure/bottomDrawer/native/BottomDrawer.js +1 -1
  60. package/dist/components/structure/bottomDrawer/native/utils.js +1 -1
  61. package/dist/components/structure/bottomDrawer/web/BottomDrawer.js +1 -1
  62. package/dist/components/structure/index.js +1 -1
  63. package/dist/components/structure/overlay/OverlayHandler.js +1 -1
  64. package/dist/components/structure/popover/Popover.js +1 -1
  65. package/dist/components/structure/popover/Popover.native.js +1 -1
  66. package/dist/components/structure/popover/Popover_BU.js +1 -0
  67. package/dist/components/tabs/ActiveTabContent.js +1 -0
  68. package/dist/components/tabs/TabsHandler.js +1 -0
  69. package/dist/components/tabs/TabsMenu.js +1 -0
  70. package/dist/components/tabs/index.js +1 -0
  71. package/dist/components/theme/ThemePicker.js +1 -0
  72. package/dist/components/theme/ThemePickerDrawer.js +1 -0
  73. package/dist/components/theme/ThemeStatusBar.js +1 -0
  74. package/dist/components/theme/ThemeStatusBar.native.js +1 -0
  75. package/dist/components/theme/ThemeThumb.js +1 -0
  76. package/dist/components/theme/index.js +1 -0
  77. package/dist/helpers/index.js +1 -1
  78. package/dist/helpers/storage.js +1 -0
  79. package/dist/helpers/string.js +1 -1
  80. package/dist/i18n/I18n.js +1 -0
  81. package/dist/i18n/I18nProvider.js +1 -0
  82. package/dist/i18n/index.js +1 -0
  83. package/dist/index.css +4 -0
  84. package/dist/index.js +1 -1
  85. package/dist/modifiers/animations/fadeEffect.web.js +1 -0
  86. package/dist/modifiers/animations/scrollEffect.web.js +1 -0
  87. package/dist/modifiers/animations/slideEffect.web.js +1 -0
  88. package/dist/modifiers/fullColor.js +1 -1
  89. package/dist/modifiers/overflow.js +1 -1
  90. package/dist/modifiers/position.js +1 -1
  91. package/dist/theme/ThemeHandler.js +1 -1
  92. package/dist/theme/default/base.js +1 -1
  93. package/dist/theme/default/blackTheme.js +1 -1
  94. package/dist/theme/default/cyberpunkTheme.js +1 -1
  95. package/dist/theme/default/darkTheme.js +1 -1
  96. package/dist/theme/default/deepWoodsTheme.js +1 -1
  97. package/dist/theme/default/forestTheme.js +1 -1
  98. package/dist/theme/default/hackerTheme.js +1 -1
  99. package/dist/theme/default/lightTheme.js +1 -1
  100. package/dist/theme/default/midnightTheme.js +1 -1
  101. package/dist/theme/default/msdosTheme.js +1 -1
  102. package/dist/theme/default/oceanTheme.js +1 -1
  103. package/dist/theme/default/paperTheme.js +1 -0
  104. package/dist/theme/default/pastelTheme.js +1 -1
  105. package/dist/theme/default/sunsetTheme.js +1 -1
  106. package/dist/theme/default/themes.js +1 -1
  107. package/dist/theme/format/formatTheme.js +1 -1
  108. package/dist/theme/helpers/contrastColor.js +1 -1
  109. package/package.json +1 -1
  110. package/src/DynamicStyleTag.js +21 -0
  111. package/src/DynamicStyleTag.native.js +3 -0
  112. package/src/NekoUI.js +21 -4
  113. package/src/abstractions/ActivityIndicator.native.js +3 -4
  114. package/src/abstractions/ActivityIndicator.web.js +43 -0
  115. package/src/abstractions/AnimatedView.web.js +3 -0
  116. package/src/abstractions/BlurView.web.js +39 -0
  117. package/src/abstractions/FlatList.js +3 -0
  118. package/src/abstractions/FlatList.native.js +36 -0
  119. package/src/abstractions/FlatList.web.js +3 -0
  120. package/src/abstractions/ScrollView.web.js +3 -0
  121. package/src/abstractions/StaticList.js +51 -0
  122. package/src/abstractions/Text.web.js +15 -0
  123. package/src/abstractions/helpers/storage.js +32 -0
  124. package/src/abstractions/helpers/storage.native.js +34 -0
  125. package/src/abstractions/helpers/useSafeAreaInsets.js +3 -0
  126. package/src/abstractions/helpers/useSafeAreaInsets.native.js +3 -0
  127. package/src/components/actions/Button.js +1 -0
  128. package/src/components/actions/Dropdown.js +24 -5
  129. package/src/components/actions/FloatingButton.js +87 -0
  130. package/src/components/actions/index.js +1 -0
  131. package/src/components/actions/menu/VerticalMenu.js +30 -5
  132. package/src/components/calendar/_helpers/calendarDays.js +2 -0
  133. package/src/components/feedback/alerter.js +1 -1
  134. package/src/components/feedback/confirmer.js +2 -2
  135. package/src/components/helpers/ConditionalLazyRender.js +6 -0
  136. package/src/components/helpers/LazyAction.js +22 -0
  137. package/src/components/helpers/LazyRender.js +2 -2
  138. package/src/components/helpers/LazyRender.native.js +1 -1
  139. package/src/components/helpers/index.js +1 -0
  140. package/src/components/index.js +2 -0
  141. package/src/components/inputs/DateInput.js +11 -1
  142. package/src/components/inputs/InputWrapper.js +0 -1
  143. package/src/components/inputs/LinkInput.js +3 -3
  144. package/src/components/inputs/NumberInput.js +105 -0
  145. package/src/components/inputs/Picker.js +61 -9
  146. package/src/components/inputs/Radio.js +1 -1
  147. package/src/components/inputs/RateInput.js +62 -0
  148. package/src/components/inputs/SegmentedPicker.js +62 -0
  149. package/src/components/inputs/Select.js +189 -0
  150. package/src/components/inputs/datePicker/DayPicker.js +4 -5
  151. package/src/components/inputs/datePicker/MonthPicker.js +2 -2
  152. package/src/components/inputs/datePicker/QuarterPicker.js +2 -2
  153. package/src/components/inputs/datePicker/WeekPicker.js +2 -2
  154. package/src/components/inputs/datePicker/YearPicker.js +9 -6
  155. package/src/components/inputs/index.js +4 -0
  156. package/src/components/layout/Layout.js +1 -1
  157. package/src/components/list/FlatList.js +91 -0
  158. package/src/components/list/index.js +1 -0
  159. package/src/components/presentation/Rate.js +58 -0
  160. package/src/components/presentation/RateTag.js +35 -0
  161. package/src/components/presentation/Result.js +2 -2
  162. package/src/components/presentation/Tooltip.js +1 -0
  163. package/src/components/presentation/index.js +2 -0
  164. package/src/components/state/LoadingView.js +10 -1
  165. package/src/components/structure/Accordion.js +1 -1
  166. package/src/components/structure/Row.js +9 -1
  167. package/src/components/structure/Segment.js +51 -0
  168. package/src/components/structure/View.js +2 -0
  169. package/src/components/structure/bottomDrawer/native/BottomDrawer.js +19 -3
  170. package/src/components/structure/bottomDrawer/native/utils.js +29 -22
  171. package/src/components/structure/bottomDrawer/web/BottomDrawer.js +3 -1
  172. package/src/components/structure/index.js +1 -0
  173. package/src/components/structure/overlay/OverlayHandler.js +6 -1
  174. package/src/components/structure/popover/Popover.js +44 -21
  175. package/src/components/structure/popover/Popover.native.js +3 -2
  176. package/src/components/structure/popover/Popover_BU.js +157 -0
  177. package/src/components/tabs/ActiveTabContent.js +35 -0
  178. package/src/components/tabs/TabsHandler.js +16 -0
  179. package/src/components/tabs/TabsMenu.js +15 -0
  180. package/src/components/tabs/index.js +3 -0
  181. package/src/components/theme/ThemePicker.js +49 -0
  182. package/src/components/theme/ThemePickerDrawer.js +13 -0
  183. package/src/components/theme/ThemeStatusBar.js +3 -0
  184. package/src/components/theme/ThemeStatusBar.native.js +9 -0
  185. package/src/components/theme/ThemeThumb.js +98 -0
  186. package/src/components/theme/index.js +3 -0
  187. package/src/helpers/index.js +1 -0
  188. package/src/helpers/storage.js +54 -0
  189. package/src/helpers/string.js +18 -1
  190. package/src/i18n/I18n.js +97 -0
  191. package/src/i18n/I18nProvider.js +40 -0
  192. package/src/i18n/index.js +2 -0
  193. package/src/index.css +4 -0
  194. package/src/index.js +1 -0
  195. package/src/modifiers/animations/fadeEffect.web.js +3 -0
  196. package/src/modifiers/animations/scrollEffect.web.js +3 -0
  197. package/src/modifiers/animations/slideEffect.web.js +3 -0
  198. package/src/modifiers/fullColor.js +2 -2
  199. package/src/modifiers/overflow.js +6 -1
  200. package/src/modifiers/position.js +7 -0
  201. package/src/theme/ThemeHandler.js +18 -2
  202. package/src/theme/default/base.js +12 -8
  203. package/src/theme/default/blackTheme.js +4 -1
  204. package/src/theme/default/cyberpunkTheme.js +3 -1
  205. package/src/theme/default/darkTheme.js +3 -1
  206. package/src/theme/default/deepWoodsTheme.js +4 -2
  207. package/src/theme/default/forestTheme.js +3 -1
  208. package/src/theme/default/hackerTheme.js +3 -1
  209. package/src/theme/default/lightTheme.js +3 -1
  210. package/src/theme/default/midnightTheme.js +3 -1
  211. package/src/theme/default/msdosTheme.js +18 -4
  212. package/src/theme/default/oceanTheme.js +4 -2
  213. package/src/theme/default/paperTheme.js +35 -0
  214. package/src/theme/default/pastelTheme.js +3 -1
  215. package/src/theme/default/sunsetTheme.js +5 -3
  216. package/src/theme/default/themes.js +7 -10
  217. package/src/theme/format/formatTheme.js +9 -3
  218. package/src/theme/helpers/contrastColor.js +49 -11
  219. package/dist/abstractions/TouchableOpacity.web.js +0 -1
  220. package/src/abstractions/TouchableOpacity.web.js +0 -3
@@ -15,11 +15,14 @@ export function Popover({
15
15
  parentWidth,
16
16
  parentMinWidth,
17
17
  useBottomDrawer = {},
18
+ bottomDrawerProps = {},
19
+ watch,
20
+ disabled,
18
21
  ...props
19
22
  }) {
20
23
  const shouldUseDrawer = useResponsiveValue(useBottomDrawer)
21
24
  const ref = React.useRef(null)
22
- const { onOpen, onClose, onFastClose, stopDelayedClosing } = useRegisterOverlay({ unmountOnClose })
25
+ const { onOpen, onUpdate, onClose, onFastClose, stopDelayedClosing } = useRegisterOverlay({ unmountOnClose })
23
26
 
24
27
  const click = trigger === 'click'
25
28
  const hover = trigger === 'hover'
@@ -27,13 +30,24 @@ export function Popover({
27
30
 
28
31
  renderContent = renderContent || (() => content)
29
32
 
30
- const show = (e) => {
31
- if (e && e.stopPropagation) e.stopPropagation()
33
+ const buildContent = () => (
34
+ <PopoverContent
35
+ placement={placement}
36
+ width={parentWidth ? ref.current?.getBoundingClientRect()?.width : undefined}
37
+ minWidth={parentMinWidth ? ref.current?.getBoundingClientRect()?.width : undefined}
38
+ {...props}
39
+ onMouseEnter={hover ? stopDelayedClosing : undefined}
40
+ onMouseLeave={hover ? onClose : undefined}
41
+ >
42
+ {renderContent({ onClose: onFastClose })}
43
+ </PopoverContent>
44
+ )
45
+
46
+ const computeTriggerRect = () => {
32
47
  const rect = ref.current.getBoundingClientRect()
33
48
  const scrollX = window.scrollX || window.pageXOffset
34
49
  const scrollY = window.scrollY || window.pageYOffset
35
-
36
- const triggerRect = {
50
+ return {
37
51
  left: rect.left + scrollX,
38
52
  right: rect.right + scrollX,
39
53
  top: rect.top + scrollY,
@@ -41,20 +55,13 @@ export function Popover({
41
55
  width: rect.width,
42
56
  height: rect.height,
43
57
  }
58
+ }
44
59
 
60
+ const show = (e) => {
61
+ if (e && e.stopPropagation) e.stopPropagation()
62
+ const triggerRect = computeTriggerRect()
45
63
  onOpen({
46
- content: (
47
- <PopoverContent
48
- placement={placement}
49
- width={parentWidth ? rect.width : undefined}
50
- minWidth={parentMinWidth ? rect.width : undefined}
51
- {...props}
52
- onMouseEnter={hover ? stopDelayedClosing : undefined}
53
- onMouseLeave={hover ? onClose : undefined}
54
- >
55
- {renderContent({ onClose: onFastClose })}
56
- </PopoverContent>
57
- ),
64
+ content: buildContent(),
58
65
  triggerRect,
59
66
  placement,
60
67
  options: { dismissOnClickOutside: click || focus },
@@ -63,15 +70,31 @@ export function Popover({
63
70
 
64
71
  React.useEffect(() => () => onClose(), [])
65
72
 
73
+ React.useEffect(() => {
74
+ if (!ref.current || !watch) return
75
+ onUpdate({
76
+ content: buildContent(),
77
+ options: { dismissOnClickOutside: click || focus },
78
+ })
79
+ }, watch)
80
+
66
81
  if (shouldUseDrawer) {
67
- return <DrawerPopover content={content} renderContent={renderContent} children={children} {...props} />
82
+ return (
83
+ <DrawerPopover
84
+ content={content}
85
+ renderContent={renderContent}
86
+ children={children}
87
+ {...props}
88
+ {...bottomDrawerProps}
89
+ />
90
+ )
68
91
  }
69
92
 
70
93
  const child = React.Children.only(children)
71
94
  let childProps = { ref, onClick: show }
72
95
 
73
- if (hover) childProps = { ref, onMouseEnter: show, onMouseLeave: onClose }
74
- if (focus) childProps = { ref, onFocus: show }
96
+ if (hover) childProps = { ref, onMouseEnter: show, onMouseLeave: onClose, disabled }
97
+ if (focus) childProps = { ref, onFocus: show, disabled }
75
98
 
76
99
  return React.cloneElement(child, childProps)
77
100
  }
@@ -87,7 +110,7 @@ function DrawerPopover({ children, content, renderContent, snapPoints, ...props
87
110
  <>
88
111
  {React.cloneElement(child, childProps)}
89
112
 
90
- <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints}>
113
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...props}>
91
114
  {renderContent({ onClose })}
92
115
  </BottomDrawer>
93
116
  </>
@@ -13,6 +13,7 @@ export function Popover({
13
13
  placement = 'bottom',
14
14
  children,
15
15
  useBottomDrawer = {},
16
+ bottomDrawerProps = {},
16
17
  snapPoints,
17
18
  ...props
18
19
  }) {
@@ -59,7 +60,7 @@ export function Popover({
59
60
  <View ref={ref}>
60
61
  {children}
61
62
 
62
- <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints}>
63
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...bottomDrawerProps}>
63
64
  {renderContent({ onClose: onClose })}
64
65
  </BottomDrawer>
65
66
  </View>
@@ -72,7 +73,7 @@ export function Popover({
72
73
 
73
74
  {open && (
74
75
  <Modal transparent visible={open} animationType="fade" onRequestClose={onClose}>
75
- <View fullW flex fullH bg="bg_op50">
76
+ <View fullW flex fullH bg="backdrop_op50">
76
77
  <TouchableWithoutFeedback onPress={onClose}>
77
78
  <View style={{ flex: 1 }}>
78
79
  {triggerRect && (
@@ -0,0 +1,157 @@
1
+ import React from 'react'
2
+
3
+ import { BottomDrawer } from '../bottomDrawer'
4
+ import { PopoverContent } from './PopoverContent'
5
+ import { useRegisterOverlay } from '../overlay/OverlayHandler'
6
+ import { useResponsiveValue } from '../../../responsive'
7
+
8
+ export function Popover({
9
+ renderContent,
10
+ content,
11
+ trigger = 'hover',
12
+ placement = 'bottom',
13
+ unmountOnClose,
14
+ children,
15
+ parentWidth,
16
+ parentMinWidth,
17
+ useBottomDrawer = {},
18
+ bottomDrawerProps = {},
19
+ watch,
20
+ ...props
21
+ }) {
22
+ const shouldUseDrawer = useResponsiveValue(useBottomDrawer)
23
+ const ref = React.useRef(null)
24
+ const { onOpen, onUpdate, onClose, onFastClose, stopDelayedClosing } = useRegisterOverlay({ unmountOnClose })
25
+
26
+ const click = trigger === 'click'
27
+ const hover = trigger === 'hover'
28
+ const focus = trigger === 'focus'
29
+
30
+ renderContent = renderContent || (() => content)
31
+
32
+ const buildContent = () => (
33
+ <PopoverContent
34
+ placement={placement}
35
+ width={parentWidth ? ref.current?.getBoundingClientRect()?.width : undefined}
36
+ minWidth={parentMinWidth ? ref.current?.getBoundingClientRect()?.width : undefined}
37
+ {...props}
38
+ onMouseEnter={hover ? stopDelayedClosing : undefined}
39
+ onMouseLeave={hover ? onClose : undefined}
40
+ >
41
+ {renderContent({ onClose: onFastClose })}
42
+ </PopoverContent>
43
+ )
44
+
45
+ const computeTriggerRect = () => {
46
+ const rect = ref.current.getBoundingClientRect()
47
+ const scrollX = window.scrollX || window.pageXOffset
48
+ const scrollY = window.scrollY || window.pageYOffset
49
+ return {
50
+ left: rect.left + scrollX,
51
+ right: rect.right + scrollX,
52
+ top: rect.top + scrollY,
53
+ bottom: rect.bottom + scrollY,
54
+ width: rect.width,
55
+ height: rect.height,
56
+ }
57
+ }
58
+
59
+ const show = (e) => {
60
+ if (e && e.stopPropagation) e.stopPropagation()
61
+ const triggerRect = computeTriggerRect()
62
+ onOpen({
63
+ content: buildContent(),
64
+ triggerRect,
65
+ placement,
66
+ options: { dismissOnClickOutside: click || focus },
67
+ })
68
+ }
69
+
70
+ React.useEffect(() => () => onClose(), [])
71
+
72
+ // 🔑 re-render do portal quando `watch` (ex.: search) mudar
73
+ React.useEffect(() => {
74
+ if (!ref.current) return
75
+ const triggerRect = computeTriggerRect()
76
+ onUpdate({
77
+ content: buildContent(),
78
+ triggerRect,
79
+ placement,
80
+ options: { dismissOnClickOutside: click || focus },
81
+ })
82
+ }, [watch, renderContent])
83
+
84
+ // const show = (e) => {
85
+ // if (e && e.stopPropagation) e.stopPropagation()
86
+ // const rect = ref.current.getBoundingClientRect()
87
+ // const scrollX = window.scrollX || window.pageXOffset
88
+ // const scrollY = window.scrollY || window.pageYOffset
89
+
90
+ // const triggerRect = {
91
+ // left: rect.left + scrollX,
92
+ // right: rect.right + scrollX,
93
+ // top: rect.top + scrollY,
94
+ // bottom: rect.bottom + scrollY,
95
+ // width: rect.width,
96
+ // height: rect.height,
97
+ // }
98
+
99
+ // onOpen({
100
+ // content: () => (
101
+ // <PopoverContent
102
+ // placement={placement}
103
+ // width={parentWidth ? rect.width : undefined}
104
+ // minWidth={parentMinWidth ? rect.width : undefined}
105
+ // {...props}
106
+ // onMouseEnter={hover ? stopDelayedClosing : undefined}
107
+ // onMouseLeave={hover ? onClose : undefined}
108
+ // >
109
+ // {renderContent({ onClose: onFastClose })}
110
+ // </PopoverContent>
111
+ // ),
112
+ // triggerRect,
113
+ // placement,
114
+ // options: { dismissOnClickOutside: click || focus },
115
+ // })
116
+ // }
117
+
118
+ // React.useEffect(() => () => onClose(), [])
119
+
120
+ if (shouldUseDrawer) {
121
+ return (
122
+ <DrawerPopover
123
+ content={content}
124
+ renderContent={renderContent}
125
+ children={children}
126
+ {...props}
127
+ {...bottomDrawerProps}
128
+ />
129
+ )
130
+ }
131
+
132
+ const child = React.Children.only(children)
133
+ let childProps = { ref, onClick: show }
134
+
135
+ if (hover) childProps = { ref, onMouseEnter: show, onMouseLeave: onClose }
136
+ if (focus) childProps = { ref, onFocus: show }
137
+
138
+ return React.cloneElement(child, childProps)
139
+ }
140
+
141
+ function DrawerPopover({ children, content, renderContent, snapPoints, ...props }) {
142
+ const [open, setOpen] = React.useState(false)
143
+ const onClose = () => setOpen(false)
144
+
145
+ const child = React.Children.only(children)
146
+ let childProps = { onClick: () => setOpen(true) }
147
+
148
+ return (
149
+ <>
150
+ {React.cloneElement(child, childProps)}
151
+
152
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...props}>
153
+ {renderContent({ onClose })}
154
+ </BottomDrawer>
155
+ </>
156
+ )
157
+ }
@@ -0,0 +1,35 @@
1
+ import React from 'react'
2
+
3
+ import { AnimatedView } from '../animations'
4
+ import { View } from '../structure'
5
+ import { useTabs } from './TabsHandler'
6
+
7
+ const duration = 100
8
+
9
+ function Item({ item, active, ...props }) {
10
+ const Content = React.useMemo(() => item.renderContent || item.Content, [item.renderContent, item.Content])
11
+ const [open, setOpen] = React.useState(active)
12
+
13
+ React.useEffect(() => {
14
+ if (!!active) {
15
+ setTimeout(() => setOpen(true), duration)
16
+ } else {
17
+ setOpen(active)
18
+ }
19
+ }, [active])
20
+
21
+ return (
22
+ <AnimatedView open={open} fade={{ duration }} flex display={!open && 'none'} {...props}>
23
+ <Content />
24
+ </AnimatedView>
25
+ )
26
+ }
27
+
28
+ export function ActiveTabContent({ lazy, unmountOnClose }) {
29
+ const { activeKey, items } = useTabs()
30
+ if (!items?.length) return false
31
+
32
+ return items.map((item) => (
33
+ <Item key={item.key} item={item} active={item.key === activeKey} lazy={lazy} unmountOnClose={unmountOnClose} />
34
+ ))
35
+ }
@@ -0,0 +1,16 @@
1
+ import React from 'react'
2
+
3
+ const TabsContext = React.createContext(null)
4
+ export const useTabs = () => React.useContext(TabsContext) || {}
5
+
6
+ export function TabsHandler({ children, items, initialKey }) {
7
+ const [activeKey, setActiveKey] = React.useState(initialKey || items?.[0]?.key)
8
+
9
+ const activeTab = React.useMemo(() => {
10
+ return items?.find((item) => item.key === activeKey)
11
+ }, [activeKey])
12
+
13
+ const value = { items, onChange: setActiveKey, activeKey, activeTab }
14
+
15
+ return <TabsContext.Provider value={value}>{children}</TabsContext.Provider>
16
+ }
@@ -0,0 +1,15 @@
1
+ import { Menu } from '../actions'
2
+ import { SegmentedPicker } from '../inputs'
3
+ import { useTabs } from './TabsHandler'
4
+
5
+ export function TabsMenu(props) {
6
+ const { activeKey, items, onChange } = useTabs()
7
+
8
+ return <Menu items={items} activeKey={activeKey} onChange={({ key }) => onChange(key)} {...props} />
9
+ }
10
+
11
+ export function TabsSegmentedMenu(props) {
12
+ const { activeKey, items, onChange } = useTabs()
13
+
14
+ return <SegmentedPicker options={items} valueKey="key" value={activeKey} onChange={onChange} {...props} />
15
+ }
@@ -0,0 +1,3 @@
1
+ export * from './TabsHandler'
2
+ export * from './TabsMenu'
3
+ export * from './ActiveTabContent'
@@ -0,0 +1,49 @@
1
+ import { mapObjIndexed, mergeDeepRight, values, pipe, filter } from 'ramda'
2
+
3
+ import { DEFAULT_THEMES, useThemeHandler } from '../../theme'
4
+ import { IconLabel } from '../presentation'
5
+ import { Link } from '../actions'
6
+ import { Picker } from '../inputs'
7
+ import { ThemeThumb } from './ThemeThumb'
8
+
9
+ export function ThemePicker({ onChange, onlyKeys, hideKeys }) {
10
+ const { activeThemeKey, setActiveThemeKey, themes, onChangeTheme } = useThemeHandler()
11
+
12
+ let options = pipe(
13
+ mergeDeepRight(DEFAULT_THEMES),
14
+ mapObjIndexed((obj, key) => ({ ...obj, value: key, key })),
15
+ values,
16
+ filter((item) => {
17
+ if (item.value === '_all') return false
18
+ if (onlyKeys && onlyKeys.includes(item.value)) return true
19
+ if (hideKeys && hideKeys.includes(item.value)) return false
20
+ return true
21
+ })
22
+ )(themes)
23
+
24
+ return (
25
+ <Picker
26
+ colSpan={12}
27
+ gap="lg"
28
+ value={activeThemeKey}
29
+ onChange={(key) => {
30
+ setActiveThemeKey(key)
31
+ onChangeTheme?.(key)
32
+ onChange?.(key)
33
+ }}
34
+ options={options}
35
+ renderOption={({ option, selected, onChange }) => (
36
+ <Link onPress={onChange} gap="xs">
37
+ <ThemeThumb value={option.value} />
38
+ <IconLabel
39
+ center
40
+ label={option.label}
41
+ icon={selected && 'checkbox-circle-fill'}
42
+ color={selected ? 'primary' : 'text3'}
43
+ strong
44
+ />
45
+ </Link>
46
+ )}
47
+ />
48
+ )
49
+ }
@@ -0,0 +1,13 @@
1
+ import { BottomDrawer } from '../structure'
2
+ import { ScrollView } from '../list/ScrollView'
3
+ import { ThemePicker } from './ThemePicker'
4
+
5
+ export function ThemePickerDrawer({ open, onClose, onChange }) {
6
+ return (
7
+ <BottomDrawer open={open} onClose={onClose} maxWidth={550} snapPoints={['50%', '85%']}>
8
+ <ScrollView padding="md">
9
+ <ThemePicker onChange={onChange} />
10
+ </ScrollView>
11
+ </BottomDrawer>
12
+ )
13
+ }
@@ -0,0 +1,3 @@
1
+ export function ThemeStatusBar() {
2
+ return false
3
+ }
@@ -0,0 +1,9 @@
1
+ import { StatusBar } from 'react-native'
2
+
3
+ import { useTheme } from '../../theme'
4
+
5
+ export function ThemeStatusBar(props) {
6
+ const { isDark } = useTheme()
7
+
8
+ return <StatusBar {...props} style={isDark ? 'dark' : 'light'} />
9
+ }
@@ -0,0 +1,98 @@
1
+ import { View } from '../structure'
2
+ import { useFormattedTheme } from '../../theme/format/formatTheme'
3
+ import { useResponsiveValue } from '../../responsive'
4
+ import { useThemeHandler } from '../../theme'
5
+
6
+ export function ThemeThumb({ value }) {
7
+ const { themes } = useThemeHandler()
8
+ const { colors, label } = useFormattedTheme(themes, value)
9
+ const isMobile = useResponsiveValue({ smd: true, df: false })
10
+
11
+ if (isMobile) {
12
+ return (
13
+ <View centerH>
14
+ <View
15
+ bg={colors.mainBG}
16
+ height={175}
17
+ fullW
18
+ br="md"
19
+ hiddenOverflow
20
+ border={2}
21
+ brColor={colors.divider}
22
+ maxWidth={100}
23
+ >
24
+ <View bg={colors.overlayBG} height={25} padding={8} row borderB brColor={colors.divider}>
25
+ <View width={25} fullH bg={colors.primary} br="xxs" />
26
+ <View flex />
27
+ <View ratio={1} fullH bg={colors.divider} round />
28
+ </View>
29
+
30
+ <View flex padding={6}>
31
+ <View br="md" bg={colors.overlayBG} flex gap={8} padding={8} border brColor={colors.divider}>
32
+ <View bg={colors.text2} height={4} br="xxs" />
33
+ <View bg={colors.text4} height={2} br="xxs" />
34
+ <View bg={colors.text4} height={2} br="xxs" />
35
+ <View bg={colors.text4} height={2} br="xxs" />
36
+ <View bg={colors.text4} height={2} br="xxs" />
37
+ <View bg={colors.text4} height={2} br="xxs" />
38
+
39
+ <View flex />
40
+
41
+ <View height={6} fullW bg={colors.primary} br="xxs" />
42
+ </View>
43
+ </View>
44
+
45
+ <View
46
+ bg={colors.overlayBG}
47
+ height={25}
48
+ padding={8}
49
+ row
50
+ borderT
51
+ brColor={colors.divider}
52
+ justify="space-around"
53
+ centerV
54
+ >
55
+ <View ratio={1} fullH bg={colors.divider} round />
56
+ <View ratio={1} fullH bg={colors.divider} round />
57
+ <View ratio={1} fullH bg={colors.divider} round />
58
+ <View ratio={1} fullH bg={colors.divider} round />
59
+ <View ratio={1} fullH bg={colors.divider} round />
60
+ </View>
61
+ </View>
62
+ </View>
63
+ )
64
+ }
65
+
66
+ return (
67
+ <View bg={colors.mainBG} height={175} fullW br="md" hiddenOverflow border={2} brColor={colors.divider}>
68
+ <View bg={colors.overlayBG} height={25} paddingV={8} paddingH={12} row borderB brColor={colors.divider}>
69
+ <View width={25} bg={colors.primary} br="xxs" />
70
+ <View flex />
71
+ <View ratio={1} fullH bg={colors.text4} round />
72
+ </View>
73
+
74
+ <View row padding={12} paddingT={8} gap={6} flex>
75
+ <View br="xs" bg={colors.overlayBG} flex gap={6} padding={7} border brColor={colors.divider}>
76
+ <View bg={colors.text4} height={2} br="xxs" />
77
+ <View bg={colors.text4} height={2} br="xxs" />
78
+ <View bg={colors.text4} height={2} br="xxs" />
79
+ <View bg={colors.text4} height={2} br="xxs" />
80
+ <View bg={colors.text4} height={2} br="xxs" />
81
+ </View>
82
+ <View br="xs" bg={colors.overlayBG} flex={4} gap={8} padding={7} border brColor={colors.divider}>
83
+ <View bg={colors.text2} height={4} br="xxs" width={30} />
84
+ <View bg={colors.text4} height={2} br="xxs" width={'80%'} />
85
+ <View bg={colors.text4} height={2} br="xxs" width={'80%'} />
86
+ <View bg={colors.text4} height={2} br="xxs" width={'80%'} />
87
+ <View bg={colors.text4} height={2} br="xxs" width={'80%'} />
88
+ <View bg={colors.text4} height={2} br="xxs" width={'80%'} />
89
+ <View flex />
90
+ <View row toRight gap={6}>
91
+ <View width={25} height={8} bg={colors.text4} br="xxs" />
92
+ <View width={25} height={8} bg={colors.primary} br="xxs" />
93
+ </View>
94
+ </View>
95
+ </View>
96
+ </View>
97
+ )
98
+ }
@@ -0,0 +1,3 @@
1
+ export * from './ThemePicker'
2
+ export * from './ThemePickerDrawer'
3
+ export * from './ThemeStatusBar'
@@ -1,3 +1,4 @@
1
1
  export * from './debounce'
2
2
  export * from './string'
3
3
  export * from './random'
4
+ export * from './storage'
@@ -0,0 +1,54 @@
1
+ import React from 'react'
2
+
3
+ import { AbsStorage } from '../abstractions/helpers/storage'
4
+
5
+ function set(key, value) {
6
+ return AbsStorage.set(key, JSON.stringify(value))
7
+ }
8
+
9
+ function setAsync(key, value) {
10
+ return AbsStorage.setAsync(key, JSON.stringify(value))
11
+ }
12
+
13
+ function get(key) {
14
+ const value = AbsStorage.get(key)
15
+ return formatStoragedValue(value)
16
+ }
17
+
18
+ function getAsync(key) {
19
+ return AbsStorage.setAsync(key).then((value) => {
20
+ return formatStoragedValue(value)
21
+ })
22
+ }
23
+
24
+ function formatStoragedValue(value) {
25
+ try {
26
+ if (!value) return value
27
+ value = JSON.parse(value)
28
+ if (value === 'undefined') return undefined
29
+ if (value === 'null') return undefined
30
+ return value
31
+ } catch (e) {
32
+ return value
33
+ }
34
+ }
35
+
36
+ function useState(key, defaultValue) {
37
+ const [value, setValue] = React.useState(get(key) || defaultValue)
38
+
39
+ const handleChange = (newValue) => {
40
+ set(key, newValue)
41
+ setValue(newValue)
42
+ }
43
+
44
+ return [value, handleChange]
45
+ }
46
+
47
+ export const Storage = {
48
+ ...AbsStorage,
49
+ set,
50
+ setAsync,
51
+ get,
52
+ getAsync,
53
+ useState,
54
+ }
@@ -1,4 +1,19 @@
1
- import { adjust, compose, defaultTo, head, join, juxt, map, pipe, replace, split, tail, toLower, toUpper } from 'ramda'
1
+ import {
2
+ adjust,
3
+ compose,
4
+ defaultTo,
5
+ head,
6
+ join,
7
+ juxt,
8
+ map,
9
+ pipe,
10
+ replace,
11
+ split,
12
+ tail,
13
+ toLower,
14
+ toUpper,
15
+ trim,
16
+ } from 'ramda'
2
17
 
3
18
  export const removeSpecialChars = replace(/[^a-zA-Z ,0-9]/g, '')
4
19
 
@@ -55,3 +70,5 @@ export const truncate = truncateString
55
70
  export const slugify = (text) => {
56
71
  return toSnakeCase(text)
57
72
  }
73
+
74
+ export const normalizeString = pipe(toLower, trim, (str) => str.normalize('NFD').replace(/[\u0300-\u036f]/g, ''))