@neko-os/ui 0.0.7 → 0.0.9

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 (274) hide show
  1. package/dist/NekoUI.js +1 -1
  2. package/dist/abstractions/ActivityIndicator.native.js +1 -1
  3. package/dist/abstractions/ActivityIndicator.web.js +1 -0
  4. package/dist/abstractions/AnimatedView.js +1 -1
  5. package/dist/abstractions/BlurView.js +1 -0
  6. package/dist/abstractions/BlurView.native.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/GradientView.js +1 -0
  12. package/dist/abstractions/GradientView.native.js +1 -0
  13. package/dist/abstractions/Icon.native.js +1 -1
  14. package/dist/abstractions/ImageBackground.js +1 -0
  15. package/dist/abstractions/ImageBackground.native.js +1 -0
  16. package/dist/abstractions/ImageBackground.web.js +1 -0
  17. package/dist/abstractions/Pressable.js +1 -0
  18. package/dist/abstractions/Pressable.native.js +1 -0
  19. package/dist/abstractions/Pressable.web.js +1 -0
  20. package/dist/abstractions/ScrollView.js +1 -0
  21. package/dist/abstractions/ScrollView.native.js +1 -0
  22. package/dist/abstractions/ScrollView.web.js +1 -0
  23. package/dist/abstractions/TextInput.js +1 -1
  24. package/dist/abstractions/helpers/storage.js +1 -0
  25. package/dist/abstractions/helpers/storage.native.js +1 -0
  26. package/dist/components/actions/Button.js +1 -1
  27. package/dist/components/actions/Dropdown.js +1 -1
  28. package/dist/components/actions/Link.js +1 -1
  29. package/dist/components/actions/Pressable.js +1 -0
  30. package/dist/components/actions/index.js +1 -1
  31. package/dist/components/actions/menu/HorizontalMenu.js +1 -1
  32. package/dist/components/actions/menu/VerticalMenu.js +1 -1
  33. package/dist/components/animations/ReanimatedView.js +1 -0
  34. package/dist/components/calendar/CalendarNav.js +1 -0
  35. package/dist/components/calendar/WeekDaysBar.js +1 -0
  36. package/dist/components/calendar/_helpers/calendarDays.js +1 -1
  37. package/dist/components/calendar/_helpers/dateDisabled.js +1 -0
  38. package/dist/components/calendar/index.js +0 -1
  39. package/dist/components/feedback/alerter.js +1 -0
  40. package/dist/components/feedback/confirmer.js +1 -0
  41. package/dist/components/feedback/index.js +1 -1
  42. package/dist/components/feedback/notifications/Notification.js +1 -1
  43. package/dist/components/feedback/notifications/NotificationsHandler.js +1 -1
  44. package/dist/components/index.js +1 -1
  45. package/dist/components/inputs/DateInput.js +1 -0
  46. package/dist/components/inputs/InputWrapper.js +1 -1
  47. package/dist/components/inputs/LinkInput.js +1 -0
  48. package/dist/components/inputs/MaskInput.js +1 -0
  49. package/dist/components/inputs/TextInput.js +1 -1
  50. package/dist/components/inputs/_DateInput.native.js +1 -0
  51. package/dist/components/inputs/datePicker/DatePicker.js +1 -0
  52. package/dist/components/inputs/datePicker/DayPicker.js +1 -0
  53. package/dist/components/inputs/datePicker/MonthPicker.js +1 -0
  54. package/dist/components/inputs/datePicker/QuarterPicker.js +1 -0
  55. package/dist/components/inputs/datePicker/WeekPicker.js +1 -0
  56. package/dist/components/inputs/datePicker/YearPicker.js +1 -0
  57. package/dist/components/inputs/index.js +1 -1
  58. package/dist/components/layout/Layout.js +1 -1
  59. package/dist/components/list/FlatList.js +1 -0
  60. package/dist/components/list/ScrollView.js +1 -0
  61. package/dist/components/list/index.js +1 -0
  62. package/dist/components/presentation/ImageBackground.js +1 -0
  63. package/dist/components/presentation/Result.js +1 -1
  64. package/dist/components/presentation/index.js +1 -1
  65. package/dist/components/state/LoadingView.js +1 -1
  66. package/dist/components/structure/Accordion.js +1 -1
  67. package/dist/components/structure/BlurView.js +1 -0
  68. package/dist/components/structure/GradientView.js +1 -0
  69. package/dist/components/structure/View.js +1 -1
  70. package/dist/components/structure/bottomDrawer/index.js +1 -0
  71. package/dist/components/structure/bottomDrawer/index.native.js +1 -0
  72. package/dist/components/structure/bottomDrawer/index.web.js +1 -0
  73. package/dist/components/structure/bottomDrawer/native/BottomDrawer.js +1 -0
  74. package/dist/components/structure/bottomDrawer/native/DrawerContext.js +1 -0
  75. package/dist/components/structure/bottomDrawer/native/DrawerHandle.js +1 -0
  76. package/dist/components/structure/bottomDrawer/native/DrawerScrollView.js +1 -0
  77. package/dist/components/structure/bottomDrawer/native/utils.js +1 -0
  78. package/dist/components/structure/bottomDrawer/web/BottomDrawer.js +1 -0
  79. package/dist/components/structure/drawer/Drawer.js +1 -0
  80. package/dist/components/structure/drawer/Drawer.native.js +1 -0
  81. package/dist/components/structure/drawer/index.js +1 -0
  82. package/dist/components/structure/index.js +1 -1
  83. package/dist/components/structure/modal/Modal.js +1 -0
  84. package/dist/components/structure/modal/Modal.native.js +1 -0
  85. package/dist/components/structure/modal/ModalBackdrop.js +1 -0
  86. package/dist/components/structure/modal/ModalContent.js +1 -0
  87. package/dist/components/structure/modal/ModalFooter.js +1 -0
  88. package/dist/components/structure/modal/ModalHeader.js +1 -0
  89. package/dist/components/structure/modal/handler/ModalsHandler.js +1 -0
  90. package/dist/components/structure/modal/index.js +1 -0
  91. package/dist/components/structure/overlay/OverlayWrapper.js +1 -1
  92. package/dist/components/structure/popover/Popover.js +1 -1
  93. package/dist/components/structure/popover/Popover.native.js +1 -1
  94. package/dist/components/theme/ThemePicker.js +1 -0
  95. package/dist/components/theme/ThemePickerDrawer.js +1 -0
  96. package/dist/components/theme/ThemeStatusBar.js +1 -0
  97. package/dist/components/theme/ThemeStatusBar.native.js +1 -0
  98. package/dist/components/theme/ThemeThumb.js +1 -0
  99. package/dist/components/theme/index.js +1 -0
  100. package/dist/helpers/index.js +1 -1
  101. package/dist/helpers/storage.js +1 -0
  102. package/dist/modifiers/animations/animatedEffects.js +1 -1
  103. package/dist/modifiers/animations/animatedEffects.native.js +1 -1
  104. package/dist/modifiers/animations/fadeEffect.js +1 -1
  105. package/dist/modifiers/animations/scaleEffect.js +1 -0
  106. package/dist/modifiers/animations/scaleEffect.native.js +1 -0
  107. package/dist/modifiers/animations/slideEffect.js +1 -1
  108. package/dist/modifiers/background.js +1 -1
  109. package/dist/modifiers/cursor.js +1 -0
  110. package/dist/modifiers/display.js +1 -1
  111. package/dist/modifiers/fullColor.js +1 -1
  112. package/dist/modifiers/hover.js +1 -0
  113. package/dist/modifiers/position.js +1 -1
  114. package/dist/modifiers/size.js +1 -1
  115. package/dist/modifiers/state.js +1 -1
  116. package/dist/responsive/responsiveHooks.js +1 -1
  117. package/dist/theme/ThemeHandler.js +1 -1
  118. package/dist/theme/default/base.js +1 -1
  119. package/dist/theme/default/blackTheme.js +1 -0
  120. package/dist/theme/default/cyberpunkTheme.js +1 -1
  121. package/dist/theme/default/darkTheme.js +1 -1
  122. package/dist/theme/default/deepWoodsTheme.js +1 -1
  123. package/dist/theme/default/forestTheme.js +1 -1
  124. package/dist/theme/default/hackerTheme.js +1 -1
  125. package/dist/theme/default/lightTheme.js +1 -1
  126. package/dist/theme/default/midnightTheme.js +1 -1
  127. package/dist/theme/default/msdosTheme.js +1 -1
  128. package/dist/theme/default/oceanTheme.js +1 -1
  129. package/dist/theme/default/paperTheme.js +1 -0
  130. package/dist/theme/default/pastelTheme.js +1 -1
  131. package/dist/theme/default/sunsetTheme.js +1 -1
  132. package/dist/theme/default/themes.js +1 -1
  133. package/dist/theme/format/formatTheme.js +1 -1
  134. package/dist/theme/helpers/contrastColor.js +1 -1
  135. package/package.json +8 -3
  136. package/src/NekoUI.js +18 -3
  137. package/src/abstractions/ActivityIndicator.native.js +3 -4
  138. package/src/abstractions/ActivityIndicator.web.js +43 -0
  139. package/src/abstractions/AnimatedView.js +3 -3
  140. package/src/abstractions/BlurView.js +43 -0
  141. package/src/abstractions/BlurView.native.js +39 -0
  142. package/src/abstractions/BlurView.web.js +39 -0
  143. package/src/abstractions/FlatList.js +39 -0
  144. package/src/abstractions/FlatList.native.js +32 -0
  145. package/src/abstractions/FlatList.web.js +3 -0
  146. package/src/abstractions/GradientView.js +5 -0
  147. package/src/abstractions/GradientView.native.js +32 -0
  148. package/src/abstractions/Icon.native.js +4 -2
  149. package/src/abstractions/ImageBackground.js +17 -0
  150. package/src/abstractions/ImageBackground.native.js +27 -0
  151. package/src/abstractions/ImageBackground.web.js +7 -0
  152. package/src/abstractions/Pressable.js +4 -0
  153. package/src/abstractions/Pressable.native.js +3 -0
  154. package/src/abstractions/Pressable.web.js +3 -0
  155. package/src/abstractions/ScrollView.js +3 -0
  156. package/src/abstractions/ScrollView.native.js +5 -0
  157. package/src/abstractions/ScrollView.web.js +3 -0
  158. package/src/abstractions/Text.web.js +15 -0
  159. package/src/abstractions/TextInput.js +2 -2
  160. package/src/abstractions/helpers/storage.js +32 -0
  161. package/src/abstractions/helpers/storage.native.js +34 -0
  162. package/src/components/actions/Button.js +8 -0
  163. package/src/components/actions/Dropdown.js +18 -2
  164. package/src/components/actions/Link.js +16 -2
  165. package/src/components/actions/Pressable.js +38 -0
  166. package/src/components/actions/index.js +1 -0
  167. package/src/components/actions/menu/HorizontalMenu.js +2 -1
  168. package/src/components/actions/menu/VerticalMenu.js +5 -4
  169. package/src/components/animations/ReanimatedView.js +40 -0
  170. package/src/components/calendar/CalendarNav.js +67 -0
  171. package/src/components/calendar/WeekDaysBar.js +18 -0
  172. package/src/components/calendar/_helpers/calendarDays.js +1 -3
  173. package/src/components/calendar/_helpers/dateDisabled.js +24 -0
  174. package/src/components/calendar/index.js +1 -1
  175. package/src/components/feedback/alerter.js +31 -0
  176. package/src/components/feedback/confirmer.js +70 -0
  177. package/src/components/feedback/index.js +2 -0
  178. package/src/components/feedback/notifications/Notification.js +1 -1
  179. package/src/components/feedback/notifications/NotificationsHandler.js +3 -3
  180. package/src/components/index.js +2 -0
  181. package/src/components/inputs/DateInput.js +111 -0
  182. package/src/components/inputs/InputWrapper.js +18 -6
  183. package/src/components/inputs/LinkInput.js +17 -0
  184. package/src/components/inputs/MaskInput.js +67 -0
  185. package/src/components/inputs/TextInput.js +2 -2
  186. package/src/components/inputs/_DateInput.native.js +89 -0
  187. package/src/components/inputs/datePicker/DatePicker.js +24 -0
  188. package/src/components/inputs/datePicker/DayPicker.js +65 -0
  189. package/src/components/inputs/datePicker/MonthPicker.js +62 -0
  190. package/src/components/inputs/datePicker/QuarterPicker.js +65 -0
  191. package/src/components/inputs/datePicker/WeekPicker.js +74 -0
  192. package/src/components/inputs/datePicker/YearPicker.js +67 -0
  193. package/src/components/inputs/index.js +4 -0
  194. package/src/components/layout/Layout.js +1 -1
  195. package/src/components/list/FlatList.js +54 -0
  196. package/src/components/list/ScrollView.js +58 -0
  197. package/src/components/list/index.js +2 -0
  198. package/src/components/presentation/ImageBackground.js +38 -0
  199. package/src/components/presentation/Result.js +2 -2
  200. package/src/components/presentation/index.js +1 -0
  201. package/src/components/state/LoadingView.js +10 -1
  202. package/src/components/structure/Accordion.js +1 -1
  203. package/src/components/structure/BlurView.js +58 -0
  204. package/src/components/structure/GradientView.js +42 -0
  205. package/src/components/structure/View.js +2 -0
  206. package/src/components/structure/bottomDrawer/index.js +1 -0
  207. package/src/components/structure/bottomDrawer/index.native.js +4 -0
  208. package/src/components/structure/bottomDrawer/index.web.js +4 -0
  209. package/src/components/structure/bottomDrawer/native/BottomDrawer.js +242 -0
  210. package/src/components/structure/bottomDrawer/native/DrawerContext.js +21 -0
  211. package/src/components/structure/bottomDrawer/native/DrawerHandle.js +12 -0
  212. package/src/components/structure/bottomDrawer/native/DrawerScrollView.js +83 -0
  213. package/src/components/structure/bottomDrawer/native/utils.js +58 -0
  214. package/src/components/structure/bottomDrawer/web/BottomDrawer.js +3 -0
  215. package/src/components/structure/drawer/Drawer.js +5 -0
  216. package/src/components/structure/drawer/Drawer.native.js +3 -0
  217. package/src/components/structure/drawer/index.js +1 -0
  218. package/src/components/structure/index.js +5 -0
  219. package/src/components/structure/modal/Modal.js +84 -0
  220. package/src/components/structure/modal/Modal.native.js +83 -0
  221. package/src/components/structure/modal/ModalBackdrop.js +58 -0
  222. package/src/components/structure/modal/ModalContent.js +28 -0
  223. package/src/components/structure/modal/ModalFooter.js +31 -0
  224. package/src/components/structure/modal/ModalHeader.js +50 -0
  225. package/src/components/structure/modal/handler/ModalsHandler.js +61 -0
  226. package/src/components/structure/modal/index.js +6 -0
  227. package/src/components/structure/overlay/OverlayWrapper.js +1 -1
  228. package/src/components/structure/popover/Popover.js +37 -2
  229. package/src/components/structure/popover/Popover.native.js +46 -16
  230. package/src/components/theme/ThemePicker.js +49 -0
  231. package/src/components/theme/ThemePickerDrawer.js +13 -0
  232. package/src/components/theme/ThemeStatusBar.js +3 -0
  233. package/src/components/theme/ThemeStatusBar.native.js +9 -0
  234. package/src/components/theme/ThemeThumb.js +98 -0
  235. package/src/components/theme/index.js +3 -0
  236. package/src/helpers/index.js +1 -0
  237. package/src/helpers/storage.js +54 -0
  238. package/src/modifiers/animations/animatedEffects.js +2 -0
  239. package/src/modifiers/animations/animatedEffects.native.js +3 -1
  240. package/src/modifiers/animations/fadeEffect.js +4 -2
  241. package/src/modifiers/animations/scaleEffect.js +45 -0
  242. package/src/modifiers/animations/scaleEffect.native.js +33 -0
  243. package/src/modifiers/animations/slideEffect.js +3 -1
  244. package/src/modifiers/background.js +16 -4
  245. package/src/modifiers/cursor.js +21 -0
  246. package/src/modifiers/display.js +2 -2
  247. package/src/modifiers/fullColor.js +2 -2
  248. package/src/modifiers/hover.js +28 -0
  249. package/src/modifiers/position.js +24 -3
  250. package/src/modifiers/size.js +2 -1
  251. package/src/modifiers/state.js +1 -1
  252. package/src/responsive/responsiveHooks.js +7 -0
  253. package/src/theme/ThemeHandler.js +18 -2
  254. package/src/theme/default/base.js +6 -6
  255. package/src/theme/default/blackTheme.js +35 -0
  256. package/src/theme/default/cyberpunkTheme.js +4 -1
  257. package/src/theme/default/darkTheme.js +4 -1
  258. package/src/theme/default/deepWoodsTheme.js +5 -2
  259. package/src/theme/default/forestTheme.js +4 -1
  260. package/src/theme/default/hackerTheme.js +4 -1
  261. package/src/theme/default/lightTheme.js +4 -1
  262. package/src/theme/default/midnightTheme.js +4 -1
  263. package/src/theme/default/msdosTheme.js +19 -4
  264. package/src/theme/default/oceanTheme.js +5 -2
  265. package/src/theme/default/paperTheme.js +35 -0
  266. package/src/theme/default/pastelTheme.js +5 -2
  267. package/src/theme/default/sunsetTheme.js +7 -4
  268. package/src/theme/default/themes.js +9 -10
  269. package/src/theme/format/formatTheme.js +9 -3
  270. package/src/theme/helpers/contrastColor.js +49 -11
  271. package/dist/abstractions/TouchableOpacity.web.js +0 -1
  272. package/dist/components/calendar/DayPicker.js +0 -1
  273. package/src/abstractions/TouchableOpacity.web.js +0 -3
  274. package/src/components/calendar/DayPicker.js +0 -94
@@ -0,0 +1,84 @@
1
+ import { pipe } from 'ramda'
2
+
3
+ import { AnimatedView } from '../../animations/AnimatedView'
4
+ import { ModalBackdrop } from './ModalBackdrop'
5
+ import { ModalContent } from './ModalContent'
6
+ import { ModalFooter } from './ModalFooter'
7
+ import { ModalHeader } from './ModalHeader'
8
+ import { Portal } from '../../helpers/Portal'
9
+ import { useDefaultModifier } from '../../../modifiers/default'
10
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
11
+
12
+ const DEFAULT_PROPS = ([{}, { position }]) => {
13
+ let radiusKey = 'br'
14
+ let height = undefined
15
+ if (position === 'bottom') {
16
+ radiusKey = 'borderRadiusT'
17
+ height = '95%'
18
+ } else if (position === 'top') {
19
+ radiusKey = 'borderRadiusB'
20
+ height = '95%'
21
+ } else if (position === 'right') {
22
+ radiusKey = 'borderRadiusL'
23
+ height = '100%'
24
+ } else if (position === 'left') {
25
+ radiusKey = 'borderRadiusR'
26
+ height = '100%'
27
+ }
28
+
29
+ return {
30
+ maxWidth: '100%',
31
+ maxHeight: !position && '95%',
32
+ height,
33
+ scale: !position,
34
+ fade: !!position,
35
+ slide: position && { from: position },
36
+ [radiusKey]: 'xl',
37
+ bg: 'overlayBG',
38
+ overflow: 'hidden',
39
+ shadow: true,
40
+ }
41
+ }
42
+
43
+ export function Modal({
44
+ open,
45
+ onClose,
46
+ title,
47
+ width = 500,
48
+ children,
49
+ header,
50
+ footer,
51
+ noLayout,
52
+ disableOutsideClick,
53
+ ...rootProps
54
+ }) {
55
+ const [{}, formattedProps] = pipe(
56
+ useThemeComponentModifier('Modal'),
57
+ useDefaultModifier(DEFAULT_PROPS)
58
+ )([{}, rootProps])
59
+
60
+ const { contentProps, headerProps, footerProps, position, ...props } = formattedProps
61
+
62
+ let content = children
63
+ if (!noLayout) {
64
+ content = (
65
+ <>
66
+ <ModalHeader title={title} onClose={onClose} {...headerProps}>
67
+ {header}
68
+ </ModalHeader>
69
+ <ModalContent {...contentProps}>{children}</ModalContent>
70
+ <ModalFooter {...footerProps}>{footer}</ModalFooter>
71
+ </>
72
+ )
73
+ }
74
+
75
+ return (
76
+ <Portal>
77
+ <ModalBackdrop open={open} onClose={!disableOutsideClick && onClose} position={position}>
78
+ <AnimatedView className="neko-modal" open={open} width={width} {...props} onPress={(e) => e.stopPropagation()}>
79
+ {content}
80
+ </AnimatedView>
81
+ </ModalBackdrop>
82
+ </Portal>
83
+ )
84
+ }
@@ -0,0 +1,83 @@
1
+ import { Modal as RNModal, ScrollView } from 'react-native'
2
+ import { pipe } from 'ramda'
3
+
4
+ import { ModalBackdrop } from './ModalBackdrop'
5
+ import { ModalContent } from './ModalContent'
6
+ import { ModalFooter } from './ModalFooter'
7
+ import { ModalHeader } from './ModalHeader'
8
+ import { Pressable } from '../../actions/Pressable'
9
+ import { View } from '../View'
10
+ import { useDefaultModifier } from '../../../modifiers/default'
11
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
12
+
13
+ const DEFAULT_PROPS = {
14
+ maxWidth: '90%',
15
+ maxHeight: '90%',
16
+ scale: true,
17
+ br: 'xl',
18
+ bg: 'overlayBG',
19
+ overflow: 'hidden',
20
+ shadow: true,
21
+ }
22
+
23
+ export function Modal({
24
+ open,
25
+ onClose,
26
+ title,
27
+ width = 500,
28
+ children,
29
+ header,
30
+ footer,
31
+ noLayout,
32
+ disableOutsideClick,
33
+ ...rootProps
34
+ }) {
35
+ const [{}, formattedProps] = pipe(
36
+ useThemeComponentModifier('Modal'),
37
+ useDefaultModifier(DEFAULT_PROPS)
38
+ )([{}, rootProps])
39
+
40
+ const { contentProps, headerProps, footerProps, ...props } = formattedProps
41
+
42
+ let content = children
43
+ if (!noLayout) {
44
+ content = (
45
+ <>
46
+ <ModalHeader title={title} onClose={onClose} {...headerProps}>
47
+ {header}
48
+ </ModalHeader>
49
+ <ScrollView>
50
+ <ModalContent {...contentProps}>{children}</ModalContent>
51
+ </ScrollView>
52
+ <ModalFooter {...footerProps}>{footer}</ModalFooter>
53
+ </>
54
+ )
55
+ }
56
+
57
+ return (
58
+ <RNModal
59
+ animationType="fade"
60
+ transparent
61
+ visible={open}
62
+ onRequestClose={onClose}
63
+ allowSwipeDismissal
64
+ navigationBarTranslucent
65
+ statusBarTranslucent
66
+ >
67
+ <ModalBackdrop open={open} useSimpleView>
68
+ <Pressable
69
+ onPress={!disableOutsideClick ? onClose : undefined}
70
+ absolute
71
+ top={0}
72
+ left={0}
73
+ right={0}
74
+ bottom={0}
75
+ pointerEvents="box-only"
76
+ />
77
+ <View width={width} {...props} zIndex={10}>
78
+ {content}
79
+ </View>
80
+ </ModalBackdrop>
81
+ </RNModal>
82
+ )
83
+ }
@@ -0,0 +1,58 @@
1
+ import { pipe } from 'ramda'
2
+ import React from 'react'
3
+
4
+ import { AnimatedView } from '../../animations/AnimatedView'
5
+ import { SafeAreaView } from '../SafeAreaView'
6
+ import { useDefaultModifier } from '../../../modifiers/default'
7
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
8
+
9
+ const DEFAULT_PROPS = ([{}, { position }]) => {
10
+ let justify = 'center'
11
+ let align = 'center'
12
+ if (position === 'bottom') {
13
+ justify = 'flex-end'
14
+ } else if (position === 'top') {
15
+ justify = 'flex-top'
16
+ } else if (position === 'left') {
17
+ align = 'flex-start'
18
+ } else if (position === 'right') {
19
+ align = 'flex-end'
20
+ }
21
+
22
+ return {
23
+ fixed: true,
24
+ top: 0,
25
+ left: 0,
26
+ right: 0,
27
+ bottom: 0,
28
+ justify,
29
+ align,
30
+ lazy: true,
31
+ unmountOnClose: true,
32
+ fade: true,
33
+ zIndex: 500,
34
+ bg: 'backdrop_op70',
35
+ }
36
+ }
37
+
38
+ export function ModalBackdrop({ open, onClose, children, useSimpleView, ...rootProps }) {
39
+ const modalRef = React.useRef()
40
+ const [{}, props] = pipe(
41
+ useThemeComponentModifier('ModalBackdrop'),
42
+ useDefaultModifier(DEFAULT_PROPS)
43
+ )([{}, rootProps])
44
+
45
+ if (useSimpleView) {
46
+ return (
47
+ <SafeAreaView className="neko-modal-backdrop" {...props}>
48
+ {children}
49
+ </SafeAreaView>
50
+ )
51
+ }
52
+
53
+ return (
54
+ <AnimatedView open={open} className="neko-modal-backdrop" onPress={onClose} {...props}>
55
+ {children}
56
+ </AnimatedView>
57
+ )
58
+ }
@@ -0,0 +1,28 @@
1
+ import { pipe } from 'ramda'
2
+
3
+ import { View } from '../View'
4
+ import { useDefaultModifier } from '../../../modifiers/default'
5
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
6
+
7
+ const DEFAULT_PROPS = {
8
+ fullW: true,
9
+ flex: true,
10
+ // fullH: true,
11
+ scrollY: true,
12
+ padding: 'md',
13
+ }
14
+
15
+ export function ModalContent({ children, ...rootProps }) {
16
+ const [{}, props] = pipe(
17
+ useThemeComponentModifier('ModalContent'), //
18
+ useDefaultModifier(DEFAULT_PROPS)
19
+ )([{}, rootProps])
20
+
21
+ if (!children) return false
22
+
23
+ return (
24
+ <View className="neko-modal-content" {...props}>
25
+ {children}
26
+ </View>
27
+ )
28
+ }
@@ -0,0 +1,31 @@
1
+ import { pipe } from 'ramda'
2
+
3
+ import { View } from '../View'
4
+ import { moveScale } from '../../../theme/helpers/sizeScale'
5
+ import { useDefaultModifier } from '../../../modifiers/default'
6
+ import { useSizeConverter } from '../../../modifiers/sizeConverter'
7
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
8
+
9
+ const DEFAULT_PROPS = ([{ sizeCode }, _]) => ({
10
+ borderT: true,
11
+ paddingH: sizeCode,
12
+ paddingV: moveScale(sizeCode, -2),
13
+ minHeight: moveScale(sizeCode, 1),
14
+ centerV: true,
15
+ })
16
+
17
+ export function ModalFooter({ children, ...rootProps }) {
18
+ const [{}, props] = pipe(
19
+ useSizeConverter('elementHeights', 'md'),
20
+ useThemeComponentModifier('ModalFooter'), //
21
+ useDefaultModifier(DEFAULT_PROPS)
22
+ )([{}, rootProps])
23
+
24
+ if (!children) return false
25
+
26
+ return (
27
+ <View className="neko-modal-footer" {...props}>
28
+ {children}
29
+ </View>
30
+ )
31
+ }
@@ -0,0 +1,50 @@
1
+ import { pipe } from 'ramda'
2
+
3
+ import { Icon } from '../../presentation/Icon'
4
+ import { Link } from '../../actions/Link'
5
+ import { Text } from '../../text/Text'
6
+ import { View } from '../View'
7
+ import { moveScale } from '../../../theme/helpers/sizeScale'
8
+ import { useDefaultModifier } from '../../../modifiers/default'
9
+ import { useSizeConverter } from '../../../modifiers/sizeConverter'
10
+ import { useThemeComponentModifier } from '../../../modifiers/themeComponent'
11
+
12
+ const DEFAULT_PROPS = ([{ sizeCode }, _]) => ({
13
+ centerV: true,
14
+ paddingH: sizeCode,
15
+ paddingV: moveScale(sizeCode, -2),
16
+ minHeight: moveScale(sizeCode, 1),
17
+ gap: 'md',
18
+ borderB: true,
19
+ justify: 'space-between',
20
+
21
+ titleProps: {
22
+ strong: true,
23
+ },
24
+ })
25
+
26
+ export function ModalHeader({ onClose, title, children, ...rootProps }) {
27
+ const [{}, formattedProps] = pipe(
28
+ useSizeConverter('elementHeights', 'md'),
29
+ useThemeComponentModifier('ModalHeader'),
30
+ useDefaultModifier(DEFAULT_PROPS)
31
+ )([{}, rootProps])
32
+
33
+ const { titleProps, ...props } = formattedProps
34
+
35
+ if (!title && !children) return false
36
+
37
+ return (
38
+ <View className="neko-modal-header" {...props} row>
39
+ {title && <Text {...titleProps}>{title}</Text>}
40
+
41
+ {children}
42
+
43
+ {!!onClose && (
44
+ <Link onPress={onClose} padding="sm" marginR={-10}>
45
+ <Icon name="close-line" />
46
+ </Link>
47
+ )}
48
+ </View>
49
+ )
50
+ }
@@ -0,0 +1,61 @@
1
+ import React from 'react'
2
+
3
+ import { Modal } from '../Modal'
4
+ import { useResponsiveValue } from '../../../../responsive/responsiveHooks'
5
+
6
+ const ModalsContext = React.createContext(null)
7
+
8
+ export const useModals = () => React.useContext(ModalsContext) || {}
9
+
10
+ let idCounter = 0
11
+
12
+ export function useModalOpener() {
13
+ const { add, remove, close } = useModals()
14
+ const open = (init) => {
15
+ const key = ++idCounter
16
+
17
+ const onClose = () => close(key)
18
+ const params = { onClose, key }
19
+
20
+ const data = init(params)
21
+
22
+ add(key, { onClose, ...data, open: true })
23
+ return params
24
+ }
25
+
26
+ return {
27
+ open,
28
+ }
29
+ }
30
+
31
+ export function ModalsHandler({ children }) {
32
+ const width = useResponsiveValue({ sm: '100%', df: 400 })
33
+ const [modals, setModals] = React.useState([])
34
+
35
+ const add = React.useCallback((key, data) => {
36
+ setModals((prev) => [...prev, { key, ...data }])
37
+ }, [])
38
+
39
+ const remove = React.useCallback((key) => {
40
+ setModals((prev) => prev.filter((p) => p.key !== key))
41
+ }, [])
42
+
43
+ const close = React.useCallback((key) => {
44
+ setModals((items) => items.map((i) => (i.key === key ? { ...i, open: false } : i)))
45
+ setTimeout(() => remove(key), 600)
46
+ }, [])
47
+
48
+ const value = React.useMemo(() => ({ add, remove, close }), [add, remove, close])
49
+
50
+ return (
51
+ <ModalsContext.Provider value={value}>
52
+ {children}
53
+
54
+ {modals?.map?.(({ key, content, ...item }) => (
55
+ <Modal key={key} {...item}>
56
+ {content}
57
+ </Modal>
58
+ ))}
59
+ </ModalsContext.Provider>
60
+ )
61
+ }
@@ -0,0 +1,6 @@
1
+ export * from './handler/ModalsHandler'
2
+ export * from './Modal'
3
+ export * from './ModalContent'
4
+ export * from './ModalHeader'
5
+ export * from './ModalFooter'
6
+ export * from './ModalBackdrop'
@@ -43,7 +43,7 @@ export function OverlayWrapper({ children, triggerRect, placement, onClickOutsid
43
43
  top={pos.y}
44
44
  left={pos.x}
45
45
  zIndex={9999}
46
- pointerEvents="none"
46
+ ointerEvents="none"
47
47
  {...props}
48
48
  >
49
49
  {children}
@@ -1,7 +1,9 @@
1
1
  import React from 'react'
2
2
 
3
+ import { BottomDrawer } from '../bottomDrawer'
3
4
  import { PopoverContent } from './PopoverContent'
4
5
  import { useRegisterOverlay } from '../overlay/OverlayHandler'
6
+ import { useResponsiveValue } from '../../../responsive'
5
7
 
6
8
  export function Popover({
7
9
  renderContent,
@@ -12,8 +14,11 @@ export function Popover({
12
14
  children,
13
15
  parentWidth,
14
16
  parentMinWidth,
17
+ useBottomDrawer = {},
18
+ bottomDrawerProps = {},
15
19
  ...props
16
20
  }) {
21
+ const shouldUseDrawer = useResponsiveValue(useBottomDrawer)
17
22
  const ref = React.useRef(null)
18
23
  const { onOpen, onClose, onFastClose, stopDelayedClosing } = useRegisterOverlay({ unmountOnClose })
19
24
 
@@ -53,17 +58,47 @@ export function Popover({
53
58
  ),
54
59
  triggerRect,
55
60
  placement,
56
- options: { dismissOnClickOutside: !!click },
61
+ options: { dismissOnClickOutside: click || focus },
57
62
  })
58
63
  }
59
64
 
60
65
  React.useEffect(() => () => onClose(), [])
61
66
 
67
+ if (shouldUseDrawer) {
68
+ return (
69
+ <DrawerPopover
70
+ content={content}
71
+ renderContent={renderContent}
72
+ children={children}
73
+ {...props}
74
+ {...bottomDrawerProps}
75
+ />
76
+ )
77
+ }
78
+
62
79
  const child = React.Children.only(children)
63
80
  let childProps = { ref, onClick: show }
64
81
 
65
82
  if (hover) childProps = { ref, onMouseEnter: show, onMouseLeave: onClose }
66
- if (focus) childProps = { ref, onFocus: show, onBlur: onClose }
83
+ if (focus) childProps = { ref, onFocus: show }
67
84
 
68
85
  return React.cloneElement(child, childProps)
69
86
  }
87
+
88
+ function DrawerPopover({ children, content, renderContent, snapPoints, ...props }) {
89
+ const [open, setOpen] = React.useState(false)
90
+ const onClose = () => setOpen(false)
91
+
92
+ const child = React.Children.only(children)
93
+ let childProps = { onClick: () => setOpen(true) }
94
+
95
+ return (
96
+ <>
97
+ {React.cloneElement(child, childProps)}
98
+
99
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...props}>
100
+ {renderContent({ onClose })}
101
+ </BottomDrawer>
102
+ </>
103
+ )
104
+ }
@@ -1,17 +1,35 @@
1
1
  import { Modal, TouchableWithoutFeedback } from 'react-native'
2
2
  import React from 'react'
3
3
 
4
+ import { BottomDrawer } from '../bottomDrawer'
4
5
  import { PopoverContent } from './PopoverContent'
5
6
  import { View } from '../View'
6
7
  import { calculatePosition } from '../overlay/calculatePosition'
8
+ import { useResponsiveValue } from '../../../responsive'
7
9
 
8
- export function Popover({ content, placement = 'bottom', children, ...props }) {
10
+ export function Popover({
11
+ content,
12
+ renderContent,
13
+ placement = 'bottom',
14
+ children,
15
+ useBottomDrawer = {},
16
+ bottomDrawerProps = {},
17
+ snapPoints,
18
+ ...props
19
+ }) {
20
+ const shouldUseDrawer = useResponsiveValue(useBottomDrawer)
9
21
  const ref = React.useRef(null)
10
- const [visible, setVisible] = React.useState(false)
22
+ const [open, setOpen] = React.useState(false)
11
23
  const [triggerRect, setTriggerRect] = React.useState(null)
12
24
  const [position, setPosition] = React.useState(null)
13
25
 
14
- const show = () => {
26
+ renderContent = renderContent || (() => content)
27
+
28
+ const onOpen = () => {
29
+ if (shouldUseDrawer) {
30
+ setOpen(true)
31
+ return
32
+ }
15
33
  if (ref.current) {
16
34
  ref.current.measureInWindow((x, y, width, height) => {
17
35
  setTriggerRect({
@@ -22,29 +40,41 @@ export function Popover({ content, placement = 'bottom', children, ...props }) {
22
40
  width,
23
41
  height,
24
42
  })
25
- setVisible(true)
43
+ setOpen(true)
26
44
  })
27
45
  }
28
46
  }
29
47
 
30
- const hide = () => {
31
- setVisible(false)
48
+ const onClose = () => {
49
+ setOpen(false)
32
50
  setTriggerRect(null)
33
51
  setPosition(null)
34
52
  }
35
53
 
36
- return (
37
- <>
54
+ children = React.cloneElement(React.Children.only(children), {
55
+ onPress: onOpen,
56
+ })
57
+
58
+ if (shouldUseDrawer) {
59
+ return (
38
60
  <View ref={ref}>
39
- {React.cloneElement(React.Children.only(children), {
40
- onPress: show,
41
- })}
61
+ {children}
62
+
63
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...bottomDrawerProps}>
64
+ {renderContent({ onClose: onClose })}
65
+ </BottomDrawer>
42
66
  </View>
67
+ )
68
+ }
69
+
70
+ return (
71
+ <>
72
+ <View ref={ref}>{children}</View>
43
73
 
44
- {visible && (
45
- <Modal transparent visible={visible} animationType="fade" onRequestClose={hide}>
46
- <View fullW flex fullH bg="bg_op50">
47
- <TouchableWithoutFeedback onPress={hide}>
74
+ {open && (
75
+ <Modal transparent visible={open} animationType="fade" onRequestClose={onClose}>
76
+ <View fullW flex fullH bg="backdrop_op50">
77
+ <TouchableWithoutFeedback onPress={onClose}>
48
78
  <View style={{ flex: 1 }}>
49
79
  {triggerRect && (
50
80
  <View
@@ -61,7 +91,7 @@ export function Popover({ content, placement = 'bottom', children, ...props }) {
61
91
  }}
62
92
  >
63
93
  <PopoverContent placement={placement} {...props}>
64
- {content}
94
+ {renderContent({ onClose: onClose })}
65
95
  </PopoverContent>
66
96
  </View>
67
97
  )}
@@ -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
+ }