@chem-po/react-native 0.0.41 → 0.0.43

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 (90) hide show
  1. package/lib/commonjs/components/form/input/Editable.js +7 -4
  2. package/lib/commonjs/components/form/input/Editable.js.map +1 -1
  3. package/lib/commonjs/components/form/input/date/index.js +2 -2
  4. package/lib/commonjs/components/form/input/date/index.js.map +1 -1
  5. package/lib/commonjs/components/form/input/datetime/index.js +2 -2
  6. package/lib/commonjs/components/form/input/datetime/index.js.map +1 -1
  7. package/lib/commonjs/components/form/input/file/index.js +3 -2
  8. package/lib/commonjs/components/form/input/file/index.js.map +1 -1
  9. package/lib/commonjs/components/form/input/multipleSelect/index.js +8 -8
  10. package/lib/commonjs/components/form/input/multipleSelect/index.js.map +1 -1
  11. package/lib/commonjs/components/form/input/select/index.js +3 -6
  12. package/lib/commonjs/components/form/input/select/index.js.map +1 -1
  13. package/lib/commonjs/components/form/view/file.js +4 -2
  14. package/lib/commonjs/components/form/view/file.js.map +1 -1
  15. package/lib/commonjs/components/form/view/index.js +9 -3
  16. package/lib/commonjs/components/form/view/index.js.map +1 -1
  17. package/lib/commonjs/components/form/view/multipleSelect.js +7 -9
  18. package/lib/commonjs/components/form/view/multipleSelect.js.map +1 -1
  19. package/lib/commonjs/components/form/view/select.js +14 -11
  20. package/lib/commonjs/components/form/view/select.js.map +1 -1
  21. package/lib/commonjs/components/image/ImageViewModal.js +2 -1
  22. package/lib/commonjs/components/image/ImageViewModal.js.map +1 -1
  23. package/lib/commonjs/components/loading/CircularProgress.js +2 -1
  24. package/lib/commonjs/components/loading/CircularProgress.js.map +1 -1
  25. package/lib/commonjs/utils/downloadFile.js +34 -23
  26. package/lib/commonjs/utils/downloadFile.js.map +1 -1
  27. package/lib/commonjs/utils/downloadFileLegacy.js +64 -0
  28. package/lib/commonjs/utils/downloadFileLegacy.js.map +1 -0
  29. package/lib/module/components/form/input/Editable.js +7 -4
  30. package/lib/module/components/form/input/Editable.js.map +1 -1
  31. package/lib/module/components/form/input/date/index.js +2 -2
  32. package/lib/module/components/form/input/date/index.js.map +1 -1
  33. package/lib/module/components/form/input/datetime/index.js +2 -2
  34. package/lib/module/components/form/input/datetime/index.js.map +1 -1
  35. package/lib/module/components/form/input/file/index.js +3 -2
  36. package/lib/module/components/form/input/file/index.js.map +1 -1
  37. package/lib/module/components/form/input/multipleSelect/index.js +9 -9
  38. package/lib/module/components/form/input/multipleSelect/index.js.map +1 -1
  39. package/lib/module/components/form/input/select/index.js +4 -7
  40. package/lib/module/components/form/input/select/index.js.map +1 -1
  41. package/lib/module/components/form/view/file.js +4 -2
  42. package/lib/module/components/form/view/file.js.map +1 -1
  43. package/lib/module/components/form/view/index.js +9 -3
  44. package/lib/module/components/form/view/index.js.map +1 -1
  45. package/lib/module/components/form/view/multipleSelect.js +7 -9
  46. package/lib/module/components/form/view/multipleSelect.js.map +1 -1
  47. package/lib/module/components/form/view/select.js +13 -10
  48. package/lib/module/components/form/view/select.js.map +1 -1
  49. package/lib/module/components/image/ImageViewModal.js +2 -1
  50. package/lib/module/components/image/ImageViewModal.js.map +1 -1
  51. package/lib/module/components/loading/CircularProgress.js +3 -2
  52. package/lib/module/components/loading/CircularProgress.js.map +1 -1
  53. package/lib/module/utils/downloadFile.js +34 -22
  54. package/lib/module/utils/downloadFile.js.map +1 -1
  55. package/lib/module/utils/downloadFileLegacy.js +57 -0
  56. package/lib/module/utils/downloadFileLegacy.js.map +1 -0
  57. package/lib/typescript/components/form/input/Editable.d.ts +1 -1
  58. package/lib/typescript/components/form/input/Editable.d.ts.map +1 -1
  59. package/lib/typescript/components/form/input/file/index.d.ts +3 -2
  60. package/lib/typescript/components/form/input/file/index.d.ts.map +1 -1
  61. package/lib/typescript/components/form/input/multipleSelect/index.d.ts.map +1 -1
  62. package/lib/typescript/components/form/input/select/index.d.ts.map +1 -1
  63. package/lib/typescript/components/form/view/file.d.ts +3 -2
  64. package/lib/typescript/components/form/view/file.d.ts.map +1 -1
  65. package/lib/typescript/components/form/view/index.d.ts +3 -2
  66. package/lib/typescript/components/form/view/index.d.ts.map +1 -1
  67. package/lib/typescript/components/form/view/multipleSelect.d.ts +6 -3
  68. package/lib/typescript/components/form/view/multipleSelect.d.ts.map +1 -1
  69. package/lib/typescript/components/form/view/select.d.ts +10 -6
  70. package/lib/typescript/components/form/view/select.d.ts.map +1 -1
  71. package/lib/typescript/components/image/ImageViewModal.d.ts.map +1 -1
  72. package/lib/typescript/components/loading/CircularProgress.d.ts.map +1 -1
  73. package/lib/typescript/utils/downloadFile.d.ts.map +1 -1
  74. package/lib/typescript/utils/downloadFileLegacy.d.ts +4 -0
  75. package/lib/typescript/utils/downloadFileLegacy.d.ts.map +1 -0
  76. package/package.json +27 -27
  77. package/src/components/form/input/Editable.tsx +5 -4
  78. package/src/components/form/input/date/index.tsx +2 -2
  79. package/src/components/form/input/datetime/index.tsx +2 -2
  80. package/src/components/form/input/file/index.tsx +4 -2
  81. package/src/components/form/input/multipleSelect/index.tsx +5 -6
  82. package/src/components/form/input/select/index.tsx +7 -12
  83. package/src/components/form/view/file.tsx +5 -3
  84. package/src/components/form/view/index.tsx +17 -3
  85. package/src/components/form/view/multipleSelect.tsx +13 -11
  86. package/src/components/form/view/select.tsx +24 -16
  87. package/src/components/image/ImageViewModal.tsx +2 -1
  88. package/src/components/loading/CircularProgress.tsx +3 -2
  89. package/src/utils/downloadFile.ts +35 -20
  90. package/src/utils/downloadFileLegacy.ts +66 -0
@@ -6,7 +6,7 @@ import { StyleSheet, Text, View } from 'react-native'
6
6
  import { Gesture, GestureDetector } from 'react-native-gesture-handler'
7
7
  import { Portal } from 'react-native-paper'
8
8
  import { DatePickerModal } from 'react-native-paper-dates'
9
- import { runOnJS } from 'react-native-reanimated'
9
+ import { scheduleOnRN } from 'react-native-worklets'
10
10
  import { FieldProps } from '../../types'
11
11
  import { DateInputClearButton } from '../common/InputClearButton'
12
12
  import { useInputColor } from '../hooks/useInputColor'
@@ -55,7 +55,7 @@ export const DateInput = forwardRef<InputRef, FieldProps<DateField>>(
55
55
  const maxDateObj = maxDate === 'now' ? new Date() : maxDate ? new Date(maxDate) : undefined
56
56
 
57
57
  const mainTap = Gesture.Tap().onStart(() => {
58
- runOnJS(onFocus)()
58
+ scheduleOnRN(onFocus)
59
59
  })
60
60
 
61
61
  return (
@@ -6,7 +6,7 @@ import { StyleSheet, Text, View } from 'react-native'
6
6
  import { Gesture, GestureDetector, Pressable } from 'react-native-gesture-handler'
7
7
  import { Portal } from 'react-native-paper'
8
8
  import { DatePickerModal, TimePickerModal } from 'react-native-paper-dates'
9
- import { runOnJS } from 'react-native-reanimated'
9
+ import { scheduleOnRN } from 'react-native-worklets'
10
10
  import { FieldProps } from '../../types'
11
11
  import { DateInputClearButton } from '../common/InputClearButton'
12
12
  import { useInputColor } from '../hooks/useInputColor'
@@ -96,7 +96,7 @@ export const DateTimeInput = forwardRef<InputRef, FieldProps<DateTimeField>>(
96
96
  const inputColor = useInputColor(value)
97
97
 
98
98
  const mainTap = Gesture.Tap().onStart(() => {
99
- runOnJS(handleFocusDate)()
99
+ scheduleOnRN(handleFocusDate)
100
100
  })
101
101
 
102
102
  return (
@@ -13,7 +13,7 @@ import { Ionicons } from '@expo/vector-icons'
13
13
  import * as DocumentPicker from 'expo-document-picker'
14
14
  import * as ImagePicker from 'expo-image-picker'
15
15
  import React, { forwardRef, useCallback, useImperativeHandle, useMemo } from 'react'
16
- import { Platform, StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native'
16
+ import { Platform, StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native'
17
17
  import { Pressable } from 'react-native-gesture-handler'
18
18
  import { downloadFile } from '../../../../utils/downloadFile'
19
19
  import { LoadingImage } from '../../../loading/LoadingImage'
@@ -56,6 +56,7 @@ export const FileView = ({
56
56
  nonImageContainerStyle,
57
57
  withDownload,
58
58
  onUploadPress,
59
+ textStyle,
59
60
  }: {
60
61
  value?: FileValue | null
61
62
  hasUpload?: boolean
@@ -64,6 +65,7 @@ export const FileView = ({
64
65
  nonImageContainerStyle?: StyleProp<ViewStyle>
65
66
  withDownload?: boolean
66
67
  onUploadPress?: () => void
68
+ textStyle?: StyleProp<TextStyle>
67
69
  }) => {
68
70
  const { storagePath, dataUrl } = value ?? {}
69
71
  const missingFile = !dataUrl && !storagePath
@@ -131,7 +133,7 @@ export const FileView = ({
131
133
  <Ionicons name="document" size={24} color={iconColor} />
132
134
  </View>
133
135
  <View style={styles.filenameContainer}>
134
- <Text numberOfLines={1} style={[styles.filename, { color: fileNameColor }]}>
136
+ <Text numberOfLines={1} style={[styles.filename, { color: fileNameColor }, textStyle]}>
135
137
  {value.filename}
136
138
  </Text>
137
139
  </View>
@@ -4,7 +4,6 @@ import {
4
4
  useBackgroundColor,
5
5
  useBorderColor,
6
6
  useColorMode,
7
- useColorModeValue,
8
7
  useIconColor,
9
8
  usePlaceholderColor,
10
9
  useTextColor,
@@ -58,7 +57,7 @@ const BaseMultipleSelectComponent = <T extends MultipleSelectField>(
58
57
  const placeholderColor = usePlaceholderColor()
59
58
  const menuBg = useBackgroundColor(100)
60
59
  const inputBg = useBackgroundColor(50)
61
- const selectedOptionBg = useColorModeValue('#ffffff22', '#ffffff22')
60
+ const selectedOptionBg = useBackgroundColor(50)
62
61
  const borderColor = useBorderColor()
63
62
 
64
63
  useImperativeHandle(ref, () => ({
@@ -86,7 +85,7 @@ const BaseMultipleSelectComponent = <T extends MultipleSelectField>(
86
85
  return RenderOption(props)
87
86
  }
88
87
  return (
89
- <View style={{ padding: 6 }}>
88
+ <View style={[container, { width: 'auto' }]}>
90
89
  <Txt style={[text]}>{props.option.label}</Txt>
91
90
  </View>
92
91
  )
@@ -100,11 +99,11 @@ const BaseMultipleSelectComponent = <T extends MultipleSelectField>(
100
99
  <View style={[styles.wrapper]}>
101
100
  <MultiSelect
102
101
  ref={inputRef}
103
- style={[container, { borderColor, boxShadow: `0 0 10px ${borderColor}`, borderWidth: 0 }]}
102
+ style={[container, { borderColor, borderBottomWidth: 1, borderRadius: 0 }]}
104
103
  placeholderStyle={[text, { color: value?.length ? textColor : placeholderColor }]}
105
104
  containerStyle={{
106
105
  backgroundColor: menuBg,
107
- boxShadow: `0 0 6px ${borderColor}`,
106
+ boxShadow: `0 0 10px #00000066`,
108
107
  borderWidth: 0,
109
108
  }}
110
109
  inputSearchStyle={[styles.inputSearch, text, { backgroundColor: inputBg, borderWidth: 0 }]}
@@ -133,7 +132,7 @@ const BaseMultipleSelectComponent = <T extends MultipleSelectField>(
133
132
  renderItem={(item, selected) => (
134
133
  <View
135
134
  style={{
136
- backgroundColor: selected ? selectedOptionBg : 'transparent',
135
+ backgroundColor: selected ? selectedOptionBg : menuBg,
137
136
  paddingVertical: 8,
138
137
  paddingHorizontal: 12,
139
138
  flexDirection: 'row',
@@ -2,7 +2,6 @@ import { InputRef, RenderSelectOptionProps } from '@chem-po/core'
2
2
  import {
3
3
  SelectField,
4
4
  useBackgroundColor,
5
- useBorderColor,
6
5
  useColorMode,
7
6
  useIconColor,
8
7
  usePlaceholderColor,
@@ -33,14 +32,11 @@ const BaseSelectComponent = <T extends SelectField>(
33
32
  const colorMode = useColorMode()
34
33
 
35
34
  const inputRef = useRef<IDropdownRef>(null)
36
- const {
37
- container: inputStyles,
38
- iconSize,
39
- text,
40
- size,
41
- clearButtonSize,
42
- buttonContainer,
43
- } = useInputStyles(inEditable, field.size, formSize)
35
+ const { container, iconSize, text, size, clearButtonSize, buttonContainer } = useInputStyles(
36
+ inEditable,
37
+ field.size,
38
+ formSize,
39
+ )
44
40
 
45
41
  useImperativeHandle(ref, () => ({
46
42
  focus: () => {
@@ -64,19 +60,18 @@ const BaseSelectComponent = <T extends SelectField>(
64
60
  const placeholderColor = usePlaceholderColor()
65
61
  const menuBg = useBackgroundColor(100)
66
62
  const selectedOptionBg = useBackgroundColor(50)
67
- const borderColor = useBorderColor()
68
63
 
69
64
  return (
70
65
  <View style={styles.wrapper}>
71
66
  <Dropdown
72
67
  ref={inputRef}
73
- style={[inputStyles, { borderColor }]}
68
+ style={container}
74
69
  placeholderStyle={[text, { color: placeholderColor }]}
75
70
  containerStyle={{
76
71
  backgroundColor: menuBg,
77
72
  borderWidth: 0,
78
73
  borderColor: 'transparent',
79
- boxShadow: `0 0 10px ${borderColor}`,
74
+ boxShadow: `0 0 10px #00000066`,
80
75
  }}
81
76
  selectedTextStyle={text}
82
77
  inputSearchStyle={[
@@ -1,7 +1,7 @@
1
1
  import { ImageViewOptions, InputSize } from '@chem-po/core'
2
2
  import { FileField, usePlaceholderColor } from '@chem-po/react'
3
3
  import React, { useMemo } from 'react'
4
- import { StyleSheet, Text, View, ViewStyle } from 'react-native'
4
+ import { StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native'
5
5
  import { Txt } from '../../text/Txt'
6
6
  import { FileView } from '../input/file'
7
7
  import { useInputStyles } from '../input/hooks/useInputStyles'
@@ -42,11 +42,13 @@ export const FileFieldView = ({
42
42
  noLabel,
43
43
  style,
44
44
  size: sizeProp,
45
+ textStyle,
45
46
  }: {
46
47
  field: FileField
47
48
  value: any
48
49
  noLabel?: boolean
49
50
  style?: ViewStyle
51
+ textStyle?: StyleProp<TextStyle>
50
52
  size?: InputSize
51
53
  }) => {
52
54
  const { imageOptions, placeholder, size } = field
@@ -66,11 +68,11 @@ export const FileFieldView = ({
66
68
  {!noLabel && <Text style={styles.label}>{placeholder}</Text>}
67
69
  {value ? (
68
70
  <View style={styles.fileContainer}>
69
- <FileView imageOptions={options} value={value} />
71
+ <FileView textStyle={textStyle} imageOptions={options} value={value} />
70
72
  </View>
71
73
  ) : (
72
74
  <View style={container}>
73
- <Txt style={[text, { color: placeholderColor }]}>None</Txt>
75
+ <Txt style={[text, { color: placeholderColor }, textStyle]}>None</Txt>
74
76
  </View>
75
77
  )}
76
78
  </View>
@@ -1,7 +1,7 @@
1
1
  import { displayField, InputSize } from '@chem-po/core'
2
2
  import { Field, FormatField, usePlaceholderColor } from '@chem-po/react'
3
3
  import React, { useMemo } from 'react'
4
- import { StyleSheet, View, ViewStyle } from 'react-native'
4
+ import { StyleProp, StyleSheet, TextStyle, View, ViewStyle } from 'react-native'
5
5
  import { Txt } from '../../text'
6
6
  import { useInputStyles } from '../input/hooks/useInputStyles'
7
7
  import { FileFieldView } from './file'
@@ -23,11 +23,13 @@ const DefaultFieldView = ({
23
23
  style,
24
24
  size: sizeProp,
25
25
  inEditable,
26
+ textStyle,
26
27
  }: {
27
28
  field: Field
28
29
  value: any
29
30
  noLabel?: boolean
30
31
  style?: ViewStyle
32
+ textStyle?: StyleProp<TextStyle>
31
33
  size?: InputSize
32
34
  inEditable?: boolean
33
35
  }) => {
@@ -48,7 +50,7 @@ const DefaultFieldView = ({
48
50
  return (
49
51
  <View style={[styles.container, containerStyles, { backgroundColor: 'transparent' }, style]}>
50
52
  {!noLabel && <Txt style={[inputViewStyles.label, text]}>{placeholder}</Txt>}
51
- <Txt style={[text, { color: hasValue ? undefined : placeholderColor }]}>
53
+ <Txt style={[text, { color: hasValue ? text.color : placeholderColor }, textStyle]}>
52
54
  {hasValue ? formatted : 'None'}
53
55
  </Txt>
54
56
  </View>
@@ -60,6 +62,7 @@ export const FieldView = ({
60
62
  value,
61
63
  noLabel,
62
64
  style,
65
+ textStyle,
63
66
  size,
64
67
  inEditable,
65
68
  }: {
@@ -67,6 +70,7 @@ export const FieldView = ({
67
70
  value?: any
68
71
  noLabel?: boolean
69
72
  style?: ViewStyle
73
+ textStyle?: StyleProp<TextStyle>
70
74
  size?: InputSize
71
75
  inEditable?: boolean
72
76
  }) => {
@@ -75,6 +79,7 @@ export const FieldView = ({
75
79
  return (
76
80
  <SelectFieldView
77
81
  style={style}
82
+ textStyle={textStyle}
78
83
  field={field}
79
84
  value={value}
80
85
  noLabel={noLabel}
@@ -88,13 +93,21 @@ export const FieldView = ({
88
93
  style={style}
89
94
  field={field}
90
95
  value={value}
96
+ textStyle={textStyle}
91
97
  noLabel={noLabel}
92
98
  size={size}
93
99
  />
94
100
  )
95
101
  case 'file':
96
102
  return (
97
- <FileFieldView style={style} field={field} value={value} noLabel={noLabel} size={size} />
103
+ <FileFieldView
104
+ textStyle={textStyle}
105
+ style={style}
106
+ field={field}
107
+ value={value}
108
+ noLabel={noLabel}
109
+ size={size}
110
+ />
98
111
  )
99
112
  default:
100
113
  return (
@@ -102,6 +115,7 @@ export const FieldView = ({
102
115
  style={style}
103
116
  field={field}
104
117
  value={value}
118
+ textStyle={textStyle}
105
119
  noLabel={noLabel}
106
120
  size={size}
107
121
  inEditable={inEditable}
@@ -1,7 +1,7 @@
1
- import { InputSize } from '@chem-po/core'
1
+ import { BaseSelectOption, InputSize } from '@chem-po/core'
2
2
  import { MultipleSelectField, useColorMode, usePlaceholderColor } from '@chem-po/react'
3
3
  import { useMemo } from 'react'
4
- import React, { StyleSheet, Text, View, ViewStyle } from 'react-native'
4
+ import React, { StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native'
5
5
  import { Txt } from '../../text/Txt'
6
6
  import { useInputStyles } from '../input/hooks/useInputStyles'
7
7
  import { SelectedOptionContainer } from '../input/multipleSelect'
@@ -31,16 +31,23 @@ const styles = StyleSheet.create({
31
31
  },
32
32
  })
33
33
 
34
- export const MultipleSelectFieldView = <F extends MultipleSelectField>({
34
+ type NativeMultipleSelectField<
35
+ Value extends any[] = string[],
36
+ Option extends BaseSelectOption<Value[number]> = BaseSelectOption<Value[number]>,
37
+ > = MultipleSelectField<Value, Option>
38
+
39
+ export const MultipleSelectFieldView = <F extends NativeMultipleSelectField>({
35
40
  field,
36
41
  value,
37
42
  noLabel,
38
43
  size: sizeProp,
39
44
  style,
45
+ textStyle,
40
46
  }: {
41
47
  field: F
42
48
  value?: F['defaultValue']
43
49
  noLabel?: boolean
50
+ textStyle?: StyleProp<TextStyle>
44
51
  size?: InputSize
45
52
  style?: ViewStyle
46
53
  }) => {
@@ -49,12 +56,6 @@ export const MultipleSelectFieldView = <F extends MultipleSelectField>({
49
56
  const colorMode = useColorMode()
50
57
  const { size, text, container } = useInputStyles(true, field.size, sizeProp)
51
58
  const placeholderColor = usePlaceholderColor()
52
- const selectedOptionStyle = useMemo<ViewStyle>(() => {
53
- return {
54
- paddingHorizontal: container.paddingHorizontal,
55
- paddingVertical: container.paddingVertical,
56
- }
57
- }, [container])
58
59
  const RenderOption = useMemo(() => customRender ?? DefaultRenderOption, [customRender])
59
60
  return (
60
61
  <View style={[styles.container, style]}>
@@ -62,10 +63,11 @@ export const MultipleSelectFieldView = <F extends MultipleSelectField>({
62
63
  {value?.length ? (
63
64
  <View style={styles.optionsContainer}>
64
65
  {selectedOptions.map(o => (
65
- <SelectedOptionContainer key={o.value} style={selectedOptionStyle}>
66
+ <SelectedOptionContainer key={o.value} style={[container, { width: 'auto' }]}>
66
67
  <RenderOption
67
68
  option={o}
68
69
  value={o.value}
70
+ textStyle={[text, textStyle]}
69
71
  colorMode={colorMode}
70
72
  isSelected
71
73
  size={size}
@@ -75,7 +77,7 @@ export const MultipleSelectFieldView = <F extends MultipleSelectField>({
75
77
  </View>
76
78
  ) : (
77
79
  <View style={container}>
78
- <Txt style={[text, { color: placeholderColor }]}>None</Txt>
80
+ <Txt style={[text, { color: placeholderColor }, textStyle]}>None</Txt>
79
81
  </View>
80
82
  )}
81
83
  </View>
@@ -1,7 +1,7 @@
1
- import { BaseSelectOption, InputSize, RenderSelectOptionProps } from '@chem-po/core'
1
+ import { InputSize, RenderSelectOptionProps } from '@chem-po/core'
2
2
  import { SelectField, useColorMode, usePlaceholderColor } from '@chem-po/react'
3
- import React from 'react'
4
- import { StyleSheet, Text, View, ViewStyle } from 'react-native'
3
+ import React, { useMemo } from 'react'
4
+ import { StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native'
5
5
  import { Txt } from '../../text'
6
6
  import { useInputStyles } from '../input/hooks/useInputStyles'
7
7
  import { inputViewStyles } from './styles'
@@ -18,31 +18,35 @@ const styles = StyleSheet.create({
18
18
  },
19
19
  })
20
20
 
21
- export const DefaultRenderOption = <
22
- Value = string,
23
- Option extends BaseSelectOption<Value> = BaseSelectOption<Value>,
24
- >({
21
+ export const DefaultRenderOption = ({
25
22
  option,
26
- }: RenderSelectOptionProps<Value, Option>) => {
23
+ containerStyle,
24
+ textStyle,
25
+ }: RenderSelectOptionProps & {
26
+ containerStyle?: StyleProp<ViewStyle>
27
+ textStyle?: StyleProp<TextStyle>
28
+ }) => {
27
29
  return (
28
- <View style={{ padding: 6 }}>
29
- <Txt style={inputViewStyles.value}>{option.label}</Txt>
30
+ <View style={containerStyle}>
31
+ <Txt style={[inputViewStyles.value, textStyle]}>{option.label}</Txt>
30
32
  </View>
31
33
  )
32
34
  }
33
35
 
34
- export const SelectFieldView = ({
36
+ export const SelectFieldView = <F extends SelectField>({
35
37
  field,
36
38
  value,
37
39
  noLabel,
38
40
  style,
39
41
  size: sizeProp,
40
42
  inEditable,
43
+ textStyle,
41
44
  }: {
42
- field: SelectField
43
- value: any
45
+ field: F
46
+ value: F['defaultValue']
44
47
  noLabel?: boolean
45
48
  style?: ViewStyle
49
+ textStyle?: StyleProp<TextStyle>
46
50
  size?: InputSize
47
51
  inEditable?: boolean
48
52
  }) => {
@@ -51,23 +55,27 @@ export const SelectFieldView = ({
51
55
  const placeholderColor = usePlaceholderColor()
52
56
  const { size, text, container } = useInputStyles(inEditable, field.size, sizeProp)
53
57
  const selectedOption = field.options.find(o => o.value === value)
54
- const RenderOption = customRender ?? DefaultRenderOption
58
+ const RenderOption = useMemo(() => customRender ?? DefaultRenderOption, [customRender])
55
59
  return (
56
60
  <View style={[styles.container, style]}>
57
61
  {!noLabel && (
58
- <Text style={[styles.label, text, { color: placeholderColor }]}>{placeholder}</Text>
62
+ <Text style={[styles.label, text, { color: placeholderColor }, textStyle]}>
63
+ {placeholder}
64
+ </Text>
59
65
  )}
60
66
  {selectedOption ? (
61
67
  <RenderOption
62
68
  value={selectedOption.value}
63
69
  option={selectedOption}
70
+ containerStyle={container}
71
+ textStyle={[text, textStyle]}
64
72
  colorMode={colorMode}
65
73
  isSelected={true}
66
74
  size={size}
67
75
  />
68
76
  ) : (
69
77
  <View style={container}>
70
- <Txt style={[text, { color: placeholderColor }]}>None</Txt>
78
+ <Txt style={[text, { color: placeholderColor }, textStyle]}>None</Txt>
71
79
  </View>
72
80
  )}
73
81
  </View>
@@ -1,7 +1,7 @@
1
1
  import { useScreen, useToast } from '@chem-po/react'
2
2
  import { Ionicons } from '@expo/vector-icons'
3
3
  import React, { useCallback, useEffect, useMemo, useState } from 'react'
4
- import { Image, Modal, Platform, SafeAreaView, StyleSheet, View } from 'react-native'
4
+ import { Image, Modal, Platform, StyleSheet, View } from 'react-native'
5
5
  import {
6
6
  Gesture,
7
7
  GestureDetector,
@@ -9,6 +9,7 @@ import {
9
9
  Pressable,
10
10
  } from 'react-native-gesture-handler'
11
11
  import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'
12
+ import { SafeAreaView } from 'react-native-safe-area-context'
12
13
  import { downloadFile } from '../../utils/downloadFile'
13
14
  import { LoadingLogo } from '../loading/Loading'
14
15
 
@@ -1,4 +1,4 @@
1
- import { useColorModeValue } from '@chem-po/react'
1
+ import { useBackgroundColor, useColorModeValue } from '@chem-po/react'
2
2
  import React, { useEffect, useRef } from 'react'
3
3
  import {
4
4
  ActivityIndicator,
@@ -24,6 +24,7 @@ export const CircularProgress = ({
24
24
  ...props
25
25
  }: CircularProgressProps) => {
26
26
  const defaultTrackColor = useColorModeValue('#959595', '#575757')
27
+ const defaultColor = useBackgroundColor(750)
27
28
  const opacity = useRef(new Animated.Value(visible ? 1 : 0)).current
28
29
 
29
30
  useEffect(() => {
@@ -42,7 +43,7 @@ export const CircularProgress = ({
42
43
  {...props}
43
44
  />
44
45
  {/* Spinning circle */}
45
- <ActivityIndicator animating={animating} color={color ?? '#575757'} {...props} />
46
+ <ActivityIndicator animating={animating} color={color ?? defaultColor} {...props} />
46
47
  </Animated.View>
47
48
  )
48
49
  }
@@ -1,46 +1,61 @@
1
- import * as FileSystem from 'expo-file-system'
2
- import { downloadAsync } from 'expo-file-system'
1
+ import { Directory, File, Paths } from 'expo-file-system'
2
+ import { StorageAccessFramework } from 'expo-file-system/legacy'
3
3
  import { shareAsync } from 'expo-sharing'
4
4
  import { Platform } from 'react-native'
5
5
 
6
6
  export const downloadFile = async (uri: string, filename: string, fileType: string) => {
7
7
  if (Platform.OS === 'android') {
8
- const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync()
8
+ const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync()
9
9
  if (!permissions.granted) {
10
10
  throw new Error('Permission not granted')
11
11
  }
12
12
 
13
- // Download to temporary location first
14
- const tempFileUri = `${FileSystem.cacheDirectory}${filename}`
13
+ // Create cache directory for temporary file
14
+ const cacheDir = new Directory(Paths.cache)
15
15
 
16
- // Download the file to temporary location
17
- await FileSystem.downloadAsync(uri, tempFileUri)
16
+ // Ensure cache directory exists
17
+ if (!cacheDir.exists) {
18
+ cacheDir.create()
19
+ }
18
20
 
19
- // Read the temporary file as base64
20
- const base64Content = await FileSystem.readAsStringAsync(tempFileUri, {
21
- encoding: FileSystem.EncodingType.Base64,
22
- })
21
+ // Download the file to cache directory using static method
22
+ const downloadedFile = await File.downloadFileAsync(uri, cacheDir)
23
+
24
+ // Read the downloaded file as bytes and convert to base64
25
+ const fileBytes = await downloadedFile.bytes()
26
+
27
+ // Convert Uint8Array to base64 safely (handles large files better than btoa)
28
+ const base64Content = Array.from(fileBytes, byte => String.fromCharCode(byte)).join('')
29
+ const encodedContent = btoa(base64Content)
23
30
 
24
31
  // Create a file within the selected directory using SAF
25
- const fileUri = await FileSystem.StorageAccessFramework.createFileAsync(
32
+ const fileUri = await StorageAccessFramework.createFileAsync(
26
33
  permissions.directoryUri,
27
34
  filename,
28
35
  fileType,
29
36
  )
30
37
 
31
- // Write the content to the SAF file
32
- await FileSystem.StorageAccessFramework.writeAsStringAsync(fileUri, base64Content, {
33
- encoding: FileSystem.EncodingType.Base64,
38
+ // Write the content to the SAF file using legacy method (as SAF might not have new API yet)
39
+ await StorageAccessFramework.writeAsStringAsync(fileUri, encodedContent, {
40
+ encoding: 'base64',
34
41
  })
35
42
 
36
43
  // Clean up temporary file
37
- await FileSystem.deleteAsync(tempFileUri, { idempotent: true })
44
+ downloadedFile.delete()
38
45
 
39
46
  return { uri: fileUri }
40
47
  }
41
- if (!FileSystem.documentDirectory) {
42
- throw new Error('Document directory not found')
48
+
49
+ // For iOS and other platforms
50
+ const documentsDir = new Directory(Paths.document)
51
+
52
+ // Ensure documents directory exists
53
+ if (!documentsDir.exists) {
54
+ documentsDir.create()
43
55
  }
44
- const result = await downloadAsync(uri, FileSystem.documentDirectory + filename)
45
- return shareAsync(result.uri)
56
+
57
+ // Download file directly to documents directory
58
+ const downloadedFile = await File.downloadFileAsync(uri, documentsDir)
59
+
60
+ return shareAsync(downloadedFile.uri)
46
61
  }
@@ -0,0 +1,66 @@
1
+ import {
2
+ cacheDirectory,
3
+ deleteAsync,
4
+ documentDirectory,
5
+ downloadAsync,
6
+ EncodingType,
7
+ readAsStringAsync,
8
+ StorageAccessFramework,
9
+ } from 'expo-file-system/legacy'
10
+ import { shareAsync } from 'expo-sharing'
11
+ import { Platform } from 'react-native'
12
+
13
+ export const downloadFileLegacy = async (uri: string, filename: string, fileType: string) => {
14
+ if (Platform.OS === 'android') {
15
+ const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync()
16
+ if (!permissions.granted) {
17
+ throw new Error('Permission not granted')
18
+ }
19
+
20
+ // Download to temporary location first
21
+ const tempFileUri = `${cacheDirectory}${filename}`
22
+
23
+ try {
24
+ // Download the file to temporary location
25
+ await downloadAsync(uri, tempFileUri)
26
+
27
+ // Read the temporary file as base64
28
+ const base64Content = await readAsStringAsync(tempFileUri, {
29
+ encoding: EncodingType.Base64,
30
+ })
31
+
32
+ // Create a file within the selected directory using SAF
33
+ const fileUri = await StorageAccessFramework.createFileAsync(
34
+ permissions.directoryUri,
35
+ filename,
36
+ fileType,
37
+ )
38
+
39
+ // Write the content to the SAF file
40
+ await StorageAccessFramework.writeAsStringAsync(fileUri, base64Content, {
41
+ encoding: EncodingType.Base64,
42
+ })
43
+
44
+ // Clean up temporary file
45
+ await deleteAsync(tempFileUri, { idempotent: true })
46
+
47
+ return { uri: fileUri }
48
+ } catch (error) {
49
+ // Clean up temporary file in case of error
50
+ try {
51
+ await deleteAsync(tempFileUri, { idempotent: true })
52
+ } catch {
53
+ // Ignore cleanup errors
54
+ }
55
+ throw error
56
+ }
57
+ }
58
+
59
+ // For iOS and other platforms
60
+ if (!documentDirectory) {
61
+ throw new Error('Document directory not found')
62
+ }
63
+
64
+ const result = await downloadAsync(uri, documentDirectory + filename)
65
+ return shareAsync(result.uri)
66
+ }