@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.
- package/package.json +10 -7
- package/src/components/DatePickerModal/index.tsx +3 -2
- package/src/components/FileInput/index.tsx +7 -7
- package/src/components/FileInput/types.ts +1 -1
- package/src/components/NumberIncrement/index.tsx +21 -3
- package/src/components/NumberIncrement/types.ts +1 -0
- package/src/components/Pager/PagerDots.tsx +56 -0
- package/src/components/Pager/index.tsx +85 -173
- package/src/components/Pager/styles.ts +6 -1
- package/src/components/Pager/types.ts +16 -26
- package/src/components/PlacesAutocomplete/index.tsx +152 -0
- package/src/components/PlacesAutocomplete/styles.ts +12 -0
- package/src/components/PlacesAutocomplete/types.ts +42 -0
- package/src/components/Select/index.tsx +9 -13
- package/src/components/SortablePhotos/index.tsx +170 -0
- package/src/components/SortablePhotos/styles.ts +9 -0
- package/src/components/SortablePhotos/types.ts +58 -0
- package/src/components/SortablePhotos/useSortablePhotos.ts +174 -0
- package/src/components/Text/index.tsx +1 -1
- package/src/components/Text/types.ts +3 -2
- package/src/components/TextInput/index.tsx +8 -0
- package/src/components/TextInput/types.ts +2 -0
- package/src/components/components.ts +2 -0
- package/src/utils/misc.ts +41 -2
|
@@ -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
|
|
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']
|
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
|
+
}
|