@jobber/components-native 0.8.0 → 0.10.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/dist/src/Card/Card.js +38 -0
- package/dist/src/Card/Card.style.js +31 -0
- package/dist/src/Card/components/InternalCardHeader.js +14 -0
- package/dist/src/Card/components/InternalCardHeader.style.js +16 -0
- package/dist/src/Card/components/index.js +1 -0
- package/dist/src/Card/index.js +1 -0
- package/dist/src/InputFieldWrapper/CommonInputStyles.style.js +33 -0
- package/dist/src/InputFieldWrapper/InputFieldWrapper.js +88 -0
- package/dist/src/InputFieldWrapper/InputFieldWrapper.style.js +79 -0
- package/dist/src/InputFieldWrapper/components/ClearAction/ClearAction.js +12 -0
- package/dist/src/InputFieldWrapper/components/ClearAction/ClearAction.style.js +25 -0
- package/dist/src/InputFieldWrapper/components/ClearAction/index.js +2 -0
- package/dist/src/InputFieldWrapper/components/ClearAction/messages.js +8 -0
- package/dist/src/InputFieldWrapper/components/Prefix/Prefix.js +34 -0
- package/dist/src/InputFieldWrapper/components/Suffix/Suffix.js +35 -0
- package/dist/src/InputFieldWrapper/hooks/useShowClear.js +15 -0
- package/dist/src/InputFieldWrapper/index.js +3 -0
- package/dist/src/index.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/Card/Card.d.ts +40 -0
- package/dist/types/src/Card/Card.style.d.ts +56 -0
- package/dist/types/src/Card/components/InternalCardHeader.d.ts +9 -0
- package/dist/types/src/Card/components/InternalCardHeader.style.d.ts +14 -0
- package/dist/types/src/Card/components/index.d.ts +1 -0
- package/dist/types/src/Card/index.d.ts +2 -0
- package/dist/types/src/InputFieldWrapper/CommonInputStyles.style.d.ts +30 -0
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +63 -0
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.style.d.ts +82 -0
- package/dist/types/src/InputFieldWrapper/components/ClearAction/ClearAction.d.ts +10 -0
- package/dist/types/src/InputFieldWrapper/components/ClearAction/ClearAction.style.d.ts +22 -0
- package/dist/types/src/InputFieldWrapper/components/ClearAction/index.d.ts +2 -0
- package/dist/types/src/InputFieldWrapper/components/ClearAction/messages.d.ts +7 -0
- package/dist/types/src/InputFieldWrapper/components/Prefix/Prefix.d.ts +23 -0
- package/dist/types/src/InputFieldWrapper/components/Suffix/Suffix.d.ts +25 -0
- package/dist/types/src/InputFieldWrapper/hooks/useShowClear.d.ts +10 -0
- package/dist/types/src/InputFieldWrapper/index.d.ts +4 -0
- package/dist/types/src/index.d.ts +2 -0
- package/package.json +4 -2
- package/src/Card/Card.style.ts +46 -0
- package/src/Card/Card.test.tsx +128 -0
- package/src/Card/Card.tsx +145 -0
- package/src/Card/components/InternalCardHeader.style.ts +19 -0
- package/src/Card/components/InternalCardHeader.test.tsx +31 -0
- package/src/Card/components/InternalCardHeader.tsx +41 -0
- package/src/Card/components/index.ts +1 -0
- package/src/Card/index.ts +2 -0
- package/src/InputFieldWrapper/CommonInputStyles.style.ts +37 -0
- package/src/InputFieldWrapper/InputFieldWrapper.style.ts +93 -0
- package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +243 -0
- package/src/InputFieldWrapper/InputFieldWrapper.tsx +317 -0
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.style.ts +27 -0
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.test.tsx +15 -0
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.tsx +32 -0
- package/src/InputFieldWrapper/components/ClearAction/index.ts +2 -0
- package/src/InputFieldWrapper/components/ClearAction/messages.ts +9 -0
- package/src/InputFieldWrapper/components/Prefix/Prefix.test.tsx +221 -0
- package/src/InputFieldWrapper/components/Prefix/Prefix.tsx +104 -0
- package/src/InputFieldWrapper/components/Suffix/Suffix.test.tsx +101 -0
- package/src/InputFieldWrapper/components/Suffix/Suffix.tsx +113 -0
- package/src/InputFieldWrapper/hooks/useShowClear.test.ts +158 -0
- package/src/InputFieldWrapper/hooks/useShowClear.ts +31 -0
- package/src/InputFieldWrapper/index.ts +4 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { IconNames } from "@jobber/design";
|
|
3
|
+
import { XOR } from "ts-xor";
|
|
4
|
+
interface CardProps {
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated Use <ActionItem /> with the title and onPress properties instead
|
|
7
|
+
*/
|
|
8
|
+
readonly header?: HeaderProps;
|
|
9
|
+
readonly footer?: FooterProps;
|
|
10
|
+
readonly children?: ReactNode;
|
|
11
|
+
readonly reportCardHeight?: (height: number) => void;
|
|
12
|
+
readonly testID?: string;
|
|
13
|
+
readonly error?: string;
|
|
14
|
+
readonly elevation?: elevationProp;
|
|
15
|
+
}
|
|
16
|
+
type elevationProp = "none" | "low" | "base" | "high";
|
|
17
|
+
export type HeaderProps = HeaderCommonProps & HeaderActionProps;
|
|
18
|
+
interface FooterProps {
|
|
19
|
+
readonly onPress: () => void;
|
|
20
|
+
readonly title: string;
|
|
21
|
+
}
|
|
22
|
+
interface HeaderCommonProps {
|
|
23
|
+
readonly title: string;
|
|
24
|
+
}
|
|
25
|
+
type HeaderActionProps = {
|
|
26
|
+
readonly onPress?: never;
|
|
27
|
+
readonly actionItem?: never;
|
|
28
|
+
} | {
|
|
29
|
+
readonly onPress: () => void;
|
|
30
|
+
readonly actionItem: ActionItem;
|
|
31
|
+
};
|
|
32
|
+
interface IconAction {
|
|
33
|
+
readonly iconName: IconNames;
|
|
34
|
+
}
|
|
35
|
+
interface ButtonAction {
|
|
36
|
+
readonly label: string;
|
|
37
|
+
}
|
|
38
|
+
export type ActionItem = XOR<IconAction, ButtonAction>;
|
|
39
|
+
export declare function Card({ header, footer, children, reportCardHeight: onCardHeightChange, testID, error, elevation, }: CardProps): JSX.Element;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare const styles: {
|
|
2
|
+
container: {
|
|
3
|
+
width: string;
|
|
4
|
+
backgroundColor: string;
|
|
5
|
+
};
|
|
6
|
+
lowElevation: {
|
|
7
|
+
shadowColor: string;
|
|
8
|
+
shadowOffset: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
shadowOpacity: number;
|
|
13
|
+
shadowRadius: number;
|
|
14
|
+
elevation: number;
|
|
15
|
+
};
|
|
16
|
+
baseElevation: {
|
|
17
|
+
shadowColor: string;
|
|
18
|
+
shadowOffset: {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
shadowOpacity: number;
|
|
23
|
+
shadowRadius: number;
|
|
24
|
+
elevation: number;
|
|
25
|
+
};
|
|
26
|
+
highElevation: {
|
|
27
|
+
shadowColor: string;
|
|
28
|
+
shadowOffset: {
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
};
|
|
32
|
+
shadowOpacity: number;
|
|
33
|
+
shadowRadius: number;
|
|
34
|
+
elevation: number;
|
|
35
|
+
};
|
|
36
|
+
headerTitle: {
|
|
37
|
+
flexGrow: number;
|
|
38
|
+
flex: number;
|
|
39
|
+
};
|
|
40
|
+
footer: {
|
|
41
|
+
height: number;
|
|
42
|
+
flex: number;
|
|
43
|
+
justifyContent: "center";
|
|
44
|
+
alignItems: "center";
|
|
45
|
+
};
|
|
46
|
+
pressed: {
|
|
47
|
+
opacity: number;
|
|
48
|
+
};
|
|
49
|
+
actionItem: {
|
|
50
|
+
height: number;
|
|
51
|
+
justifyContent: "center";
|
|
52
|
+
};
|
|
53
|
+
actionLabel: {
|
|
54
|
+
paddingTop: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
interface InternalCardHeaderProps {
|
|
3
|
+
readonly children: ReactNode[] | ReactNode;
|
|
4
|
+
readonly onPress?: () => void;
|
|
5
|
+
readonly testID?: string;
|
|
6
|
+
readonly collapsable: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function InternalCardHeader({ onPress, children, testID, collapsable, }: InternalCardHeaderProps): JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InternalCardHeader } from "./InternalCardHeader";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const commonInputStyles: {
|
|
2
|
+
input: {
|
|
3
|
+
width: string;
|
|
4
|
+
flexShrink: number;
|
|
5
|
+
flexGrow: number;
|
|
6
|
+
color: string;
|
|
7
|
+
fontFamily: string | undefined;
|
|
8
|
+
fontSize: number | undefined;
|
|
9
|
+
letterSpacing: number | undefined;
|
|
10
|
+
minHeight: number;
|
|
11
|
+
padding: number;
|
|
12
|
+
};
|
|
13
|
+
inputEmpty: {
|
|
14
|
+
paddingTop: number;
|
|
15
|
+
};
|
|
16
|
+
inputDisabled: {
|
|
17
|
+
color: import("react-native").ColorValue | undefined;
|
|
18
|
+
};
|
|
19
|
+
container: {
|
|
20
|
+
marginVertical: number;
|
|
21
|
+
backgroundColor: string;
|
|
22
|
+
minHeight: number;
|
|
23
|
+
flexDirection: "row";
|
|
24
|
+
justifyContent: "space-between";
|
|
25
|
+
width: string;
|
|
26
|
+
borderColor: string;
|
|
27
|
+
borderStyle: "solid";
|
|
28
|
+
borderBottomWidth: number;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
3
|
+
import { FieldError } from "react-hook-form";
|
|
4
|
+
import { IconNames } from "@jobber/design";
|
|
5
|
+
export type Clearable = "never" | "while-editing" | "always";
|
|
6
|
+
export interface InputFieldStyleOverride {
|
|
7
|
+
prefixLabel?: StyleProp<TextStyle>;
|
|
8
|
+
suffixLabel?: StyleProp<TextStyle>;
|
|
9
|
+
container?: StyleProp<ViewStyle>;
|
|
10
|
+
placeholderText?: StyleProp<TextStyle>;
|
|
11
|
+
}
|
|
12
|
+
export interface InputFieldWrapperProps {
|
|
13
|
+
/**
|
|
14
|
+
* Highlights the field red and shows message below (if string) to indicate an error
|
|
15
|
+
*/
|
|
16
|
+
readonly invalid?: boolean | string;
|
|
17
|
+
/**
|
|
18
|
+
* Disable the input
|
|
19
|
+
*/
|
|
20
|
+
readonly disabled?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Hint text that goes above the value once the field is filled out
|
|
23
|
+
*/
|
|
24
|
+
readonly placeholder?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Text that goes below the input to help the user understand the input
|
|
27
|
+
*/
|
|
28
|
+
readonly assistiveText?: string;
|
|
29
|
+
readonly hasMiniLabel?: boolean;
|
|
30
|
+
readonly hasValue?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Symbol to display before the text input
|
|
33
|
+
*/
|
|
34
|
+
readonly prefix?: {
|
|
35
|
+
icon?: IconNames;
|
|
36
|
+
label?: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Symbol to display after the text input
|
|
40
|
+
*/
|
|
41
|
+
readonly suffix?: {
|
|
42
|
+
icon?: IconNames;
|
|
43
|
+
label?: string;
|
|
44
|
+
onPress?: () => void;
|
|
45
|
+
};
|
|
46
|
+
readonly error?: FieldError;
|
|
47
|
+
readonly focused?: boolean;
|
|
48
|
+
readonly children: React.ReactNode;
|
|
49
|
+
/**
|
|
50
|
+
* Adds the ClearAction that will call the onClear handler when pressed
|
|
51
|
+
*/
|
|
52
|
+
readonly showClearAction?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Callback called when the user clicks the ClearAction button. Should clear the value passed.
|
|
55
|
+
* To disallow clearing set the clearable prop to never
|
|
56
|
+
*/
|
|
57
|
+
readonly onClear?: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Custom styling to override default style of the input field
|
|
60
|
+
*/
|
|
61
|
+
readonly styleOverride?: InputFieldStyleOverride;
|
|
62
|
+
}
|
|
63
|
+
export declare function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, hasMiniLabel, hasValue, error, focused, children, onClear, showClearAction, styleOverride, }: InputFieldWrapperProps): JSX.Element;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export declare const styles: {
|
|
2
|
+
container: {
|
|
3
|
+
marginVertical: number;
|
|
4
|
+
backgroundColor: string;
|
|
5
|
+
minHeight: number;
|
|
6
|
+
flexDirection: "row";
|
|
7
|
+
justifyContent: "space-between";
|
|
8
|
+
width: string;
|
|
9
|
+
borderColor: string;
|
|
10
|
+
borderStyle: "solid";
|
|
11
|
+
borderBottomWidth: number;
|
|
12
|
+
};
|
|
13
|
+
inputContainer: {
|
|
14
|
+
flexDirection: "row";
|
|
15
|
+
flex: number;
|
|
16
|
+
justifyContent: "flex-start";
|
|
17
|
+
};
|
|
18
|
+
inputFocused: {
|
|
19
|
+
borderColor: string;
|
|
20
|
+
};
|
|
21
|
+
inputInvalid: {
|
|
22
|
+
borderColor: string;
|
|
23
|
+
};
|
|
24
|
+
label: {
|
|
25
|
+
position: "absolute";
|
|
26
|
+
top: number | undefined;
|
|
27
|
+
right: number;
|
|
28
|
+
bottom: number;
|
|
29
|
+
left: number;
|
|
30
|
+
};
|
|
31
|
+
miniLabel: {
|
|
32
|
+
top: number;
|
|
33
|
+
paddingTop: number;
|
|
34
|
+
backgroundColor: string;
|
|
35
|
+
maxHeight: number;
|
|
36
|
+
zIndex: number;
|
|
37
|
+
};
|
|
38
|
+
miniLabelShowClearAction: {
|
|
39
|
+
backgroundColor: string;
|
|
40
|
+
};
|
|
41
|
+
disabled: {
|
|
42
|
+
backgroundColor: string;
|
|
43
|
+
borderTopLeftRadius: number;
|
|
44
|
+
borderTopRightRadius: number;
|
|
45
|
+
};
|
|
46
|
+
fieldAffix: {
|
|
47
|
+
flexDirection: "row";
|
|
48
|
+
};
|
|
49
|
+
fieldAffixMiniLabel: {
|
|
50
|
+
paddingTop: number;
|
|
51
|
+
top: number;
|
|
52
|
+
right: number;
|
|
53
|
+
bottom: number;
|
|
54
|
+
left: number;
|
|
55
|
+
};
|
|
56
|
+
prefixIcon: {
|
|
57
|
+
justifyContent: "center";
|
|
58
|
+
paddingRight: number;
|
|
59
|
+
};
|
|
60
|
+
prefixLabel: {
|
|
61
|
+
justifyContent: "center";
|
|
62
|
+
paddingTop: number;
|
|
63
|
+
paddingRight: number;
|
|
64
|
+
};
|
|
65
|
+
suffixIcon: {
|
|
66
|
+
justifyContent: "center";
|
|
67
|
+
};
|
|
68
|
+
suffixLabel: {
|
|
69
|
+
justifyContent: "center";
|
|
70
|
+
paddingTop: number;
|
|
71
|
+
};
|
|
72
|
+
suffixIconMargin: {
|
|
73
|
+
marginLeft: number;
|
|
74
|
+
};
|
|
75
|
+
suffixLabelMargin: {
|
|
76
|
+
marginLeft: number;
|
|
77
|
+
};
|
|
78
|
+
inputEndContainer: {
|
|
79
|
+
flexDirection: "row";
|
|
80
|
+
zIndex: number;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
interface ClearActionProps {
|
|
3
|
+
/**
|
|
4
|
+
* Press handler
|
|
5
|
+
*/
|
|
6
|
+
readonly onPress: () => void;
|
|
7
|
+
readonly hasMarginRight?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function ClearAction({ onPress, hasMarginRight, }: ClearActionProps): JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const styles: {
|
|
2
|
+
container: {
|
|
3
|
+
width: number;
|
|
4
|
+
height: string;
|
|
5
|
+
flexDirection: "row";
|
|
6
|
+
justifyContent: "center";
|
|
7
|
+
alignItems: "center";
|
|
8
|
+
alignSelf: "center";
|
|
9
|
+
};
|
|
10
|
+
circle: {
|
|
11
|
+
backgroundColor: string;
|
|
12
|
+
borderRadius: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
flexDirection: "row";
|
|
16
|
+
justifyContent: "center";
|
|
17
|
+
alignItems: "center";
|
|
18
|
+
};
|
|
19
|
+
addedMargin: {
|
|
20
|
+
marginRight: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
3
|
+
import { IconNames } from "@jobber/design";
|
|
4
|
+
export interface PrefixLabelProps {
|
|
5
|
+
focused: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
hasMiniLabel: boolean;
|
|
8
|
+
inputInvalid: boolean;
|
|
9
|
+
label: string;
|
|
10
|
+
styleOverride?: StyleProp<TextStyle>;
|
|
11
|
+
}
|
|
12
|
+
export declare const prefixLabelTestId = "ATL-InputFieldWrapper-PrefixLabel";
|
|
13
|
+
export declare const prefixIconTestId = "ATL-InputFieldWrapper-PrefixIcon";
|
|
14
|
+
export declare function PrefixLabel({ focused, disabled, hasMiniLabel, inputInvalid, label, styleOverride, }: PrefixLabelProps): JSX.Element;
|
|
15
|
+
export interface PrefixIconProps {
|
|
16
|
+
focused: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
hasMiniLabel: boolean;
|
|
19
|
+
inputInvalid?: boolean;
|
|
20
|
+
icon: IconNames;
|
|
21
|
+
styleOverride?: StyleProp<ViewStyle>;
|
|
22
|
+
}
|
|
23
|
+
export declare function PrefixIcon({ focused, disabled, inputInvalid, icon, }: PrefixIconProps): JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { StyleProp, TextStyle } from "react-native";
|
|
3
|
+
import { IconNames } from "@jobber/design";
|
|
4
|
+
export interface SuffixLabelProps {
|
|
5
|
+
focused: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
hasMiniLabel: boolean;
|
|
8
|
+
inputInvalid?: boolean;
|
|
9
|
+
label: string;
|
|
10
|
+
hasLeftMargin?: boolean;
|
|
11
|
+
styleOverride?: StyleProp<TextStyle>;
|
|
12
|
+
}
|
|
13
|
+
export declare const suffixLabelTestId = "ATL-InputFieldWrapper-SuffixLabel";
|
|
14
|
+
export declare const suffixIconTestId = "ATL-InputFieldWrapper-SuffixIcon";
|
|
15
|
+
export declare function SuffixLabel({ focused, disabled, hasMiniLabel, inputInvalid, label, hasLeftMargin, styleOverride, }: SuffixLabelProps): JSX.Element;
|
|
16
|
+
export interface SuffixIconProps {
|
|
17
|
+
focused: boolean;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
hasMiniLabel: boolean;
|
|
20
|
+
inputInvalid?: boolean;
|
|
21
|
+
icon: IconNames;
|
|
22
|
+
hasLeftMargin?: boolean;
|
|
23
|
+
onPress?: () => void;
|
|
24
|
+
}
|
|
25
|
+
export declare function SuffixIcon({ focused, disabled, inputInvalid, icon, hasLeftMargin, onPress, }: SuffixIconProps): JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Clearable } from "../InputFieldWrapper";
|
|
2
|
+
interface UseShowClearParameters {
|
|
3
|
+
clearable: Clearable;
|
|
4
|
+
multiline: boolean;
|
|
5
|
+
focused: boolean;
|
|
6
|
+
hasValue: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function useShowClear({ clearable, multiline, focused, hasValue, disabled, }: UseShowClearParameters): boolean | undefined;
|
|
10
|
+
export {};
|
|
@@ -6,5 +6,7 @@ export * from "./ErrorMessageWrapper";
|
|
|
6
6
|
export * from "./ActionLabel";
|
|
7
7
|
export * from "./Content";
|
|
8
8
|
export * from "./ActivityIndicator";
|
|
9
|
+
export * from "./Card";
|
|
9
10
|
export * from "./StatusLabel";
|
|
10
11
|
export * from "./AtlantisContext";
|
|
12
|
+
export * from "./InputFieldWrapper";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"module": "dist/src/index.js",
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@jobber/design": "^0.39.0",
|
|
25
|
+
"react-hook-form": "^7.30.0",
|
|
26
|
+
"react-intl": "^6.4.2",
|
|
25
27
|
"react-native-gesture-handler": "^2.5.0",
|
|
26
28
|
"react-native-localize": "^2.2.6",
|
|
27
29
|
"react-native-svg": "^13.9.0",
|
|
@@ -44,5 +46,5 @@
|
|
|
44
46
|
"react": "^18",
|
|
45
47
|
"react-native": ">=0.69.2"
|
|
46
48
|
},
|
|
47
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "d363c516d3f72dc510c7b0ad002fdbf479bf9292"
|
|
48
50
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
import { tokens } from "../utils/design";
|
|
3
|
+
|
|
4
|
+
export const styles = StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
width: "100%",
|
|
7
|
+
backgroundColor: tokens["color-surface"],
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
lowElevation: {
|
|
11
|
+
...tokens["shadow-low"],
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
baseElevation: {
|
|
15
|
+
...tokens["shadow-base"],
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
highElevation: {
|
|
19
|
+
...tokens["shadow-high"],
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
headerTitle: {
|
|
23
|
+
flexGrow: 1,
|
|
24
|
+
flex: 1,
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
footer: {
|
|
28
|
+
height: tokens["space-largest"],
|
|
29
|
+
flex: 1,
|
|
30
|
+
justifyContent: "center",
|
|
31
|
+
alignItems: "center",
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
pressed: {
|
|
35
|
+
opacity: tokens["opacity-pressed"],
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
actionItem: {
|
|
39
|
+
height: tokens["typography--lineHeight-base"],
|
|
40
|
+
justifyContent: "center",
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
actionLabel: {
|
|
44
|
+
paddingTop: tokens["space-smallest"],
|
|
45
|
+
},
|
|
46
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { fireEvent, render } from "@testing-library/react-native";
|
|
3
|
+
import { Card } from "./Card";
|
|
4
|
+
import { Text } from "../Text";
|
|
5
|
+
|
|
6
|
+
const cardHeaderTestID = "cardHeader";
|
|
7
|
+
const cardFooterTestID = "cardFooter";
|
|
8
|
+
|
|
9
|
+
it("renders with only a header title", () => {
|
|
10
|
+
const title = "Foobar";
|
|
11
|
+
const { getByTestId, getByText, queryAllByRole } = render(
|
|
12
|
+
<Card header={{ title }} />,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
expect(getByText(title)).toBeDefined();
|
|
16
|
+
expect(getByTestId(cardHeaderTestID)).toBeDefined();
|
|
17
|
+
expect(queryAllByRole("button")).toEqual([]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("renders with an icon action", () => {
|
|
21
|
+
const iconName = "plus2";
|
|
22
|
+
const { getByTestId } = render(
|
|
23
|
+
<Card
|
|
24
|
+
header={{
|
|
25
|
+
title: "Foobar",
|
|
26
|
+
actionItem: { iconName },
|
|
27
|
+
onPress: jest.fn(),
|
|
28
|
+
}}
|
|
29
|
+
/>,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(getByTestId(iconName)).toBeDefined();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("renders with a button action", () => {
|
|
36
|
+
const label = "Edit";
|
|
37
|
+
const { getByText } = render(
|
|
38
|
+
<Card
|
|
39
|
+
header={{
|
|
40
|
+
title: "Foobar",
|
|
41
|
+
actionItem: { label },
|
|
42
|
+
onPress: jest.fn(),
|
|
43
|
+
}}
|
|
44
|
+
/>,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(getByText(label)).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("renders without a header and footer", () => {
|
|
51
|
+
const content = "I am the content";
|
|
52
|
+
const { getByText, queryByTestId } = render(
|
|
53
|
+
<Card>
|
|
54
|
+
<Text>{content}</Text>
|
|
55
|
+
</Card>,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(getByText(content)).toBeDefined();
|
|
59
|
+
expect(queryByTestId(cardHeaderTestID)).toBeNull();
|
|
60
|
+
expect(queryByTestId(cardFooterTestID)).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should call the onPress when pressing the header", () => {
|
|
64
|
+
const pressHandler = jest.fn();
|
|
65
|
+
|
|
66
|
+
const { getByText } = render(
|
|
67
|
+
<Card
|
|
68
|
+
header={{
|
|
69
|
+
title: "Header",
|
|
70
|
+
actionItem: { iconName: "plus2" },
|
|
71
|
+
onPress: pressHandler,
|
|
72
|
+
}}
|
|
73
|
+
/>,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
fireEvent.press(getByText("Header"));
|
|
77
|
+
expect(pressHandler).toHaveBeenCalled();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should call the onPress when pressing the action button", () => {
|
|
81
|
+
const pressHandler = jest.fn();
|
|
82
|
+
|
|
83
|
+
const { getByText } = render(
|
|
84
|
+
<Card
|
|
85
|
+
header={{
|
|
86
|
+
title: "Header",
|
|
87
|
+
actionItem: { label: "Edit" },
|
|
88
|
+
onPress: pressHandler,
|
|
89
|
+
}}
|
|
90
|
+
/>,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
fireEvent.press(getByText("Edit"));
|
|
94
|
+
expect(pressHandler).toHaveBeenCalled();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("renders with a footer", () => {
|
|
98
|
+
const title = "View All";
|
|
99
|
+
const { getByText, getByTestId, queryByTestId } = render(
|
|
100
|
+
<Card footer={{ title: title, onPress: jest.fn() }} />,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
expect(getByText(title)).toBeDefined();
|
|
104
|
+
expect(getByTestId(cardFooterTestID)).toBeDefined();
|
|
105
|
+
expect(queryByTestId(cardHeaderTestID)).toBeNull();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("should call the onPress when pressing the footer", () => {
|
|
109
|
+
const headerPressHandler = jest.fn();
|
|
110
|
+
const footerPressHandler = jest.fn();
|
|
111
|
+
|
|
112
|
+
const { getByText } = render(
|
|
113
|
+
<Card
|
|
114
|
+
header={{
|
|
115
|
+
title: "Header",
|
|
116
|
+
actionItem: { iconName: "plus2" },
|
|
117
|
+
onPress: headerPressHandler,
|
|
118
|
+
}}
|
|
119
|
+
footer={{
|
|
120
|
+
title: "View All",
|
|
121
|
+
onPress: footerPressHandler,
|
|
122
|
+
}}
|
|
123
|
+
/>,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
fireEvent.press(getByText("View All"));
|
|
127
|
+
expect(footerPressHandler).toHaveBeenCalled();
|
|
128
|
+
});
|