@prototyp/skeletor 1.0.2
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/.eslintrc.json +19 -0
- package/.github/CODEOWNERS +2 -0
- package/.gitignore +5 -0
- package/README.md +418 -0
- package/lib/module/components/Block/Block.js +71 -0
- package/lib/module/components/Block/Block.js.map +1 -0
- package/lib/module/components/Block/index.js +2 -0
- package/lib/module/components/Block/index.js.map +1 -0
- package/lib/module/components/InputFocusScrollView/InputFocusScrollView.js +93 -0
- package/lib/module/components/InputFocusScrollView/InputFocusScrollView.js.map +1 -0
- package/lib/module/components/InputFocusScrollView/index.js +2 -0
- package/lib/module/components/InputFocusScrollView/index.js.map +1 -0
- package/lib/module/components/Screen/Screen.js +55 -0
- package/lib/module/components/Screen/Screen.js.map +1 -0
- package/lib/module/components/Screen/index.js +2 -0
- package/lib/module/components/Screen/index.js.map +1 -0
- package/lib/module/components/SkeletorProvider/SkeletorContext.js +9 -0
- package/lib/module/components/SkeletorProvider/SkeletorContext.js.map +1 -0
- package/lib/module/components/SkeletorProvider/SkeletorProvider.js +17 -0
- package/lib/module/components/SkeletorProvider/SkeletorProvider.js.map +1 -0
- package/lib/module/components/SkeletorProvider/index.js +3 -0
- package/lib/module/components/SkeletorProvider/index.js.map +1 -0
- package/lib/module/components/Text/Text.js +64 -0
- package/lib/module/components/Text/Text.js.map +1 -0
- package/lib/module/components/Text/index.js +2 -0
- package/lib/module/components/Text/index.js.map +1 -0
- package/lib/module/components/index.js +6 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/hooks/index.js +7 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useAndroidBackHandler.js +24 -0
- package/lib/module/hooks/useAndroidBackHandler.js.map +1 -0
- package/lib/module/hooks/useAnimation.js +33 -0
- package/lib/module/hooks/useAnimation.js.map +1 -0
- package/lib/module/hooks/useAnimationTimeline.js +97 -0
- package/lib/module/hooks/useAnimationTimeline.js.map +1 -0
- package/lib/module/hooks/useAppState.js +21 -0
- package/lib/module/hooks/useAppState.js.map +1 -0
- package/lib/module/hooks/useForm.js +159 -0
- package/lib/module/hooks/useForm.js.map +1 -0
- package/lib/module/hooks/useSkeletor.js +6 -0
- package/lib/module/hooks/useSkeletor.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/models/Alignment.js +2 -0
- package/lib/module/models/Alignment.js.map +1 -0
- package/lib/module/models/Border.js +2 -0
- package/lib/module/models/Border.js.map +1 -0
- package/lib/module/models/Size.js +2 -0
- package/lib/module/models/Size.js.map +1 -0
- package/lib/module/models/SkeletorConfig.js +2 -0
- package/lib/module/models/SkeletorConfig.js.map +1 -0
- package/lib/module/models/Spacing.js +2 -0
- package/lib/module/models/Spacing.js.map +1 -0
- package/lib/module/models/index.js +6 -0
- package/lib/module/models/index.js.map +1 -0
- package/lib/module/types/Font.d.js +2 -0
- package/lib/module/types/Font.d.js.map +1 -0
- package/lib/module/utils/extractAlignmentProperties.js +10 -0
- package/lib/module/utils/extractAlignmentProperties.js.map +1 -0
- package/lib/module/utils/extractSizeProperties.js +12 -0
- package/lib/module/utils/extractSizeProperties.js.map +1 -0
- package/lib/module/utils/index.js +3 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/typescript/lib/module/components/Block/Block.d.ts +4 -0
- package/lib/typescript/lib/module/components/Block/Block.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/Block/index.d.ts +2 -0
- package/lib/typescript/lib/module/components/Block/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/InputFocusScrollView/InputFocusScrollView.d.ts +4 -0
- package/lib/typescript/lib/module/components/InputFocusScrollView/InputFocusScrollView.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/InputFocusScrollView/index.d.ts +2 -0
- package/lib/typescript/lib/module/components/InputFocusScrollView/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/Screen/Screen.d.ts +5 -0
- package/lib/typescript/lib/module/components/Screen/Screen.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/Screen/index.d.ts +2 -0
- package/lib/typescript/lib/module/components/Screen/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorContext.d.ts +14 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorContext.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorProvider.d.ts +8 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorProvider.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/index.d.ts +3 -0
- package/lib/typescript/lib/module/components/SkeletorProvider/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/Text/Text.d.ts +4 -0
- package/lib/typescript/lib/module/components/Text/Text.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/Text/index.d.ts +2 -0
- package/lib/typescript/lib/module/components/Text/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/components/index.d.ts +6 -0
- package/lib/typescript/lib/module/components/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/index.d.ts +7 -0
- package/lib/typescript/lib/module/hooks/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useAndroidBackHandler.d.ts +2 -0
- package/lib/typescript/lib/module/hooks/useAndroidBackHandler.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useAnimation.d.ts +9 -0
- package/lib/typescript/lib/module/hooks/useAnimation.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useAnimationTimeline.d.ts +10 -0
- package/lib/typescript/lib/module/hooks/useAnimationTimeline.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useAppState.d.ts +2 -0
- package/lib/typescript/lib/module/hooks/useAppState.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useForm.d.ts +33 -0
- package/lib/typescript/lib/module/hooks/useForm.d.ts.map +1 -0
- package/lib/typescript/lib/module/hooks/useSkeletor.d.ts +7 -0
- package/lib/typescript/lib/module/hooks/useSkeletor.d.ts.map +1 -0
- package/lib/typescript/lib/module/index.d.ts +5 -0
- package/lib/typescript/lib/module/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/Alignment.d.ts +2 -0
- package/lib/typescript/lib/module/models/Alignment.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/Border.d.ts +1 -0
- package/lib/typescript/lib/module/models/Border.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/Size.d.ts +1 -0
- package/lib/typescript/lib/module/models/Size.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/SkeletorConfig.d.ts +1 -0
- package/lib/typescript/lib/module/models/SkeletorConfig.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/Spacing.d.ts +1 -0
- package/lib/typescript/lib/module/models/Spacing.d.ts.map +1 -0
- package/lib/typescript/lib/module/models/index.d.ts +2 -0
- package/lib/typescript/lib/module/models/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/types/Font.d.d.ts +1 -0
- package/lib/typescript/lib/module/types/Font.d.d.ts.map +1 -0
- package/lib/typescript/lib/module/utils/extractAlignmentProperties.d.ts +8 -0
- package/lib/typescript/lib/module/utils/extractAlignmentProperties.d.ts.map +1 -0
- package/lib/typescript/lib/module/utils/extractSizeProperties.d.ts +10 -0
- package/lib/typescript/lib/module/utils/extractSizeProperties.d.ts.map +1 -0
- package/lib/typescript/lib/module/utils/index.d.ts +3 -0
- package/lib/typescript/lib/module/utils/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Block/Block.d.ts +23 -0
- package/lib/typescript/src/components/Block/Block.d.ts.map +1 -0
- package/lib/typescript/src/components/Block/index.d.ts +2 -0
- package/lib/typescript/src/components/Block/index.d.ts.map +1 -0
- package/lib/typescript/src/components/InputFocusScrollView/InputFocusScrollView.d.ts +18 -0
- package/lib/typescript/src/components/InputFocusScrollView/InputFocusScrollView.d.ts.map +1 -0
- package/lib/typescript/src/components/InputFocusScrollView/index.d.ts +2 -0
- package/lib/typescript/src/components/InputFocusScrollView/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Screen/Screen.d.ts +16 -0
- package/lib/typescript/src/components/Screen/Screen.d.ts.map +1 -0
- package/lib/typescript/src/components/Screen/index.d.ts +2 -0
- package/lib/typescript/src/components/Screen/index.d.ts.map +1 -0
- package/lib/typescript/src/components/SkeletorProvider/SkeletorContext.d.ts +5 -0
- package/lib/typescript/src/components/SkeletorProvider/SkeletorContext.d.ts.map +1 -0
- package/lib/typescript/src/components/SkeletorProvider/SkeletorProvider.d.ts +8 -0
- package/lib/typescript/src/components/SkeletorProvider/SkeletorProvider.d.ts.map +1 -0
- package/lib/typescript/src/components/SkeletorProvider/index.d.ts +3 -0
- package/lib/typescript/src/components/SkeletorProvider/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Text/Text.d.ts +21 -0
- package/lib/typescript/src/components/Text/Text.d.ts.map +1 -0
- package/lib/typescript/src/components/Text/index.d.ts +2 -0
- package/lib/typescript/src/components/Text/index.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +6 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +7 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts +16 -0
- package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAnimation.d.ts +20 -0
- package/lib/typescript/src/hooks/useAnimation.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAnimationTimeline.d.ts +30 -0
- package/lib/typescript/src/hooks/useAnimationTimeline.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAppState.d.ts +7 -0
- package/lib/typescript/src/hooks/useAppState.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useForm.d.ts +52 -0
- package/lib/typescript/src/hooks/useForm.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useSkeletor.d.ts +3 -0
- package/lib/typescript/src/hooks/useSkeletor.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/models/Alignment.d.ts +9 -0
- package/lib/typescript/src/models/Alignment.d.ts.map +1 -0
- package/lib/typescript/src/models/Border.d.ts +16 -0
- package/lib/typescript/src/models/Border.d.ts.map +1 -0
- package/lib/typescript/src/models/Size.d.ts +10 -0
- package/lib/typescript/src/models/Size.d.ts.map +1 -0
- package/lib/typescript/src/models/SkeletorConfig.d.ts +7 -0
- package/lib/typescript/src/models/SkeletorConfig.d.ts.map +1 -0
- package/lib/typescript/src/models/Spacing.d.ts +21 -0
- package/lib/typescript/src/models/Spacing.d.ts.map +1 -0
- package/lib/typescript/src/models/index.d.ts +6 -0
- package/lib/typescript/src/models/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/extractAlignmentProperties.d.ts +3 -0
- package/lib/typescript/src/utils/extractAlignmentProperties.d.ts.map +1 -0
- package/lib/typescript/src/utils/extractSizeProperties.d.ts +3 -0
- package/lib/typescript/src/utils/extractSizeProperties.d.ts.map +1 -0
- package/lib/typescript/src/utils/index.d.ts +3 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -0
- package/package.json +63 -0
- package/prototyp-skeletor-v1.0.0.tgz +0 -0
- package/src/components/Block/Block.tsx +106 -0
- package/src/components/Block/index.ts +1 -0
- package/src/components/InputFocusScrollView/InputFocusScrollView.tsx +120 -0
- package/src/components/InputFocusScrollView/index.ts +1 -0
- package/src/components/Screen/Screen.tsx +91 -0
- package/src/components/Screen/index.ts +1 -0
- package/src/components/SkeletorProvider/SkeletorContext.ts +12 -0
- package/src/components/SkeletorProvider/SkeletorProvider.tsx +18 -0
- package/src/components/SkeletorProvider/index.ts +2 -0
- package/src/components/Text/Text.tsx +99 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/index.ts +5 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useAndroidBackHandler.ts +45 -0
- package/src/hooks/useAnimation.ts +62 -0
- package/src/hooks/useAnimationTimeline.ts +139 -0
- package/src/hooks/useAppState.ts +26 -0
- package/src/hooks/useForm.ts +190 -0
- package/src/hooks/useSkeletor.ts +7 -0
- package/src/index.ts +4 -0
- package/src/models/Alignment.ts +9 -0
- package/src/models/Border.ts +15 -0
- package/src/models/Size.ts +9 -0
- package/src/models/SkeletorConfig.ts +6 -0
- package/src/models/Spacing.ts +20 -0
- package/src/models/index.ts +5 -0
- package/src/types/Font.d.ts +1 -0
- package/src/utils/extractAlignmentProperties.ts +13 -0
- package/src/utils/extractSizeProperties.ts +13 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +16 -0
- package/yarn.lock +6080 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from "react";
|
|
2
|
+
import {
|
|
3
|
+
SafeAreaView,
|
|
4
|
+
View,
|
|
5
|
+
ViewProps,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
StatusBar,
|
|
8
|
+
Platform,
|
|
9
|
+
Dimensions,
|
|
10
|
+
} from "react-native";
|
|
11
|
+
import { useSkeletor } from "../../hooks";
|
|
12
|
+
import { Block } from "../Block";
|
|
13
|
+
|
|
14
|
+
type OwnProps = {
|
|
15
|
+
/** Pass a specific background view OR just a background color value. Custom components should be 100% height and width. */
|
|
16
|
+
background?: JSX.Element | string;
|
|
17
|
+
hideTopSafeArea?: boolean;
|
|
18
|
+
hideBottomSafeArea?: boolean;
|
|
19
|
+
bottomSafeAreaColor?: string;
|
|
20
|
+
topSafeAreaColor?: string;
|
|
21
|
+
statusBarType?: "default" | "light-content" | "dark-content";
|
|
22
|
+
isLandscape?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type ScreenProps = OwnProps & ViewProps;
|
|
26
|
+
|
|
27
|
+
export const Screen: React.FC<PropsWithChildren<ScreenProps>> = ({
|
|
28
|
+
background,
|
|
29
|
+
children,
|
|
30
|
+
hideBottomSafeArea,
|
|
31
|
+
hideTopSafeArea,
|
|
32
|
+
bottomSafeAreaColor,
|
|
33
|
+
topSafeAreaColor,
|
|
34
|
+
style,
|
|
35
|
+
statusBarType,
|
|
36
|
+
isLandscape,
|
|
37
|
+
...rest
|
|
38
|
+
}) => {
|
|
39
|
+
const { defaultStatusBarType } = useSkeletor();
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
{background &&
|
|
44
|
+
(typeof background === "string" ? (
|
|
45
|
+
<View style={[styles.container, { backgroundColor: background }]} />
|
|
46
|
+
) : (
|
|
47
|
+
<View style={styles.container}>{background}</View>
|
|
48
|
+
))}
|
|
49
|
+
|
|
50
|
+
{!hideTopSafeArea && (
|
|
51
|
+
<SafeAreaView style={{ backgroundColor: topSafeAreaColor }} />
|
|
52
|
+
)}
|
|
53
|
+
|
|
54
|
+
<StatusBar
|
|
55
|
+
translucent
|
|
56
|
+
backgroundColor="transparent"
|
|
57
|
+
barStyle={statusBarType || defaultStatusBarType}
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<Block
|
|
61
|
+
paddings={{
|
|
62
|
+
paddingTop:
|
|
63
|
+
Platform.OS === "android" && !isLandscape
|
|
64
|
+
? StatusBar.currentHeight || 24
|
|
65
|
+
: 0,
|
|
66
|
+
}}
|
|
67
|
+
flex={1}
|
|
68
|
+
style={style}
|
|
69
|
+
{...rest}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</Block>
|
|
73
|
+
|
|
74
|
+
{!hideBottomSafeArea && (
|
|
75
|
+
<SafeAreaView
|
|
76
|
+
style={{
|
|
77
|
+
backgroundColor: bottomSafeAreaColor,
|
|
78
|
+
}}
|
|
79
|
+
/>
|
|
80
|
+
)}
|
|
81
|
+
</>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const styles = StyleSheet.create({
|
|
86
|
+
container: {
|
|
87
|
+
position: "absolute",
|
|
88
|
+
height: Dimensions.get("screen").height,
|
|
89
|
+
width: Dimensions.get("screen").width,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Screen";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SkeletorConfig } from "../../models";
|
|
3
|
+
|
|
4
|
+
export const SkeletorDefaults: SkeletorConfig = {
|
|
5
|
+
defaultFont: undefined,
|
|
6
|
+
defaultFontSize: [12, 16],
|
|
7
|
+
defaultStatusBarType: "dark-content",
|
|
8
|
+
defaultTextColor: "black",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const SkeletorContext =
|
|
12
|
+
React.createContext<SkeletorConfig>(SkeletorDefaults);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from "react";
|
|
2
|
+
import { SkeletorConfig } from "../../models";
|
|
3
|
+
import { SkeletorContext, SkeletorDefaults } from "./SkeletorContext";
|
|
4
|
+
|
|
5
|
+
type Props = Partial<SkeletorConfig>;
|
|
6
|
+
|
|
7
|
+
/** Create a Font.d.ts type in your typescript types directory and define fonts as follows:
|
|
8
|
+
* @example type Font = "Helvetica" | "Montserrat" ... */
|
|
9
|
+
export const SkeletorProvider: React.FC<PropsWithChildren<Props>> = ({
|
|
10
|
+
children,
|
|
11
|
+
...config
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<SkeletorContext.Provider value={{ ...SkeletorDefaults, ...config }}>
|
|
15
|
+
{children}
|
|
16
|
+
</SkeletorContext.Provider>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { PropsWithChildren, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
StyleSheet,
|
|
4
|
+
Text as RNText,
|
|
5
|
+
TextProps as RNTextProps,
|
|
6
|
+
TextStyle,
|
|
7
|
+
} from "react-native";
|
|
8
|
+
import { Size, Spacing } from "../../models";
|
|
9
|
+
import { extractSizeProperties } from "../../utils";
|
|
10
|
+
import { useSkeletor } from "../../hooks";
|
|
11
|
+
|
|
12
|
+
interface OwnProps extends RNTextProps {
|
|
13
|
+
/** Create a Font.d.ts type in your typescript types directory and define fonts as follows:
|
|
14
|
+
* @example type Font = "Helvetica" | "Montserrat" ... */
|
|
15
|
+
font?: Font;
|
|
16
|
+
/** Either define [fontSize, lineHeight] or just one size applied to both fontSize and lineHeight */
|
|
17
|
+
size?: [number, number] | number;
|
|
18
|
+
textTransform?: TextStyle["textTransform"];
|
|
19
|
+
letterSpacing?: TextStyle["letterSpacing"];
|
|
20
|
+
color?: string;
|
|
21
|
+
textAlign?: TextStyle["textAlign"];
|
|
22
|
+
opacity?: TextStyle["opacity"];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type TextProps = OwnProps & Spacing & Size;
|
|
26
|
+
|
|
27
|
+
/** Create a Font.d.ts type in your typescript types directory and define fonts as follows:
|
|
28
|
+
* @example type Font = "Helvetica" | "Montserrat" ... */
|
|
29
|
+
export const Text: React.FC<PropsWithChildren<TextProps>> = ({
|
|
30
|
+
font,
|
|
31
|
+
size,
|
|
32
|
+
textTransform,
|
|
33
|
+
letterSpacing,
|
|
34
|
+
color,
|
|
35
|
+
style,
|
|
36
|
+
children,
|
|
37
|
+
textAlign,
|
|
38
|
+
opacity,
|
|
39
|
+
margins,
|
|
40
|
+
paddings,
|
|
41
|
+
...props
|
|
42
|
+
}) => {
|
|
43
|
+
const { defaultFont, defaultFontSize, defaultTextColor } = useSkeletor();
|
|
44
|
+
const sizeProps = extractSizeProperties(props);
|
|
45
|
+
|
|
46
|
+
const textSize = useMemo(() => {
|
|
47
|
+
function mapper(value: [number, number] | number) {
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
const [fontSize, lineHeight] = value;
|
|
50
|
+
return { fontSize, lineHeight };
|
|
51
|
+
} else {
|
|
52
|
+
return { fontSize: value, lineHeight: value };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return mapper(size || defaultFontSize);
|
|
57
|
+
}, [size, defaultFontSize]);
|
|
58
|
+
|
|
59
|
+
const styles = useMemo(
|
|
60
|
+
() =>
|
|
61
|
+
StyleSheet.flatten([
|
|
62
|
+
{
|
|
63
|
+
color: color || defaultTextColor,
|
|
64
|
+
...textSize,
|
|
65
|
+
fontFamily: font || defaultFont,
|
|
66
|
+
opacity,
|
|
67
|
+
textAlign,
|
|
68
|
+
textTransform,
|
|
69
|
+
letterSpacing,
|
|
70
|
+
...margins,
|
|
71
|
+
...paddings,
|
|
72
|
+
...sizeProps,
|
|
73
|
+
},
|
|
74
|
+
style,
|
|
75
|
+
]),
|
|
76
|
+
[
|
|
77
|
+
color,
|
|
78
|
+
font,
|
|
79
|
+
opacity,
|
|
80
|
+
textAlign,
|
|
81
|
+
textTransform,
|
|
82
|
+
textSize,
|
|
83
|
+
margins,
|
|
84
|
+
paddings,
|
|
85
|
+
style,
|
|
86
|
+
]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<RNText
|
|
91
|
+
style={styles}
|
|
92
|
+
allowFontScaling={false}
|
|
93
|
+
maxFontSizeMultiplier={1}
|
|
94
|
+
{...props}
|
|
95
|
+
>
|
|
96
|
+
{children}
|
|
97
|
+
</RNText>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Text";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { BackHandler } from "react-native";
|
|
3
|
+
|
|
4
|
+
interface DefaultProps {
|
|
5
|
+
/** Whether the custom handler is enabled or disabled. */
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface WithCallback extends DefaultProps {
|
|
9
|
+
/** Callback function to execute on back button press. Will disable default behavior. */
|
|
10
|
+
handlePress: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface WithDisable extends DefaultProps {
|
|
14
|
+
/** Whether or not the default android back button behavior will be blocked */
|
|
15
|
+
disableDefault: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type AndroidBackHandlerConfig = WithCallback | WithDisable;
|
|
19
|
+
|
|
20
|
+
function isWithCallback(
|
|
21
|
+
props: AndroidBackHandlerConfig,
|
|
22
|
+
): props is WithCallback {
|
|
23
|
+
return Object.keys(props).some((key) => key === "handlePress");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function useAndroidBackHandler(props: AndroidBackHandlerConfig) {
|
|
27
|
+
const { enabled } = props;
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!enabled) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const handler = BackHandler.addEventListener("hardwareBackPress", () => {
|
|
35
|
+
if (isWithCallback(props)) {
|
|
36
|
+
props.handlePress();
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return props.disableDefault;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return handler.remove;
|
|
44
|
+
}, [enabled]);
|
|
45
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useMemo, useRef } from "react";
|
|
2
|
+
import { Animated, ViewStyle } from "react-native";
|
|
3
|
+
|
|
4
|
+
/** Any is a hotfix, requires more investigation */
|
|
5
|
+
type Animation<Keys extends keyof Partial<ViewStyle>> = Record<
|
|
6
|
+
Keys,
|
|
7
|
+
Animated.AnimatedInterpolation<string | number> | any
|
|
8
|
+
>;
|
|
9
|
+
type Definition<Keys extends keyof Partial<ViewStyle>> = Record<
|
|
10
|
+
Keys,
|
|
11
|
+
number[] | string[]
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
interface Configuration {
|
|
15
|
+
/** In miliseconds */
|
|
16
|
+
duration: number;
|
|
17
|
+
/** Loop will disable native driver because it breaks the loop animation (at least it did last time I tested in 2020.) */
|
|
18
|
+
loop?: boolean;
|
|
19
|
+
useNativeDriver?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface AnimationSet<Keys extends keyof Partial<ViewStyle>> {
|
|
23
|
+
values: Animated.Value[];
|
|
24
|
+
definitions: Definition<Keys>;
|
|
25
|
+
animations: Animation<Keys>;
|
|
26
|
+
configuration: Configuration;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function useAnimation<Keys extends keyof Partial<ViewStyle>>(
|
|
30
|
+
styles: Definition<Keys>,
|
|
31
|
+
configuration?: Configuration,
|
|
32
|
+
): AnimationSet<Keys> {
|
|
33
|
+
const keys = Object.keys(styles).map((key) => key as Keys);
|
|
34
|
+
/** Values always start at 0. These are not output values, more like indexes to output values defined in the array. */
|
|
35
|
+
const values = useRef(keys.map(() => new Animated.Value(0))).current;
|
|
36
|
+
|
|
37
|
+
const animations = useMemo(() => {
|
|
38
|
+
const result: Partial<Animation<Keys>> = {};
|
|
39
|
+
|
|
40
|
+
keys.forEach((key, index) => {
|
|
41
|
+
const value = values[index];
|
|
42
|
+
// We know the definition exists, otherwise we wouldn't be here.
|
|
43
|
+
const definition = styles[key]!;
|
|
44
|
+
|
|
45
|
+
const interpolation = value.interpolate({
|
|
46
|
+
inputRange: definition.map((_, i) => i),
|
|
47
|
+
outputRange: definition,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
result[key] = interpolation;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return result as Animation<Keys>;
|
|
54
|
+
}, [styles]);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
values,
|
|
58
|
+
animations,
|
|
59
|
+
configuration: configuration || { duration: 250 },
|
|
60
|
+
definitions: styles,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { Animated, ViewStyle } from "react-native";
|
|
3
|
+
import { AnimationSet } from "./useAnimation";
|
|
4
|
+
|
|
5
|
+
interface BaseTimelineType {
|
|
6
|
+
elements: AnimationSet<any>[];
|
|
7
|
+
start: boolean;
|
|
8
|
+
onFinished?: () => void;
|
|
9
|
+
onStarted?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type DelayTimeline = BaseTimelineType & {
|
|
13
|
+
delay: number;
|
|
14
|
+
};
|
|
15
|
+
type StaggerTimeline = BaseTimelineType & {
|
|
16
|
+
stagger: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
interface TimelineConfiguration {
|
|
20
|
+
delay?: DelayTimeline;
|
|
21
|
+
parallel?: BaseTimelineType;
|
|
22
|
+
sequence?: BaseTimelineType;
|
|
23
|
+
stagger?: StaggerTimeline;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Used to layout animated values on a timeline and handle starting/reversing the animations.
|
|
27
|
+
* Supports all Animated types (delay, stagger, parallel, sequence).
|
|
28
|
+
* @example
|
|
29
|
+
* useAnimationTimeline({
|
|
30
|
+
stagger: { elements: [ring1, ring2, ring3], stagger: 900, start: show },
|
|
31
|
+
sequence: { elements: [button], start: Boolean(show && !disabled) },
|
|
32
|
+
});
|
|
33
|
+
*/
|
|
34
|
+
export function useAnimationTimeline(config: TimelineConfiguration): void {
|
|
35
|
+
const { delay, parallel, sequence, stagger } = config;
|
|
36
|
+
const staggerStart = Boolean(stagger?.start);
|
|
37
|
+
const delayStart = Boolean(delay?.start);
|
|
38
|
+
const sequenceStart = Boolean(sequence?.start);
|
|
39
|
+
const parallelStart = Boolean(parallel?.start);
|
|
40
|
+
|
|
41
|
+
const [previousDelayStart, setPreviousDelayStart] = useState(false);
|
|
42
|
+
const [previousStaggerStart, setPreviousStaggerStart] = useState(false);
|
|
43
|
+
const [previousSequenceStart, setPreviousSequenceStart] = useState(false);
|
|
44
|
+
const [previousParallelStart, setPreviousParallelStart] = useState(false);
|
|
45
|
+
|
|
46
|
+
function getBaseAnimations(
|
|
47
|
+
timeline: BaseTimelineType | StaggerTimeline | DelayTimeline,
|
|
48
|
+
) {
|
|
49
|
+
const compositions: Animated.CompositeAnimation[] = [];
|
|
50
|
+
timeline.elements.forEach(
|
|
51
|
+
({ values, animations, configuration, definitions }) => {
|
|
52
|
+
const keys = Object.keys(animations).map(
|
|
53
|
+
(key) => key as keyof Partial<ViewStyle>,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const elementCompositions = keys.map((key, index) => {
|
|
57
|
+
const value = values[index];
|
|
58
|
+
const lastValue = definitions[key]!.length - 1;
|
|
59
|
+
const nativeAnimation = configuration.loop
|
|
60
|
+
? false
|
|
61
|
+
: configuration.useNativeDriver || false;
|
|
62
|
+
|
|
63
|
+
const base = Animated.timing(value, {
|
|
64
|
+
toValue: timeline.start ? lastValue : 0,
|
|
65
|
+
duration: configuration.duration,
|
|
66
|
+
useNativeDriver: nativeAnimation,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return configuration.loop ? Animated.loop(base) : base;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
compositions.push(Animated.parallel(elementCompositions));
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return compositions;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function setupParallelAnimations(timeline: BaseTimelineType) {
|
|
80
|
+
if (timeline.onStarted) {
|
|
81
|
+
timeline.onStarted();
|
|
82
|
+
}
|
|
83
|
+
Animated.parallel(getBaseAnimations(timeline)).start(timeline.onFinished);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function setupSequenceAnimations(timeline: BaseTimelineType) {
|
|
87
|
+
if (timeline.onStarted) {
|
|
88
|
+
timeline.onStarted();
|
|
89
|
+
}
|
|
90
|
+
Animated.sequence(getBaseAnimations(timeline)).start(timeline.onFinished);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function setupStaggerAnimations(timeline: StaggerTimeline) {
|
|
94
|
+
if (timeline.onStarted) {
|
|
95
|
+
timeline.onStarted();
|
|
96
|
+
}
|
|
97
|
+
Animated.stagger(timeline.stagger, getBaseAnimations(timeline)).start(
|
|
98
|
+
timeline.onFinished,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function setupDelayAnimations(timeline: DelayTimeline) {
|
|
103
|
+
Animated.delay(timeline.delay).start(() =>
|
|
104
|
+
setupParallelAnimations(timeline),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (stagger && previousStaggerStart !== staggerStart) {
|
|
110
|
+
setupStaggerAnimations(stagger);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
setPreviousStaggerStart(staggerStart);
|
|
114
|
+
}, [previousStaggerStart, staggerStart, stagger]);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (parallel && previousParallelStart !== parallelStart) {
|
|
118
|
+
setupParallelAnimations(parallel);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setPreviousParallelStart(parallelStart);
|
|
122
|
+
}, [previousParallelStart, parallelStart, parallel]);
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (sequence && previousSequenceStart !== sequenceStart) {
|
|
126
|
+
setupSequenceAnimations(sequence);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
setPreviousSequenceStart(sequenceStart);
|
|
130
|
+
}, [previousSequenceStart, sequenceStart, sequence]);
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (delay && previousDelayStart !== delayStart) {
|
|
134
|
+
setupDelayAnimations(delay);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
setPreviousDelayStart(delayStart);
|
|
138
|
+
}, [previousDelayStart, delayStart, delay]);
|
|
139
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useCallback, useEffect } from "react";
|
|
2
|
+
import { AppState, AppStateStatus } from "react-native";
|
|
3
|
+
|
|
4
|
+
interface Config {
|
|
5
|
+
onForeground?: () => void;
|
|
6
|
+
onBackground?: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useAppState({ onForeground, onBackground }: Config) {
|
|
10
|
+
const handleAppStateChange = useCallback(
|
|
11
|
+
(state: AppStateStatus) => {
|
|
12
|
+
if (state.match(/background|inactive/)) {
|
|
13
|
+
onBackground?.();
|
|
14
|
+
}
|
|
15
|
+
if (state === "active") {
|
|
16
|
+
onForeground?.();
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
[onBackground, onForeground],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const event = AppState.addEventListener("change", handleAppStateChange);
|
|
24
|
+
return event.remove;
|
|
25
|
+
}, [handleAppStateChange]);
|
|
26
|
+
}
|