@pagopa/io-app-design-system 4.4.8 → 4.5.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.
Files changed (53) hide show
  1. package/lib/commonjs/components/alert/Alert.js.map +1 -1
  2. package/lib/commonjs/components/listitems/ListItemInfo.js +47 -13
  3. package/lib/commonjs/components/listitems/ListItemInfo.js.map +1 -1
  4. package/lib/commonjs/components/listitems/PressableListItemBase.js.map +1 -1
  5. package/lib/commonjs/components/modules/PressableModuleBase.js +10 -2
  6. package/lib/commonjs/components/modules/PressableModuleBase.js.map +1 -1
  7. package/lib/commonjs/components/textInput/TextInputBase.js +18 -15
  8. package/lib/commonjs/components/textInput/TextInputBase.js.map +1 -1
  9. package/lib/commonjs/components/textInput/TextInputValidation.js +8 -6
  10. package/lib/commonjs/components/textInput/TextInputValidation.js.map +1 -1
  11. package/lib/commonjs/core/IOColors.js +15 -2
  12. package/lib/commonjs/core/IOColors.js.map +1 -1
  13. package/lib/commonjs/core/IOThemeContextProvider.js +12 -7
  14. package/lib/commonjs/core/IOThemeContextProvider.js.map +1 -1
  15. package/lib/module/components/alert/Alert.js.map +1 -1
  16. package/lib/module/components/listitems/ListItemInfo.js +48 -15
  17. package/lib/module/components/listitems/ListItemInfo.js.map +1 -1
  18. package/lib/module/components/listitems/PressableListItemBase.js.map +1 -1
  19. package/lib/module/components/modules/PressableModuleBase.js +10 -2
  20. package/lib/module/components/modules/PressableModuleBase.js.map +1 -1
  21. package/lib/module/components/textInput/TextInputBase.js +19 -16
  22. package/lib/module/components/textInput/TextInputBase.js.map +1 -1
  23. package/lib/module/components/textInput/TextInputValidation.js +8 -6
  24. package/lib/module/components/textInput/TextInputValidation.js.map +1 -1
  25. package/lib/module/core/IOColors.js +15 -2
  26. package/lib/module/core/IOColors.js.map +1 -1
  27. package/lib/module/core/IOThemeContextProvider.js +14 -8
  28. package/lib/module/core/IOThemeContextProvider.js.map +1 -1
  29. package/lib/typescript/components/alert/Alert.d.ts.map +1 -1
  30. package/lib/typescript/components/listitems/ListItemInfo.d.ts +13 -11
  31. package/lib/typescript/components/listitems/ListItemInfo.d.ts.map +1 -1
  32. package/lib/typescript/components/listitems/PressableListItemBase.d.ts +2 -2
  33. package/lib/typescript/components/listitems/PressableListItemBase.d.ts.map +1 -1
  34. package/lib/typescript/components/modules/PressableModuleBase.d.ts.map +1 -1
  35. package/lib/typescript/components/textInput/TextInputBase.d.ts +2 -2
  36. package/lib/typescript/components/textInput/TextInputBase.d.ts.map +1 -1
  37. package/lib/typescript/components/textInput/TextInputValidation.d.ts.map +1 -1
  38. package/lib/typescript/components/tooltip/styles.d.ts +2 -2
  39. package/lib/typescript/core/IOColors.d.ts +1 -1
  40. package/lib/typescript/core/IOColors.d.ts.map +1 -1
  41. package/lib/typescript/core/IOStyles.d.ts +2 -2
  42. package/lib/typescript/core/IOThemeContextProvider.d.ts +6 -6
  43. package/lib/typescript/core/IOThemeContextProvider.d.ts.map +1 -1
  44. package/lib/typescript/utils/fonts.d.ts +1 -1
  45. package/package.json +3 -3
  46. package/src/components/alert/Alert.tsx +3 -2
  47. package/src/components/listitems/ListItemInfo.tsx +107 -53
  48. package/src/components/listitems/PressableListItemBase.tsx +3 -2
  49. package/src/components/modules/PressableModuleBase.tsx +15 -4
  50. package/src/components/textInput/TextInputBase.tsx +28 -16
  51. package/src/components/textInput/TextInputValidation.tsx +18 -10
  52. package/src/core/IOColors.ts +18 -0
  53. package/src/core/IOThemeContextProvider.tsx +27 -15
@@ -1,11 +1,13 @@
1
- import React, { ComponentProps, useCallback, useMemo } from "react";
2
- import { AccessibilityRole, Platform, View } from "react-native";
1
+ import React, { ComponentProps, ReactNode, useCallback, useMemo } from "react";
2
+ import { AccessibilityRole, Platform, Pressable, View } from "react-native";
3
+ import Animated from "react-native-reanimated";
3
4
  import {
4
5
  IOListItemStyles,
5
6
  IOListItemVisualParams,
6
7
  IOStyles,
7
8
  useIOTheme
8
9
  } from "../../core";
10
+ import { useListItemAnimation } from "../../hooks";
9
11
  import { useIOFontDynamicScale } from "../../utils/accessibility";
10
12
  import { WithTestID } from "../../utils/types";
11
13
  import { Badge } from "../badge";
@@ -13,7 +15,7 @@ import { ButtonLink, IconButton } from "../buttons";
13
15
  import { LogoPaymentWithFallback } from "../common/LogoPaymentWithFallback";
14
16
  import { IOIconSizeScale, IOIcons, Icon } from "../icons";
15
17
  import { IOLogoPaymentType } from "../logos";
16
- import { H6, BodySmall } from "../typography";
18
+ import { BodySmall, H6 } from "../typography";
17
19
 
18
20
  type ButtonLinkActionProps = {
19
21
  type: "buttonLink";
@@ -35,25 +37,32 @@ type EndElementProps =
35
37
  | IconButtonActionProps
36
38
  | BadgeProps;
37
39
 
40
+ type GraphicProps =
41
+ | {
42
+ paymentLogoIcon?: IOLogoPaymentType;
43
+ icon?: never;
44
+ }
45
+ | {
46
+ paymentLogoIcon?: never;
47
+ icon?: IOIcons;
48
+ };
49
+
50
+ type InteractiveProps = Pick<
51
+ ComponentProps<typeof Pressable>,
52
+ "onLongPress" | "accessibilityActions" | "onAccessibilityAction"
53
+ >;
54
+
38
55
  export type ListItemInfo = WithTestID<{
39
56
  label: string;
40
- value: string | React.ReactNode;
57
+ value: string | ReactNode;
41
58
  numberOfLines?: number;
42
59
  endElement?: EndElementProps;
43
60
  // Accessibility
44
61
  accessibilityLabel?: string;
45
62
  accessibilityRole?: AccessibilityRole;
46
63
  }> &
47
- (
48
- | {
49
- paymentLogoIcon?: IOLogoPaymentType;
50
- icon?: never;
51
- }
52
- | {
53
- icon?: IOIcons;
54
- paymentLogoIcon?: never;
55
- }
56
- );
64
+ GraphicProps &
65
+ InteractiveProps;
57
66
 
58
67
  const PAYMENT_LOGO_SIZE: IOIconSizeScale = 24;
59
68
 
@@ -66,22 +75,25 @@ export const ListItemInfo = ({
66
75
  endElement,
67
76
  accessibilityLabel,
68
77
  accessibilityRole,
78
+ accessibilityActions,
79
+ onAccessibilityAction,
80
+ onLongPress,
69
81
  testID
70
82
  }: ListItemInfo) => {
71
83
  const theme = useIOTheme();
72
84
  const { dynamicFontScale, spacingScaleMultiplier, hugeFontEnabled } =
73
85
  useIOFontDynamicScale();
74
86
 
87
+ const { onPressIn, onPressOut, scaleAnimatedStyle, backgroundAnimatedStyle } =
88
+ useListItemAnimation();
89
+
75
90
  const componentValueToAccessibility = useMemo(
76
91
  () => (typeof value === "string" ? value : ""),
77
92
  [value]
78
93
  );
79
94
 
80
95
  const listItemAccessibilityLabel = useMemo(
81
- () =>
82
- accessibilityLabel
83
- ? accessibilityLabel
84
- : `${label}; ${componentValueToAccessibility}`,
96
+ () => accessibilityLabel ?? `${label}; ${componentValueToAccessibility}`,
85
97
  [label, componentValueToAccessibility, accessibilityLabel]
86
98
  );
87
99
 
@@ -136,44 +148,86 @@ export const ListItemInfo = ({
136
148
  return <></>;
137
149
  }, [endElement]);
138
150
 
139
- return (
140
- <View
141
- style={IOListItemStyles.listItem}
142
- testID={testID}
143
- accessible={endElement === undefined ? true : false}
144
- accessibilityLabel={listItemAccessibilityLabel}
145
- accessibilityRole={accessibilityRole}
146
- >
151
+ const ListItemInfoContent = () => (
152
+ <>
153
+ {icon && !hugeFontEnabled && (
154
+ <Icon
155
+ allowFontScaling
156
+ name={icon}
157
+ color="grey-450"
158
+ size={IOListItemVisualParams.iconSize}
159
+ />
160
+ )}
161
+ {paymentLogoIcon && (
162
+ <LogoPaymentWithFallback
163
+ brand={paymentLogoIcon}
164
+ size={PAYMENT_LOGO_SIZE}
165
+ />
166
+ )}
167
+ <View style={IOStyles.flex}>{itemInfoTextComponent}</View>
168
+ {endElement && <View>{listItemInfoAction()}</View>}
169
+ </>
170
+ );
171
+
172
+ if (onLongPress) {
173
+ return (
174
+ <Pressable
175
+ onLongPress={onLongPress}
176
+ testID={testID}
177
+ accessible={!endElement}
178
+ onPressIn={onPressIn}
179
+ onPressOut={onPressOut}
180
+ onTouchEnd={onPressOut}
181
+ accessibilityRole={"button"}
182
+ accessibilityLabel={listItemAccessibilityLabel}
183
+ accessibilityActions={accessibilityActions}
184
+ onAccessibilityAction={onAccessibilityAction}
185
+ >
186
+ <Animated.View
187
+ style={[IOListItemStyles.listItem, backgroundAnimatedStyle]}
188
+ >
189
+ <Animated.View
190
+ style={[
191
+ IOListItemStyles.listItemInner,
192
+ {
193
+ columnGap:
194
+ IOListItemVisualParams.iconMargin *
195
+ dynamicFontScale *
196
+ spacingScaleMultiplier
197
+ },
198
+ scaleAnimatedStyle
199
+ ]}
200
+ >
201
+ <ListItemInfoContent />
202
+ </Animated.View>
203
+ </Animated.View>
204
+ </Pressable>
205
+ );
206
+ } else {
207
+ return (
147
208
  <View
148
- style={[
149
- IOListItemStyles.listItemInner,
150
- {
151
- columnGap:
152
- IOListItemVisualParams.iconMargin *
153
- dynamicFontScale *
154
- spacingScaleMultiplier
155
- }
156
- ]}
209
+ style={IOListItemStyles.listItem}
210
+ testID={testID}
211
+ accessible={!endElement}
212
+ accessibilityLabel={listItemAccessibilityLabel}
213
+ accessibilityRole={accessibilityRole}
157
214
  >
158
- {icon && !hugeFontEnabled && (
159
- <Icon
160
- allowFontScaling
161
- name={icon}
162
- color="grey-450"
163
- size={IOListItemVisualParams.iconSize}
164
- />
165
- )}
166
- {paymentLogoIcon && (
167
- <LogoPaymentWithFallback
168
- brand={paymentLogoIcon}
169
- size={PAYMENT_LOGO_SIZE}
170
- />
171
- )}
172
- <View style={IOStyles.flex}>{itemInfoTextComponent}</View>
173
- {endElement && <View>{listItemInfoAction()}</View>}
215
+ <View
216
+ style={[
217
+ IOListItemStyles.listItemInner,
218
+ {
219
+ columnGap:
220
+ IOListItemVisualParams.iconMargin *
221
+ dynamicFontScale *
222
+ spacingScaleMultiplier
223
+ }
224
+ ]}
225
+ >
226
+ <ListItemInfoContent />
227
+ </View>
174
228
  </View>
175
- </View>
176
- );
229
+ );
230
+ }
177
231
  };
178
232
 
179
233
  export default ListItemInfo;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { PropsWithChildren } from "react";
2
+ import { ComponentProps, PropsWithChildren } from "react";
3
3
  import { Pressable } from "react-native";
4
4
  import Animated from "react-native-reanimated";
5
5
  import { IOListItemStyles, IOListItemVisualParams } from "../../core";
@@ -8,7 +8,7 @@ import { useListItemAnimation } from "../../hooks";
8
8
 
9
9
  export type PressableBaseProps = WithTestID<
10
10
  Pick<
11
- React.ComponentProps<typeof Pressable>,
11
+ ComponentProps<typeof Pressable>,
12
12
  | "onPress"
13
13
  | "accessibilityLabel"
14
14
  | "accessibilityHint"
@@ -26,6 +26,7 @@ export const PressableListItemBase = ({
26
26
  }: PropsWithChildren<PressableBaseProps>) => {
27
27
  const { onPressIn, onPressOut, scaleAnimatedStyle, backgroundAnimatedStyle } =
28
28
  useListItemAnimation();
29
+
29
30
  return (
30
31
  <Pressable
31
32
  onPress={onPress}
@@ -1,14 +1,15 @@
1
1
  import * as React from "react";
2
- import { PropsWithChildren } from "react";
3
- import { Pressable } from "react-native";
2
+ import { PropsWithChildren, useCallback } from "react";
3
+ import { GestureResponderEvent, Pressable } from "react-native";
4
+ import ReactNativeHapticFeedback from "react-native-haptic-feedback";
4
5
  import Animated, { useReducedMotion } from "react-native-reanimated";
5
- import { useScaleAnimation } from "../../hooks";
6
6
  import {
7
7
  IOColors,
8
8
  IOModuleIDPSavedVSpacing,
9
9
  IOModuleStyles,
10
10
  useIOTheme
11
11
  } from "../../core";
12
+ import { useScaleAnimation } from "../../hooks";
12
13
  import { WithTestID } from "../../utils/types";
13
14
 
14
15
  export type PressableModuleBaseProps = WithTestID<
@@ -39,9 +40,19 @@ export const PressableModuleBase = ({
39
40
  If we remove it, they they won't be able to understand
40
41
  if there's an ongoing interaction. */
41
42
 
43
+ const handleOnPress = useCallback(
44
+ (event: GestureResponderEvent) => {
45
+ if (onPress) {
46
+ ReactNativeHapticFeedback.trigger("impactLight");
47
+ onPress(event);
48
+ }
49
+ },
50
+ [onPress]
51
+ );
52
+
42
53
  return (
43
54
  <Pressable
44
- onPress={onPress}
55
+ onPress={handleOnPress}
45
56
  testID={testID}
46
57
  accessible={true}
47
58
  onPressIn={onPressIn}
@@ -1,5 +1,12 @@
1
1
  /* eslint-disable functional/immutable-data */
2
- import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
+ import React, {
3
+ ReactNode,
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState
9
+ } from "react";
3
10
  import {
4
11
  ColorValue,
5
12
  LayoutChangeEvent,
@@ -46,7 +53,7 @@ type InputTextProps = WithTestID<{
46
53
  inputType?: InputType;
47
54
  status?: InputStatus;
48
55
  icon?: IOIcons;
49
- rightElement?: React.ReactNode;
56
+ rightElement?: ReactNode;
50
57
  counterLimit?: number;
51
58
  bottomMessage?: string;
52
59
  bottomMessageColor?: IOColors;
@@ -67,12 +74,8 @@ const inputLabelScaleFactor: number = 0.75; /* 16pt becomes 12pt */
67
74
  const inputLabelFontSize: IOFontSize = 16;
68
75
  const inputDisabledOpacity: number = 0.5;
69
76
  const inputRightElementMargin: IOSpacingScale = 8;
70
- const iconColor: IOColors = "grey-300";
71
77
  const iconSize: IOIconSizeScale = 24;
72
78
  const iconMargin: IOSpacingScale = 8;
73
- const inputLabelColor: ColorValue = IOColors["grey-700"];
74
- const inputTextColor: ColorValue = IOColors.black;
75
- const inputDisabledTextColor: ColorValue = IOColors["grey-850"];
76
79
 
77
80
  const styles = StyleSheet.create({
78
81
  textInput: {
@@ -126,11 +129,9 @@ const styles = StyleSheet.create({
126
129
  justifyContent: "center"
127
130
  },
128
131
  textInputLabel: {
129
- color: inputLabelColor,
130
132
  ...makeFontStyleObject(inputLabelFontSize, "Titillio", undefined, "Regular")
131
133
  },
132
134
  textInputLabelLegacyFont: {
133
- color: inputLabelColor,
134
135
  ...makeFontStyleObject(
135
136
  inputLabelFontSize,
136
137
  "TitilliumSansPro",
@@ -149,10 +150,15 @@ const HelperRow = ({
149
150
  value,
150
151
  counterLimit,
151
152
  bottomMessage,
152
- bottomMessageColor = "grey-700"
153
+ bottomMessageColor
153
154
  }: InputTextHelperRow) => {
155
+ const theme = useIOTheme();
154
156
  const valueCount = useMemo(() => value.length, [value]);
155
157
 
158
+ const bottomMessageColorDefault: IOColors = theme["textBody-tertiary"];
159
+ const bottomMessageColorValue =
160
+ bottomMessageColor ?? bottomMessageColorDefault;
161
+
156
162
  const helperRowStyle: ViewStyle = useMemo(() => {
157
163
  if (counterLimit && bottomMessage) {
158
164
  return {
@@ -189,14 +195,14 @@ const HelperRow = ({
189
195
  }
190
196
  >
191
197
  {bottomMessage && (
192
- <BodySmall weight="Regular" color={bottomMessageColor}>
198
+ <BodySmall weight="Regular" color={bottomMessageColorValue}>
193
199
  {bottomMessage}
194
200
  </BodySmall>
195
201
  )}
196
202
  {counterLimit && (
197
203
  <BodySmall
198
204
  weight="Regular"
199
- color="grey-700"
205
+ color={bottomMessageColorValue}
200
206
  >{`${valueCount} / ${counterLimit}`}</BodySmall>
201
207
  )}
202
208
  </View>
@@ -226,7 +232,7 @@ export const TextInputBase = ({
226
232
  }: InputTextProps) => {
227
233
  const inputRef = useRef<TextInput>(null);
228
234
  const isSecretInput = useMemo(() => isPassword, [isPassword]);
229
- const [inputStatus, setInputStatus] = React.useState<InputStatus>(
235
+ const [inputStatus, setInputStatus] = useState<InputStatus>(
230
236
  disabled ? "disabled" : "initial"
231
237
  );
232
238
  const focusedState = useSharedValue<number>(0);
@@ -234,9 +240,14 @@ export const TextInputBase = ({
234
240
  const { dynamicFontScale, spacingScaleMultiplier } = useIOFontDynamicScale();
235
241
 
236
242
  const theme = useIOTheme();
243
+ const iconColor: IOColors = theme["icon-decorative"];
244
+ const inputLabelColor: ColorValue = IOColors[theme["textInputLabel-default"]];
245
+ const inputTextColor: ColorValue = IOColors[theme["textInputValue-default"]];
246
+ const inputDisabledTextColor: ColorValue =
247
+ IOColors[theme["textInputValue-disabled"]];
237
248
 
238
249
  /* Get the label width to enable the correct translation */
239
- const [labelWidth, setLabelWidth] = React.useState<number>(0);
250
+ const [labelWidth, setLabelWidth] = useState<number>(0);
240
251
 
241
252
  const getLabelWidth = ({ nativeEvent }: LayoutChangeEvent) => {
242
253
  setLabelWidth(nativeEvent.layout.width);
@@ -255,10 +266,10 @@ export const TextInputBase = ({
255
266
 
256
267
  const borderColorMap: Record<InputStatus, string> = useMemo(
257
268
  () => ({
258
- initial: IOColors["grey-200"],
259
- disabled: IOColors["grey-200"],
269
+ initial: IOColors[theme["textInputBorder-default"]],
270
+ disabled: IOColors[theme["textInputBorder-default"]],
260
271
  focused: IOColors[theme["interactiveElem-default"]],
261
- error: IOColors["error-600"]
272
+ error: IOColors[theme.errorText]
262
273
  }),
263
274
  [theme]
264
275
  );
@@ -467,6 +478,7 @@ export const TextInputBase = ({
467
478
  isExperimental
468
479
  ? styles.textInputLabel
469
480
  : styles.textInputLabelLegacyFont,
481
+ { color: inputLabelColor },
470
482
  animatedLabelStyle
471
483
  ]}
472
484
  >
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { useCallback, useMemo, useState } from "react";
3
3
  import { AccessibilityInfo, View } from "react-native";
4
4
  import Animated from "react-native-reanimated";
5
+ import { useIOTheme } from "../../core";
5
6
  import { IOColors } from "../../core/IOColors";
6
7
  import {
7
8
  enterTransitionInputIcon,
@@ -18,8 +19,8 @@ type TextInputValidationProps = Omit<
18
19
  "rightElement" | "status" | "bottomMessageColor" | "isPassword"
19
20
  > & {
20
21
  /**
21
- * This function can return either a `boolean` or a `ValidationWithOptions` object.
22
- * If a `boolean` is returned and the field is not valid, the value of the errorMessage prop will be displayed/announced.
22
+ * This function can return either a `boolean` or a `ValidationWithOptions` object.
23
+ * If a `boolean` is returned and the field is not valid, the value of the errorMessage prop will be displayed/announced.
23
24
  * If a `ValidationWithOptions` object is returned and the field is not valid, the value displayed/announced will be the one contained within this object.
24
25
  */
25
26
  onValidate: (value: string) => boolean | ValidationWithOptions;
@@ -29,8 +30,14 @@ type TextInputValidationProps = Omit<
29
30
  errorMessage: string;
30
31
  };
31
32
 
32
- function isValidationWithOptions(validation: boolean | ValidationWithOptions): validation is ValidationWithOptions {
33
- return typeof validation === 'object' && 'isValid' in validation && 'errorMessage' in validation;
33
+ function isValidationWithOptions(
34
+ validation: boolean | ValidationWithOptions
35
+ ): validation is ValidationWithOptions {
36
+ return (
37
+ typeof validation === "object" &&
38
+ "isValid" in validation &&
39
+ "errorMessage" in validation
40
+ );
34
41
  }
35
42
 
36
43
  const feedbackIconSize: IOIconSizeScale = 24;
@@ -44,6 +51,7 @@ export const TextInputValidation = ({
44
51
  onFocus,
45
52
  ...props
46
53
  }: TextInputValidationProps) => {
54
+ const theme = useIOTheme();
47
55
  const [isValid, setIsValid] = useState<boolean | undefined>(undefined);
48
56
  const [errMessage, setErrMessage] = useState(errorMessage);
49
57
 
@@ -78,13 +86,13 @@ export const TextInputValidation = ({
78
86
  }, [onFocus]);
79
87
 
80
88
  const labelError = useMemo(
81
- () => (isValid === false && errMessage ? errMessage : bottomMessage),
89
+ () => (!isValid && errMessage ? errMessage : bottomMessage),
82
90
  [isValid, errMessage, bottomMessage]
83
91
  );
84
92
 
85
93
  const labelErrorColor: IOColors | undefined = useMemo(
86
- () => (isValid === false && errMessage ? "error-600" : undefined),
87
- [isValid, errMessage]
94
+ () => (!isValid && errMessage ? theme.errorText : undefined),
95
+ [isValid, errMessage, theme.errorText]
88
96
  );
89
97
 
90
98
  const feedbackIconAttrMap: Record<
@@ -94,14 +102,14 @@ export const TextInputValidation = ({
94
102
  () => ({
95
103
  valid: {
96
104
  name: "success",
97
- color: "green"
105
+ color: theme.successIcon
98
106
  },
99
107
  notValid: {
100
108
  name: "errorFilled",
101
- color: "error-600"
109
+ color: theme.errorIcon
102
110
  }
103
111
  }),
104
- []
112
+ [theme]
105
113
  );
106
114
 
107
115
  const feedbackIcon = useMemo(() => {
@@ -276,12 +276,19 @@ const themeKeys = [
276
276
  "textBody-tertiary",
277
277
  // Design System related
278
278
  "cardBorder-default",
279
+ "textInputBorder-default",
279
280
  "icon-default",
280
281
  "icon-decorative",
282
+ // Inputs
283
+ "textInputBorder-default",
284
+ "textInputLabel-default",
285
+ "textInputValue-default",
286
+ "textInputValue-disabled",
281
287
  // Layout
282
288
  "divider-header",
283
289
  "divider-default",
284
290
  "divider-bottomBar",
291
+ "pdfViewer-background",
285
292
  // Status
286
293
  "errorIcon",
287
294
  "errorText",
@@ -320,10 +327,16 @@ export const IOThemeLight: IOTheme = {
320
327
  "cardBorder-default": "grey-100",
321
328
  "icon-default": "grey-650",
322
329
  "icon-decorative": "grey-300",
330
+ // Inputs
331
+ "textInputBorder-default": "grey-200",
332
+ "textInputLabel-default": "grey-700",
333
+ "textInputValue-default": "black",
334
+ "textInputValue-disabled": "grey-850",
323
335
  // Layout
324
336
  "divider-header": "grey-100",
325
337
  "divider-default": "grey-200",
326
338
  "divider-bottomBar": "grey-200",
339
+ "pdfViewer-background": "grey-700",
327
340
  // Status
328
341
  errorIcon: "error-600",
329
342
  errorText: "error-600",
@@ -365,6 +378,11 @@ export const IOThemeDark: IOTheme = {
365
378
  "cardBorder-default": "grey-850",
366
379
  "icon-default": "grey-450",
367
380
  "icon-decorative": "grey-650",
381
+ // Inputs
382
+ "textInputBorder-default": "grey-850",
383
+ "textInputLabel-default": "grey-450",
384
+ "textInputValue-default": "white",
385
+ "textInputValue-disabled": "grey-100",
368
386
  // Layout
369
387
  "divider-header": "grey-850",
370
388
  "divider-default": "grey-850",
@@ -1,5 +1,12 @@
1
- import React, { useMemo } from "react";
2
- import { Appearance } from "react-native";
1
+ import React, {
2
+ createContext,
3
+ PropsWithChildren,
4
+ useCallback,
5
+ useContext,
6
+ useMemo,
7
+ useState
8
+ } from "react";
9
+ import { Appearance, ColorSchemeName } from "react-native";
3
10
  import {
4
11
  IOTheme,
5
12
  IOThemeDark,
@@ -10,39 +17,44 @@ import { useIOExperimentalDesign } from "./IODSExperimentalContextProvider";
10
17
 
11
18
  export const IOThemes = { light: IOThemeLight, dark: IOThemeDark };
12
19
  export const legacyIOThemes = { light: IOThemeLightLegacy, dark: IOThemeDark };
13
- type IOThemeType = keyof typeof IOThemes;
20
+ // type IOThemeType = keyof typeof IOThemes | null;
14
21
 
15
22
  type IOThemeContextType = {
16
- themeType: IOThemeType;
23
+ themeType: ColorSchemeName;
17
24
  theme: IOTheme;
18
- setTheme: (theme: IOThemeType) => void;
25
+ setTheme: (theme: ColorSchemeName) => void;
19
26
  };
20
27
 
21
28
  export const IOThemeContext: React.Context<IOThemeContextType> =
22
- React.createContext<IOThemeContextType>({
23
- themeType: Appearance.getColorScheme() === "dark" ? "dark" : "light",
29
+ createContext<IOThemeContextType>({
30
+ themeType: Appearance.getColorScheme(),
24
31
  theme:
25
32
  Appearance.getColorScheme() === "dark" ? IOThemes.dark : IOThemes.light,
26
- setTheme: () => void 0
33
+ setTheme: (theme: ColorSchemeName) => Appearance.setColorScheme(theme)
27
34
  });
28
35
 
29
- export const useIOThemeContext = () => React.useContext(IOThemeContext);
36
+ export const useIOThemeContext = () => useContext(IOThemeContext);
30
37
 
31
38
  export const useIOTheme = () => useIOThemeContext().theme;
32
39
 
33
40
  type IOThemeContextProviderProps = {
34
- theme?: IOThemeType;
41
+ theme?: ColorSchemeName;
35
42
  };
36
43
 
37
44
  export const IOThemeContextProvider = ({
38
45
  children,
39
46
  theme
40
- }: React.PropsWithChildren<IOThemeContextProviderProps>) => {
41
- const [currentTheme, setCurrentTheme] = React.useState<IOThemeType>(
42
- theme ?? "light"
47
+ }: PropsWithChildren<IOThemeContextProviderProps>) => {
48
+ const [currentTheme, setCurrentTheme] = useState<ColorSchemeName>(
49
+ theme ?? Appearance.getColorScheme()
43
50
  );
44
51
  const { isExperimental } = useIOExperimentalDesign();
45
52
 
53
+ const handleThemeChange = useCallback((newTheme: ColorSchemeName) => {
54
+ setCurrentTheme(newTheme);
55
+ Appearance.setColorScheme(newTheme);
56
+ }, []);
57
+
46
58
  const themeMap = useMemo(
47
59
  () => (isExperimental ? IOThemes : legacyIOThemes),
48
60
  [isExperimental]
@@ -52,8 +64,8 @@ export const IOThemeContextProvider = ({
52
64
  <IOThemeContext.Provider
53
65
  value={{
54
66
  themeType: currentTheme,
55
- theme: themeMap[currentTheme],
56
- setTheme: setCurrentTheme
67
+ theme: themeMap[currentTheme ?? "light"],
68
+ setTheme: handleThemeChange
57
69
  }}
58
70
  >
59
71
  {children}