@neko-os/ui 0.0.8 → 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 (102) 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/BlurView.web.js +1 -0
  5. package/dist/abstractions/FlatList.js +1 -0
  6. package/dist/abstractions/FlatList.native.js +1 -0
  7. package/dist/abstractions/FlatList.web.js +1 -0
  8. package/dist/abstractions/ScrollView.web.js +1 -0
  9. package/dist/abstractions/helpers/storage.js +1 -0
  10. package/dist/abstractions/helpers/storage.native.js +1 -0
  11. package/dist/components/actions/Button.js +1 -1
  12. package/dist/components/actions/Dropdown.js +1 -1
  13. package/dist/components/actions/menu/VerticalMenu.js +1 -1
  14. package/dist/components/index.js +1 -1
  15. package/dist/components/layout/Layout.js +1 -1
  16. package/dist/components/list/FlatList.js +1 -0
  17. package/dist/components/list/index.js +1 -1
  18. package/dist/components/state/LoadingView.js +1 -1
  19. package/dist/components/structure/View.js +1 -1
  20. package/dist/components/structure/bottomDrawer/native/BottomDrawer.js +1 -1
  21. package/dist/components/structure/popover/Popover.js +1 -1
  22. package/dist/components/structure/popover/Popover.native.js +1 -1
  23. package/dist/components/theme/ThemePicker.js +1 -0
  24. package/dist/components/theme/ThemePickerDrawer.js +1 -0
  25. package/dist/components/theme/ThemeStatusBar.js +1 -0
  26. package/dist/components/theme/ThemeStatusBar.native.js +1 -0
  27. package/dist/components/theme/ThemeThumb.js +1 -0
  28. package/dist/components/theme/index.js +1 -0
  29. package/dist/helpers/index.js +1 -1
  30. package/dist/helpers/storage.js +1 -0
  31. package/dist/modifiers/fullColor.js +1 -1
  32. package/dist/theme/ThemeHandler.js +1 -1
  33. package/dist/theme/default/base.js +1 -1
  34. package/dist/theme/default/blackTheme.js +1 -1
  35. package/dist/theme/default/cyberpunkTheme.js +1 -1
  36. package/dist/theme/default/darkTheme.js +1 -1
  37. package/dist/theme/default/deepWoodsTheme.js +1 -1
  38. package/dist/theme/default/forestTheme.js +1 -1
  39. package/dist/theme/default/hackerTheme.js +1 -1
  40. package/dist/theme/default/lightTheme.js +1 -1
  41. package/dist/theme/default/midnightTheme.js +1 -1
  42. package/dist/theme/default/msdosTheme.js +1 -1
  43. package/dist/theme/default/oceanTheme.js +1 -1
  44. package/dist/theme/default/paperTheme.js +1 -0
  45. package/dist/theme/default/pastelTheme.js +1 -1
  46. package/dist/theme/default/sunsetTheme.js +1 -1
  47. package/dist/theme/default/themes.js +1 -1
  48. package/dist/theme/format/formatTheme.js +1 -1
  49. package/dist/theme/helpers/contrastColor.js +1 -1
  50. package/package.json +1 -1
  51. package/src/NekoUI.js +13 -1
  52. package/src/abstractions/ActivityIndicator.native.js +3 -4
  53. package/src/abstractions/ActivityIndicator.web.js +43 -0
  54. package/src/abstractions/BlurView.web.js +39 -0
  55. package/src/abstractions/FlatList.js +39 -0
  56. package/src/abstractions/FlatList.native.js +32 -0
  57. package/src/abstractions/FlatList.web.js +3 -0
  58. package/src/abstractions/ScrollView.web.js +3 -0
  59. package/src/abstractions/Text.web.js +15 -0
  60. package/src/abstractions/helpers/storage.js +32 -0
  61. package/src/abstractions/helpers/storage.native.js +34 -0
  62. package/src/components/actions/Button.js +1 -0
  63. package/src/components/actions/Dropdown.js +17 -2
  64. package/src/components/actions/menu/VerticalMenu.js +1 -1
  65. package/src/components/index.js +1 -0
  66. package/src/components/layout/Layout.js +1 -1
  67. package/src/components/list/FlatList.js +54 -0
  68. package/src/components/list/index.js +1 -0
  69. package/src/components/state/LoadingView.js +10 -1
  70. package/src/components/structure/View.js +2 -0
  71. package/src/components/structure/bottomDrawer/native/BottomDrawer.js +15 -2
  72. package/src/components/structure/popover/Popover.js +11 -2
  73. package/src/components/structure/popover/Popover.native.js +3 -2
  74. package/src/components/theme/ThemePicker.js +49 -0
  75. package/src/components/theme/ThemePickerDrawer.js +13 -0
  76. package/src/components/theme/ThemeStatusBar.js +3 -0
  77. package/src/components/theme/ThemeStatusBar.native.js +9 -0
  78. package/src/components/theme/ThemeThumb.js +98 -0
  79. package/src/components/theme/index.js +3 -0
  80. package/src/helpers/index.js +1 -0
  81. package/src/helpers/storage.js +54 -0
  82. package/src/modifiers/fullColor.js +2 -2
  83. package/src/theme/ThemeHandler.js +18 -2
  84. package/src/theme/default/base.js +6 -6
  85. package/src/theme/default/blackTheme.js +4 -1
  86. package/src/theme/default/cyberpunkTheme.js +3 -1
  87. package/src/theme/default/darkTheme.js +3 -1
  88. package/src/theme/default/deepWoodsTheme.js +4 -2
  89. package/src/theme/default/forestTheme.js +3 -1
  90. package/src/theme/default/hackerTheme.js +3 -1
  91. package/src/theme/default/lightTheme.js +3 -1
  92. package/src/theme/default/midnightTheme.js +3 -1
  93. package/src/theme/default/msdosTheme.js +18 -4
  94. package/src/theme/default/oceanTheme.js +4 -2
  95. package/src/theme/default/paperTheme.js +35 -0
  96. package/src/theme/default/pastelTheme.js +3 -1
  97. package/src/theme/default/sunsetTheme.js +5 -3
  98. package/src/theme/default/themes.js +7 -10
  99. package/src/theme/format/formatTheme.js +9 -3
  100. package/src/theme/helpers/contrastColor.js +49 -11
  101. package/dist/abstractions/TouchableOpacity.web.js +0 -1
  102. package/src/abstractions/TouchableOpacity.web.js +0 -3
@@ -0,0 +1,39 @@
1
+ import { AbsView } from './View'
2
+
3
+ let AbsBlurView
4
+
5
+ try {
6
+ const { BlurView } = require('expo-blur') || {}
7
+ AbsBlurView = ({ intensity, tint, disabledForAndroid, style, children, ...props }) => {
8
+ return (
9
+ <BlurView
10
+ intensity={intensity}
11
+ tint={tint}
12
+ style={[style, { overflow: 'hidden' }]}
13
+ experimentalBlurMethod={disabledForAndroid ? 'none' : 'dimezisBlurView'}
14
+ >
15
+ {children}
16
+ </BlurView>
17
+ )
18
+
19
+ // return (
20
+ // <AbsView style={[style, { overflow: 'hidden' }]} {...props}>
21
+ // <BlurView
22
+ // intensity={intensity}
23
+ // tint={tint}
24
+ // style={[style, { width: '100%' }]}
25
+ // experimentalBlurMethod={disabledForAndroid ? 'none' : 'dimezisBlurView'}
26
+ // >
27
+ // {children}
28
+ // </BlurView>
29
+ // </AbsView>
30
+ // )
31
+ }
32
+ } catch {
33
+ AbsBlurView = (props) => {
34
+ console.warn('expo-blur not instaled.')
35
+ return <AbsView {...props} />
36
+ }
37
+ }
38
+
39
+ export { AbsBlurView }
@@ -0,0 +1,39 @@
1
+ import React from 'react'
2
+ import { AbsView } from './View'
3
+
4
+ const defaultRender = () => false
5
+
6
+ export function AbsFlatList({
7
+ data,
8
+ renderItem,
9
+ ListEmptyComponent,
10
+ Empty,
11
+ renderEmpty,
12
+ ListFooterComponent,
13
+ Footer,
14
+ renderFooter,
15
+ ListHeaderComponent,
16
+ Header,
17
+ renderHeader,
18
+ keyExtractor,
19
+ ...props
20
+ }) {
21
+ ListEmptyComponent = ListEmptyComponent || Empty || defaultRender
22
+ ListFooterComponent = ListFooterComponent || Footer || renderFooter || defaultRender
23
+ ListHeaderComponent = ListHeaderComponent || Header || renderHeader || defaultRender
24
+ keyExtractor = keyExtractor || ((item, index) => index)
25
+ renderItem = renderItem || defaultRender
26
+
27
+ return (
28
+ <AbsView {...props}>
29
+ <ListHeaderComponent />
30
+
31
+ {!data?.length && <ListEmptyComponent />}
32
+ {data?.map?.((item, index) => (
33
+ <React.Fragment key={keyExtractor(item, index)}>{renderItem({ item, index })}</React.Fragment>
34
+ ))}
35
+
36
+ <ListFooterComponent />
37
+ </AbsView>
38
+ )
39
+ }
@@ -0,0 +1,32 @@
1
+ import { FlatList } from 'react-native'
2
+
3
+ export const AbsFlatList = ({
4
+ style: { height, width, ...style },
5
+ ListEmptyComponent,
6
+ Empty,
7
+ renderEmpty,
8
+ ListFooterComponent,
9
+ Footer,
10
+ renderFooter,
11
+ ListHeaderComponent,
12
+ Header,
13
+ renderHeader,
14
+
15
+ ...props
16
+ }) => {
17
+ ListEmptyComponent = ListEmptyComponent || Empty || defaultRender
18
+ ListFooterComponent = ListFooterComponent || Footer || renderFooter || defaultRender
19
+ ListHeaderComponent = ListHeaderComponent || Header || renderHeader || defaultRender
20
+
21
+ return (
22
+ <FlatList
23
+ height={height}
24
+ width={width}
25
+ {...props}
26
+ ListEmptyComponent={ListEmptyComponent}
27
+ ListFooterComponent={ListFooterComponent}
28
+ ListHeaderComponent={ListHeaderComponent}
29
+ contentContainerStyle={style}
30
+ />
31
+ )
32
+ }
@@ -0,0 +1,3 @@
1
+ import { AbsFlatList as NativeFlatList } from './FlatList.native'
2
+
3
+ export const AbsFlatList = NativeFlatList
@@ -0,0 +1,3 @@
1
+ import { AbsScrollView as NativeAbsScrollView } from './ScrollView.native'
2
+
3
+ export const AbsScrollView = NativeAbsScrollView
@@ -1,3 +1,18 @@
1
+ // export const AbsText = ({ numberOfLines, style, ...props }) => {
2
+ // style = style || {}
3
+
4
+ // const limitLinesStyle = !!numberOfLines
5
+ // ? {
6
+ // display: '-webkit-box',
7
+ // WebkitLineClamp: numberOfLines,
8
+ // WebkitBoxOrient: 'vertical',
9
+ // overflow: 'hidden',
10
+ // }
11
+ // : {}
12
+
13
+ // return <AbsText {...props} style={[limitLinesStyle, style]} />
14
+ // }
15
+
1
16
  import { Text as RNText } from 'react-native'
2
17
 
3
18
  export const AbsText = RNText
@@ -0,0 +1,32 @@
1
+ function set(key, value) {
2
+ return localStorage.setItem(key, value)
3
+ }
4
+
5
+ function setAsync(key, value) {
6
+ return Promise.resulve(set(key, value))
7
+ }
8
+
9
+ function get(key) {
10
+ return localStorage.getItem(key)
11
+ }
12
+
13
+ function getAsync(key) {
14
+ return Promise.resulve(get(key))
15
+ }
16
+
17
+ function remove(key) {
18
+ return localStorage.removeItem(key)
19
+ }
20
+
21
+ function removeAsync(key) {
22
+ return Promise.resulve(remove(key))
23
+ }
24
+
25
+ export const AbsStorage = {
26
+ set,
27
+ setAsync,
28
+ get,
29
+ getAsync,
30
+ remove,
31
+ removeAsync,
32
+ }
@@ -0,0 +1,34 @@
1
+ let set = () => console.warn('expo-sqlite not installed. Neko Storage needs expo-sqlite to work properly')
2
+ let setAsync = () => Promise.resolve(set())
3
+
4
+ let get = () => console.warn('expo-sqlite not installed. Neko Storage needs expo-sqlite to work properly')
5
+ let getAsync = () => Promise.resolve(get())
6
+
7
+ let remove = () => console.warn('expo-sqlite not installed. Neko Storage needs expo-sqlite to work properly')
8
+ let removeAsync = () => Promise.resolve(remove())
9
+
10
+ try {
11
+ const StorageModule = require('expo-sqlite/kv-store')
12
+ if (StorageModule?.default) {
13
+ const Storage = StorageModule.default
14
+ set = Storage.setItemSync.bind(Storage)
15
+ setAsync = Storage.setItem.bind(Storage)
16
+
17
+ get = Storage.getItemSync.bind(Storage)
18
+ getAsync = Storage.getItem.bind(Storage)
19
+
20
+ remove = Storage.removeItemSync.bind(Storage)
21
+ removeAsync = Storage.removeItem.bind(Storage)
22
+ }
23
+ } catch (e) {
24
+ console.log('expo-sqlite not available:', e)
25
+ }
26
+
27
+ export const AbsStorage = {
28
+ set,
29
+ setAsync,
30
+ get,
31
+ getAsync,
32
+ remove,
33
+ removeAsync,
34
+ }
@@ -27,6 +27,7 @@ const DEFAULT_PROPS = ([{ sizeCode }]) => ({
27
27
  br: sizeCode,
28
28
  border: 1,
29
29
  center: true,
30
+ pointer: true,
30
31
  hover: {
31
32
  opacity: 0.7,
32
33
  },
@@ -31,6 +31,8 @@ export function Dropdown({ items, ...rootProps }) {
31
31
  popoverProps,
32
32
  iconLabelProps,
33
33
  children,
34
+ placement,
35
+ gap,
34
36
  ...props
35
37
  } = formattedProps
36
38
 
@@ -38,17 +40,29 @@ export function Dropdown({ items, ...rootProps }) {
38
40
  <View className="neko-dropdown" {...props}>
39
41
  <Popover
40
42
  useParentMinWidth
41
- placement="bottomLeft"
43
+ placement={placement || 'bottomLeft'}
42
44
  trigger={trigger}
43
45
  padding="xs"
44
46
  useBottomDrawer={{ native: true, sm: true, md: true }}
47
+ bottomDrawerProps={{
48
+ bg: 'mainBG',
49
+ contentProps: { bg: 'overlayBG', br: 'lg', margin: 'md' },
50
+ }}
45
51
  {...popoverProps}
46
52
  renderContent={({ onClose }) => {
47
53
  const handleChange = (...params) => {
48
54
  if (onChange) onChange(...params)
49
55
  onClose()
50
56
  }
51
- return <Menu vertical items={items} onChange={handleChange} linkPaddingH="xs" />
57
+ return (
58
+ <Menu
59
+ vertical
60
+ items={items}
61
+ onChange={handleChange}
62
+ _linkPaddingV="lg"
63
+ _linkProps={{ borderB: true, padding: 'lg', borderL: 0, brColor: 'divider' }}
64
+ />
65
+ )
52
66
  }}
53
67
  >
54
68
  {children || (
@@ -59,6 +73,7 @@ export function Dropdown({ items, ...rootProps }) {
59
73
  strong={strong}
60
74
  color={color}
61
75
  invert
76
+ gap={gap}
62
77
  {...iconLabelProps}
63
78
  />
64
79
  </Link>
@@ -42,7 +42,7 @@ function LinkItem({
42
42
  marginR={3}
43
43
  borderL={3}
44
44
  marginV={-4}
45
- borderColor={active ? activeColor : 'transparent'}
45
+ brColor={active ? activeColor : 'transparent'}
46
46
  bg={bg}
47
47
  transition="border-color 0.5s ease, background 0.3s ease"
48
48
  hover={{ br: 0 }}
@@ -12,3 +12,4 @@ export * from './table'
12
12
  export * from './feedback'
13
13
  export * from './calendar'
14
14
  export * from './list'
15
+ export * from './theme'
@@ -32,7 +32,7 @@ export function Layout({ children, ...rootProps }) {
32
32
 
33
33
  return (
34
34
  <LayoutContext.Provider value={value}>
35
- <View className="neko-layout" bg="bg" flex relative {...rootProps} ref={layoutRef}>
35
+ <View className="neko-layout" bg="mainBG" flex relative {...rootProps} ref={layoutRef}>
36
36
  {children}
37
37
  </View>
38
38
  </LayoutContext.Provider>
@@ -0,0 +1,54 @@
1
+ import { pipe } from 'ramda'
2
+
3
+ import { AbsFlatList } from '../../abstractions/FlatList'
4
+ import { useAnimationModifier } from '../../modifiers/animation'
5
+ import { useBackgroundModifier } from '../../modifiers/background'
6
+ import { useBorderModifier } from '../../modifiers/border'
7
+ import { useDefaultModifier } from '../../modifiers/default'
8
+ import { useDisplayModifier } from '../../modifiers/display'
9
+ import { useFlexModifier } from '../../modifiers/flex'
10
+ import { useFlexWrapperModifier } from '../../modifiers/flexWrapper'
11
+ import { useMarginModifier } from '../../modifiers/margin'
12
+ import { useOverflowModifier } from '../../modifiers/overflow'
13
+ import { usePaddingModifier } from '../../modifiers/padding'
14
+ import { usePositionModifier } from '../../modifiers/position'
15
+ import { useShadowModifier } from '../../modifiers/shadow'
16
+ import { useSizeModifier } from '../../modifiers/size'
17
+ import { useStateModifier } from '../../modifiers/state'
18
+ import { useThemeComponentModifier } from '../../modifiers/themeComponent'
19
+
20
+ const DEFAULT_PROPS = ([_, { horizontal }]) => {
21
+ const overflowKey = horizontal ? 'scrollX' : 'scrollY'
22
+
23
+ return {
24
+ [overflowKey]: true,
25
+ row: !!horizontal,
26
+ }
27
+ }
28
+
29
+ export function FlatList({ children, ...rootProps }) {
30
+ const [_, props] = pipe(
31
+ useThemeComponentModifier('FlatList'),
32
+ useDefaultModifier(DEFAULT_PROPS),
33
+ useFlexWrapperModifier,
34
+ useDisplayModifier,
35
+ useAnimationModifier,
36
+ useStateModifier,
37
+ useSizeModifier,
38
+ usePositionModifier,
39
+ useOverflowModifier,
40
+ usePaddingModifier,
41
+ useMarginModifier,
42
+ useFlexModifier,
43
+ useBackgroundModifier,
44
+ useBorderModifier,
45
+ useShadowModifier
46
+ )([{}, rootProps])
47
+ // useNormalView = useResponsiveValue(useNormalView)
48
+
49
+ return (
50
+ <AbsFlatList className="neko-flat-list" {...props}>
51
+ {children}
52
+ </AbsFlatList>
53
+ )
54
+ }
@@ -1 +1,2 @@
1
1
  export * from './ScrollView'
2
+ export * from './FlatList'
@@ -18,7 +18,16 @@ export function LoadingView({ active, children, size, color, replaceChildren, no
18
18
  return (
19
19
  <View className="neko-loading-view" relative {...props}>
20
20
  {children}
21
- <View className="neko-laoding-view-overlay" bg="bg_op90" absolute top={0} left={0} right={0} bottom={0} center>
21
+ <View
22
+ className="neko-laoding-view-overlay"
23
+ bg="mainBG_op90"
24
+ absolute
25
+ top={0}
26
+ left={0}
27
+ right={0}
28
+ bottom={0}
29
+ center
30
+ >
22
31
  {loader}
23
32
  </View>
24
33
  </View>
@@ -4,6 +4,7 @@ import { AbsView } from '../../abstractions/View'
4
4
  import { useAnimationModifier } from '../../modifiers/animation'
5
5
  import { useBackgroundModifier } from '../../modifiers/background'
6
6
  import { useBorderModifier } from '../../modifiers/border'
7
+ import { useCursorModifier } from '../../modifiers/cursor'
7
8
  import { useDisplayModifier } from '../../modifiers/display'
8
9
  import { useFlexModifier } from '../../modifiers/flex'
9
10
  import { useFlexWrapperModifier } from '../../modifiers/flexWrapper'
@@ -21,6 +22,7 @@ export function View({ children, ...rootProps }) {
21
22
  useThemeComponentModifier('View'),
22
23
  useFlexWrapperModifier,
23
24
  useDisplayModifier,
25
+ useCursorModifier,
24
26
  useAnimationModifier,
25
27
  useStateModifier,
26
28
  useSizeModifier,
@@ -189,8 +189,21 @@ function InnerContent({
189
189
 
190
190
  <DrawerProvider value={contextValue}>
191
191
  <GestureDetector gesture={panGesture}>
192
- <Animated.View style={[styles.container, { height: SCREEN_HEIGHT }, animatedSheetStyle]}>
193
- <View flex bg="overlayBG" shadow paddingB={useSafeArea && bottomInset} borderRadiusT="xxxl" {...props}>
192
+ <Animated.View
193
+ style={[styles.container, { height: SCREEN_HEIGHT }, animatedSheetStyle]}
194
+ pointerEvents="box-none"
195
+ >
196
+ <View
197
+ flex
198
+ bg="overlayBG"
199
+ shadow
200
+ paddingB={useSafeArea && bottomInset}
201
+ borderRadiusT="xxxl"
202
+ marginL="auto"
203
+ marginR="auto"
204
+ fullW
205
+ {...props}
206
+ >
194
207
  <DrawerHandle hide={hideHandle} />
195
208
  <View flex {...contentProps}>
196
209
  {children}
@@ -15,6 +15,7 @@ export function Popover({
15
15
  parentWidth,
16
16
  parentMinWidth,
17
17
  useBottomDrawer = {},
18
+ bottomDrawerProps = {},
18
19
  ...props
19
20
  }) {
20
21
  const shouldUseDrawer = useResponsiveValue(useBottomDrawer)
@@ -64,7 +65,15 @@ export function Popover({
64
65
  React.useEffect(() => () => onClose(), [])
65
66
 
66
67
  if (shouldUseDrawer) {
67
- return <DrawerPopover content={content} renderContent={renderContent} children={children} {...props} />
68
+ return (
69
+ <DrawerPopover
70
+ content={content}
71
+ renderContent={renderContent}
72
+ children={children}
73
+ {...props}
74
+ {...bottomDrawerProps}
75
+ />
76
+ )
68
77
  }
69
78
 
70
79
  const child = React.Children.only(children)
@@ -87,7 +96,7 @@ function DrawerPopover({ children, content, renderContent, snapPoints, ...props
87
96
  <>
88
97
  {React.cloneElement(child, childProps)}
89
98
 
90
- <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints}>
99
+ <BottomDrawer open={open} onClose={onClose} snapPoints={snapPoints} {...props}>
91
100
  {renderContent({ onClose })}
92
101
  </BottomDrawer>
93
102
  </>
@@ -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,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'