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.
Files changed (91) hide show
  1. package/dist/Avatar.js +5 -6
  2. package/dist/Avatar.js.map +1 -1
  3. package/dist/Badge.js +4 -3
  4. package/dist/Badge.js.map +1 -1
  5. package/dist/Body.d.ts +10 -5
  6. package/dist/Body.js +14 -15
  7. package/dist/Body.js.map +1 -1
  8. package/dist/Box.js +9 -7
  9. package/dist/Box.js.map +1 -1
  10. package/dist/Button.js +5 -3
  11. package/dist/Button.js.map +1 -1
  12. package/dist/Common.d.ts +7 -19
  13. package/dist/Common.js.map +1 -1
  14. package/dist/DateTimeActionSheet.js +9 -7
  15. package/dist/DateTimeActionSheet.js.map +1 -1
  16. package/dist/DateTimeField.android.js +5 -4
  17. package/dist/DateTimeField.android.js.map +1 -1
  18. package/dist/DateTimeField.ios.js +6 -5
  19. package/dist/DateTimeField.ios.js.map +1 -1
  20. package/dist/FernsProvider.js +4 -2
  21. package/dist/FernsProvider.js.map +1 -1
  22. package/dist/Heading.d.ts +1 -9
  23. package/dist/Heading.js +22 -43
  24. package/dist/Heading.js.map +1 -1
  25. package/dist/Icon.js +4 -3
  26. package/dist/Icon.js.map +1 -1
  27. package/dist/IconButton.d.ts +1 -1
  28. package/dist/IconButton.js +4 -2
  29. package/dist/IconButton.js.map +1 -1
  30. package/dist/Modal.js +2 -1
  31. package/dist/Modal.js.map +1 -1
  32. package/dist/Page.js +1 -3
  33. package/dist/Page.js.map +1 -1
  34. package/dist/ProgressBar.d.ts +5 -7
  35. package/dist/ProgressBar.js +30 -36
  36. package/dist/ProgressBar.js.map +1 -1
  37. package/dist/SelectList.js +6 -5
  38. package/dist/SelectList.js.map +1 -1
  39. package/dist/Spinner.d.ts +5 -1
  40. package/dist/Spinner.js +1 -1
  41. package/dist/Spinner.js.map +1 -1
  42. package/dist/SplitPage.js +4 -3
  43. package/dist/SplitPage.js.map +1 -1
  44. package/dist/SplitPage.native.js +4 -2
  45. package/dist/SplitPage.native.js.map +1 -1
  46. package/dist/Text.js +6 -5
  47. package/dist/Text.js.map +1 -1
  48. package/dist/TextField.js +11 -10
  49. package/dist/TextField.js.map +1 -1
  50. package/dist/Theme.d.ts +12 -0
  51. package/dist/Theme.js +108 -0
  52. package/dist/Theme.js.map +1 -0
  53. package/dist/Tooltip.js +4 -2
  54. package/dist/Tooltip.js.map +1 -1
  55. package/dist/Unifier.d.ts +1 -6
  56. package/dist/Unifier.js +0 -134
  57. package/dist/Unifier.js.map +1 -1
  58. package/dist/Utilities.d.ts +1 -0
  59. package/dist/Utilities.js +4 -0
  60. package/dist/Utilities.js.map +1 -1
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.js +1 -0
  63. package/dist/index.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/Avatar.tsx +6 -6
  66. package/src/Badge.tsx +5 -3
  67. package/src/Body.tsx +32 -21
  68. package/src/Box.tsx +10 -8
  69. package/src/Button.tsx +5 -3
  70. package/src/Common.ts +11 -22
  71. package/src/DateTimeActionSheet.tsx +11 -7
  72. package/src/DateTimeField.android.tsx +5 -4
  73. package/src/DateTimeField.ios.tsx +6 -5
  74. package/src/FernsProvider.tsx +14 -11
  75. package/src/Heading.tsx +27 -44
  76. package/src/Icon.tsx +4 -3
  77. package/src/IconButton.tsx +12 -3
  78. package/src/Modal.tsx +2 -1
  79. package/src/Page.tsx +1 -5
  80. package/src/ProgressBar.tsx +41 -44
  81. package/src/SelectList.tsx +7 -5
  82. package/src/Spinner.tsx +7 -2
  83. package/src/SplitPage.native.tsx +4 -2
  84. package/src/SplitPage.tsx +4 -3
  85. package/src/Text.tsx +7 -5
  86. package/src/TextField.tsx +13 -11
  87. package/src/Theme.tsx +189 -0
  88. package/src/Tooltip.tsx +4 -2
  89. package/src/Unifier.ts +0 -196
  90. package/src/Utilities.tsx +5 -0
  91. package/src/index.tsx +1 -0
@@ -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?: "transparent" | "transparentDarkGray" | "gray" | "lightGray" | "white"; // default transparent
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 = Unifier.theme[bgColor];
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}
@@ -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 {ProgressBarProps} from "./Common";
5
- import {Unifier} from "./Unifier";
4
+ import {Color} from "./Common";
5
+ import {ThemeContext} from "./Theme";
6
6
 
7
- interface ProgressBarState {}
7
+ export interface ProgressBarProps {
8
+ color: Color;
9
+ completed: number;
10
+ }
8
11
 
9
- export class ProgressBar extends React.Component<ProgressBarProps, ProgressBarState> {
10
- constructor(props: ProgressBarProps) {
11
- super(props);
12
- this.state = {};
13
- }
12
+ export function ProgressBar({color, completed}: ProgressBarProps): React.ReactElement {
13
+ const {theme} = useContext(ThemeContext);
14
14
 
15
- render() {
16
- // console.log("PROGRESS", Unifier.theme[this.props.color], `${this.props.completed / 100}%`);
17
- return (
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
- <View
25
- style={{
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
  }
@@ -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 {Unifier} from "./Unifier";
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 || Unifier.theme.white;
39
+ let backgroundColor = style?.backgroundColor || theme.white;
38
40
  if (disabled) {
39
- backgroundColor = Unifier.theme.lightGray;
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 || Unifier.theme.gray,
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 {SpinnerProps} from "./Common";
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 || "darkGray"} size={spinnerSize} />;
24
+ return <ActivityIndicator color={color ?? "darkGray"} size={spinnerSize} />;
20
25
  }
@@ -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={Unifier.theme.darkGray as any} size="md" />}
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 {Unifier} from "./Unifier";
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={Unifier.theme.darkGray as any} size="md" />}
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 {Unifier} from "./Unifier";
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 = Unifier.theme[computedFont as keyof typeof Unifier.theme];
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 = Unifier.theme[color];
91
+ style.color = theme[color];
90
92
  } else {
91
- style.color = Unifier.theme.darkGray;
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 {Unifier} from "./Unifier";
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={Unifier.theme.primary} size="small" />
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 = Unifier.theme.red;
123
+ borderColor = theme.red;
122
124
  } else if (focused) {
123
- borderColor = Unifier.theme.blue;
125
+ borderColor = theme.blue;
124
126
  } else {
125
- borderColor = Unifier.theme.gray;
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: Unifier.theme.darkGray,
148
- fontFamily: Unifier.theme.primaryFont,
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 ? Unifier.theme.gray : Unifier.theme.white,
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={Unifier.theme.gray}
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 {Unifier} from "./Unifier";
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: Unifier.theme[bgColor ?? "darkGray"],
235
+ backgroundColor: theme[bgColor ?? "darkGray"],
234
236
  borderRadius: 16,
235
237
  paddingVertical: 8,
236
238
  display: "flex",