@codeleap/mobile 4.0.1 → 4.1.0

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.
@@ -104,7 +104,7 @@ Text.elements = ['text', 'pressFeedback']
104
104
  Text.rootElement = 'text'
105
105
 
106
106
  Text.withVariantTypes = <S extends AnyRecord>(styles: S) => {
107
- return Text as (props: StyledComponentProps<TextProps & { ref?: React.MutableRefObject<NativeText> }, typeof styles>) => IJSX
107
+ return Text as (props: StyledComponentProps<TextProps, typeof styles>) => IJSX
108
108
  }
109
109
 
110
110
  Text.defaultProps = {
@@ -1,11 +1,11 @@
1
1
  import { StyledProp } from '@codeleap/styles'
2
2
  import { ReactNode } from 'react'
3
- import { TextProps as RNTextProps, Animated, ViewStyle, ImageStyle, TextStyle } from 'react-native'
3
+ import { TextProps as RNTextProps, Animated, ViewStyle, ImageStyle, TextStyle, Text as NativeText } from 'react-native'
4
4
  import { AnimatedStyleProp } from 'react-native-reanimated'
5
5
  import { TextComposition } from './styles'
6
6
 
7
7
  export type TextProps =
8
- Omit<RNTextProps, 'style'> &
8
+ Omit<RNTextProps, 'style' | 'ref'> &
9
9
  {
10
10
  text?: ReactNode
11
11
  animated?: boolean
@@ -15,4 +15,5 @@ export type TextProps =
15
15
  pressDisabled?: boolean
16
16
  style?: StyledProp<TextComposition>
17
17
  animatedStyle?: AnimatedStyleProp<ViewStyle | ImageStyle | TextStyle>
18
+ ref?: React.ForwardedRef<NativeText>
18
19
  }
@@ -17,6 +17,7 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
17
17
  const innerInputRef = React.useRef<NativeTextInput>(null)
18
18
 
19
19
  const [isFocused, setIsFocused] = useState(false)
20
+ const [currentSelection, setCurrentSelection] = useState({ start: 0 })
20
21
 
21
22
  const {
22
23
  inputBaseProps,
@@ -38,6 +39,8 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
38
39
  visibleIcon,
39
40
  hiddenIcon,
40
41
  style,
42
+ autoAdjustSelection,
43
+ selectionStart,
41
44
  _error = null,
42
45
  ...textInputProps
43
46
  } = others
@@ -68,12 +71,14 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
68
71
  const handleBlur = React.useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
69
72
  validation.onInputBlurred()
70
73
  setIsFocused(false)
74
+ if (autoAdjustSelection) setCurrentSelection({ start: selectionStart })
71
75
  props.onBlur?.(e)
72
76
  }, [validation.onInputBlurred, props.onBlur])
73
77
 
74
78
  const handleFocus = React.useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
75
79
  validation.onInputFocused()
76
80
  setIsFocused(true)
81
+ if (autoAdjustSelection) setCurrentSelection(null)
77
82
  props.onFocus?.(e)
78
83
  }, [validation.onInputFocused, props.onFocus])
79
84
 
@@ -153,6 +158,7 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
153
158
  allowFontScaling={false}
154
159
  editable={!isPressable && !isDisabled}
155
160
  {...buttonModeProps}
161
+ selection={autoAdjustSelection ? currentSelection : undefined}
156
162
  placeholderTextColor={placeholderTextColor}
157
163
  value={value}
158
164
  selectionColor={selectionColor}
@@ -188,6 +194,8 @@ TextInput.defaultProps = {
188
194
  hiddenIcon: 'input-visiblity:hidden' as AppIcon,
189
195
  visibleIcon: 'input-visiblity:visible' as AppIcon,
190
196
  visibilityToggle: false,
197
+ autoAdjustSelection: false,
198
+ selectionStart: 0,
191
199
  } as Partial<TextInputProps>
192
200
 
193
201
  MobileStyleRegistry.registerComponent(TextInput)
@@ -12,6 +12,8 @@ export type TextInputProps =
12
12
  password?: boolean
13
13
  validate?: FormTypes.ValidatorFunctionWithoutForm | yup.SchemaOf<string>
14
14
  debugName: string
15
+ autoAdjustSelection?: boolean
16
+ selectionStart?: number
15
17
  visibilityToggle?: boolean
16
18
  masking?: FormTypes.TextField['masking']
17
19
  onChangeMask?: TextInputMaskProps['onChangeText']
@@ -38,3 +38,5 @@ export * from './NumberIncrement'
38
38
  export * from './Badge'
39
39
  export * from './SearchInput'
40
40
  export * from './PaginationIndicator'
41
+ export * from './PlacesAutocomplete'
42
+ export * from './SortablePhotos'
package/src/utils/misc.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MobileFile, MobileInputFile, parseFilePathData, FileWithPreview } from '@codeleap/common'
1
+ import { MobileFile, MobileInputFile, parseFilePathData, FileWithPreview, TypeGuards } from '@codeleap/common'
2
2
 
3
3
  export const stringToFile = (str: string): MobileInputFile => {
4
4
  if (!str) {
@@ -62,7 +62,7 @@ export function isFile(param:any): param is MobileInputFile {
62
62
  }
63
63
  }
64
64
 
65
- export function toMultipart(body) {
65
+ export function toMultipart(body, defaultFileValue = 'null') {
66
66
  const form = new FormData()
67
67
 
68
68
  for (const [key, value] of Object.entries(body)) {
@@ -71,6 +71,17 @@ export function toMultipart(body) {
71
71
  formValue = value.map((file) => form.append(key, toMultipartFile(file)))
72
72
  } else if (isFile(value)) {
73
73
  formValue = toMultipartFile(value)
74
+ } else if (key === 'files' && typeof value === 'object') {
75
+
76
+ if (TypeGuards.isNil(value)) {
77
+ form.append(key, defaultFileValue)
78
+ } else {
79
+
80
+ for (const [filename, file] of Object.entries(value)) {
81
+ form.append(filename, toMultipartFile(file))
82
+ }
83
+ }
84
+
74
85
  } else if (typeof value === 'object') {
75
86
  formValue = JSON.stringify(value)
76
87
  } else {
@@ -81,3 +92,31 @@ export function toMultipart(body) {
81
92
 
82
93
  return form
83
94
  }
95
+
96
+ export function getFileMimeType(uri: string) {
97
+ const extension = uri.split('.').pop().toLowerCase()
98
+
99
+ const mimeTypes = {
100
+ jpg: 'image/jpeg',
101
+ jpeg: 'image/jpeg',
102
+ png: 'image/png',
103
+ gif: 'image/gif',
104
+ webp: 'image/webp',
105
+ pdf: 'application/pdf',
106
+ txt: 'text/plain',
107
+ mp4: 'video/mp4',
108
+ }
109
+
110
+ return mimeTypes[extension] || 'application/octet-stream'
111
+ }
112
+
113
+ export function getFileInfo(uri: string) {
114
+ const fileName = uri.split('/').pop()
115
+ const fileType = getFileMimeType(fileName)
116
+
117
+ return {
118
+ name: fileName,
119
+ type: fileType,
120
+ uri: uri,
121
+ }
122
+ }