@terreno/ui 0.5.0 → 0.7.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 (61) hide show
  1. package/README.md +5 -5
  2. package/dist/ActionSheet.js +10 -4
  3. package/dist/ActionSheet.js.map +1 -1
  4. package/dist/Common.d.ts +13 -0
  5. package/dist/Common.js.map +1 -1
  6. package/dist/CommonIconTypes.d.ts +1 -1
  7. package/dist/FlatList.js.map +1 -1
  8. package/dist/GPTChat.d.ts +2 -1
  9. package/dist/GPTChat.js +14 -4
  10. package/dist/GPTChat.js.map +1 -1
  11. package/dist/HeightActionSheet.js +18 -10
  12. package/dist/HeightActionSheet.js.map +1 -1
  13. package/dist/HeightField.d.ts +3 -0
  14. package/dist/HeightField.js +167 -0
  15. package/dist/HeightField.js.map +1 -0
  16. package/dist/Page.js +2 -1
  17. package/dist/Page.js.map +1 -1
  18. package/dist/ScrollView.js.map +1 -1
  19. package/dist/TextField.js +2 -2
  20. package/dist/TextField.js.map +1 -1
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +1 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/login/LoginScreen.js +1 -1
  25. package/dist/login/LoginScreen.js.map +1 -1
  26. package/dist/signUp/SignUpScreen.js +1 -1
  27. package/dist/signUp/SignUpScreen.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/ActionSheet.tsx +7 -5
  30. package/src/Common.ts +14 -0
  31. package/src/CommonIconTypes.ts +1 -1
  32. package/src/FlatList.tsx +1 -0
  33. package/src/GPTChat.tsx +40 -2
  34. package/src/HeightActionSheet.tsx +23 -8
  35. package/src/HeightField.test.tsx +178 -0
  36. package/src/HeightField.tsx +360 -0
  37. package/src/HeightFieldDesktop.test.tsx +137 -0
  38. package/src/Page.tsx +20 -9
  39. package/src/ScrollView.tsx +1 -0
  40. package/src/TextField.tsx +2 -0
  41. package/src/__snapshots__/AddressField.test.tsx.snap +4 -0
  42. package/src/__snapshots__/CustomSelectField.test.tsx.snap +1 -0
  43. package/src/__snapshots__/EmailField.test.tsx.snap +2 -0
  44. package/src/__snapshots__/Field.test.tsx.snap +12 -0
  45. package/src/__snapshots__/HeightActionSheet.test.tsx.snap +162 -48
  46. package/src/__snapshots__/HeightField.test.tsx.snap +4011 -0
  47. package/src/__snapshots__/HeightFieldDesktop.test.tsx.snap +613 -0
  48. package/src/__snapshots__/MobileAddressAutoComplete.test.tsx.snap +1 -0
  49. package/src/__snapshots__/NumberField.test.tsx.snap +1 -0
  50. package/src/__snapshots__/Page.test.tsx.snap +15 -20
  51. package/src/__snapshots__/PhoneNumberField.test.tsx.snap +5 -0
  52. package/src/__snapshots__/TapToEdit.test.tsx.snap +1 -0
  53. package/src/__snapshots__/TextArea.test.tsx.snap +5 -0
  54. package/src/__snapshots__/TextField.test.tsx.snap +5 -0
  55. package/src/__snapshots__/UnifiedAddressAutoComplete.test.tsx.snap +4 -0
  56. package/src/__snapshots__/WebAddressAutocomplete.test.tsx.snap +3 -0
  57. package/src/index.tsx +1 -0
  58. package/src/login/LoginScreen.tsx +1 -0
  59. package/src/login/__snapshots__/LoginScreen.test.tsx.snap +2 -0
  60. package/src/signUp/SignUpScreen.tsx +1 -0
  61. package/src/signUp/__snapshots__/SignUpScreen.test.tsx.snap +3 -0
@@ -0,0 +1,137 @@
1
+ import {afterAll, afterEach, beforeEach, describe, expect, it, mock} from "bun:test";
2
+ import {fireEvent} from "@testing-library/react-native";
3
+
4
+ // Mock isNative to return false so the desktop/web path is rendered
5
+ mock.module("./Utilities", () => ({
6
+ isNative: () => false,
7
+ }));
8
+
9
+ import {HeightField} from "./HeightField";
10
+ import {renderWithTheme} from "./test-utils";
11
+
12
+ describe("HeightField (desktop/web path)", () => {
13
+ let mockOnChange: ReturnType<typeof mock>;
14
+
15
+ beforeEach(() => {
16
+ mockOnChange = mock(() => {});
17
+ });
18
+
19
+ afterEach(() => {});
20
+
21
+ afterAll(() => {
22
+ // Restore isNative to default native behavior so the mock doesn't leak to other test files
23
+ mock.module("./Utilities", () => ({
24
+ isNative: () => true,
25
+ }));
26
+ });
27
+
28
+ describe("rendering", () => {
29
+ it("renders two text inputs for feet and inches", () => {
30
+ const {getAllByLabelText} = renderWithTheme(<HeightField onChange={mockOnChange} value="" />);
31
+ expect(getAllByLabelText("ft input").length).toBe(1);
32
+ expect(getAllByLabelText("in input").length).toBe(1);
33
+ });
34
+
35
+ it("renders the correct initial feet and inches from value", () => {
36
+ const {getByDisplayValue} = renderWithTheme(
37
+ <HeightField onChange={mockOnChange} value="70" />
38
+ );
39
+ // 70 inches = 5ft 10in
40
+ expect(getByDisplayValue("5")).toBeTruthy();
41
+ expect(getByDisplayValue("10")).toBeTruthy();
42
+ });
43
+
44
+ it("renders title when provided", () => {
45
+ const {getByText} = renderWithTheme(
46
+ <HeightField onChange={mockOnChange} title="Height" value="" />
47
+ );
48
+ expect(getByText("Height")).toBeTruthy();
49
+ });
50
+
51
+ it("renders helper text", () => {
52
+ const {getByText} = renderWithTheme(
53
+ <HeightField helperText="Enter your height" onChange={mockOnChange} value="" />
54
+ );
55
+ expect(getByText("Enter your height")).toBeTruthy();
56
+ });
57
+
58
+ it("renders error text", () => {
59
+ const {getByText} = renderWithTheme(
60
+ <HeightField errorText="Invalid height" onChange={mockOnChange} value="" />
61
+ );
62
+ expect(getByText("Invalid height")).toBeTruthy();
63
+ });
64
+ });
65
+
66
+ describe("onChange behavior", () => {
67
+ it("calls onChange with correct total inches when feet changes", () => {
68
+ const {getAllByLabelText} = renderWithTheme(
69
+ <HeightField onChange={mockOnChange} value="70" />
70
+ );
71
+ const feetInput = getAllByLabelText("ft input")[0];
72
+ fireEvent.changeText(feetInput, "6");
73
+ // 6 feet + 10 inches (from value "70" = 5ft 10in, inches = 10) = 82 inches
74
+ expect(mockOnChange).toHaveBeenCalledWith("82");
75
+ });
76
+
77
+ it("calls onChange with correct total inches when inches changes", () => {
78
+ const {getAllByLabelText} = renderWithTheme(
79
+ <HeightField onChange={mockOnChange} value="70" />
80
+ );
81
+ const inchesInput = getAllByLabelText("in input")[0];
82
+ fireEvent.changeText(inchesInput, "0");
83
+ // 5 feet (from value "70" = 5ft 10in, feet = 5) + 0 inches = 60 inches
84
+ expect(mockOnChange).toHaveBeenCalledWith("60");
85
+ });
86
+
87
+ it("calls onChange with empty string when both inputs are cleared", () => {
88
+ const {getAllByLabelText} = renderWithTheme(
89
+ <HeightField onChange={mockOnChange} value="70" />
90
+ );
91
+ const feetInput = getAllByLabelText("ft input")[0];
92
+ const inchesInput = getAllByLabelText("in input")[0];
93
+ fireEvent.changeText(feetInput, "");
94
+ fireEvent.changeText(inchesInput, "");
95
+ expect(mockOnChange).toHaveBeenCalledWith("");
96
+ });
97
+
98
+ it("does not call onChange with values exceeding max feet", () => {
99
+ const {getAllByLabelText} = renderWithTheme(
100
+ <HeightField max={95} onChange={mockOnChange} value="" />
101
+ );
102
+ const feetInput = getAllByLabelText("ft input")[0];
103
+ // max is 95 inches = 7ft 11in, so maxFeet = 7
104
+ fireEvent.changeText(feetInput, "8");
105
+ expect(mockOnChange).not.toHaveBeenCalled();
106
+ });
107
+ });
108
+
109
+ describe("disabled state", () => {
110
+ it("renders text inputs as non-editable when disabled", () => {
111
+ const {getAllByLabelText} = renderWithTheme(
112
+ <HeightField disabled onChange={mockOnChange} value="70" />
113
+ );
114
+ const feetInput = getAllByLabelText("ft input")[0];
115
+ expect(feetInput.props.editable).toBe(false);
116
+ });
117
+ });
118
+
119
+ describe("snapshots", () => {
120
+ it("matches snapshot with default props", () => {
121
+ const component = renderWithTheme(<HeightField onChange={mockOnChange} value="" />);
122
+ expect(component.toJSON()).toMatchSnapshot();
123
+ });
124
+
125
+ it("matches snapshot with value", () => {
126
+ const component = renderWithTheme(<HeightField onChange={mockOnChange} value="70" />);
127
+ expect(component.toJSON()).toMatchSnapshot();
128
+ });
129
+
130
+ it("matches snapshot when disabled", () => {
131
+ const component = renderWithTheme(
132
+ <HeightField disabled onChange={mockOnChange} value="70" />
133
+ );
134
+ expect(component.toJSON()).toMatchSnapshot();
135
+ });
136
+ });
137
+ });
package/src/Page.tsx CHANGED
@@ -8,6 +8,7 @@ import {ErrorBoundary} from "./ErrorBoundary";
8
8
  import {Heading} from "./Heading";
9
9
  import {IconButton} from "./IconButton";
10
10
  import {Spinner} from "./Spinner";
11
+ import {Text} from "./Text";
11
12
 
12
13
  export class Page extends React.Component<PageProps, {}> {
13
14
  actionSheetRef: React.RefObject<any> = React.createRef();
@@ -74,15 +75,25 @@ export class Page extends React.Component<PageProps, {}> {
74
75
  width="100%"
75
76
  >
76
77
  {this.renderHeader()}
77
- {this.props.loading === true && <Spinner />}
78
- {/* <KeyboardAccessoryNavigation
79
- avoidKeyboard
80
- doneButton={true}
81
- nextButton={true}
82
- previousButton={true}
83
- /> */}
84
-
85
- {this.props.children}
78
+ {this.props.loading ? (
79
+ <Box
80
+ alignItems="center"
81
+ direction="column"
82
+ display="flex"
83
+ flex="grow"
84
+ justifyContent="center"
85
+ marginTop={8}
86
+ >
87
+ <Spinner />
88
+ {Boolean(this.props.loadingText) && (
89
+ <Box marginTop={2}>
90
+ <Text color="secondaryDark">{this.props.loadingText}</Text>
91
+ </Box>
92
+ )}
93
+ </Box>
94
+ ) : (
95
+ this.props.children
96
+ )}
86
97
  </Box>
87
98
  {Boolean(this.props.footer) && (
88
99
  <Box
@@ -1,2 +1,3 @@
1
1
  import {ScrollView} from "react-native";
2
+
2
3
  export {ScrollView};
package/src/TextField.tsx CHANGED
@@ -78,6 +78,7 @@ export const TextField: FC<TextFieldProps> = ({
78
78
  onEnter,
79
79
  onSubmitEditing,
80
80
  testID,
81
+ id,
81
82
  }) => {
82
83
  const {theme} = useTheme();
83
84
 
@@ -167,6 +168,7 @@ export const TextField: FC<TextFieldProps> = ({
167
168
  enterKeyHint={returnKeyType}
168
169
  keyboardType={keyboardType as KeyboardTypeOptions}
169
170
  multiline={multiline}
171
+ nativeID={id}
170
172
  numberOfLines={rows || 4}
171
173
  onBlur={() => {
172
174
  if (disabled) return;
@@ -41,6 +41,7 @@ exports[`AddressField renders correctly with default props 1`] = `
41
41
  "enterKeyHint": undefined,
42
42
  "keyboardType": "default",
43
43
  "multiline": undefined,
44
+ "nativeID": undefined,
44
45
  "numberOfLines": 1,
45
46
  "onBlur": [Function],
46
47
  "onChangeText": [Function],
@@ -144,6 +145,7 @@ exports[`AddressField renders correctly with default props 1`] = `
144
145
  "enterKeyHint": undefined,
145
146
  "keyboardType": "default",
146
147
  "multiline": undefined,
148
+ "nativeID": "address2",
147
149
  "numberOfLines": 1,
148
150
  "onBlur": [Function],
149
151
  "onChangeText": [Function],
@@ -247,6 +249,7 @@ exports[`AddressField renders correctly with default props 1`] = `
247
249
  "enterKeyHint": undefined,
248
250
  "keyboardType": "default",
249
251
  "multiline": undefined,
252
+ "nativeID": "city",
250
253
  "numberOfLines": 1,
251
254
  "onBlur": [Function],
252
255
  "onChangeText": [Function],
@@ -1129,6 +1132,7 @@ exports[`AddressField renders correctly with default props 1`] = `
1129
1132
  "enterKeyHint": undefined,
1130
1133
  "keyboardType": "default",
1131
1134
  "multiline": undefined,
1135
+ "nativeID": "zipcode",
1132
1136
  "numberOfLines": 1,
1133
1137
  "onBlur": [Function],
1134
1138
  "onChangeText": [Function],
@@ -1590,6 +1590,7 @@ exports[`CustomSelectField renders with custom value (not in options) 1`] = `
1590
1590
  "enterKeyHint": undefined,
1591
1591
  "keyboardType": "default",
1592
1592
  "multiline": undefined,
1593
+ "nativeID": "customOptions",
1593
1594
  "numberOfLines": 1,
1594
1595
  "onBlur": [Function],
1595
1596
  "onChangeText": [Function],
@@ -22,6 +22,7 @@ exports[`EmailField renders correctly with default props 1`] = `
22
22
  "enterKeyHint": undefined,
23
23
  "keyboardType": "email-address",
24
24
  "multiline": undefined,
25
+ "nativeID": undefined,
25
26
  "numberOfLines": 1,
26
27
  "onBlur": [Function],
27
28
  "onChangeText": [Function],
@@ -101,6 +102,7 @@ exports[`EmailField renders with icon 1`] = `
101
102
  "enterKeyHint": undefined,
102
103
  "keyboardType": "email-address",
103
104
  "multiline": undefined,
105
+ "nativeID": undefined,
104
106
  "numberOfLines": 1,
105
107
  "onBlur": [Function],
106
108
  "onChangeText": [Function],
@@ -22,6 +22,7 @@ exports[`Field renders text field by default 1`] = `
22
22
  "enterKeyHint": undefined,
23
23
  "keyboardType": "default",
24
24
  "multiline": undefined,
25
+ "nativeID": undefined,
25
26
  "numberOfLines": 1,
26
27
  "onBlur": [Function],
27
28
  "onChangeText": [Function],
@@ -101,6 +102,7 @@ exports[`Field renders text field with type text 1`] = `
101
102
  "enterKeyHint": undefined,
102
103
  "keyboardType": "default",
103
104
  "multiline": undefined,
105
+ "nativeID": undefined,
104
106
  "numberOfLines": 1,
105
107
  "onBlur": [Function],
106
108
  "onChangeText": [Function],
@@ -180,6 +182,7 @@ exports[`Field renders password field 1`] = `
180
182
  "enterKeyHint": undefined,
181
183
  "keyboardType": "default",
182
184
  "multiline": undefined,
185
+ "nativeID": undefined,
183
186
  "numberOfLines": 1,
184
187
  "onBlur": [Function],
185
188
  "onChangeText": [Function],
@@ -259,6 +262,7 @@ exports[`Field renders email field 1`] = `
259
262
  "enterKeyHint": undefined,
260
263
  "keyboardType": "email-address",
261
264
  "multiline": undefined,
265
+ "nativeID": undefined,
262
266
  "numberOfLines": 1,
263
267
  "onBlur": [Function],
264
268
  "onChangeText": [Function],
@@ -338,6 +342,7 @@ exports[`Field renders url field 1`] = `
338
342
  "enterKeyHint": undefined,
339
343
  "keyboardType": "url",
340
344
  "multiline": undefined,
345
+ "nativeID": undefined,
341
346
  "numberOfLines": 1,
342
347
  "onBlur": [Function],
343
348
  "onChangeText": [Function],
@@ -417,6 +422,7 @@ exports[`Field renders number field 1`] = `
417
422
  "enterKeyHint": undefined,
418
423
  "keyboardType": "default",
419
424
  "multiline": undefined,
425
+ "nativeID": undefined,
420
426
  "numberOfLines": 1,
421
427
  "onBlur": [Function],
422
428
  "onChangeText": [Function],
@@ -496,6 +502,7 @@ exports[`Field renders textarea field 1`] = `
496
502
  "enterKeyHint": undefined,
497
503
  "keyboardType": "default",
498
504
  "multiline": true,
505
+ "nativeID": undefined,
499
506
  "numberOfLines": 1,
500
507
  "onBlur": [Function],
501
508
  "onChangeText": [Function],
@@ -3275,6 +3282,7 @@ exports[`Field renders address field 1`] = `
3275
3282
  "enterKeyHint": undefined,
3276
3283
  "keyboardType": "default",
3277
3284
  "multiline": undefined,
3285
+ "nativeID": undefined,
3278
3286
  "numberOfLines": 1,
3279
3287
  "onBlur": [Function],
3280
3288
  "onChangeText": [Function],
@@ -3378,6 +3386,7 @@ exports[`Field renders address field 1`] = `
3378
3386
  "enterKeyHint": undefined,
3379
3387
  "keyboardType": "default",
3380
3388
  "multiline": undefined,
3389
+ "nativeID": "address2",
3381
3390
  "numberOfLines": 1,
3382
3391
  "onBlur": [Function],
3383
3392
  "onChangeText": [Function],
@@ -3481,6 +3490,7 @@ exports[`Field renders address field 1`] = `
3481
3490
  "enterKeyHint": undefined,
3482
3491
  "keyboardType": "default",
3483
3492
  "multiline": undefined,
3493
+ "nativeID": "city",
3484
3494
  "numberOfLines": 1,
3485
3495
  "onBlur": [Function],
3486
3496
  "onChangeText": [Function],
@@ -4363,6 +4373,7 @@ exports[`Field renders address field 1`] = `
4363
4373
  "enterKeyHint": undefined,
4364
4374
  "keyboardType": "default",
4365
4375
  "multiline": undefined,
4376
+ "nativeID": "zipcode",
4366
4377
  "numberOfLines": 1,
4367
4378
  "onBlur": [Function],
4368
4379
  "onChangeText": [Function],
@@ -4452,6 +4463,7 @@ exports[`Field renders phoneNumber field 1`] = `
4452
4463
  "enterKeyHint": undefined,
4453
4464
  "keyboardType": "number-pad",
4454
4465
  "multiline": undefined,
4466
+ "nativeID": undefined,
4455
4467
  "numberOfLines": 1,
4456
4468
  "onBlur": [Function],
4457
4469
  "onChangeText": [Function],