@edge-zuq/core 1.2.7 → 1.3.4
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/README.md +2 -2
- package/lib/module/data/use-cases/remote-get-comment-list.js.map +1 -1
- package/lib/module/data/use-cases/remote-get-image-list.js.map +1 -1
- package/lib/module/infra/axios-http-client-adapter.js +45 -72
- package/lib/module/infra/axios-http-client-adapter.js.map +1 -1
- package/lib/module/infra/offline-mutation-queue.js.map +1 -1
- package/lib/module/infra/rnp-permission-manager-adapter.js.map +1 -1
- package/lib/module/presentation/components/atoms/UIIcon.js +40 -40
- package/lib/module/presentation/components/atoms/UIIcon.js.map +1 -1
- package/lib/module/presentation/components/atoms/UIProgress.js.map +1 -1
- package/lib/module/presentation/components/molecules/UIActionSheet.js.map +1 -1
- package/lib/module/presentation/components/molecules/UIButton.js +5 -5
- package/lib/module/presentation/components/molecules/UIButton.js.map +1 -1
- package/lib/module/presentation/components/molecules/UICurrencyInput.js.map +1 -1
- package/lib/module/presentation/components/molecules/UIDatetimeInput.js +1 -0
- package/lib/module/presentation/components/molecules/UIDatetimeInput.js.map +1 -1
- package/lib/module/presentation/components/molecules/UIImage.js.map +1 -1
- package/lib/module/presentation/components/molecules/UISkeleton.js +41 -9
- package/lib/module/presentation/components/molecules/UISkeleton.js.map +1 -1
- package/lib/module/presentation/components/molecules/UITextInput.js +6 -2
- package/lib/module/presentation/components/molecules/UITextInput.js.map +1 -1
- package/lib/module/presentation/components/molecules/UITextInputMask.js +6 -2
- package/lib/module/presentation/components/molecules/UITextInputMask.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormButton.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormCheckboxInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormCurrencyInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormDatetimeInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormMultiselectInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormSelectInput.js +8 -2
- package/lib/module/presentation/components/organisms/UIFormSelectInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIFormTextInput.js.map +1 -1
- package/lib/module/presentation/components/organisms/UIMultipleSelectChip.js +129 -0
- package/lib/module/presentation/components/organisms/UIMultipleSelectChip.js.map +1 -0
- package/lib/module/presentation/components/organisms/UISelectChip.js +33 -2
- package/lib/module/presentation/components/organisms/UISelectChip.js.map +1 -1
- package/lib/module/presentation/components/organisms/UISignature.js +3 -2
- package/lib/module/presentation/components/organisms/UISignature.js.map +1 -1
- package/lib/module/presentation/components/organisms/UISlideButton.js.map +1 -1
- package/lib/module/presentation/components/organisms/index.js +1 -0
- package/lib/module/presentation/components/organisms/index.js.map +1 -1
- package/lib/module/presentation/components/permissions/request-permissions.js.map +1 -1
- package/lib/module/presentation/domain/offline/use-offline-mutation.js +1 -1
- package/lib/module/presentation/domain/offline/use-offline-mutation.js.map +1 -1
- package/lib/module/presentation/domain/offline/use-offline-query.js.map +1 -1
- package/lib/module/theme.js +22 -22
- package/lib/module/theme.js.map +1 -1
- package/lib/typescript/src/infra/axios-http-client-adapter.d.ts +1 -1
- package/lib/typescript/src/infra/axios-http-client-adapter.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/atoms/UIIcon.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/atoms/UIProgress.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UIActionSheet.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UIButton.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UIDatetimeInput.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UIImage.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UISkeleton.d.ts +3 -1
- package/lib/typescript/src/presentation/components/molecules/UISkeleton.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UITextInput.d.ts +1 -0
- package/lib/typescript/src/presentation/components/molecules/UITextInput.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/molecules/UITextInputMask.d.ts +1 -0
- package/lib/typescript/src/presentation/components/molecules/UITextInputMask.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/UIFormMultiselectInput.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/UIFormSelectInput.d.ts +4 -1
- package/lib/typescript/src/presentation/components/organisms/UIFormSelectInput.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/UIMultipleSelectChip.d.ts +17 -0
- package/lib/typescript/src/presentation/components/organisms/UIMultipleSelectChip.d.ts.map +1 -0
- package/lib/typescript/src/presentation/components/organisms/UISelectChip.d.ts +6 -2
- package/lib/typescript/src/presentation/components/organisms/UISelectChip.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/UISignature.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/UISlideButton.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/organisms/index.d.ts +1 -0
- package/lib/typescript/src/presentation/components/organisms/index.d.ts.map +1 -1
- package/lib/typescript/src/presentation/components/permissions/request-permissions.d.ts.map +1 -1
- package/package.json +71 -75
- package/src/data/use-cases/remote-get-comment-list.ts +1 -1
- package/src/data/use-cases/remote-get-image-list.ts +2 -2
- package/src/infra/axios-http-client-adapter.ts +46 -70
- package/src/infra/offline-mutation-queue.ts +4 -4
- package/src/infra/rnp-permission-manager-adapter.ts +4 -4
- package/src/presentation/components/atoms/UIIcon.tsx +75 -110
- package/src/presentation/components/atoms/UIProgress.tsx +2 -3
- package/src/presentation/components/molecules/UIActionSheet.tsx +9 -13
- package/src/presentation/components/molecules/UIButton.tsx +6 -7
- package/src/presentation/components/molecules/UICurrencyInput.tsx +2 -2
- package/src/presentation/components/molecules/UIDatetimeInput.tsx +1 -0
- package/src/presentation/components/molecules/UIImage.tsx +3 -5
- package/src/presentation/components/molecules/UISkeleton.tsx +19 -7
- package/src/presentation/components/molecules/UITextInput.tsx +8 -7
- package/src/presentation/components/molecules/UITextInputMask.tsx +8 -7
- package/src/presentation/components/organisms/UIFormButton.tsx +1 -1
- package/src/presentation/components/organisms/UIFormCheckboxInput.tsx +1 -1
- package/src/presentation/components/organisms/UIFormCurrencyInput.tsx +1 -1
- package/src/presentation/components/organisms/UIFormDatetimeInput.tsx +1 -1
- package/src/presentation/components/organisms/UIFormMultiselectInput.tsx +7 -9
- package/src/presentation/components/organisms/UIFormSelectInput.tsx +13 -6
- package/src/presentation/components/organisms/UIFormTextInput.tsx +1 -1
- package/src/presentation/components/organisms/UIMultipleSelectChip.tsx +139 -0
- package/src/presentation/components/organisms/UISelectChip.tsx +26 -3
- package/src/presentation/components/organisms/UISignature.tsx +10 -8
- package/src/presentation/components/organisms/UISlideButton.tsx +5 -7
- package/src/presentation/components/organisms/index.ts +1 -0
- package/src/presentation/components/permissions/request-permissions.tsx +5 -7
- package/src/presentation/domain/offline/use-offline-mutation.ts +2 -2
- package/src/presentation/domain/offline/use-offline-query.ts +1 -1
- package/src/theme.ts +22 -22
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { StyleSheet, type ViewStyle, type StyleProp } from 'react-native';
|
|
3
3
|
import Animated, {
|
|
4
4
|
cancelAnimation,
|
|
5
5
|
interpolate,
|
|
@@ -9,14 +9,17 @@ import Animated, {
|
|
|
9
9
|
withTiming,
|
|
10
10
|
} from 'react-native-reanimated';
|
|
11
11
|
import { UIStack } from '../atoms';
|
|
12
|
+
import Svg, { Defs, LinearGradient, Rect, Stop } from 'react-native-svg';
|
|
13
|
+
import { theme } from '../../../theme';
|
|
12
14
|
|
|
13
15
|
type Props = {
|
|
14
16
|
circle?: boolean;
|
|
15
17
|
width: number;
|
|
16
18
|
height: number;
|
|
19
|
+
style?: StyleProp<ViewStyle>;
|
|
17
20
|
};
|
|
18
21
|
|
|
19
|
-
export const UISkeleton = ({ width, height, circle }: Props) => {
|
|
22
|
+
export const UISkeleton = ({ width, height, circle, style }: Props) => {
|
|
20
23
|
const translateX = useSharedValue(0);
|
|
21
24
|
const animatedStyle = useAnimatedStyle(() => {
|
|
22
25
|
return {
|
|
@@ -38,6 +41,7 @@ export const UISkeleton = ({ width, height, circle }: Props) => {
|
|
|
38
41
|
style={[
|
|
39
42
|
styles.skeleton,
|
|
40
43
|
{ width, height, borderRadius: circle ? width / 2 : 2 },
|
|
44
|
+
style,
|
|
41
45
|
]}
|
|
42
46
|
>
|
|
43
47
|
<Animated.View
|
|
@@ -46,20 +50,28 @@ export const UISkeleton = ({ width, height, circle }: Props) => {
|
|
|
46
50
|
{
|
|
47
51
|
width: 0.9 * width,
|
|
48
52
|
height,
|
|
49
|
-
opacity: 0.125,
|
|
50
53
|
borderRadius: circle ? width / 2 : 2,
|
|
51
|
-
backgroundColor: '#000',
|
|
52
54
|
},
|
|
53
55
|
]}
|
|
54
|
-
|
|
56
|
+
>
|
|
57
|
+
<Svg height={height} width={width}>
|
|
58
|
+
<Defs>
|
|
59
|
+
<LinearGradient id="grad" x1="0" y1="0" x2="1" y2="0">
|
|
60
|
+
<Stop offset="0" stopColor="white" stopOpacity="0" />
|
|
61
|
+
<Stop offset="0.5" stopColor="white" stopOpacity="0.5" />
|
|
62
|
+
<Stop offset="1" stopColor="white" stopOpacity="0" />
|
|
63
|
+
</LinearGradient>
|
|
64
|
+
</Defs>
|
|
65
|
+
<Rect x="0" y="0" width={width} height={height} fill="url(#grad)" />
|
|
66
|
+
</Svg>
|
|
67
|
+
</Animated.View>
|
|
55
68
|
</UIStack>
|
|
56
69
|
);
|
|
57
70
|
};
|
|
58
71
|
|
|
59
72
|
const styles = StyleSheet.create({
|
|
60
73
|
skeleton: {
|
|
61
|
-
backgroundColor: '
|
|
62
|
-
opacity: 0.1,
|
|
74
|
+
backgroundColor: theme.color.neutral.light['20'],
|
|
63
75
|
borderRadius: 2,
|
|
64
76
|
overflow: 'hidden',
|
|
65
77
|
},
|
|
@@ -12,6 +12,7 @@ type Props = React.ComponentProps<typeof TextInput> & {
|
|
|
12
12
|
label?: string;
|
|
13
13
|
containerStyle?: StyleProp<ViewStyle>;
|
|
14
14
|
wrapperStyle?: StyleProp<ViewStyle>;
|
|
15
|
+
required?: boolean;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
@@ -29,6 +30,7 @@ export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
|
29
30
|
wrapperStyle,
|
|
30
31
|
editable = true,
|
|
31
32
|
value,
|
|
33
|
+
required,
|
|
32
34
|
...props
|
|
33
35
|
},
|
|
34
36
|
ref
|
|
@@ -36,7 +38,7 @@ export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
|
36
38
|
const [hidden, setHidden] = React.useState(secureTextEntry);
|
|
37
39
|
const [focused, setFocused] = React.useState(false);
|
|
38
40
|
|
|
39
|
-
const toggleHidden = () => setHidden(
|
|
41
|
+
const toggleHidden = () => setHidden(value => !value);
|
|
40
42
|
|
|
41
43
|
return (
|
|
42
44
|
<View style={wrapperStyle}>
|
|
@@ -44,9 +46,9 @@ export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
|
44
46
|
<UIText
|
|
45
47
|
weight="700"
|
|
46
48
|
variant="label"
|
|
47
|
-
style={[styles.label, focused && styles.labelFocused]}
|
|
48
|
-
>
|
|
49
|
+
style={[styles.label, focused && styles.labelFocused]}>
|
|
49
50
|
{label}
|
|
51
|
+
{required && <UIText color="feedback-red-500"> *</UIText>}
|
|
50
52
|
</UIText>
|
|
51
53
|
)}
|
|
52
54
|
<View
|
|
@@ -57,8 +59,7 @@ export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
|
57
59
|
Boolean(endIcon) && styles.endIcon,
|
|
58
60
|
styles[variant],
|
|
59
61
|
containerStyle,
|
|
60
|
-
]}
|
|
61
|
-
>
|
|
62
|
+
]}>
|
|
62
63
|
{startIcon && React.cloneElement(startIcon, { focused })}
|
|
63
64
|
<TextInput
|
|
64
65
|
accessible
|
|
@@ -76,11 +77,11 @@ export const UITextInput = React.forwardRef<TextInput, Props>(
|
|
|
76
77
|
Boolean(endIcon) && styles.endIcon,
|
|
77
78
|
style,
|
|
78
79
|
]}
|
|
79
|
-
onFocus={
|
|
80
|
+
onFocus={e => {
|
|
80
81
|
setFocused(true);
|
|
81
82
|
onFocus?.(e);
|
|
82
83
|
}}
|
|
83
|
-
onBlur={
|
|
84
|
+
onBlur={e => {
|
|
84
85
|
setFocused(false);
|
|
85
86
|
onBlur?.(e);
|
|
86
87
|
}}
|
|
@@ -14,6 +14,7 @@ type Props = React.ComponentProps<typeof MaskInput> & {
|
|
|
14
14
|
containerStyle?: StyleProp<ViewStyle>;
|
|
15
15
|
wrapperStyle?: StyleProp<ViewStyle>;
|
|
16
16
|
mask?: Mask;
|
|
17
|
+
required?: boolean;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
@@ -32,6 +33,7 @@ export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
|
32
33
|
mask,
|
|
33
34
|
value,
|
|
34
35
|
editable = true,
|
|
36
|
+
required,
|
|
35
37
|
...props
|
|
36
38
|
},
|
|
37
39
|
ref
|
|
@@ -39,7 +41,7 @@ export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
|
39
41
|
const [hidden, setHidden] = React.useState(secureTextEntry);
|
|
40
42
|
const [focused, setFocused] = React.useState(false);
|
|
41
43
|
|
|
42
|
-
const toggleHidden = () => setHidden(
|
|
44
|
+
const toggleHidden = () => setHidden(value => !value);
|
|
43
45
|
|
|
44
46
|
return (
|
|
45
47
|
<View style={wrapperStyle}>
|
|
@@ -47,9 +49,9 @@ export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
|
47
49
|
<UIText
|
|
48
50
|
weight="700"
|
|
49
51
|
variant="label"
|
|
50
|
-
style={[styles.label, focused && styles.labelFocused]}
|
|
51
|
-
>
|
|
52
|
+
style={[styles.label, focused && styles.labelFocused]}>
|
|
52
53
|
{label}
|
|
54
|
+
{required && <UIText color="feedback-red-500"> *</UIText>}
|
|
53
55
|
</UIText>
|
|
54
56
|
)}
|
|
55
57
|
<View
|
|
@@ -58,8 +60,7 @@ export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
|
58
60
|
focused && styles.focused,
|
|
59
61
|
styles[variant],
|
|
60
62
|
containerStyle,
|
|
61
|
-
]}
|
|
62
|
-
>
|
|
63
|
+
]}>
|
|
63
64
|
{startIcon && React.cloneElement(startIcon, { focused })}
|
|
64
65
|
<MaskInput
|
|
65
66
|
ref={ref}
|
|
@@ -76,11 +77,11 @@ export const UITextInputMask = React.forwardRef<TextInput, Props>(
|
|
|
76
77
|
!editable && Boolean(value) && styles.disabled,
|
|
77
78
|
style,
|
|
78
79
|
]}
|
|
79
|
-
onFocus={
|
|
80
|
+
onFocus={e => {
|
|
80
81
|
setFocused(true);
|
|
81
82
|
onFocus?.(e);
|
|
82
83
|
}}
|
|
83
|
-
onBlur={
|
|
84
|
+
onBlur={e => {
|
|
84
85
|
setFocused(false);
|
|
85
86
|
onBlur?.(e);
|
|
86
87
|
}}
|
|
@@ -18,7 +18,7 @@ export const UIFormButton = ({
|
|
|
18
18
|
const { handleSubmit, setError, clearErrors, reset } = useFormContext();
|
|
19
19
|
|
|
20
20
|
const onPress = handleSubmit(
|
|
21
|
-
async
|
|
21
|
+
async values => {
|
|
22
22
|
try {
|
|
23
23
|
await KeyboardController.dismiss({ animated: false, keepFocus: false });
|
|
24
24
|
clearErrors('_formError');
|
|
@@ -27,7 +27,7 @@ export const UIFormDatetimeInput = ({
|
|
|
27
27
|
<UIStack style={[styles.container, formContainerStyle]}>
|
|
28
28
|
<UIDatetimeInput
|
|
29
29
|
value={field.value && new Date(field.value)}
|
|
30
|
-
onSelect={
|
|
30
|
+
onSelect={date => {
|
|
31
31
|
field.onChange(date.getTime());
|
|
32
32
|
}}
|
|
33
33
|
{...props}
|
|
@@ -109,12 +109,12 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
109
109
|
const onSelect = (item: T) => {
|
|
110
110
|
const current = (getValuesContext(name) ?? []) as T[];
|
|
111
111
|
const isSelected = current.find(
|
|
112
|
-
|
|
112
|
+
value => getItemKey(value) === getItemKey(item)
|
|
113
113
|
);
|
|
114
114
|
if (isSelected) {
|
|
115
115
|
setValueContext(
|
|
116
116
|
name,
|
|
117
|
-
current.filter(
|
|
117
|
+
current.filter(data => getItemKey(data) !== getItemKey(item))
|
|
118
118
|
);
|
|
119
119
|
} else {
|
|
120
120
|
setValueContext(name, [...current, item]);
|
|
@@ -136,7 +136,7 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
136
136
|
if (!data) return [];
|
|
137
137
|
if (!Array.isArray(data)) return [];
|
|
138
138
|
if (!search) return data;
|
|
139
|
-
return data.filter(
|
|
139
|
+
return data.filter(item =>
|
|
140
140
|
String(getItemLabel(item) ?? '')
|
|
141
141
|
.toLowerCase()
|
|
142
142
|
.includes(search.toLowerCase())
|
|
@@ -145,7 +145,7 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
145
145
|
|
|
146
146
|
const value = React.useMemo(() => {
|
|
147
147
|
const current = (getValuesContext(name) ?? []) as T[];
|
|
148
|
-
return current.map(
|
|
148
|
+
return current.map(value => getItemLabel(value)).join(', ');
|
|
149
149
|
}, [name, getItemLabel, getValuesContext, watchContext(name)]); //eslint-disable-line
|
|
150
150
|
|
|
151
151
|
return (
|
|
@@ -165,8 +165,7 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
165
165
|
visible={visible}
|
|
166
166
|
onRequestClose={onClose}
|
|
167
167
|
title={title}
|
|
168
|
-
style={[styles.sheet, sheetStyle]}
|
|
169
|
-
>
|
|
168
|
+
style={[styles.sheet, sheetStyle]}>
|
|
170
169
|
<UIStack>
|
|
171
170
|
<UIForm schema={schema} form={form} style={styles.form}>
|
|
172
171
|
<UIFormTextInput
|
|
@@ -185,8 +184,7 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
185
184
|
loading={isCreating}
|
|
186
185
|
variant={createVariant}
|
|
187
186
|
onSubmit={onSubmit}
|
|
188
|
-
getErrorMessage={getErrorMessage}
|
|
189
|
-
>
|
|
187
|
+
getErrorMessage={getErrorMessage}>
|
|
190
188
|
<UIStack style={styles.create} horizontal center>
|
|
191
189
|
<UIText color="neutral-light-00">{createMessage}</UIText>
|
|
192
190
|
<UIIcon
|
|
@@ -218,7 +216,7 @@ export const UIFormMultiselectInput = <T,>({
|
|
|
218
216
|
renderItem={({ item }) => {
|
|
219
217
|
const current = (watchContext(name) ?? []) as T[];
|
|
220
218
|
const isSelected = Boolean(
|
|
221
|
-
current.find(
|
|
219
|
+
current.find(value => getItemKey(value) === getItemKey(item))
|
|
222
220
|
);
|
|
223
221
|
const label = String(getItemLabel(item));
|
|
224
222
|
return (
|
|
@@ -73,6 +73,9 @@ type Props<T> = {
|
|
|
73
73
|
enableClientSearch?: boolean;
|
|
74
74
|
onFocus?: () => void;
|
|
75
75
|
onBlur?: () => void;
|
|
76
|
+
testID?: string;
|
|
77
|
+
accessibilityLabel?: string;
|
|
78
|
+
required?: boolean;
|
|
76
79
|
};
|
|
77
80
|
|
|
78
81
|
export const UIFormSelectInput = <T,>({
|
|
@@ -111,6 +114,9 @@ export const UIFormSelectInput = <T,>({
|
|
|
111
114
|
inputFormContainerStyle,
|
|
112
115
|
onFocus,
|
|
113
116
|
onBlur,
|
|
117
|
+
testID,
|
|
118
|
+
accessibilityLabel,
|
|
119
|
+
required,
|
|
114
120
|
}: Props<T>) => {
|
|
115
121
|
const ref = React.useRef<TextInput>(null);
|
|
116
122
|
const { visible, onClose: onCloseFromHook, onOpen } = useActionSheet();
|
|
@@ -168,7 +174,7 @@ export const UIFormSelectInput = <T,>({
|
|
|
168
174
|
if (!Array.isArray(data)) return [];
|
|
169
175
|
let filtered = data;
|
|
170
176
|
if (enableClientSearch && search) {
|
|
171
|
-
filtered = data.filter(
|
|
177
|
+
filtered = data.filter(item =>
|
|
172
178
|
String(getItemLabel(item) ?? '')
|
|
173
179
|
.toLowerCase()
|
|
174
180
|
.includes(search.toLowerCase())
|
|
@@ -218,14 +224,16 @@ export const UIFormSelectInput = <T,>({
|
|
|
218
224
|
style={inputStyle}
|
|
219
225
|
containerStyle={inputContainerStyle}
|
|
220
226
|
formContainerStyle={inputFormContainerStyle}
|
|
227
|
+
testID={testID}
|
|
228
|
+
accessibilityLabel={accessibilityLabel}
|
|
229
|
+
required={required}
|
|
221
230
|
/>
|
|
222
231
|
<UIActionSheet
|
|
223
232
|
visible={visible}
|
|
224
233
|
onRequestClose={onClose}
|
|
225
234
|
title={title}
|
|
226
235
|
style={sheetStyle}
|
|
227
|
-
estimatedHeight={520}
|
|
228
|
-
>
|
|
236
|
+
estimatedHeight={520}>
|
|
229
237
|
<UIStack flex={1}>
|
|
230
238
|
<UIForm schema={schema} form={form} style={styles.form}>
|
|
231
239
|
<UIStack horizontal center>
|
|
@@ -233,7 +241,7 @@ export const UIFormSelectInput = <T,>({
|
|
|
233
241
|
name="search"
|
|
234
242
|
placeholder={searchPlaceholder}
|
|
235
243
|
variant={searchVariant}
|
|
236
|
-
onChangeText={
|
|
244
|
+
onChangeText={text => onSearchDebounced(text)}
|
|
237
245
|
endIcon={<UIInputIcon position="end" name="search" size={24} />}
|
|
238
246
|
/>
|
|
239
247
|
{action}
|
|
@@ -248,8 +256,7 @@ export const UIFormSelectInput = <T,>({
|
|
|
248
256
|
loading={isCreating}
|
|
249
257
|
variant={createVariant}
|
|
250
258
|
onSubmit={onSubmit}
|
|
251
|
-
getErrorMessage={getErrorMessage}
|
|
252
|
-
>
|
|
259
|
+
getErrorMessage={getErrorMessage}>
|
|
253
260
|
<UIStack style={styles.create} horizontal center>
|
|
254
261
|
<UIText color="neutral-light-00">{createMessage}</UIText>
|
|
255
262
|
<UIIcon
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { UIButton, UIChip, UIList, UISkeleton } from '../molecules';
|
|
3
|
+
import { UIIcon, UISeparator, UISpacer, UIStack, UIText } from '../atoms';
|
|
4
|
+
import { theme } from '../../../theme';
|
|
5
|
+
|
|
6
|
+
type PropsToOmit = 'renderItem' | 'ItemSeparatorComponent';
|
|
7
|
+
|
|
8
|
+
type Props<T> = Omit<React.ComponentProps<typeof UIList<T>>, PropsToOmit> & {
|
|
9
|
+
data: T[];
|
|
10
|
+
getItemLabel: (item: T) => string;
|
|
11
|
+
getItemKey: (item: T) => string;
|
|
12
|
+
selected: T[];
|
|
13
|
+
onSelect: (item: T) => void;
|
|
14
|
+
onReset: () => void;
|
|
15
|
+
loading?: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const UIMultipleSelectChip = <T,>({
|
|
19
|
+
data,
|
|
20
|
+
getItemLabel,
|
|
21
|
+
getItemKey,
|
|
22
|
+
selected,
|
|
23
|
+
onSelect,
|
|
24
|
+
onReset,
|
|
25
|
+
loading = false,
|
|
26
|
+
...props
|
|
27
|
+
}: Props<T>) => {
|
|
28
|
+
const isAllSelected = selected.length === 0;
|
|
29
|
+
|
|
30
|
+
const isSelected = (item: T) => {
|
|
31
|
+
return selected.some(
|
|
32
|
+
currentItem => getItemKey(currentItem) === getItemKey(item)
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
if (loading) return <UIMultipleSelectChip.Skeleton />;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<UIList
|
|
40
|
+
horizontal
|
|
41
|
+
data={data}
|
|
42
|
+
ListHeaderComponent={() => (
|
|
43
|
+
<UIStack horizontal center size="md" style={styles.header}>
|
|
44
|
+
<UIButton onPress={() => onReset()} style={styles.button}>
|
|
45
|
+
<UIChip
|
|
46
|
+
content={
|
|
47
|
+
<UIStack horizontal center>
|
|
48
|
+
{isAllSelected && (
|
|
49
|
+
<UIIcon
|
|
50
|
+
name="check-alt"
|
|
51
|
+
color={theme.color.neutral.light['00']}
|
|
52
|
+
/>
|
|
53
|
+
)}
|
|
54
|
+
<UIText
|
|
55
|
+
weight="500"
|
|
56
|
+
color={
|
|
57
|
+
isAllSelected ? 'neutral-light-00' : 'neutral-mid-60'
|
|
58
|
+
}>
|
|
59
|
+
Todos
|
|
60
|
+
</UIText>
|
|
61
|
+
</UIStack>
|
|
62
|
+
}
|
|
63
|
+
color={isAllSelected ? 'brand-violet-500' : 'neutral-light-05'}
|
|
64
|
+
borderColor={
|
|
65
|
+
isAllSelected ? 'brand-violet-500' : 'neutral-light-50'
|
|
66
|
+
}
|
|
67
|
+
style={styles.chip}
|
|
68
|
+
/>
|
|
69
|
+
</UIButton>
|
|
70
|
+
<UISeparator horizontal={false} />
|
|
71
|
+
</UIStack>
|
|
72
|
+
)}
|
|
73
|
+
renderItem={({ item }) => {
|
|
74
|
+
const isSelectedItem = isSelected(item);
|
|
75
|
+
return (
|
|
76
|
+
<UIButton onPress={() => onSelect(item)} style={styles.button}>
|
|
77
|
+
<UIChip
|
|
78
|
+
content={
|
|
79
|
+
<UIStack horizontal center>
|
|
80
|
+
{isSelectedItem && (
|
|
81
|
+
<UIIcon
|
|
82
|
+
name="check-alt"
|
|
83
|
+
color={theme.color.neutral.light['00']}
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
<UIText
|
|
87
|
+
weight="500"
|
|
88
|
+
color={
|
|
89
|
+
isSelectedItem ? 'neutral-light-00' : 'neutral-mid-60'
|
|
90
|
+
}>
|
|
91
|
+
{getItemLabel(item)}
|
|
92
|
+
</UIText>
|
|
93
|
+
</UIStack>
|
|
94
|
+
}
|
|
95
|
+
color={isSelectedItem ? 'brand-violet-500' : 'neutral-light-05'}
|
|
96
|
+
borderColor={
|
|
97
|
+
isSelectedItem ? 'brand-violet-500' : 'neutral-light-50'
|
|
98
|
+
}
|
|
99
|
+
style={styles.chip}
|
|
100
|
+
/>
|
|
101
|
+
</UIButton>
|
|
102
|
+
);
|
|
103
|
+
}}
|
|
104
|
+
ItemSeparatorComponent={() => <UISpacer horizontal />}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
UIMultipleSelectChip.Skeleton = () => {
|
|
111
|
+
return (
|
|
112
|
+
<UIList
|
|
113
|
+
horizontal
|
|
114
|
+
data={Array.from({ length: 3 })}
|
|
115
|
+
renderItem={() => <UISkeleton width={100} height={36} circle />}
|
|
116
|
+
ListHeaderComponent={() => (
|
|
117
|
+
<UIStack horizontal center size="md" style={styles.header}>
|
|
118
|
+
<UISkeleton width={85} height={36} circle />
|
|
119
|
+
<UISeparator horizontal={false} />
|
|
120
|
+
</UIStack>
|
|
121
|
+
)}
|
|
122
|
+
ItemSeparatorComponent={() => <UISpacer horizontal />}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const styles = StyleSheet.create({
|
|
128
|
+
chip: {
|
|
129
|
+
paddingTop: 6,
|
|
130
|
+
paddingBottom: 6,
|
|
131
|
+
paddingHorizontal: 16,
|
|
132
|
+
},
|
|
133
|
+
header: {
|
|
134
|
+
marginRight: 8,
|
|
135
|
+
},
|
|
136
|
+
button: {
|
|
137
|
+
padding: 0,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
|
-
import { UIButton, UIChip, UIList } from '../molecules';
|
|
2
|
+
import { UIButton, UIChip, UIList, UISkeleton } from '../molecules';
|
|
3
3
|
import { UIIcon, UISeparator, UISpacer, UIStack, UIText } from '../atoms';
|
|
4
4
|
import { theme } from '../../../theme';
|
|
5
5
|
|
|
@@ -9,9 +9,10 @@ type Props<T> = Omit<React.ComponentProps<typeof UIList<T>>, PropsToOmit> & {
|
|
|
9
9
|
data: T[];
|
|
10
10
|
getItemLabel: (item: T) => string;
|
|
11
11
|
getItemKey: (item: T) => string;
|
|
12
|
-
selected: T;
|
|
12
|
+
selected: T | null;
|
|
13
13
|
onSelect: (item: T) => void;
|
|
14
14
|
onReset: () => void;
|
|
15
|
+
loading?: boolean;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export const UISelectChip = <T,>({
|
|
@@ -21,14 +22,19 @@ export const UISelectChip = <T,>({
|
|
|
21
22
|
selected,
|
|
22
23
|
onSelect,
|
|
23
24
|
onReset,
|
|
25
|
+
loading = false,
|
|
24
26
|
...props
|
|
25
27
|
}: Props<T>) => {
|
|
28
|
+
if (loading) return <UISelectChip.Skeleton />;
|
|
29
|
+
|
|
26
30
|
return (
|
|
27
31
|
<UIList
|
|
28
32
|
horizontal
|
|
29
33
|
data={data}
|
|
30
34
|
renderItem={({ item }) => {
|
|
31
|
-
const isSelected =
|
|
35
|
+
const isSelected = Boolean(
|
|
36
|
+
selected && getItemKey(selected) === getItemKey(item)
|
|
37
|
+
);
|
|
32
38
|
return (
|
|
33
39
|
<UIButton onPress={() => onSelect(item)} style={styles.button}>
|
|
34
40
|
<UIChip
|
|
@@ -89,6 +95,23 @@ export const UISelectChip = <T,>({
|
|
|
89
95
|
);
|
|
90
96
|
};
|
|
91
97
|
|
|
98
|
+
UISelectChip.Skeleton = () => {
|
|
99
|
+
return (
|
|
100
|
+
<UIList
|
|
101
|
+
horizontal
|
|
102
|
+
data={Array.from({ length: 3 })}
|
|
103
|
+
renderItem={() => <UISkeleton width={100} height={36} circle />}
|
|
104
|
+
ListHeaderComponent={() => (
|
|
105
|
+
<UIStack horizontal center size="md" style={styles.header}>
|
|
106
|
+
<UISkeleton width={85} height={36} circle />
|
|
107
|
+
<UISeparator horizontal={false} />
|
|
108
|
+
</UIStack>
|
|
109
|
+
)}
|
|
110
|
+
ItemSeparatorComponent={() => <UISpacer horizontal />}
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
92
115
|
const styles = StyleSheet.create({
|
|
93
116
|
chip: {
|
|
94
117
|
paddingTop: 6,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
useCanvasRef,
|
|
7
7
|
} from '@shopify/react-native-skia';
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import { Dimensions, Image, StyleSheet } from 'react-native';
|
|
9
|
+
import { Dimensions, Image, Platform, StyleSheet } from 'react-native';
|
|
10
10
|
import ReactNativeBlobUtil from 'react-native-blob-util';
|
|
11
11
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
12
12
|
import { useSharedValue } from 'react-native-reanimated';
|
|
@@ -76,7 +76,11 @@ export const UISignature = ({
|
|
|
76
76
|
const image = canvasRef.current?.makeImageSnapshot(SNAPSHOT_PARAMS);
|
|
77
77
|
if (!image) return;
|
|
78
78
|
const name = `${Date.now()}.png`;
|
|
79
|
-
const
|
|
79
|
+
const directory =
|
|
80
|
+
Platform.OS === 'android'
|
|
81
|
+
? ReactNativeBlobUtil.fs.dirs.DCIMDir
|
|
82
|
+
: ReactNativeBlobUtil.fs.dirs.DocumentDir;
|
|
83
|
+
const path = directory + `/signatures/${name}`;
|
|
80
84
|
const base64 = image.encodeToBase64();
|
|
81
85
|
await ReactNativeBlobUtil.fs.writeFile(path, base64, 'base64');
|
|
82
86
|
const values = {
|
|
@@ -93,13 +97,13 @@ export const UISignature = ({
|
|
|
93
97
|
.averageTouches(true)
|
|
94
98
|
.maxPointers(1)
|
|
95
99
|
.minDistance(1)
|
|
96
|
-
.onStart(
|
|
100
|
+
.onStart(e => {
|
|
97
101
|
currentPath.value.moveTo(e.x, e.y);
|
|
98
102
|
currentPath.value.lineTo(e.x, e.y);
|
|
99
103
|
notifyChange(currentPath);
|
|
100
104
|
if (onTouchStart) scheduleOnRN(onTouchStart);
|
|
101
105
|
})
|
|
102
|
-
.onUpdate(
|
|
106
|
+
.onUpdate(e => {
|
|
103
107
|
scheduleOnRN(setIsDirty, true);
|
|
104
108
|
currentPath.value.lineTo(e.x, e.y);
|
|
105
109
|
notifyChange(currentPath);
|
|
@@ -136,8 +140,7 @@ export const UISignature = ({
|
|
|
136
140
|
ref={canvasRef}
|
|
137
141
|
testID={testID}
|
|
138
142
|
accessibilityLabel={accessibilityLabel}
|
|
139
|
-
style={[styles.container, signatureStyle]}
|
|
140
|
-
>
|
|
143
|
+
style={[styles.container, signatureStyle]}>
|
|
141
144
|
<Path
|
|
142
145
|
path={currentPath}
|
|
143
146
|
strokeWidth={5}
|
|
@@ -154,8 +157,7 @@ export const UISignature = ({
|
|
|
154
157
|
<UIButton
|
|
155
158
|
style={styles.clear}
|
|
156
159
|
onPress={resetSignature}
|
|
157
|
-
disabled={disabled}
|
|
158
|
-
>
|
|
160
|
+
disabled={disabled}>
|
|
159
161
|
<UIIcon name="close" />
|
|
160
162
|
</UIButton>
|
|
161
163
|
</UIStack>
|
|
@@ -46,7 +46,7 @@ export const UISlideButton = ({ children, helperText, onPress }: Props) => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
const pan = Gesture.Pan()
|
|
49
|
-
.onUpdate(
|
|
49
|
+
.onUpdate(event => {
|
|
50
50
|
animation.value = interpolate(
|
|
51
51
|
clamp(event.translationX, 0, max),
|
|
52
52
|
[0, max],
|
|
@@ -69,10 +69,9 @@ export const UISlideButton = ({ children, helperText, onPress }: Props) => {
|
|
|
69
69
|
return (
|
|
70
70
|
<UIStack
|
|
71
71
|
style={styles.container}
|
|
72
|
-
onLayout={
|
|
72
|
+
onLayout={event => {
|
|
73
73
|
setContainerWidth(event.nativeEvent.layout.width);
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
74
|
+
}}>
|
|
76
75
|
{helperText && (
|
|
77
76
|
<Animated.View style={[styles.text, labelAnimatedStyle]}>
|
|
78
77
|
<UIText weight="600">{helperText}</UIText>
|
|
@@ -83,10 +82,9 @@ export const UISlideButton = ({ children, helperText, onPress }: Props) => {
|
|
|
83
82
|
<UIButton
|
|
84
83
|
variant="contained"
|
|
85
84
|
style={styles.button}
|
|
86
|
-
onLayout={
|
|
85
|
+
onLayout={event => {
|
|
87
86
|
setButtonWidth(event.nativeEvent.layout.width);
|
|
88
|
-
}}
|
|
89
|
-
>
|
|
87
|
+
}}>
|
|
90
88
|
{children}
|
|
91
89
|
</UIButton>
|
|
92
90
|
</Animated.View>
|