sapo-components-ui-rn 1.0.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/README.md +69 -0
- package/dist/assets/error.png +0 -0
- package/dist/assets/icon-checkbox-active.svg +4 -0
- package/dist/assets/icon-checkbox.svg +3 -0
- package/dist/assets/image_default.png +0 -0
- package/dist/assets/images/error.png +0 -0
- package/dist/assets/images/image_default.png +0 -0
- package/dist/assets/images/info.png +0 -0
- package/dist/assets/images/success.png +0 -0
- package/dist/assets/images/warning.png +0 -0
- package/dist/assets/info.png +0 -0
- package/dist/assets/success.png +0 -0
- package/dist/assets/svg/icon-checkbox-active.svg +4 -0
- package/dist/assets/svg/icon-checkbox.svg +3 -0
- package/dist/assets/warning.png +0 -0
- package/dist/components/ActivityIndicator.d.ts +28 -0
- package/dist/components/Avatar/index.d.ts +17 -0
- package/dist/components/Badge/index.d.ts +13 -0
- package/dist/components/Button/index.d.ts +23 -0
- package/dist/components/ButtonIcon/index.d.ts +18 -0
- package/dist/components/Checkbox/index.d.ts +14 -0
- package/dist/components/ChipBar/index.d.ts +16 -0
- package/dist/components/CountingDot/index.d.ts +13 -0
- package/dist/components/FloatingButton/index.d.ts +17 -0
- package/dist/components/Icon/index.d.ts +17 -0
- package/dist/components/IconSvg/index.d.ts +12 -0
- package/dist/components/Image/index.d.ts +14 -0
- package/dist/components/ProgressBar.d.ts +42 -0
- package/dist/components/RadioButton/index.d.ts +13 -0
- package/dist/components/ScaleButton/index.d.ts +4 -0
- package/dist/components/SelectionField/index.d.ts +24 -0
- package/dist/components/Spacer/index.d.ts +9 -0
- package/dist/components/Switch/Switch.d.ts +47 -0
- package/dist/components/Switch/utils.d.ts +14 -0
- package/dist/components/Text/index.d.ts +14 -0
- package/dist/components/TextInput/Addons/Outline.d.ts +15 -0
- package/dist/components/TextInput/Addons/Underline.d.ts +19 -0
- package/dist/components/TextInput/Adornment/TextInputAdornment.d.ts +43 -0
- package/dist/components/TextInput/Adornment/TextInputAffix.d.ts +72 -0
- package/dist/components/TextInput/Adornment/enums.d.ts +12 -0
- package/dist/components/TextInput/Adornment/types.d.ts +11 -0
- package/dist/components/TextInput/Adornment/utils.d.ts +11 -0
- package/dist/components/TextInput/Label/InputLabel.d.ts +4 -0
- package/dist/components/TextInput/Label/LabelBackground.d.ts +4 -0
- package/dist/components/TextInput/TextInput.d.ts +171 -0
- package/dist/components/TextInput/TextInputDefault.d.ts +4 -0
- package/dist/components/TextInput/TextInputFlat.d.ts +4 -0
- package/dist/components/TextInput/constants.d.ts +31 -0
- package/dist/components/TextInput/helpers.d.ts +95 -0
- package/dist/components/TextInput/types.d.ts +154 -0
- package/dist/components/Toast/ToastProvider.d.ts +21 -0
- package/dist/components/Toast/index.d.ts +3 -0
- package/dist/components/Typography/AnimatedText.d.ts +34 -0
- package/dist/components/Typography/StyledText.d.ts +12 -0
- package/dist/components/Typography/Text.d.ts +35 -0
- package/dist/components/Typography/types.d.ts +2 -0
- package/dist/components/View/index.d.ts +38 -0
- package/dist/components/ViewVisibleAnimated/index.d.ts +25 -0
- package/dist/constants.d.ts +1 -0
- package/dist/core/theming.d.ts +43 -0
- package/dist/icons/IconArrowDown.d.ts +4 -0
- package/dist/icons/IconCheckbox.d.ts +4 -0
- package/dist/icons/IconCheckboxActive.d.ts +4 -0
- package/dist/icons/IconClearText.d.ts +4 -0
- package/dist/icons/IconRadio.d.ts +4 -0
- package/dist/icons/IconRadioActive.d.ts +4 -0
- package/dist/icons/IconRadioDisable.d.ts +4 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.esm.js +6758 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +6823 -0
- package/dist/index.js.map +1 -0
- package/dist/styles/fonts.d.ts +78 -0
- package/dist/styles/overlay.d.ts +3 -0
- package/dist/styles/shadow.d.ts +18 -0
- package/dist/styles/themes/DarkTheme.d.ts +2 -0
- package/dist/styles/themes/LightTheme.d.ts +2 -0
- package/dist/styles/themes/index.d.ts +2 -0
- package/dist/styles/themes/tokens.d.ts +830 -0
- package/dist/theme/blue.d.ts +14 -0
- package/dist/theme/colors.d.ts +99 -0
- package/dist/theme/container-styles.d.ts +124 -0
- package/dist/theme/dimensions.d.ts +36 -0
- package/dist/theme/green.d.ts +15 -0
- package/dist/theme/icon.d.ts +5 -0
- package/dist/theme/ink.d.ts +11 -0
- package/dist/theme/orange.d.ts +14 -0
- package/dist/theme/purple.d.ts +6 -0
- package/dist/theme/red.d.ts +15 -0
- package/dist/theme/themes.d.ts +277 -0
- package/dist/theme/white.d.ts +10 -0
- package/dist/theme/yellow.d.ts +15 -0
- package/dist/types/index.d.ts +65 -0
- package/dist/types.d.ts +220 -0
- package/dist/utils/BackHandler/BackHandler.d.ts +9 -0
- package/dist/utils/BackHandler/BackHandler.native.d.ts +2 -0
- package/dist/utils/addEventListener.d.ts +12 -0
- package/dist/utils/forwardRef.d.ts +11 -0
- package/dist/utils/function-utils.d.ts +12 -0
- package/dist/utils/getContrastingColor.d.ts +2 -0
- package/dist/utils/hasTouchHandler.d.ts +5 -0
- package/dist/utils/roundLayoutSize.d.ts +1 -0
- package/dist/utils/splitStyles.d.ts +19 -0
- package/dist/utils/toast-manager.d.ts +21 -0
- package/dist/utils/useAnimatedValue.d.ts +2 -0
- package/dist/utils/useAnimatedValueArray.d.ts +2 -0
- package/dist/utils/useIsKeyboardShown.d.ts +6 -0
- package/dist/utils/useLayout.d.ts +6 -0
- package/dist/utils/useLazyRef.d.ts +2 -0
- package/package.json +104 -0
- package/src/.DS_Store +0 -0
- package/src/assets/images/error.png +0 -0
- package/src/assets/images/image_default.png +0 -0
- package/src/assets/images/info.png +0 -0
- package/src/assets/images/success.png +0 -0
- package/src/assets/images/warning.png +0 -0
- package/src/assets/svg/icon-checkbox-active.svg +4 -0
- package/src/assets/svg/icon-checkbox.svg +3 -0
- package/src/babel/.eslintrc +7 -0
- package/src/babel/index.js +63 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/ActivityIndicator.tsx +238 -0
- package/src/components/Avatar/index.tsx +102 -0
- package/src/components/Badge/index.tsx +55 -0
- package/src/components/Button/index.tsx +162 -0
- package/src/components/ButtonIcon/index.tsx +98 -0
- package/src/components/Checkbox/index.tsx +107 -0
- package/src/components/ChipBar/index.tsx +112 -0
- package/src/components/CountingDot/index.tsx +63 -0
- package/src/components/FloatingButton/index.tsx +99 -0
- package/src/components/Icon/index.tsx +135 -0
- package/src/components/IconSvg/index.tsx +42 -0
- package/src/components/Image/index.tsx +127 -0
- package/src/components/ProgressBar.tsx +272 -0
- package/src/components/RadioButton/index.tsx +105 -0
- package/src/components/ScaleButton/index.tsx +17 -0
- package/src/components/SelectionField/index.tsx +166 -0
- package/src/components/Spacer/index.tsx +19 -0
- package/src/components/Switch/Switch.tsx +110 -0
- package/src/components/Switch/utils.ts +96 -0
- package/src/components/Text/index.tsx +69 -0
- package/src/components/TextInput/.DS_Store +0 -0
- package/src/components/TextInput/Addons/Outline.tsx +62 -0
- package/src/components/TextInput/Addons/Underline.tsx +71 -0
- package/src/components/TextInput/Adornment/TextInputAdornment.tsx +191 -0
- package/src/components/TextInput/Adornment/TextInputAffix.tsx +212 -0
- package/src/components/TextInput/Adornment/enums.tsx +12 -0
- package/src/components/TextInput/Adornment/types.tsx +11 -0
- package/src/components/TextInput/Adornment/utils.ts +39 -0
- package/src/components/TextInput/Label/InputLabel.tsx +216 -0
- package/src/components/TextInput/Label/LabelBackground.tsx +100 -0
- package/src/components/TextInput/TextInput.tsx +564 -0
- package/src/components/TextInput/TextInputDefault.tsx +187 -0
- package/src/components/TextInput/TextInputFlat.tsx +452 -0
- package/src/components/TextInput/constants.tsx +48 -0
- package/src/components/TextInput/helpers.tsx +546 -0
- package/src/components/TextInput/types.tsx +155 -0
- package/src/components/Toast/ToastProvider.tsx +69 -0
- package/src/components/Toast/index.tsx +239 -0
- package/src/components/Typography/AnimatedText.tsx +84 -0
- package/src/components/Typography/StyledText.tsx +53 -0
- package/src/components/Typography/Text.tsx +189 -0
- package/src/components/Typography/types.tsx +5 -0
- package/src/components/View/index.tsx +175 -0
- package/src/components/ViewVisibleAnimated/index.tsx +199 -0
- package/src/constants.tsx +16 -0
- package/src/core/theming.tsx +144 -0
- package/src/icons/IconArrowDown.tsx +14 -0
- package/src/icons/IconCheckbox.tsx +20 -0
- package/src/icons/IconCheckboxActive.tsx +18 -0
- package/src/icons/IconClearText.tsx +14 -0
- package/src/icons/IconRadio.tsx +11 -0
- package/src/icons/IconRadioActive.tsx +12 -0
- package/src/icons/IconRadioDisable.tsx +12 -0
- package/src/index.ts +51 -0
- package/src/index.tsx +50 -0
- package/src/styles/fonts.tsx +89 -0
- package/src/styles/overlay.tsx +69 -0
- package/src/styles/shadow.tsx +47 -0
- package/src/styles/themes/DarkTheme.tsx +157 -0
- package/src/styles/themes/LightTheme.tsx +160 -0
- package/src/styles/themes/index.ts +3 -0
- package/src/styles/themes/tokens.tsx +481 -0
- package/src/theme/blue.ts +25 -0
- package/src/theme/colors.ts +21 -0
- package/src/theme/container-styles.tsx +126 -0
- package/src/theme/dimensions.ts +44 -0
- package/src/theme/green.ts +27 -0
- package/src/theme/icon.ts +7 -0
- package/src/theme/ink.ts +18 -0
- package/src/theme/orange.ts +24 -0
- package/src/theme/purple.ts +8 -0
- package/src/theme/red.ts +26 -0
- package/src/theme/themes.tsx +287 -0
- package/src/theme/white.ts +16 -0
- package/src/theme/yellow.ts +26 -0
- package/src/types/index.ts +71 -0
- package/src/types/svg.d.ts +5 -0
- package/src/types.ts +259 -0
- package/src/types.tsx +284 -0
- package/src/utils/BackHandler/BackHandler.native.tsx +3 -0
- package/src/utils/BackHandler/BackHandler.tsx +11 -0
- package/src/utils/addEventListener.tsx +56 -0
- package/src/utils/forwardRef.tsx +23 -0
- package/src/utils/function-utils.tsx +108 -0
- package/src/utils/getContrastingColor.tsx +15 -0
- package/src/utils/hasTouchHandler.tsx +23 -0
- package/src/utils/roundLayoutSize.ts +2 -0
- package/src/utils/splitStyles.ts +60 -0
- package/src/utils/toast-manager.tsx +46 -0
- package/src/utils/useAnimatedValue.tsx +9 -0
- package/src/utils/useAnimatedValueArray.tsx +13 -0
- package/src/utils/useIsKeyboardShown.tsx +55 -0
- package/src/utils/useLayout.tsx +29 -0
- package/src/utils/useLazyRef.tsx +11 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React, { forwardRef, memo } from "react";
|
|
2
|
+
import { Animated } from "react-native";
|
|
3
|
+
import isEqual from "lodash/isEqual";
|
|
4
|
+
|
|
5
|
+
// Helper function to check if value is Date object
|
|
6
|
+
function isDateObject(value: any): boolean {
|
|
7
|
+
return value instanceof Date && !isNaN(value.getTime());
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Wrapper function for deepEqual to handle Date object comparison
|
|
11
|
+
export function deepEqualWithDate(a: any, b: any): boolean {
|
|
12
|
+
// Handle Date object comparison
|
|
13
|
+
if (isDateObject(a) !== isDateObject(b)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (isDateObject(a) && isDateObject(b)) {
|
|
17
|
+
return a.getTime() === b.getTime();
|
|
18
|
+
}
|
|
19
|
+
return isEqual(a, b);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Wrapper function for deepEqual to handle arguments object comparison
|
|
23
|
+
export function deepEqualWithArguments(a: any, b: any): boolean {
|
|
24
|
+
// Handle arguments object comparison
|
|
25
|
+
if (isArguments(a) !== isArguments(b)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return deepEqualWithDate(a, b);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Helper function to check if value is arguments object
|
|
32
|
+
function isArguments(value: any): boolean {
|
|
33
|
+
return Object.prototype.toString.call(value) === "[object Arguments]";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function memoDeepEqual<T>(component: React.ComponentType<T>) {
|
|
37
|
+
return memo(component, (prevProps, nextProps) =>
|
|
38
|
+
deepEqualWithArguments(prevProps, nextProps)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const memoWithRef = (component: any) => {
|
|
43
|
+
return memo(forwardRef(component), (prevProps, nextProps) =>
|
|
44
|
+
isEqual(prevProps, nextProps)
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const detectEmail = (email: string) => {
|
|
49
|
+
var re =
|
|
50
|
+
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
51
|
+
return re.test(email);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const detectUserName = (name: string) => {
|
|
55
|
+
var re =
|
|
56
|
+
/^[a-zA-Z0-9ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂưăạảấầẩẫậắằẳẵặẹẻẽềềểỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹ ]*$/i;
|
|
57
|
+
return re.test(name);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const detectPhoneNumber = (phoneNum: string) => {
|
|
61
|
+
var filter = /^[0-9]+$/;
|
|
62
|
+
if (filter.test(phoneNum)) {
|
|
63
|
+
return true;
|
|
64
|
+
} else {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export function withAnimated(
|
|
70
|
+
WrappedComponent: React.ComponentType<any>
|
|
71
|
+
): React.ComponentType {
|
|
72
|
+
const displayName =
|
|
73
|
+
WrappedComponent.displayName || WrappedComponent.name || "Component";
|
|
74
|
+
class WithAnimated extends React.Component {
|
|
75
|
+
static displayName = `WithAnimated(${displayName})`;
|
|
76
|
+
|
|
77
|
+
render(): React.ReactNode {
|
|
78
|
+
return <WrappedComponent {...this.props} />;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return Animated.createAnimatedComponent(WithAnimated);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const phoneValid = (phone: string) => {
|
|
86
|
+
const phoneRegex = /(((\+|)84)|0)(3|5|7|8|9)+([0-9]{8})\b/;
|
|
87
|
+
return phoneRegex.test(phone?.trim());
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const lightenColor = (color: string, percent: number) => {
|
|
91
|
+
const num = parseInt(color.slice(1), 16);
|
|
92
|
+
const amt = Math.round(2.55 * percent);
|
|
93
|
+
const R = (num >> 16) + amt;
|
|
94
|
+
const G = ((num >> 8) & 0x00ff) + amt;
|
|
95
|
+
const B = (num & 0x0000ff) + amt;
|
|
96
|
+
return `#${(
|
|
97
|
+
0x1000000 +
|
|
98
|
+
(R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
|
|
99
|
+
(G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +
|
|
100
|
+
(B < 255 ? (B < 1 ? 0 : B) : 255)
|
|
101
|
+
)
|
|
102
|
+
.toString(16)
|
|
103
|
+
.slice(1)}`;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export function getFileExtension(filename: string) {
|
|
107
|
+
return filename.substring(filename.lastIndexOf(".") + 1);
|
|
108
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ColorValue } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import color from 'color';
|
|
4
|
+
|
|
5
|
+
export default function getContrastingColor(
|
|
6
|
+
input: ColorValue,
|
|
7
|
+
light: string,
|
|
8
|
+
dark: string
|
|
9
|
+
): string {
|
|
10
|
+
if (typeof input === 'string') {
|
|
11
|
+
return color(input).isLight() ? dark : light;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return light;
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GestureResponderEvent } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const touchableEvents = [
|
|
4
|
+
'onPress',
|
|
5
|
+
'onLongPress',
|
|
6
|
+
'onPressIn',
|
|
7
|
+
'onPressOut',
|
|
8
|
+
] as const;
|
|
9
|
+
|
|
10
|
+
type TouchableEventObject = Partial<
|
|
11
|
+
Record<
|
|
12
|
+
(typeof touchableEvents)[number],
|
|
13
|
+
(event: GestureResponderEvent) => void
|
|
14
|
+
>
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
export default function hasTouchHandler(
|
|
18
|
+
touchableEventObject: TouchableEventObject
|
|
19
|
+
) {
|
|
20
|
+
return touchableEvents.some((event) => {
|
|
21
|
+
return Boolean(touchableEventObject[event]);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
type FiltersArray = readonly ((style: keyof ViewStyle) => boolean)[];
|
|
4
|
+
|
|
5
|
+
type MappedTuple<Tuple extends FiltersArray> = {
|
|
6
|
+
[Index in keyof Tuple]: ViewStyle;
|
|
7
|
+
} & { length: Tuple['length'] };
|
|
8
|
+
|
|
9
|
+
type Style = ViewStyle[keyof ViewStyle];
|
|
10
|
+
type Entry = [keyof ViewStyle, Style];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Utility function to extract styles in separate objects
|
|
14
|
+
*
|
|
15
|
+
* @param styles The style object you want to filter
|
|
16
|
+
* @param filters The filters by which you want to split the styles
|
|
17
|
+
* @returns An array of filtered style objects:
|
|
18
|
+
* - The first style object contains the properties that didn't match any filter
|
|
19
|
+
* - After that there will be a style object for each filter you passed in the same order as the matching filters
|
|
20
|
+
* - A style property will exist in a single style object, the first filter it matched
|
|
21
|
+
*/
|
|
22
|
+
export function splitStyles<Tuple extends FiltersArray>(
|
|
23
|
+
styles: ViewStyle,
|
|
24
|
+
...filters: Tuple
|
|
25
|
+
) {
|
|
26
|
+
if (process.env.NODE_ENV !== 'production' && filters.length === 0) {
|
|
27
|
+
console.error('No filters were passed when calling splitStyles');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// `Object.entries` will be used to iterate over the styles and `Object.fromEntries` will be called before returning
|
|
31
|
+
// Entries which match the given filters will be temporarily stored in `newStyles`
|
|
32
|
+
const newStyles = filters.map(() => [] as Entry[]);
|
|
33
|
+
|
|
34
|
+
// Entries which match no filter
|
|
35
|
+
const rest: Entry[] = [];
|
|
36
|
+
|
|
37
|
+
// Iterate every style property
|
|
38
|
+
outer: for (const item of Object.entries(styles) as Entry[]) {
|
|
39
|
+
// Check each filter
|
|
40
|
+
for (let i = 0; i < filters.length; i++) {
|
|
41
|
+
// Check if filter matches
|
|
42
|
+
if (filters[i](item[0])) {
|
|
43
|
+
newStyles[i].push(item); // Push to temporary filtered entries array
|
|
44
|
+
continue outer; // Skip to checking next style property
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Adds to rest styles if not filtered
|
|
49
|
+
rest.push(item);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Put unmatched styles in the beginning
|
|
53
|
+
newStyles.unshift(rest);
|
|
54
|
+
|
|
55
|
+
// Convert arrays of entries into objects
|
|
56
|
+
return newStyles.map((styles) => Object.fromEntries(styles)) as unknown as [
|
|
57
|
+
ViewStyle,
|
|
58
|
+
...MappedTuple<Tuple>
|
|
59
|
+
];
|
|
60
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface ToastRef {
|
|
4
|
+
show: (params: {
|
|
5
|
+
message?: string;
|
|
6
|
+
duration?: number;
|
|
7
|
+
position?: "top" | "bottom";
|
|
8
|
+
type?: "success" | "info" | "warning" | "error";
|
|
9
|
+
onPress?: () => void;
|
|
10
|
+
title?: string;
|
|
11
|
+
}) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const toastRef = React.createRef<ToastRef>();
|
|
15
|
+
|
|
16
|
+
export const showToast = ({
|
|
17
|
+
message,
|
|
18
|
+
duration = 5000,
|
|
19
|
+
position = "top",
|
|
20
|
+
type = "success",
|
|
21
|
+
onPress = () => {},
|
|
22
|
+
title,
|
|
23
|
+
}: {
|
|
24
|
+
message?: string;
|
|
25
|
+
duration?: number;
|
|
26
|
+
position?: "top" | "bottom";
|
|
27
|
+
type?: "success" | "info" | "warning" | "error";
|
|
28
|
+
onPress?: () => void;
|
|
29
|
+
title?: string;
|
|
30
|
+
}) => {
|
|
31
|
+
if (!toastRef.current) {
|
|
32
|
+
console.warn(
|
|
33
|
+
"Toast component is not mounted. Make sure to add <ToastProvider> to your app."
|
|
34
|
+
);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
toastRef.current.show({
|
|
39
|
+
message,
|
|
40
|
+
duration,
|
|
41
|
+
position,
|
|
42
|
+
type,
|
|
43
|
+
onPress,
|
|
44
|
+
title,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export default function useAnimatedValueArray(initialValues: number[]) {
|
|
5
|
+
const refs = React.useRef<Animated.Value[]>([]);
|
|
6
|
+
|
|
7
|
+
refs.current.length = initialValues.length;
|
|
8
|
+
initialValues.forEach((initialValue, i) => {
|
|
9
|
+
refs.current[i] = refs.current[i] ?? new Animated.Value(initialValue);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
return refs.current;
|
|
13
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Keyboard, NativeEventSubscription, Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
onShow: () => void;
|
|
6
|
+
onHide: () => void;
|
|
7
|
+
};
|
|
8
|
+
export default function useIsKeyboardShown({ onShow, onHide }: Props) {
|
|
9
|
+
React.useEffect(() => {
|
|
10
|
+
let willShowSubscription: NativeEventSubscription | undefined;
|
|
11
|
+
let willHideSubscription: NativeEventSubscription | undefined;
|
|
12
|
+
let didShowSubscription: NativeEventSubscription | undefined;
|
|
13
|
+
let didHideSubscription: NativeEventSubscription | undefined;
|
|
14
|
+
|
|
15
|
+
if (Platform.OS === 'ios') {
|
|
16
|
+
willShowSubscription = Keyboard.addListener('keyboardWillShow', onShow);
|
|
17
|
+
willHideSubscription = Keyboard.addListener('keyboardWillHide', onHide);
|
|
18
|
+
} else {
|
|
19
|
+
didShowSubscription = Keyboard.addListener('keyboardDidShow', onShow);
|
|
20
|
+
didHideSubscription = Keyboard.addListener('keyboardDidHide', onHide);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return () => {
|
|
24
|
+
if (Platform.OS === 'ios') {
|
|
25
|
+
if (willShowSubscription?.remove) {
|
|
26
|
+
willShowSubscription.remove();
|
|
27
|
+
} else {
|
|
28
|
+
// @ts-expect-error: We keep deprecated listener remove method for backwards compat with old RN versions
|
|
29
|
+
Keyboard.removeListener('keyboardWillShow', onShow);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (willHideSubscription?.remove) {
|
|
33
|
+
willHideSubscription.remove();
|
|
34
|
+
} else {
|
|
35
|
+
// @ts-expect-error: We keep deprecated listener remove method for backwards compat with old RN versions
|
|
36
|
+
Keyboard.removeListener('keyboardWillHide', onHide);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
if (didShowSubscription?.remove) {
|
|
40
|
+
didShowSubscription.remove();
|
|
41
|
+
} else {
|
|
42
|
+
// @ts-expect-error: We keep deprecated listener remove method for backwards compat with old RN versions
|
|
43
|
+
Keyboard.removeListener('keyboardDidShow', onShow);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (didHideSubscription?.remove) {
|
|
47
|
+
didHideSubscription.remove();
|
|
48
|
+
} else {
|
|
49
|
+
// @ts-expect-error: We keep deprecated listener remove method for backwards compat with old RN versions
|
|
50
|
+
Keyboard.removeListener('keyboardDidHide', onHide);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}, [onHide, onShow]);
|
|
55
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { LayoutChangeEvent } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export default function useLayout() {
|
|
5
|
+
const [layout, setLayout] = React.useState<{
|
|
6
|
+
height: number;
|
|
7
|
+
width: number;
|
|
8
|
+
measured: boolean;
|
|
9
|
+
}>({ height: 0, width: 0, measured: false });
|
|
10
|
+
|
|
11
|
+
const onLayout = React.useCallback(
|
|
12
|
+
(e: LayoutChangeEvent) => {
|
|
13
|
+
const { height, width } = e.nativeEvent.layout;
|
|
14
|
+
|
|
15
|
+
if (height === layout.height && width === layout.width) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setLayout({
|
|
20
|
+
height,
|
|
21
|
+
width,
|
|
22
|
+
measured: true,
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
[layout.height, layout.width]
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return [layout, onLayout] as const;
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
export default function useLazyRef<T>(callback: () => T) {
|
|
4
|
+
const lazyRef = React.useRef<T | undefined>(null);
|
|
5
|
+
|
|
6
|
+
if (lazyRef.current === undefined) {
|
|
7
|
+
lazyRef.current = callback();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return lazyRef as React.MutableRefObject<T>;
|
|
11
|
+
}
|