ferns-ui 0.37.0 → 0.37.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/dist/Avatar.js +5 -6
- package/dist/Avatar.js.map +1 -1
- package/dist/Badge.js +4 -3
- package/dist/Badge.js.map +1 -1
- package/dist/Body.d.ts +10 -5
- package/dist/Body.js +14 -15
- package/dist/Body.js.map +1 -1
- package/dist/Box.js +9 -7
- package/dist/Box.js.map +1 -1
- package/dist/Button.js +5 -3
- package/dist/Button.js.map +1 -1
- package/dist/Common.d.ts +7 -19
- package/dist/Common.js.map +1 -1
- package/dist/DateTimeActionSheet.js +9 -7
- package/dist/DateTimeActionSheet.js.map +1 -1
- package/dist/DateTimeField.android.js +5 -4
- package/dist/DateTimeField.android.js.map +1 -1
- package/dist/DateTimeField.ios.js +6 -5
- package/dist/DateTimeField.ios.js.map +1 -1
- package/dist/FernsProvider.js +4 -2
- package/dist/FernsProvider.js.map +1 -1
- package/dist/Heading.d.ts +1 -9
- package/dist/Heading.js +22 -43
- package/dist/Heading.js.map +1 -1
- package/dist/Icon.js +4 -3
- package/dist/Icon.js.map +1 -1
- package/dist/IconButton.d.ts +1 -1
- package/dist/IconButton.js +4 -2
- package/dist/IconButton.js.map +1 -1
- package/dist/Modal.js +2 -1
- package/dist/Modal.js.map +1 -1
- package/dist/Page.js +1 -3
- package/dist/Page.js.map +1 -1
- package/dist/ProgressBar.d.ts +5 -7
- package/dist/ProgressBar.js +30 -36
- package/dist/ProgressBar.js.map +1 -1
- package/dist/SelectList.js +6 -5
- package/dist/SelectList.js.map +1 -1
- package/dist/Spinner.d.ts +5 -1
- package/dist/Spinner.js +1 -1
- package/dist/Spinner.js.map +1 -1
- package/dist/SplitPage.js +4 -3
- package/dist/SplitPage.js.map +1 -1
- package/dist/SplitPage.native.js +4 -2
- package/dist/SplitPage.native.js.map +1 -1
- package/dist/Text.js +6 -5
- package/dist/Text.js.map +1 -1
- package/dist/TextField.js +11 -10
- package/dist/TextField.js.map +1 -1
- package/dist/Theme.d.ts +12 -0
- package/dist/Theme.js +108 -0
- package/dist/Theme.js.map +1 -0
- package/dist/Tooltip.js +4 -2
- package/dist/Tooltip.js.map +1 -1
- package/dist/Unifier.d.ts +1 -6
- package/dist/Unifier.js +0 -134
- package/dist/Unifier.js.map +1 -1
- package/dist/Utilities.d.ts +1 -0
- package/dist/Utilities.js +4 -0
- package/dist/Utilities.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Avatar.tsx +6 -6
- package/src/Badge.tsx +5 -3
- package/src/Body.tsx +32 -21
- package/src/Box.tsx +10 -8
- package/src/Button.tsx +5 -3
- package/src/Common.ts +11 -22
- package/src/DateTimeActionSheet.tsx +11 -7
- package/src/DateTimeField.android.tsx +5 -4
- package/src/DateTimeField.ios.tsx +6 -5
- package/src/FernsProvider.tsx +14 -11
- package/src/Heading.tsx +27 -44
- package/src/Icon.tsx +4 -3
- package/src/IconButton.tsx +12 -3
- package/src/Modal.tsx +2 -1
- package/src/Page.tsx +1 -5
- package/src/ProgressBar.tsx +41 -44
- package/src/SelectList.tsx +7 -5
- package/src/Spinner.tsx +7 -2
- package/src/SplitPage.native.tsx +4 -2
- package/src/SplitPage.tsx +4 -3
- package/src/Text.tsx +7 -5
- package/src/TextField.tsx +13 -11
- package/src/Theme.tsx +189 -0
- package/src/Tooltip.tsx +4 -2
- package/src/Unifier.ts +0 -196
- package/src/Utilities.tsx +5 -0
- package/src/index.tsx +1 -0
package/src/IconButton.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {forwardRef, useState} from "react";
|
|
1
|
+
import React, {forwardRef, useContext, useState} from "react";
|
|
2
2
|
import {Platform, Pressable, View, ViewStyle} from "react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import {Icon} from "./Icon";
|
|
17
17
|
import {Modal} from "./Modal";
|
|
18
18
|
import {Text} from "./Text";
|
|
19
|
+
import {ThemeContext} from "./Theme";
|
|
19
20
|
import {Tooltip} from "./Tooltip";
|
|
20
21
|
import {Unifier} from "./Unifier";
|
|
21
22
|
|
|
@@ -26,7 +27,14 @@ export interface IconButtonProps {
|
|
|
26
27
|
iconColor: "darkGray" | ButtonColor | ThemeColor | Color;
|
|
27
28
|
onClick: () => void;
|
|
28
29
|
size?: IconSize;
|
|
29
|
-
bgColor?:
|
|
30
|
+
bgColor?:
|
|
31
|
+
| "transparent"
|
|
32
|
+
| "transparentDarkGray"
|
|
33
|
+
| "gray"
|
|
34
|
+
| "lightGray"
|
|
35
|
+
| "white"
|
|
36
|
+
| "background"
|
|
37
|
+
| "backgroundSecondary"; // default transparent
|
|
30
38
|
disabled?: boolean;
|
|
31
39
|
selected?: boolean;
|
|
32
40
|
withConfirmation?: boolean;
|
|
@@ -59,6 +67,7 @@ export const IconButton = forwardRef(
|
|
|
59
67
|
}: IconButtonProps,
|
|
60
68
|
ref
|
|
61
69
|
) => {
|
|
70
|
+
const {theme} = useContext(ThemeContext);
|
|
62
71
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
|
63
72
|
|
|
64
73
|
const opacity = 1;
|
|
@@ -68,7 +77,7 @@ export const IconButton = forwardRef(
|
|
|
68
77
|
} else if (bgColor === "transparent" || !bgColor) {
|
|
69
78
|
color = "rgba(0, 0, 0, 0.0)";
|
|
70
79
|
} else {
|
|
71
|
-
color =
|
|
80
|
+
color = theme[bgColor];
|
|
72
81
|
}
|
|
73
82
|
|
|
74
83
|
const IndicatorPosition = {
|
package/src/Modal.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {Heading} from "./Heading";
|
|
|
8
8
|
import {IconButton} from "./IconButton";
|
|
9
9
|
import {isMobileDevice} from "./MediaQuery";
|
|
10
10
|
import {Text} from "./Text";
|
|
11
|
+
import {isNative} from "./Utilities";
|
|
11
12
|
|
|
12
13
|
interface ModalProps {
|
|
13
14
|
onDismiss: () => void;
|
|
@@ -240,7 +241,7 @@ export const Modal = ({
|
|
|
240
241
|
);
|
|
241
242
|
};
|
|
242
243
|
|
|
243
|
-
if (isMobileDevice()) {
|
|
244
|
+
if (isMobileDevice() && isNative()) {
|
|
244
245
|
return renderActionSheet();
|
|
245
246
|
} else {
|
|
246
247
|
return renderModal();
|
package/src/Page.tsx
CHANGED
|
@@ -6,9 +6,7 @@ import {Color, UnsignedUpTo12} from "./Common";
|
|
|
6
6
|
import {ErrorBoundary} from "./ErrorBoundary";
|
|
7
7
|
import {Heading} from "./Heading";
|
|
8
8
|
import {IconButton} from "./IconButton";
|
|
9
|
-
// import {KeyboardAccessoryNavigation} from "react-native-keyboard-accessory";
|
|
10
9
|
import {Spinner} from "./Spinner";
|
|
11
|
-
import {Unifier} from "./Unifier";
|
|
12
10
|
|
|
13
11
|
interface PageProps {
|
|
14
12
|
// TODO: figure out navigation
|
|
@@ -99,9 +97,7 @@ export class Page extends React.Component<PageProps, {}> {
|
|
|
99
97
|
width="100%"
|
|
100
98
|
>
|
|
101
99
|
{this.renderHeader()}
|
|
102
|
-
{this.props.loading === true &&
|
|
103
|
-
<Spinner color={Unifier.theme.darkGray as any} size="md" />
|
|
104
|
-
)}
|
|
100
|
+
{this.props.loading === true && <Spinner color="darkGray" size="md" />}
|
|
105
101
|
{/* <KeyboardAccessoryNavigation
|
|
106
102
|
avoidKeyboard
|
|
107
103
|
doneButton={true}
|
package/src/ProgressBar.tsx
CHANGED
|
@@ -1,55 +1,52 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, {useContext} from "react";
|
|
2
2
|
import {View} from "react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {Color} from "./Common";
|
|
5
|
+
import {ThemeContext} from "./Theme";
|
|
6
6
|
|
|
7
|
-
interface
|
|
7
|
+
export interface ProgressBarProps {
|
|
8
|
+
color: Color;
|
|
9
|
+
completed: number;
|
|
10
|
+
}
|
|
8
11
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
super(props);
|
|
12
|
-
this.state = {};
|
|
13
|
-
}
|
|
12
|
+
export function ProgressBar({color, completed}: ProgressBarProps): React.ReactElement {
|
|
13
|
+
const {theme} = useContext(ThemeContext);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
return (
|
|
16
|
+
<View
|
|
17
|
+
style={{
|
|
18
|
+
width: "100%",
|
|
19
|
+
height: 6,
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
18
22
|
<View
|
|
19
23
|
style={{
|
|
20
24
|
width: "100%",
|
|
25
|
+
position: "absolute",
|
|
26
|
+
top: 0,
|
|
27
|
+
left: 0,
|
|
28
|
+
height: 6,
|
|
29
|
+
borderRadius: 6,
|
|
30
|
+
borderWidth: 1,
|
|
31
|
+
borderColor: theme[color],
|
|
32
|
+
backgroundColor: theme[color],
|
|
33
|
+
opacity: 0.3,
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
<View
|
|
37
|
+
style={{
|
|
38
|
+
width: `${Math.min(completed / 100, 1) * 100}%`,
|
|
39
|
+
position: "absolute",
|
|
40
|
+
top: 0,
|
|
41
|
+
left: 0,
|
|
21
42
|
height: 6,
|
|
43
|
+
borderRadius: 6,
|
|
44
|
+
borderWidth: 1,
|
|
45
|
+
borderColor: theme[color],
|
|
46
|
+
backgroundColor: theme[color],
|
|
47
|
+
opacity: 1,
|
|
22
48
|
}}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
width: "100%",
|
|
27
|
-
position: "absolute",
|
|
28
|
-
top: 0,
|
|
29
|
-
left: 0,
|
|
30
|
-
height: 6,
|
|
31
|
-
borderRadius: 6,
|
|
32
|
-
borderWidth: 1,
|
|
33
|
-
borderColor: Unifier.theme[this.props.color],
|
|
34
|
-
backgroundColor: Unifier.theme[this.props.color],
|
|
35
|
-
opacity: 0.3,
|
|
36
|
-
}}
|
|
37
|
-
/>
|
|
38
|
-
<View
|
|
39
|
-
style={{
|
|
40
|
-
width: `${Math.min(this.props.completed / 100, 1) * 100}%`,
|
|
41
|
-
position: "absolute",
|
|
42
|
-
top: 0,
|
|
43
|
-
left: 0,
|
|
44
|
-
height: 6,
|
|
45
|
-
borderRadius: 6,
|
|
46
|
-
borderWidth: 1,
|
|
47
|
-
borderColor: Unifier.theme[this.props.color],
|
|
48
|
-
backgroundColor: Unifier.theme[this.props.color],
|
|
49
|
-
opacity: 1,
|
|
50
|
-
}}
|
|
51
|
-
/>
|
|
52
|
-
</View>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
49
|
+
/>
|
|
50
|
+
</View>
|
|
51
|
+
);
|
|
55
52
|
}
|
package/src/SelectList.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, {useContext} from "react";
|
|
2
2
|
import {Platform} from "react-native";
|
|
3
3
|
|
|
4
4
|
import {FieldWithLabelsProps, StyleProp} from "./Common";
|
|
5
5
|
import {Icon} from "./Icon";
|
|
6
6
|
import {RNPickerSelect} from "./PickerSelect";
|
|
7
|
-
import {
|
|
7
|
+
import {ThemeContext} from "./Theme";
|
|
8
8
|
import {WithLabel} from "./WithLabel";
|
|
9
9
|
|
|
10
10
|
// Use "" if you want to have an "unset" value.
|
|
@@ -32,11 +32,13 @@ export function SelectList({
|
|
|
32
32
|
placeholder,
|
|
33
33
|
disabled,
|
|
34
34
|
}: SelectListProps) {
|
|
35
|
+
const {theme} = useContext(ThemeContext);
|
|
36
|
+
|
|
35
37
|
const withLabelProps = {label, labelColor};
|
|
36
38
|
|
|
37
|
-
let backgroundColor = style?.backgroundColor ||
|
|
39
|
+
let backgroundColor = style?.backgroundColor || theme.white;
|
|
38
40
|
if (disabled) {
|
|
39
|
-
backgroundColor =
|
|
41
|
+
backgroundColor = theme.lightGray;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
return (
|
|
@@ -58,7 +60,7 @@ export function SelectList({
|
|
|
58
60
|
alignItems: style?.alignItems || "center",
|
|
59
61
|
minHeight: style?.minHeight || 50,
|
|
60
62
|
width: style?.width || "100%",
|
|
61
|
-
borderColor: style?.borderColor ||
|
|
63
|
+
borderColor: style?.borderColor || theme.gray,
|
|
62
64
|
borderWidth: style?.borderWidth || 1,
|
|
63
65
|
borderRadius: style?.borderRadius || 5,
|
|
64
66
|
backgroundColor,
|
package/src/Spinner.tsx
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import React, {ReactElement, useEffect, useState} from "react";
|
|
2
2
|
import {ActivityIndicator} from "react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {Color} from "./Common";
|
|
5
|
+
|
|
6
|
+
export interface SpinnerProps {
|
|
7
|
+
size?: "sm" | "md";
|
|
8
|
+
color?: Color;
|
|
9
|
+
}
|
|
5
10
|
|
|
6
11
|
export function Spinner({size, color}: SpinnerProps): ReactElement | null {
|
|
7
12
|
const [show, setShow] = useState(false);
|
|
@@ -16,5 +21,5 @@ export function Spinner({size, color}: SpinnerProps): ReactElement | null {
|
|
|
16
21
|
return null;
|
|
17
22
|
}
|
|
18
23
|
const spinnerSize: "small" | "large" = size === "sm" ? "small" : "large";
|
|
19
|
-
return <ActivityIndicator color={color
|
|
24
|
+
return <ActivityIndicator color={color ?? "darkGray"} size={spinnerSize} />;
|
|
20
25
|
}
|
package/src/SplitPage.native.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// TODO: Update SplitPage native to have desktop UX for tablet sized screens
|
|
2
|
-
import React, {useCallback, useEffect, useState} from "react";
|
|
2
|
+
import React, {useCallback, useContext, useEffect, useState} from "react";
|
|
3
3
|
import flattenChildren from "react-keyed-flatten-children";
|
|
4
4
|
import {Dimensions, ListRenderItemInfo, View} from "react-native";
|
|
5
5
|
import {SwiperFlatList} from "react-native-swiper-flatlist";
|
|
@@ -9,6 +9,7 @@ import {SplitPageProps} from "./Common";
|
|
|
9
9
|
import {FlatList} from "./FlatList";
|
|
10
10
|
import {IconButton} from "./IconButton";
|
|
11
11
|
import {Spinner} from "./Spinner";
|
|
12
|
+
import {ThemeContext} from "./Theme";
|
|
12
13
|
import {Unifier} from "./Unifier";
|
|
13
14
|
|
|
14
15
|
export const SplitPage = ({
|
|
@@ -25,6 +26,7 @@ export const SplitPage = ({
|
|
|
25
26
|
bottomNavBarHeight,
|
|
26
27
|
showItemList,
|
|
27
28
|
}: SplitPageProps) => {
|
|
29
|
+
const {theme} = useContext(ThemeContext);
|
|
28
30
|
const [selectedId, setSelectedId] = useState<number | undefined>(undefined);
|
|
29
31
|
|
|
30
32
|
// flattenChildren is necessary to pull children from a React Fragment. Without this,
|
|
@@ -153,7 +155,7 @@ export const SplitPage = ({
|
|
|
153
155
|
keyboardOffset={keyboardOffset}
|
|
154
156
|
width="100%"
|
|
155
157
|
>
|
|
156
|
-
{loading === true && <Spinner color={
|
|
158
|
+
{loading === true && <Spinner color={theme.darkGray as any} size="md" />}
|
|
157
159
|
{selectedId === undefined ? renderList() : renderMainContent}
|
|
158
160
|
</Box>
|
|
159
161
|
);
|
package/src/SplitPage.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {Children, useCallback, useEffect, useState} from "react";
|
|
1
|
+
import React, {Children, useCallback, useContext, useEffect, useState} from "react";
|
|
2
2
|
import {Dimensions, ListRenderItemInfo, ScrollView, View} from "react-native";
|
|
3
3
|
import {SwiperFlatList} from "react-native-swiper-flatlist";
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ import {IconButton} from "./IconButton";
|
|
|
9
9
|
import {mediaQueryLargerThan} from "./MediaQuery";
|
|
10
10
|
import {SegmentedControl} from "./SegmentedControl";
|
|
11
11
|
import {Spinner} from "./Spinner";
|
|
12
|
-
import {
|
|
12
|
+
import {ThemeContext} from "./Theme";
|
|
13
13
|
|
|
14
14
|
// A component for rendering a list on one side and a details view on the right for large screens,
|
|
15
15
|
// and a scrollable list where clicking an item takes you the details view.
|
|
@@ -30,6 +30,7 @@ export const SplitPage = ({
|
|
|
30
30
|
showItemList,
|
|
31
31
|
selectLimit,
|
|
32
32
|
}: SplitPageProps) => {
|
|
33
|
+
const {theme} = useContext(ThemeContext);
|
|
33
34
|
const [selectedId, setSelectedId] = useState<number | undefined>(undefined);
|
|
34
35
|
const [activeTabs, setActiveTabs] = useState<number[]>([0, 1]);
|
|
35
36
|
const {width} = Dimensions.get("window");
|
|
@@ -295,7 +296,7 @@ export const SplitPage = ({
|
|
|
295
296
|
padding={2}
|
|
296
297
|
width="100%"
|
|
297
298
|
>
|
|
298
|
-
{loading === true && <Spinner color={
|
|
299
|
+
{loading === true && <Spinner color={theme.darkGray as any} size="md" />}
|
|
299
300
|
{Boolean(isMobileDevice) ? renderMobileSplitPage() : renderSplitPage()}
|
|
300
301
|
</Box>
|
|
301
302
|
);
|
package/src/Text.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, {useContext} from "react";
|
|
2
2
|
import {Text as NativeText, TextStyle} from "react-native";
|
|
3
3
|
|
|
4
4
|
import {AllColors, Font, TextSize} from "./Common";
|
|
5
5
|
import {Hyperlink} from "./Hyperlink";
|
|
6
|
-
import {
|
|
6
|
+
import {ThemeContext} from "./Theme";
|
|
7
7
|
|
|
8
8
|
export interface TextProps {
|
|
9
9
|
align?: "left" | "right" | "center" | "justify"; // default "left"
|
|
@@ -44,6 +44,8 @@ export function Text({
|
|
|
44
44
|
testID,
|
|
45
45
|
weight = "normal",
|
|
46
46
|
}: TextProps): React.ReactElement {
|
|
47
|
+
const {theme} = useContext(ThemeContext);
|
|
48
|
+
|
|
47
49
|
function propsToStyle(): any {
|
|
48
50
|
const style: TextStyle = {};
|
|
49
51
|
if (overflow) {
|
|
@@ -79,16 +81,16 @@ export function Text({
|
|
|
79
81
|
style.fontWeight = "bold";
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
style.fontFamily =
|
|
84
|
+
style.fontFamily = theme[computedFont as keyof typeof theme];
|
|
83
85
|
|
|
84
86
|
style.fontSize = fontSizes[size || "md"];
|
|
85
87
|
if (align) {
|
|
86
88
|
style.textAlign = align;
|
|
87
89
|
}
|
|
88
90
|
if (color) {
|
|
89
|
-
style.color =
|
|
91
|
+
style.color = theme[color];
|
|
90
92
|
} else {
|
|
91
|
-
style.color =
|
|
93
|
+
style.color = theme.darkGray;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
if (italic) {
|
package/src/TextField.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {AsYouType} from "libphonenumber-js";
|
|
2
|
-
import React, {ReactElement, useCallback, useMemo, useState} from "react";
|
|
2
|
+
import React, {ReactElement, useCallback, useContext, useMemo, useState} from "react";
|
|
3
3
|
import {
|
|
4
4
|
ActivityIndicator,
|
|
5
5
|
KeyboardTypeOptions,
|
|
@@ -17,7 +17,7 @@ import {DecimalRangeActionSheet} from "./DecimalRangeActionSheet";
|
|
|
17
17
|
import {HeightActionSheet} from "./HeightActionSheet";
|
|
18
18
|
import {Icon} from "./Icon";
|
|
19
19
|
import {NumberPickerActionSheet} from "./NumberPickerActionSheet";
|
|
20
|
-
import {
|
|
20
|
+
import {ThemeContext} from "./Theme";
|
|
21
21
|
import {WithLabel} from "./WithLabel";
|
|
22
22
|
|
|
23
23
|
const keyboardMap: {[id: string]: string | undefined} = {
|
|
@@ -88,6 +88,8 @@ export function TextField({
|
|
|
88
88
|
onEnter,
|
|
89
89
|
onSubmitEditing,
|
|
90
90
|
}: TextFieldProps): ReactElement {
|
|
91
|
+
const {theme} = useContext(ThemeContext);
|
|
92
|
+
|
|
91
93
|
const dateActionSheetRef: React.RefObject<any> = React.createRef();
|
|
92
94
|
const numberRangeActionSheetRef: React.RefObject<any> = React.createRef();
|
|
93
95
|
const decimalRangeActionSheetRef: React.RefObject<any> = React.createRef();
|
|
@@ -104,7 +106,7 @@ export function TextField({
|
|
|
104
106
|
if (searching) {
|
|
105
107
|
return (
|
|
106
108
|
<Box marginRight={4}>
|
|
107
|
-
<ActivityIndicator color={
|
|
109
|
+
<ActivityIndicator color={theme.primary} size="small" />
|
|
108
110
|
</Box>
|
|
109
111
|
);
|
|
110
112
|
} else {
|
|
@@ -118,11 +120,11 @@ export function TextField({
|
|
|
118
120
|
|
|
119
121
|
let borderColor;
|
|
120
122
|
if (errorMessage) {
|
|
121
|
-
borderColor =
|
|
123
|
+
borderColor = theme.red;
|
|
122
124
|
} else if (focused) {
|
|
123
|
-
borderColor =
|
|
125
|
+
borderColor = theme.blue;
|
|
124
126
|
} else {
|
|
125
|
-
borderColor =
|
|
127
|
+
borderColor = theme.gray;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
const getHeight = useCallback(() => {
|
|
@@ -144,8 +146,8 @@ export function TextField({
|
|
|
144
146
|
paddingLeft: 0,
|
|
145
147
|
height: getHeight(),
|
|
146
148
|
width: "100%",
|
|
147
|
-
color:
|
|
148
|
-
fontFamily:
|
|
149
|
+
color: theme.darkGray,
|
|
150
|
+
fontFamily: theme.primaryFont,
|
|
149
151
|
...style,
|
|
150
152
|
};
|
|
151
153
|
|
|
@@ -154,7 +156,7 @@ export function TextField({
|
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
return defaultStyles;
|
|
157
|
-
}, [getHeight, style]);
|
|
159
|
+
}, [getHeight, style, theme.darkGray, theme.primaryFont]);
|
|
158
160
|
|
|
159
161
|
const isHandledByModal = [
|
|
160
162
|
"date",
|
|
@@ -258,7 +260,7 @@ export function TextField({
|
|
|
258
260
|
borderColor,
|
|
259
261
|
borderWidth: focused ? 5 : 1,
|
|
260
262
|
borderRadius: 16,
|
|
261
|
-
backgroundColor: disabled ?
|
|
263
|
+
backgroundColor: disabled ? theme.gray : theme.white,
|
|
262
264
|
overflow: "hidden",
|
|
263
265
|
}}
|
|
264
266
|
onPress={() => {
|
|
@@ -286,7 +288,7 @@ export function TextField({
|
|
|
286
288
|
multiline={multiline}
|
|
287
289
|
numberOfLines={rows || 4}
|
|
288
290
|
placeholder={placeholder}
|
|
289
|
-
placeholderTextColor={
|
|
291
|
+
placeholderTextColor={theme.gray}
|
|
290
292
|
returnKeyType={type === "number" || type === "decimal" ? "done" : returnKeyType}
|
|
291
293
|
secureTextEntry={type === "password"}
|
|
292
294
|
style={defaultTextInputStyles}
|
package/src/Theme.tsx
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import React, {createContext, useState} from "react";
|
|
2
|
+
|
|
3
|
+
import {UnifiedTheme} from "./Common";
|
|
4
|
+
import {changeColorLuminance} from "./Unifier";
|
|
5
|
+
|
|
6
|
+
const DEFAULT_FONT = "Cochin";
|
|
7
|
+
const DEFAULT_BOLD_FONT = "Cochin";
|
|
8
|
+
|
|
9
|
+
const darkGray = "#111111";
|
|
10
|
+
const lightGray = "#efefef";
|
|
11
|
+
const gray = "#8e8e8e";
|
|
12
|
+
const white = "#fdfdfd";
|
|
13
|
+
const primary = "#5c58bb";
|
|
14
|
+
const secondary = "#8d58bb";
|
|
15
|
+
const accent = "#58b3bb";
|
|
16
|
+
const tertiary = "#b7956f";
|
|
17
|
+
|
|
18
|
+
const defaultTheme: UnifiedTheme = {
|
|
19
|
+
// Primary colors
|
|
20
|
+
white,
|
|
21
|
+
lightGray,
|
|
22
|
+
gray,
|
|
23
|
+
darkGray,
|
|
24
|
+
// secondary colors
|
|
25
|
+
green: "#0fa573",
|
|
26
|
+
red: "#bd081c",
|
|
27
|
+
springGreen: "#008753",
|
|
28
|
+
pine: "#0a6955",
|
|
29
|
+
olive: "#364a4c",
|
|
30
|
+
blue: "#4a90e2",
|
|
31
|
+
navy: "#004b91",
|
|
32
|
+
midnight: "#133a5e",
|
|
33
|
+
purple: "#b469eb",
|
|
34
|
+
orchid: "#8046a5",
|
|
35
|
+
eggplant: "#5b2677",
|
|
36
|
+
maroon: "#6e0f3c",
|
|
37
|
+
watermelon: "#f13535",
|
|
38
|
+
orange: "#e3780c",
|
|
39
|
+
black: "#000000",
|
|
40
|
+
|
|
41
|
+
primaryLighter: changeColorLuminance(primary, "lighter"),
|
|
42
|
+
primaryLight: changeColorLuminance(primary, "light"),
|
|
43
|
+
primary,
|
|
44
|
+
primaryDark: changeColorLuminance(primary, "dark"),
|
|
45
|
+
primaryDarker: changeColorLuminance(primary, "darker"),
|
|
46
|
+
|
|
47
|
+
secondaryLighter: changeColorLuminance(secondary, "lighter"),
|
|
48
|
+
secondaryLight: changeColorLuminance(secondary, "light"),
|
|
49
|
+
secondary,
|
|
50
|
+
secondaryDark: changeColorLuminance(secondary, "dark"),
|
|
51
|
+
secondaryDarker: changeColorLuminance(secondary, "darker"),
|
|
52
|
+
|
|
53
|
+
accentLighter: changeColorLuminance(accent, "lighter"),
|
|
54
|
+
accentLight: changeColorLuminance(accent, "light"),
|
|
55
|
+
accent,
|
|
56
|
+
accentDark: changeColorLuminance(accent, "dark"),
|
|
57
|
+
accentDarker: changeColorLuminance(accent, "darker"),
|
|
58
|
+
|
|
59
|
+
tertiaryLighter: changeColorLuminance(tertiary, "lighter"),
|
|
60
|
+
tertiaryLight: changeColorLuminance(tertiary, "light"),
|
|
61
|
+
tertiary,
|
|
62
|
+
tertiaryDark: changeColorLuminance(tertiary, "dark"),
|
|
63
|
+
tertiaryDarker: changeColorLuminance(tertiary, "darker"),
|
|
64
|
+
|
|
65
|
+
background: white,
|
|
66
|
+
backgroundSecondary: lightGray,
|
|
67
|
+
textPrimary: darkGray,
|
|
68
|
+
textSecondary: lightGray,
|
|
69
|
+
textDisabled: gray,
|
|
70
|
+
divider: gray,
|
|
71
|
+
|
|
72
|
+
// From the Atlassian templates
|
|
73
|
+
neutral900: "#091E42",
|
|
74
|
+
neutral800: "#172B4D",
|
|
75
|
+
neutral700: "#253858",
|
|
76
|
+
neutral600: "#344563",
|
|
77
|
+
neutral500: "#42526E",
|
|
78
|
+
neutral400: "#505F79",
|
|
79
|
+
neutral300: "#5E6C84",
|
|
80
|
+
neutral200: "#6B778C",
|
|
81
|
+
neutral100: "#7A869A",
|
|
82
|
+
neutral90: "#8993A4",
|
|
83
|
+
neutral80: "#97A0AF",
|
|
84
|
+
neutral70: "#A5ADBA",
|
|
85
|
+
neutral60: "#B3BAC5",
|
|
86
|
+
neutral50: "#C1C7D0",
|
|
87
|
+
neutral40: "#DFE1E6",
|
|
88
|
+
neutral30: "#EBECF0",
|
|
89
|
+
neutral20: "#F4F5F7",
|
|
90
|
+
neutral10: "#FAFBFC",
|
|
91
|
+
|
|
92
|
+
primaryFont: DEFAULT_FONT,
|
|
93
|
+
primaryBoldFont: DEFAULT_BOLD_FONT,
|
|
94
|
+
|
|
95
|
+
secondaryFont: DEFAULT_FONT,
|
|
96
|
+
secondaryBoldFont: DEFAULT_BOLD_FONT,
|
|
97
|
+
|
|
98
|
+
accentFont: DEFAULT_FONT,
|
|
99
|
+
accentBoldFont: DEFAULT_BOLD_FONT,
|
|
100
|
+
|
|
101
|
+
buttonFont: DEFAULT_FONT,
|
|
102
|
+
titleFont: DEFAULT_FONT,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const ThemeContext = createContext({
|
|
106
|
+
setTheme: (_theme: Partial<UnifiedTheme>) => {},
|
|
107
|
+
theme: defaultTheme,
|
|
108
|
+
resetTheme: () => {},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
interface ThemeProviderProps {
|
|
112
|
+
children: any;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function setThemeWithLuminances(
|
|
116
|
+
oldTheme: UnifiedTheme,
|
|
117
|
+
newTheme: Partial<UnifiedTheme>
|
|
118
|
+
): UnifiedTheme {
|
|
119
|
+
return {
|
|
120
|
+
...oldTheme,
|
|
121
|
+
...newTheme,
|
|
122
|
+
primaryLighter:
|
|
123
|
+
newTheme.primaryLighter ??
|
|
124
|
+
changeColorLuminance(newTheme.primary ?? oldTheme.primary, "lighter"),
|
|
125
|
+
primaryLight:
|
|
126
|
+
newTheme.primaryLight ?? changeColorLuminance(newTheme.primary ?? oldTheme.primary, "light"),
|
|
127
|
+
primary: newTheme.primary ?? oldTheme.primary,
|
|
128
|
+
primaryDark:
|
|
129
|
+
newTheme.primaryDark ?? changeColorLuminance(newTheme.primary ?? oldTheme.primary, "dark"),
|
|
130
|
+
primaryDarker:
|
|
131
|
+
newTheme.primaryDarker ??
|
|
132
|
+
changeColorLuminance(newTheme.primary ?? oldTheme.primary, "darker"),
|
|
133
|
+
|
|
134
|
+
secondaryLighter:
|
|
135
|
+
newTheme.secondaryLighter ??
|
|
136
|
+
changeColorLuminance(newTheme.secondary ?? oldTheme.secondary, "lighter"),
|
|
137
|
+
secondaryLight:
|
|
138
|
+
newTheme.secondaryLight ??
|
|
139
|
+
changeColorLuminance(newTheme.secondary ?? oldTheme.secondary, "light"),
|
|
140
|
+
secondary: newTheme.secondary ?? oldTheme.secondary,
|
|
141
|
+
secondaryDark:
|
|
142
|
+
newTheme.secondaryDark ??
|
|
143
|
+
changeColorLuminance(newTheme.secondary ?? oldTheme.secondary, "dark"),
|
|
144
|
+
secondaryDarker:
|
|
145
|
+
newTheme.secondaryDarker ??
|
|
146
|
+
changeColorLuminance(newTheme.secondary ?? oldTheme.secondary, "darker"),
|
|
147
|
+
|
|
148
|
+
accentLighter:
|
|
149
|
+
newTheme.accentLighter ?? changeColorLuminance(newTheme.accent ?? oldTheme.accent, "lighter"),
|
|
150
|
+
accentLight:
|
|
151
|
+
newTheme.accentLight ?? changeColorLuminance(newTheme.accent ?? oldTheme.accent, "light"),
|
|
152
|
+
accent: newTheme.accent ?? oldTheme.accent,
|
|
153
|
+
accentDark:
|
|
154
|
+
newTheme.accentDark ?? changeColorLuminance(newTheme.accent ?? oldTheme.accent, "dark"),
|
|
155
|
+
accentDarker:
|
|
156
|
+
newTheme.accentDarker ?? changeColorLuminance(newTheme.accent ?? oldTheme.accent, "darker"),
|
|
157
|
+
|
|
158
|
+
tertiaryLighter:
|
|
159
|
+
newTheme.tertiaryLighter ??
|
|
160
|
+
changeColorLuminance(newTheme.tertiary ?? oldTheme.tertiary, "lighter"),
|
|
161
|
+
tertiaryLight:
|
|
162
|
+
newTheme.tertiaryLight ??
|
|
163
|
+
changeColorLuminance(newTheme.tertiary ?? oldTheme.tertiary, "light"),
|
|
164
|
+
tertiary: newTheme.tertiary ?? oldTheme.tertiary,
|
|
165
|
+
tertiaryDark:
|
|
166
|
+
newTheme.tertiaryDark ?? changeColorLuminance(newTheme.tertiary ?? oldTheme.tertiary, "dark"),
|
|
167
|
+
tertiaryDarker:
|
|
168
|
+
newTheme.tertiaryDarker ??
|
|
169
|
+
changeColorLuminance(newTheme.tertiary ?? oldTheme.tertiary, "darker"),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const ThemeProvider = ({children}: ThemeProviderProps) => {
|
|
174
|
+
const [providerTheme, setProviderTheme] = useState<UnifiedTheme>(defaultTheme);
|
|
175
|
+
|
|
176
|
+
const setTheme = (newTheme: Partial<UnifiedTheme>) => {
|
|
177
|
+
setProviderTheme(setThemeWithLuminances(providerTheme, newTheme));
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const resetTheme = () => {
|
|
181
|
+
setProviderTheme(defaultTheme);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<ThemeContext.Provider value={{theme: providerTheme, setTheme, resetTheme}}>
|
|
186
|
+
{children}
|
|
187
|
+
</ThemeContext.Provider>
|
|
188
|
+
);
|
|
189
|
+
};
|
package/src/Tooltip.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import {useContext} from "react";
|
|
2
3
|
import {
|
|
3
4
|
Dimensions,
|
|
4
5
|
LayoutChangeEvent,
|
|
@@ -11,7 +12,7 @@ import {Portal} from "react-native-portalize";
|
|
|
11
12
|
|
|
12
13
|
import {TooltipDirection} from "./Common";
|
|
13
14
|
import {Text} from "./Text";
|
|
14
|
-
import {
|
|
15
|
+
import {ThemeContext} from "./Theme";
|
|
15
16
|
|
|
16
17
|
const TOOLTIP_OFFSET = 8;
|
|
17
18
|
// How many pixels to leave between the tooltip and the edge of the screen
|
|
@@ -125,6 +126,7 @@ interface TooltipProps {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
export const Tooltip = (props: TooltipProps) => {
|
|
129
|
+
const {theme} = useContext(ThemeContext);
|
|
128
130
|
const {text, children, bgColor, idealDirection} = props;
|
|
129
131
|
const hoverDelay = 500;
|
|
130
132
|
const hoverEndDelay = 1500;
|
|
@@ -230,7 +232,7 @@ export const Tooltip = (props: TooltipProps) => {
|
|
|
230
232
|
alignSelf: "flex-start",
|
|
231
233
|
justifyContent: "center",
|
|
232
234
|
paddingHorizontal: 16,
|
|
233
|
-
backgroundColor:
|
|
235
|
+
backgroundColor: theme[bgColor ?? "darkGray"],
|
|
234
236
|
borderRadius: 16,
|
|
235
237
|
paddingVertical: 8,
|
|
236
238
|
display: "flex",
|