@jobber/components-native 0.86.1-JOB-136074-a7a2b82.0 → 0.86.2-JOB-89949-9a8f51e.6

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 (47) hide show
  1. package/dist/package.json +3 -9
  2. package/dist/src/Form/Form.js +1 -4
  3. package/dist/src/Form/components/FormCache/FormCache.js +1 -0
  4. package/dist/src/InputCurrency/InputCurrency.js +42 -30
  5. package/dist/src/InputEmail/InputEmail.js +12 -4
  6. package/dist/src/InputNumber/InputNumber.js +10 -4
  7. package/dist/src/Typography/Typography.js +13 -2
  8. package/dist/src/hooks/useAtlantisI18n/locales/en.json +1 -0
  9. package/dist/src/hooks/useAtlantisI18n/locales/es.json +1 -0
  10. package/dist/src/hooks/useFormController.js +5 -14
  11. package/dist/tsconfig.build.tsbuildinfo +1 -1
  12. package/dist/types/src/ActionLabel/ActionLabel.d.ts +3 -2
  13. package/dist/types/src/Form/components/FormCache/FormCache.d.ts +2 -2
  14. package/dist/types/src/Form/context/types.d.ts +2 -2
  15. package/dist/types/src/Form/hooks/useInternalForm.d.ts +2 -2
  16. package/dist/types/src/Form/types.d.ts +3 -3
  17. package/dist/types/src/Heading/Heading.d.ts +3 -2
  18. package/dist/types/src/Text/Text.d.ts +3 -2
  19. package/dist/types/src/Typography/Typography.d.ts +2 -2
  20. package/package.json +3 -9
  21. package/src/ActionLabel/ActionLabel.test.tsx +12 -0
  22. package/src/ActionLabel/ActionLabel.tsx +2 -2
  23. package/src/ActionLabel/__snapshots__/ActionLabel.test.tsx.snap +66 -0
  24. package/src/Form/Form.tsx +0 -6
  25. package/src/Form/components/FormCache/FormCache.tsx +4 -3
  26. package/src/Form/context/types.ts +2 -2
  27. package/src/Form/hooks/useInternalForm.ts +2 -1
  28. package/src/Form/types.ts +3 -4
  29. package/src/Heading/Heading.test.tsx +13 -0
  30. package/src/Heading/Heading.tsx +2 -2
  31. package/src/Heading/__snapshots__/Heading.test.tsx.snap +65 -0
  32. package/src/InputCurrency/InputCurrency.tsx +71 -57
  33. package/src/InputEmail/InputEmail.tsx +15 -8
  34. package/src/InputNumber/InputNumber.tsx +11 -7
  35. package/src/Text/Text.test.tsx +21 -0
  36. package/src/Text/Text.tsx +2 -2
  37. package/src/Text/__snapshots__/Text.test.tsx.snap +104 -0
  38. package/src/Typography/Typography.test.tsx +61 -0
  39. package/src/Typography/Typography.tsx +20 -4
  40. package/src/Typography/__snapshots__/Typography.test.tsx.snap +222 -0
  41. package/src/hooks/useAtlantisI18n/locales/en.json +1 -0
  42. package/src/hooks/useAtlantisI18n/locales/es.json +1 -0
  43. package/src/hooks/useFormController.ts +6 -13
  44. package/dist/src/utils/buildConfig/isEdgeToEdgeEnabled.js +0 -17
  45. package/dist/types/src/utils/buildConfig/isEdgeToEdgeEnabled.d.ts +0 -1
  46. package/src/types/buildConfig.d.ts +0 -7
  47. package/src/utils/buildConfig/isEdgeToEdgeEnabled.ts +0 -20
@@ -2,11 +2,25 @@ import type { Ref } from "react";
2
2
  import React, { forwardRef } from "react";
3
3
  import type { InputTextProps, InputTextRef } from "../InputText";
4
4
  import { InputText } from "../InputText";
5
+ import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
5
6
 
6
7
  export const InputEmail = forwardRef(InputEmailInternal);
7
8
  type InputEmailProps = Omit<InputTextProps, "keyboard">;
8
9
 
9
10
  function InputEmailInternal(props: InputEmailProps, ref: Ref<InputTextRef>) {
11
+ const { t } = useAtlantisI18n();
12
+
13
+ const defaultValidations = {
14
+ pattern: {
15
+ value:
16
+ /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
17
+ message: t("InputEmail.enterEmail"),
18
+ },
19
+ } as const;
20
+ const mergedValidations = props.validations
21
+ ? Object.assign({}, defaultValidations, props.validations)
22
+ : defaultValidations;
23
+
10
24
  return (
11
25
  <InputText
12
26
  {...props}
@@ -14,14 +28,7 @@ function InputEmailInternal(props: InputEmailProps, ref: Ref<InputTextRef>) {
14
28
  autoCapitalize="none"
15
29
  autoCorrect={false}
16
30
  keyboard={"email-address"}
17
- validations={{
18
- pattern: {
19
- value:
20
- /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
21
- message: "Enter a valid email address (email@example.com)",
22
- },
23
- ...props.validations,
24
- }}
31
+ validations={mergedValidations}
25
32
  />
26
33
  );
27
34
  }
@@ -46,6 +46,16 @@ function InputNumberInternal(props: InputNumberProps, ref: Ref<InputTextRef>) {
46
46
  const { inputTransform: convertToString, outputTransform: convertToNumber } =
47
47
  useNumberTransform(props.value);
48
48
 
49
+ const defaultValidations = {
50
+ pattern: {
51
+ value: NUMBER_VALIDATION_REGEX,
52
+ message: t("errors.notANumber"),
53
+ },
54
+ } as const;
55
+ const mergedValidations = props.validations
56
+ ? Object.assign({}, defaultValidations, props.validations)
57
+ : defaultValidations;
58
+
49
59
  return (
50
60
  <InputText
51
61
  {...props}
@@ -58,13 +68,7 @@ function InputNumberInternal(props: InputNumberProps, ref: Ref<InputTextRef>) {
58
68
  value={props.value?.toString()}
59
69
  defaultValue={props.defaultValue?.toString()}
60
70
  onChangeText={handleChange}
61
- validations={{
62
- pattern: {
63
- value: NUMBER_VALIDATION_REGEX,
64
- message: t("errors.notANumber"),
65
- },
66
- ...props.validations,
67
- }}
71
+ validations={mergedValidations}
68
72
  />
69
73
  );
70
74
  }
@@ -151,6 +151,16 @@ it("renders text with underline styling", () => {
151
151
  expect(text.toJSON()).toMatchSnapshot();
152
152
  });
153
153
 
154
+ it("supports nested Text children with mixed styles", () => {
155
+ const { getByText, toJSON } = render(
156
+ <Text>
157
+ Hello <Text emphasis="strong">World</Text>!
158
+ </Text>,
159
+ );
160
+ expect(getByText("World")).toBeDefined();
161
+ expect(toJSON()).toMatchSnapshot();
162
+ });
163
+
154
164
  describe("UNSAFE_style", () => {
155
165
  it("applies custom styles via UNSAFE_style prop", () => {
156
166
  const customStyle = {
@@ -219,3 +229,14 @@ describe("TypographyGestureDetector", () => {
219
229
  expect(textElement.props.collapsable).toBeUndefined();
220
230
  });
221
231
  });
232
+
233
+ it("works when nested inside a native RN Text wrapper", () => {
234
+ const { Text: RNText } = require("react-native");
235
+ const { getByText, toJSON } = render(
236
+ <RNText>
237
+ Outer <Text emphasis="strong">Atlantis</Text> Text
238
+ </RNText>,
239
+ );
240
+ expect(getByText("Atlantis")).toBeDefined();
241
+ expect(toJSON()).toMatchSnapshot();
242
+ });
package/src/Text/Text.tsx CHANGED
@@ -53,9 +53,9 @@ export interface TextProps
53
53
  readonly align?: TextAlign;
54
54
 
55
55
  /**
56
- * Text to display
56
+ * Text to display. Supports strings, numbers, and nested text nodes.
57
57
  */
58
- readonly children?: string;
58
+ readonly children?: React.ReactNode;
59
59
 
60
60
  /**
61
61
  * Reverse theme for better display on dark background
@@ -694,3 +694,107 @@ exports[`renders with strikethrough styling 1`] = `
694
694
  Test Text
695
695
  </Text>
696
696
  `;
697
+
698
+ exports[`supports nested Text children with mixed styles 1`] = `
699
+ <Text
700
+ accessibilityRole="text"
701
+ adjustsFontSizeToFit={false}
702
+ allowFontScaling={true}
703
+ collapsable={false}
704
+ maxFontSizeMultiplier={3.125}
705
+ selectable={true}
706
+ selectionColor="hsl(86, 100%, 46%)"
707
+ style={
708
+ [
709
+ {
710
+ "fontFamily": "inter-regular",
711
+ },
712
+ {
713
+ "color": "hsl(198, 35%, 21%)",
714
+ },
715
+ {
716
+ "textAlign": "left",
717
+ },
718
+ {
719
+ "fontSize": 16,
720
+ "lineHeight": 20,
721
+ },
722
+ {
723
+ "letterSpacing": 0,
724
+ },
725
+ ]
726
+ }
727
+ >
728
+ Hello
729
+ <Text
730
+ accessibilityRole="text"
731
+ adjustsFontSizeToFit={false}
732
+ allowFontScaling={true}
733
+ collapsable={false}
734
+ maxFontSizeMultiplier={3.125}
735
+ selectable={true}
736
+ selectionColor="hsl(86, 100%, 46%)"
737
+ style={
738
+ [
739
+ {
740
+ "fontFamily": "inter-semibold",
741
+ },
742
+ {
743
+ "color": "hsl(198, 35%, 21%)",
744
+ },
745
+ {
746
+ "textAlign": "left",
747
+ },
748
+ {
749
+ "fontSize": 16,
750
+ "lineHeight": 20,
751
+ },
752
+ {
753
+ "letterSpacing": 0,
754
+ },
755
+ ]
756
+ }
757
+ >
758
+ World
759
+ </Text>
760
+ !
761
+ </Text>
762
+ `;
763
+
764
+ exports[`works when nested inside a native RN Text wrapper 1`] = `
765
+ <Text>
766
+ Outer
767
+ <Text
768
+ accessibilityRole="text"
769
+ adjustsFontSizeToFit={false}
770
+ allowFontScaling={true}
771
+ collapsable={false}
772
+ maxFontSizeMultiplier={3.125}
773
+ selectable={true}
774
+ selectionColor="hsl(86, 100%, 46%)"
775
+ style={
776
+ [
777
+ {
778
+ "fontFamily": "inter-semibold",
779
+ },
780
+ {
781
+ "color": "hsl(198, 35%, 21%)",
782
+ },
783
+ {
784
+ "textAlign": "left",
785
+ },
786
+ {
787
+ "fontSize": 16,
788
+ "lineHeight": 20,
789
+ },
790
+ {
791
+ "letterSpacing": 0,
792
+ },
793
+ ]
794
+ }
795
+ >
796
+ Atlantis
797
+ </Text>
798
+ Text
799
+ </Text>
800
+ `;
@@ -79,6 +79,67 @@ it("renders text with lowercase transform", () => {
79
79
  expect(typography.toJSON()).toMatchSnapshot();
80
80
  });
81
81
 
82
+ it("supports nested children and applies transform only to string children", () => {
83
+ const typography = render(
84
+ <Typography transform="uppercase">
85
+ before <Typography fontWeight="bold">Inner</Typography> after
86
+ </Typography>,
87
+ );
88
+ expect(typography.toJSON()).toMatchSnapshot();
89
+ });
90
+
91
+ it("allows child Typography to control its own transform", () => {
92
+ const view = render(
93
+ <Typography transform="uppercase">
94
+ {"before "}
95
+ <Typography fontWeight="bold" transform="lowercase">
96
+ Inner
97
+ </Typography>
98
+ {" after"}
99
+ </Typography>,
100
+ ).toJSON();
101
+
102
+ expect(view).toMatchSnapshot();
103
+ });
104
+
105
+ it("supports multi-level nesting across Typography and Text", () => {
106
+ const view = render(
107
+ <Typography transform="uppercase">
108
+ {"level1 "}
109
+ <Typography>
110
+ and <Typography transform="lowercase">INNER</Typography>
111
+ </Typography>
112
+ {" end"}
113
+ </Typography>,
114
+ ).toJSON();
115
+
116
+ expect(view).toMatchSnapshot();
117
+ });
118
+
119
+ it("applies transform to parent strings only", () => {
120
+ const { getByText } = render(
121
+ <Typography transform="uppercase">
122
+ {"test "}
123
+ <Typography>inner</Typography>
124
+ </Typography>,
125
+ );
126
+
127
+ expect(getByText(/TEST/)).toBeDefined();
128
+ expect(getByText("inner")).toBeDefined();
129
+ });
130
+
131
+ it("allows child transform to override parent transform", () => {
132
+ const { getByText } = render(
133
+ <Typography transform="uppercase">
134
+ before <Typography transform="lowercase">INNER</Typography> after
135
+ </Typography>,
136
+ );
137
+
138
+ expect(getByText(/BEFORE/)).toBeDefined();
139
+ expect(getByText("inner")).toBeDefined();
140
+ expect(getByText(/AFTER/)).toBeDefined();
141
+ });
142
+
82
143
  it("renders text with white color", () => {
83
144
  const typography = render(<Typography color="white">Test Text</Typography>);
84
145
  expect(typography.toJSON()).toMatchSnapshot();
@@ -41,9 +41,9 @@ export interface TypographyProps<T extends FontFamily> {
41
41
  readonly size?: TextSize;
42
42
 
43
43
  /**
44
- * Text to display
44
+ * Text to display. Supports strings, numbers, and nested text nodes.
45
45
  */
46
- readonly children?: string;
46
+ readonly children?: React.ReactNode;
47
47
 
48
48
  /**
49
49
  * The maximum amount of lines the text can occupy before being truncated with "...".
@@ -204,7 +204,7 @@ function InternalTypography<T extends FontFamily = "base">({
204
204
 
205
205
  const numberOfLinesForNativeText = maxNumberOfLines[maxLines];
206
206
 
207
- const text = getTransformedText(children, transform);
207
+ const content = transformChildren(children, transform);
208
208
  const accessibilityProps: AccessibilityProps = hideFromScreenReader
209
209
  ? {
210
210
  accessibilityRole: "none",
@@ -232,7 +232,7 @@ function InternalTypography<T extends FontFamily = "base">({
232
232
  selectionColor={tokens["color-brand--highlight"]}
233
233
  onTextLayout={onTextLayout}
234
234
  >
235
- {text}
235
+ {content}
236
236
  </Text>
237
237
  );
238
238
 
@@ -286,6 +286,22 @@ function getTransformedText(text?: string, transform?: TextTransform) {
286
286
  }
287
287
  }
288
288
 
289
+ function transformChildren(
290
+ children: React.ReactNode,
291
+ transform?: TextTransform,
292
+ ): React.ReactNode {
293
+ if (children == null) return children;
294
+
295
+ return React.Children.map(children, child => {
296
+ if (typeof child === "string") {
297
+ return getTransformedText(child, transform);
298
+ }
299
+
300
+ // Keep non-string children (numbers, elements, fragments) unchanged
301
+ return child as React.ReactNode;
302
+ });
303
+ }
304
+
289
305
  function getColorStyle(
290
306
  styles: ReturnType<typeof useTypographyStyles>,
291
307
  color?: TextColor,
@@ -1,5 +1,69 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`allows child Typography to control its own transform 1`] = `
4
+ <Text
5
+ accessibilityRole="text"
6
+ adjustsFontSizeToFit={false}
7
+ allowFontScaling={true}
8
+ collapsable={false}
9
+ selectable={true}
10
+ selectionColor="hsl(86, 100%, 46%)"
11
+ style={
12
+ [
13
+ {
14
+ "fontFamily": "inter-regular",
15
+ },
16
+ {
17
+ "color": "hsl(197, 15%, 43%)",
18
+ },
19
+ {
20
+ "textAlign": "left",
21
+ },
22
+ {
23
+ "fontSize": 16,
24
+ "lineHeight": 20,
25
+ },
26
+ {
27
+ "letterSpacing": 0,
28
+ },
29
+ ]
30
+ }
31
+ >
32
+ BEFORE
33
+ <Text
34
+ accessibilityRole="text"
35
+ adjustsFontSizeToFit={false}
36
+ allowFontScaling={true}
37
+ collapsable={false}
38
+ selectable={true}
39
+ selectionColor="hsl(86, 100%, 46%)"
40
+ style={
41
+ [
42
+ {
43
+ "fontFamily": "inter-bold",
44
+ },
45
+ {
46
+ "color": "hsl(197, 15%, 43%)",
47
+ },
48
+ {
49
+ "textAlign": "left",
50
+ },
51
+ {
52
+ "fontSize": 16,
53
+ "lineHeight": 20,
54
+ },
55
+ {
56
+ "letterSpacing": 0,
57
+ },
58
+ ]
59
+ }
60
+ >
61
+ inner
62
+ </Text>
63
+ AFTER
64
+ </Text>
65
+ `;
66
+
3
67
  exports[`renders text respecting the text direction 1`] = `
4
68
  <Text
5
69
  accessibilityRole="text"
@@ -902,6 +966,164 @@ exports[`renders text with white color 1`] = `
902
966
  </Text>
903
967
  `;
904
968
 
969
+ exports[`supports multi-level nesting across Typography and Text 1`] = `
970
+ <Text
971
+ accessibilityRole="text"
972
+ adjustsFontSizeToFit={false}
973
+ allowFontScaling={true}
974
+ collapsable={false}
975
+ selectable={true}
976
+ selectionColor="hsl(86, 100%, 46%)"
977
+ style={
978
+ [
979
+ {
980
+ "fontFamily": "inter-regular",
981
+ },
982
+ {
983
+ "color": "hsl(197, 15%, 43%)",
984
+ },
985
+ {
986
+ "textAlign": "left",
987
+ },
988
+ {
989
+ "fontSize": 16,
990
+ "lineHeight": 20,
991
+ },
992
+ {
993
+ "letterSpacing": 0,
994
+ },
995
+ ]
996
+ }
997
+ >
998
+ LEVEL1
999
+ <Text
1000
+ accessibilityRole="text"
1001
+ adjustsFontSizeToFit={false}
1002
+ allowFontScaling={true}
1003
+ collapsable={false}
1004
+ selectable={true}
1005
+ selectionColor="hsl(86, 100%, 46%)"
1006
+ style={
1007
+ [
1008
+ {
1009
+ "fontFamily": "inter-regular",
1010
+ },
1011
+ {
1012
+ "color": "hsl(197, 15%, 43%)",
1013
+ },
1014
+ {
1015
+ "textAlign": "left",
1016
+ },
1017
+ {
1018
+ "fontSize": 16,
1019
+ "lineHeight": 20,
1020
+ },
1021
+ {
1022
+ "letterSpacing": 0,
1023
+ },
1024
+ ]
1025
+ }
1026
+ >
1027
+ and
1028
+ <Text
1029
+ accessibilityRole="text"
1030
+ adjustsFontSizeToFit={false}
1031
+ allowFontScaling={true}
1032
+ collapsable={false}
1033
+ selectable={true}
1034
+ selectionColor="hsl(86, 100%, 46%)"
1035
+ style={
1036
+ [
1037
+ {
1038
+ "fontFamily": "inter-regular",
1039
+ },
1040
+ {
1041
+ "color": "hsl(197, 15%, 43%)",
1042
+ },
1043
+ {
1044
+ "textAlign": "left",
1045
+ },
1046
+ {
1047
+ "fontSize": 16,
1048
+ "lineHeight": 20,
1049
+ },
1050
+ {
1051
+ "letterSpacing": 0,
1052
+ },
1053
+ ]
1054
+ }
1055
+ >
1056
+ inner
1057
+ </Text>
1058
+ </Text>
1059
+ END
1060
+ </Text>
1061
+ `;
1062
+
1063
+ exports[`supports nested children and applies transform only to string children 1`] = `
1064
+ <Text
1065
+ accessibilityRole="text"
1066
+ adjustsFontSizeToFit={false}
1067
+ allowFontScaling={true}
1068
+ collapsable={false}
1069
+ selectable={true}
1070
+ selectionColor="hsl(86, 100%, 46%)"
1071
+ style={
1072
+ [
1073
+ {
1074
+ "fontFamily": "inter-regular",
1075
+ },
1076
+ {
1077
+ "color": "hsl(197, 15%, 43%)",
1078
+ },
1079
+ {
1080
+ "textAlign": "left",
1081
+ },
1082
+ {
1083
+ "fontSize": 16,
1084
+ "lineHeight": 20,
1085
+ },
1086
+ {
1087
+ "letterSpacing": 0,
1088
+ },
1089
+ ]
1090
+ }
1091
+ >
1092
+ BEFORE
1093
+ <Text
1094
+ accessibilityRole="text"
1095
+ adjustsFontSizeToFit={false}
1096
+ allowFontScaling={true}
1097
+ collapsable={false}
1098
+ selectable={true}
1099
+ selectionColor="hsl(86, 100%, 46%)"
1100
+ style={
1101
+ [
1102
+ {
1103
+ "fontFamily": "inter-bold",
1104
+ },
1105
+ {
1106
+ "color": "hsl(197, 15%, 43%)",
1107
+ },
1108
+ {
1109
+ "textAlign": "left",
1110
+ },
1111
+ {
1112
+ "fontSize": 16,
1113
+ "lineHeight": 20,
1114
+ },
1115
+ {
1116
+ "letterSpacing": 0,
1117
+ },
1118
+ ]
1119
+ }
1120
+ >
1121
+ Inner
1122
+ </Text>
1123
+ AFTER
1124
+ </Text>
1125
+ `;
1126
+
905
1127
  exports[`underline renders text with dashed underline 1`] = `
906
1128
  <Text
907
1129
  accessibilityRole="text"
@@ -18,6 +18,7 @@
18
18
  "goBack": "Go back",
19
19
  "InputFieldWrapper.clear": "Clear input",
20
20
  "InputPassword.enterPassword": "Enter a password",
21
+ "InputEmail.enterEmail": "Enter a valid email address (email@example.com)",
21
22
  "loading": "Loading",
22
23
  "menu": "Menu",
23
24
  "more": "More",
@@ -18,6 +18,7 @@
18
18
  "goBack": "Volver",
19
19
  "InputFieldWrapper.clear": "Borrar",
20
20
  "InputPassword.enterPassword": "Escriba una contraseña",
21
+ "InputEmail.enterEmail": "Introduzca una dirección de correo electrónico válida (email@example.com)",
21
22
  "loading": "Cargando",
22
23
  "menu": "Menú",
23
24
  "more": "Más",
@@ -4,7 +4,7 @@ import type {
4
4
  RegisterOptions,
5
5
  UseControllerReturn,
6
6
  } from "react-hook-form";
7
- import { useController, useForm, useFormContext } from "react-hook-form";
7
+ import { get, useController, useForm, useFormContext } from "react-hook-form";
8
8
  import { useState } from "react";
9
9
 
10
10
  interface UseFormControllerProps<T> {
@@ -44,18 +44,11 @@ export function useFormController<T>({
44
44
  });
45
45
 
46
46
  // The naming convention established by react-hook-form for arrays of fields is, for example, "emails.0.description".
47
- // This corresponds to the structure of the error object, e.g. { emails: { 0: { description: "foobar" } } }
48
- // We assume here that fields will either follow this period-delimited three-part convention, or else that they are simple and indivisible (e.g. "city").
49
- // TODO: Add support for two-part identifiers (e.g. "property.province")
50
- const fieldIdentifiers = fieldName.split(".");
51
- let error: FieldError | undefined;
52
-
53
- if (fieldIdentifiers.length === 3) {
54
- const [section, item, identifier] = fieldIdentifiers;
55
- error = errors[section]?.[item]?.[identifier];
56
- } else {
57
- error = errors[fieldName];
58
- }
47
+ // Preserve original behavior: only treat three-part names as nested paths.
48
+ // For anything else, perform a flat lookup to avoid behavioral changes.
49
+ const identifiers = fieldName.split(".");
50
+ const error =
51
+ identifiers.length === 3 ? get(errors, fieldName) : errors[fieldName];
59
52
 
60
53
  return { error, field };
61
54
  }
@@ -1,17 +0,0 @@
1
- import { Platform } from "react-native";
2
- function loadBuildConfig() {
3
- var _a;
4
- try {
5
- const mod = require("react-native-build-config");
6
- return ((_a = mod === null || mod === void 0 ? void 0 : mod.default) !== null && _a !== void 0 ? _a : mod);
7
- }
8
- catch (_b) {
9
- return null; // module not installed or not linked
10
- }
11
- }
12
- export function isEdgeToEdgeEnabled() {
13
- if (Platform.OS !== "android")
14
- return false;
15
- const cfg = loadBuildConfig();
16
- return !!(cfg === null || cfg === void 0 ? void 0 : cfg.IS_EDGE_TO_EDGE_ENABLED);
17
- }
@@ -1 +0,0 @@
1
- export declare function isEdgeToEdgeEnabled(): boolean;
@@ -1,7 +0,0 @@
1
- declare module "react-native-build-config" {
2
- const BuildConfig: {
3
- IS_EDGE_TO_EDGE_ENABLED?: boolean;
4
- [k: string]: unknown;
5
- };
6
- export = BuildConfig;
7
- }
@@ -1,20 +0,0 @@
1
- import { Platform } from "react-native";
2
-
3
- type BuildCfg = { IS_EDGE_TO_EDGE_ENABLED?: boolean } | undefined | null;
4
-
5
- function loadBuildConfig(): BuildCfg {
6
- try {
7
- const mod = require("react-native-build-config");
8
-
9
- return (mod?.default ?? mod) as BuildCfg;
10
- } catch {
11
- return null; // module not installed or not linked
12
- }
13
- }
14
-
15
- export function isEdgeToEdgeEnabled(): boolean {
16
- if (Platform.OS !== "android") return false;
17
- const cfg = loadBuildConfig();
18
-
19
- return !!cfg?.IS_EDGE_TO_EDGE_ENABLED;
20
- }