@terreno/ui 0.0.14 → 0.0.16

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 (156) hide show
  1. package/README.md +1 -1
  2. package/dist/Card.d.ts +1 -1
  3. package/dist/Card.js +2 -2
  4. package/dist/Card.js.map +1 -1
  5. package/dist/DateUtilities.js +2 -2
  6. package/package.json +1 -1
  7. package/src/ActionSheet.test.tsx +77 -0
  8. package/src/Banner.test.tsx +106 -0
  9. package/src/Body.test.tsx +79 -0
  10. package/src/BooleanField.test.tsx +84 -0
  11. package/src/Button.test.tsx +160 -0
  12. package/src/Card.test.tsx +61 -0
  13. package/src/Card.tsx +1 -2
  14. package/src/CheckBox.test.tsx +53 -0
  15. package/src/CustomSelectField.test.tsx +85 -0
  16. package/src/DataTable.test.tsx +133 -0
  17. package/src/DateTimeActionSheet.test.tsx +16 -0
  18. package/src/DateUtilities.tsx +2 -2
  19. package/src/DecimalRangeActionSheet.test.tsx +46 -0
  20. package/src/DismissButton.test.tsx +49 -0
  21. package/src/EmailField.test.tsx +106 -0
  22. package/src/ErrorBoundary.test.tsx +44 -0
  23. package/src/ErrorPage.test.tsx +44 -0
  24. package/src/Field.test.tsx +128 -0
  25. package/src/Heading.test.tsx +66 -0
  26. package/src/HeightActionSheet.test.tsx +34 -0
  27. package/src/Hyperlink.test.tsx +52 -0
  28. package/src/Icon.test.tsx +61 -0
  29. package/src/IconButton.test.tsx +145 -0
  30. package/src/Image.test.tsx +65 -0
  31. package/src/ImageBackground.test.tsx +46 -0
  32. package/src/InfoModalIcon.test.tsx +54 -0
  33. package/src/InfoTooltipButton.test.tsx +22 -0
  34. package/src/Link.test.tsx +64 -0
  35. package/src/MarkdownView.test.tsx +50 -0
  36. package/src/MobileAddressAutoComplete.test.tsx +15 -0
  37. package/src/Modal.test.tsx +169 -0
  38. package/src/ModalSheet.test.tsx +20 -0
  39. package/src/MultiselectField.test.tsx +134 -0
  40. package/src/NumberField.test.tsx +133 -0
  41. package/src/NumberPickerActionSheet.test.tsx +46 -0
  42. package/src/OpenAPIContext.test.tsx +36 -0
  43. package/src/Page.test.tsx +128 -0
  44. package/src/Pagination.test.tsx +86 -0
  45. package/src/PasswordField.test.tsx +17 -0
  46. package/src/PhoneNumberField.test.tsx +79 -0
  47. package/src/PickerSelect.test.tsx +16 -0
  48. package/src/Radio.test.tsx +30 -0
  49. package/src/RadioField.test.tsx +89 -0
  50. package/src/SectionDivider.test.tsx +17 -0
  51. package/src/SegmentedControl.test.tsx +84 -0
  52. package/src/SelectBadge.test.tsx +103 -0
  53. package/src/SelectField.test.tsx +84 -0
  54. package/src/SideDrawer.test.tsx +99 -0
  55. package/src/Signature.test.tsx +15 -0
  56. package/src/SignatureField.test.tsx +16 -0
  57. package/src/Spinner.test.tsx +74 -0
  58. package/src/SplitPage.test.tsx +15 -0
  59. package/src/TapToEdit.test.tsx +147 -0
  60. package/src/TerrenoProvider.test.tsx +36 -0
  61. package/src/Text.test.tsx +147 -0
  62. package/src/Theme.test.tsx +153 -0
  63. package/src/TimezonePicker.test.tsx +57 -0
  64. package/src/Toast.test.tsx +82 -0
  65. package/src/Tooltip.test.tsx +89 -0
  66. package/src/UnifiedAddressAutoComplete.test.tsx +15 -0
  67. package/src/Utilities.test.tsx +237 -0
  68. package/src/WebAddressAutocomplete.test.tsx +15 -0
  69. package/src/__snapshots__/ActionSheet.test.tsx.snap +889 -0
  70. package/src/__snapshots__/Banner.test.tsx.snap +546 -0
  71. package/src/__snapshots__/Body.test.tsx.snap +685 -0
  72. package/src/__snapshots__/BooleanField.test.tsx.snap +553 -0
  73. package/src/__snapshots__/Button.test.tsx.snap +1281 -0
  74. package/src/__snapshots__/Card.test.tsx.snap +195 -0
  75. package/src/__snapshots__/CheckBox.test.tsx.snap +190 -0
  76. package/src/__snapshots__/CustomSelectField.test.tsx.snap +2299 -0
  77. package/src/__snapshots__/DataTable.test.tsx.snap +9614 -0
  78. package/src/__snapshots__/DecimalRangeActionSheet.test.tsx.snap +1719 -0
  79. package/src/__snapshots__/DismissButton.test.tsx.snap +91 -0
  80. package/src/__snapshots__/EmailField.test.tsx.snap +168 -0
  81. package/src/__snapshots__/ErrorBoundary.test.tsx.snap +57 -0
  82. package/src/__snapshots__/ErrorPage.test.tsx.snap +195 -0
  83. package/src/__snapshots__/Field.test.tsx.snap +4510 -0
  84. package/src/__snapshots__/Heading.test.tsx.snap +193 -0
  85. package/src/__snapshots__/HeightActionSheet.test.tsx.snap +1269 -0
  86. package/src/__snapshots__/Hyperlink.test.tsx.snap +81 -0
  87. package/src/__snapshots__/Icon.test.tsx.snap +47 -0
  88. package/src/__snapshots__/IconButton.test.tsx.snap +29 -0
  89. package/src/__snapshots__/Image.test.tsx.snap +282 -0
  90. package/src/__snapshots__/ImageBackground.test.tsx.snap +120 -0
  91. package/src/__snapshots__/InfoModalIcon.test.tsx.snap +1229 -0
  92. package/src/__snapshots__/InfoTooltipButton.test.tsx.snap +7 -0
  93. package/src/__snapshots__/Link.test.tsx.snap +41 -0
  94. package/src/__snapshots__/MarkdownView.test.tsx.snap +965 -0
  95. package/src/__snapshots__/Modal.test.tsx.snap +1477 -0
  96. package/src/__snapshots__/MultiselectField.test.tsx.snap +1454 -0
  97. package/src/__snapshots__/NumberField.test.tsx.snap +80 -0
  98. package/src/__snapshots__/NumberPickerActionSheet.test.tsx.snap +5359 -0
  99. package/src/__snapshots__/OpenAPIContext.test.tsx.snap +14 -0
  100. package/src/__snapshots__/Page.test.tsx.snap +1647 -0
  101. package/src/__snapshots__/Pagination.test.tsx.snap +1913 -0
  102. package/src/__snapshots__/PasswordField.test.tsx.snap +15 -0
  103. package/src/__snapshots__/PhoneNumberField.test.tsx.snap +405 -0
  104. package/src/__snapshots__/PickerSelect.test.tsx.snap +266 -0
  105. package/src/__snapshots__/Radio.test.tsx.snap +111 -0
  106. package/src/__snapshots__/RadioField.test.tsx.snap +944 -0
  107. package/src/__snapshots__/SectionDivider.test.tsx.snap +37 -0
  108. package/src/__snapshots__/SegmentedControl.test.tsx.snap +1422 -0
  109. package/src/__snapshots__/SelectBadge.test.tsx.snap +2377 -0
  110. package/src/__snapshots__/SelectField.test.tsx.snap +1658 -0
  111. package/src/__snapshots__/SideDrawer.test.tsx.snap +1857 -0
  112. package/src/__snapshots__/SignatureField.test.tsx.snap +133 -0
  113. package/src/__snapshots__/Spinner.test.tsx.snap +73 -0
  114. package/src/__snapshots__/TapToEdit.test.tsx.snap +839 -0
  115. package/src/__snapshots__/TerrenoProvider.test.tsx.snap +203 -0
  116. package/src/__snapshots__/Text.test.tsx.snap +558 -0
  117. package/src/__snapshots__/TimezonePicker.test.tsx.snap +6676 -0
  118. package/src/__snapshots__/Toast.test.tsx.snap +1982 -0
  119. package/src/__snapshots__/Tooltip.test.tsx.snap +456 -0
  120. package/src/bunSetup.ts +101 -8
  121. package/src/fieldElements/FieldError.test.tsx +40 -0
  122. package/src/fieldElements/FieldHelperText.test.tsx +34 -0
  123. package/src/fieldElements/FieldTitle.test.tsx +30 -0
  124. package/src/fieldElements/__snapshots__/FieldError.test.tsx.snap +85 -0
  125. package/src/fieldElements/__snapshots__/FieldHelperText.test.tsx.snap +30 -0
  126. package/src/fieldElements/__snapshots__/FieldTitle.test.tsx.snap +19 -0
  127. package/src/icons/MobileIcon.test.tsx +21 -0
  128. package/src/icons/OfflineIcon.test.tsx +21 -0
  129. package/src/icons/OnlineIcon.test.tsx +21 -0
  130. package/src/icons/OutOfficeIcon.test.tsx +21 -0
  131. package/src/icons/__snapshots__/MobileIcon.test.tsx.snap +160 -0
  132. package/src/icons/__snapshots__/OfflineIcon.test.tsx.snap +133 -0
  133. package/src/icons/__snapshots__/OnlineIcon.test.tsx.snap +124 -0
  134. package/src/icons/__snapshots__/OutOfficeIcon.test.tsx.snap +160 -0
  135. package/src/table/Table.test.tsx +107 -0
  136. package/src/table/TableBadge.test.tsx +53 -0
  137. package/src/table/TableBoolean.test.tsx +38 -0
  138. package/src/table/TableDate.test.tsx +27 -0
  139. package/src/table/TableHeader.test.tsx +67 -0
  140. package/src/table/TableHeaderCell.test.tsx +113 -0
  141. package/src/table/TableIconButton.test.tsx +51 -0
  142. package/src/table/TableNumber.test.tsx +45 -0
  143. package/src/table/TableRow.test.tsx +83 -0
  144. package/src/table/TableText.test.tsx +30 -0
  145. package/src/table/TableTitle.test.tsx +30 -0
  146. package/src/table/__snapshots__/Table.test.tsx.snap +2090 -0
  147. package/src/table/__snapshots__/TableBadge.test.tsx.snap +710 -0
  148. package/src/table/__snapshots__/TableBoolean.test.tsx.snap +231 -0
  149. package/src/table/__snapshots__/TableDate.test.tsx.snap +61 -0
  150. package/src/table/__snapshots__/TableHeader.test.tsx.snap +1089 -0
  151. package/src/table/__snapshots__/TableHeaderCell.test.tsx.snap +1773 -0
  152. package/src/table/__snapshots__/TableIconButton.test.tsx.snap +81 -0
  153. package/src/table/__snapshots__/TableNumber.test.tsx.snap +91 -0
  154. package/src/table/__snapshots__/TableRow.test.tsx.snap +1391 -0
  155. package/src/table/__snapshots__/TableText.test.tsx.snap +73 -0
  156. package/src/table/__snapshots__/TableTitle.test.tsx.snap +109 -0
package/README.md CHANGED
@@ -56,7 +56,7 @@ differentiating based on screen size and format.
56
56
  Check out the demo app for easily seeing how the UIs work in iOS/Android/Web
57
57
  in apps/demo.
58
58
 
59
- You can see the [web demo here](https://terreno-ui.netlify.app)
59
+ You can see the [web demo here](https://terreno-demo.netlify.app)
60
60
 
61
61
  # Installation
62
62
 
package/dist/Card.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import type { BoxProps } from "./Common";
2
- export declare const Card: ({ children, color, padding, width, ...rest }: BoxProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const Card: ({ children, color, padding, ...rest }: BoxProps) => import("react/jsx-runtime").JSX.Element;
package/dist/Card.js CHANGED
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { Box } from "./Box";
14
14
  export const Card = (_a) => {
15
- var { children, color = "base", padding = 4, width } = _a, rest = __rest(_a, ["children", "color", "padding", "width"]);
16
- return (_jsx(Box, Object.assign({ color: color, direction: "column", display: "flex", padding: padding, rounding: "md", shadow: true, width: width }, rest, { children: children })));
15
+ var { children, color = "base", padding = 4 } = _a, rest = __rest(_a, ["children", "color", "padding"]);
16
+ return (_jsx(Box, Object.assign({ color: color, direction: "column", display: "flex", padding: padding, rounding: "md", shadow: true }, rest, { children: children })));
17
17
  };
18
18
  //# sourceMappingURL=Card.js.map
package/dist/Card.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Card.js","sourceRoot":"","sources":["../src/Card.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAiE,EAAE,EAAE;QAArE,EAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,OAAoB,EAAf,IAAI,cAAtD,yCAAuD,CAAD;IACzE,OAAO,CACL,KAAC,GAAG,kBACF,KAAK,EAAE,KAAK,EACZ,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAC,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAC,IAAI,EACb,MAAM,QACN,KAAK,EAAE,KAAK,IACR,IAAI,cAEP,QAAQ,IACL,CACP,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"Card.js","sourceRoot":"","sources":["../src/Card.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAA0D,EAAE,EAAE;QAA9D,EAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,EAAE,OAAO,GAAG,CAAC,OAAoB,EAAf,IAAI,cAA/C,gCAAgD,CAAD;IAClE,OAAO,CACL,KAAC,GAAG,kBACF,KAAK,EAAE,KAAK,EACZ,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAC,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAC,IAAI,EACb,MAAM,UACF,IAAI,cAEP,QAAQ,IACL,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -75,7 +75,7 @@ export function humanDate(date, { timezone, dontShowTime } = {}) {
75
75
  }
76
76
  else {
77
77
  // December 25, 2022
78
- return clonedDate.toFormat("MMM d, iiii");
78
+ return clonedDate.toFormat("MMM d, yyyy");
79
79
  }
80
80
  }
81
81
  // Prints a human friendly date and time, e.g. "Tomorrow 9:00 AM", "Yesterday 9:00 AM", "Monday
@@ -119,7 +119,7 @@ export function humanDateAndTime(date, { timezone, showTimezone = true } = {}) {
119
119
  }
120
120
  else {
121
121
  // December 25, 2022
122
- return `${clonedDate.toFormat("MMM d, iiii")} ${time}`;
122
+ return `${clonedDate.toFormat("MMM d, yyyy")} ${time}`;
123
123
  }
124
124
  }
125
125
  // Print date in the format of M/D/YY, taking timezones into account.
package/package.json CHANGED
@@ -128,5 +128,5 @@
128
128
  "test:ci": "TZ=America/New_York bun test",
129
129
  "types": "bunx typedoc"
130
130
  },
131
- "version": "0.0.14"
131
+ "version": "0.0.16"
132
132
  }
@@ -0,0 +1,77 @@
1
+ import {describe, expect, it} from "bun:test";
2
+ import {render} from "@testing-library/react-native";
3
+ import {createRef} from "react";
4
+ import {Text} from "react-native";
5
+
6
+ import {ActionSheet, getDeviceHeight, getElevation} from "./ActionSheet";
7
+ import {ThemeProvider} from "./Theme";
8
+
9
+ describe("ActionSheet", () => {
10
+ it("component is defined", () => {
11
+ expect(ActionSheet).toBeDefined();
12
+ expect(typeof ActionSheet).toBe("function");
13
+ });
14
+
15
+ it("renders correctly", () => {
16
+ const ref = createRef<ActionSheet>();
17
+ const {toJSON} = render(
18
+ <ThemeProvider>
19
+ <ActionSheet ref={ref}>
20
+ <Text>Test content</Text>
21
+ </ActionSheet>
22
+ </ThemeProvider>
23
+ );
24
+ expect(toJSON()).toMatchSnapshot();
25
+ });
26
+
27
+ it("renders with custom overlay color", () => {
28
+ const ref = createRef<ActionSheet>();
29
+ const {toJSON} = render(
30
+ <ThemeProvider>
31
+ <ActionSheet overlayColor="rgba(0,0,0,0.5)" ref={ref}>
32
+ <Text>Content</Text>
33
+ </ActionSheet>
34
+ </ThemeProvider>
35
+ );
36
+ expect(toJSON()).toMatchSnapshot();
37
+ });
38
+
39
+ it("renders with gesture enabled", () => {
40
+ const ref = createRef<ActionSheet>();
41
+ const {toJSON} = render(
42
+ <ThemeProvider>
43
+ <ActionSheet gestureEnabled ref={ref}>
44
+ <Text>Gesture content</Text>
45
+ </ActionSheet>
46
+ </ThemeProvider>
47
+ );
48
+ expect(toJSON()).toMatchSnapshot();
49
+ });
50
+
51
+ describe("getDeviceHeight", () => {
52
+ it("returns a number", () => {
53
+ const height = getDeviceHeight(false);
54
+ expect(typeof height).toBe("number");
55
+ expect(height).toBeGreaterThan(0);
56
+ });
57
+
58
+ it("works with statusBarTranslucent true", () => {
59
+ const height = getDeviceHeight(true);
60
+ expect(typeof height).toBe("number");
61
+ expect(height).toBeGreaterThan(0);
62
+ });
63
+ });
64
+
65
+ describe("getElevation", () => {
66
+ it("returns empty object for no elevation", () => {
67
+ expect(getElevation()).toEqual({});
68
+ expect(getElevation(0)).toEqual({});
69
+ });
70
+
71
+ it("returns elevation styles for positive elevation", () => {
72
+ const result = getElevation(5);
73
+ expect(result).toHaveProperty("elevation", 5);
74
+ expect(result).toHaveProperty("boxShadow");
75
+ });
76
+ });
77
+ });
@@ -0,0 +1,106 @@
1
+ import {describe, expect, it, mock} from "bun:test";
2
+ import {act, fireEvent, waitFor} from "@testing-library/react-native";
3
+
4
+ import {Banner} from "./Banner";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("Banner", () => {
8
+ it("renders correctly with default props", () => {
9
+ const {toJSON} = renderWithTheme(<Banner id="test-banner" text="Test message" />);
10
+ expect(toJSON()).toMatchSnapshot();
11
+ });
12
+
13
+ it("renders text content correctly", () => {
14
+ const {getByText} = renderWithTheme(<Banner id="test-banner" text="Important notice" />);
15
+ expect(getByText("Important notice")).toBeTruthy();
16
+ });
17
+
18
+ it("renders with info status (default)", () => {
19
+ const {toJSON} = renderWithTheme(<Banner id="test-banner" status="info" text="Info message" />);
20
+ expect(toJSON()).toMatchSnapshot();
21
+ });
22
+
23
+ it("renders with alert status", () => {
24
+ const {toJSON} = renderWithTheme(
25
+ <Banner id="test-banner" status="alert" text="Alert message" />
26
+ );
27
+ expect(toJSON()).toMatchSnapshot();
28
+ });
29
+
30
+ it("renders with warning status", () => {
31
+ const {toJSON} = renderWithTheme(
32
+ <Banner id="test-banner" status="warning" text="Warning message" />
33
+ );
34
+ expect(toJSON()).toMatchSnapshot();
35
+ });
36
+
37
+ it("renders with icon when hasIcon is true", () => {
38
+ const {toJSON} = renderWithTheme(<Banner hasIcon id="test-banner" text="With icon" />);
39
+ expect(toJSON()).toMatchSnapshot();
40
+ });
41
+
42
+ it("renders dismissible banner with dismiss button", () => {
43
+ const {getByLabelText} = renderWithTheme(
44
+ <Banner dismissible id="test-banner" text="Dismissible" />
45
+ );
46
+ expect(getByLabelText("Dismiss")).toBeTruthy();
47
+ });
48
+
49
+ it("hides banner when dismiss button is clicked", async () => {
50
+ const {getByLabelText, queryByText} = renderWithTheme(
51
+ <Banner dismissible id="test-dismiss-banner" text="Dismissible banner" />
52
+ );
53
+
54
+ await act(async () => {
55
+ fireEvent.press(getByLabelText("Dismiss"));
56
+ });
57
+
58
+ await waitFor(() => {
59
+ expect(queryByText("Dismissible banner")).toBeNull();
60
+ });
61
+ });
62
+
63
+ it("renders with button", async () => {
64
+ const handleClick = mock(() => Promise.resolve());
65
+ const {getByText, toJSON} = renderWithTheme(
66
+ <Banner
67
+ buttonOnClick={handleClick}
68
+ buttonText="Action"
69
+ id="test-banner"
70
+ text="Banner with button"
71
+ />
72
+ );
73
+ expect(toJSON()).toMatchSnapshot();
74
+ expect(getByText("Action")).toBeTruthy();
75
+ });
76
+
77
+ it("renders with button and icon", () => {
78
+ const handleClick = mock(() => Promise.resolve());
79
+ const {toJSON} = renderWithTheme(
80
+ <Banner
81
+ buttonIconName="arrow-right"
82
+ buttonOnClick={handleClick}
83
+ buttonText="Go"
84
+ id="test-banner"
85
+ text="Banner with button and icon"
86
+ />
87
+ );
88
+ expect(toJSON()).toMatchSnapshot();
89
+ });
90
+
91
+ it("calls buttonOnClick when button is pressed", async () => {
92
+ const handleClick = mock(() => Promise.resolve());
93
+ const {getByText} = renderWithTheme(
94
+ <Banner buttonOnClick={handleClick} buttonText="Click me" id="test-banner" text="Banner" />
95
+ );
96
+
97
+ await act(async () => {
98
+ fireEvent.press(getByText("Click me"));
99
+ await new Promise((resolve) => setTimeout(resolve, 100));
100
+ });
101
+
102
+ await waitFor(() => {
103
+ expect(handleClick).toHaveBeenCalled();
104
+ });
105
+ });
106
+ });
@@ -0,0 +1,79 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {Body} from "./Body";
4
+ import {Text} from "./Text";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("Body", () => {
8
+ it("renders correctly with default props", () => {
9
+ const {toJSON} = renderWithTheme(
10
+ <Body>
11
+ <Text>Body content</Text>
12
+ </Body>
13
+ );
14
+ expect(toJSON()).toMatchSnapshot();
15
+ });
16
+
17
+ it("renders children correctly", () => {
18
+ const {getByText} = renderWithTheme(
19
+ <Body>
20
+ <Text>Test content</Text>
21
+ </Body>
22
+ );
23
+ expect(getByText("Test content")).toBeTruthy();
24
+ });
25
+
26
+ it("renders with scroll enabled", () => {
27
+ const {toJSON} = renderWithTheme(
28
+ <Body scroll>
29
+ <Text>Scrollable content</Text>
30
+ </Body>
31
+ );
32
+ expect(toJSON()).toMatchSnapshot();
33
+ });
34
+
35
+ it("renders with loading state", () => {
36
+ const {toJSON} = renderWithTheme(
37
+ <Body loading>
38
+ <Text>Content</Text>
39
+ </Body>
40
+ );
41
+ expect(toJSON()).toMatchSnapshot();
42
+ });
43
+
44
+ it("renders with custom padding", () => {
45
+ const {toJSON} = renderWithTheme(
46
+ <Body padding={10}>
47
+ <Text>Content</Text>
48
+ </Body>
49
+ );
50
+ expect(toJSON()).toMatchSnapshot();
51
+ });
52
+
53
+ it("renders with custom height", () => {
54
+ const {toJSON} = renderWithTheme(
55
+ <Body height={500}>
56
+ <Text>Content</Text>
57
+ </Body>
58
+ );
59
+ expect(toJSON()).toMatchSnapshot();
60
+ });
61
+
62
+ it("renders without keyboard avoiding when avoidKeyboard is false", () => {
63
+ const {toJSON} = renderWithTheme(
64
+ <Body avoidKeyboard={false}>
65
+ <Text>Content</Text>
66
+ </Body>
67
+ );
68
+ expect(toJSON()).toMatchSnapshot();
69
+ });
70
+
71
+ it("renders with keyboard avoiding by default", () => {
72
+ const {toJSON} = renderWithTheme(
73
+ <Body>
74
+ <Text>Content</Text>
75
+ </Body>
76
+ );
77
+ expect(toJSON()).toMatchSnapshot();
78
+ });
79
+ });
@@ -0,0 +1,84 @@
1
+ import {describe, expect, it, mock} from "bun:test";
2
+ import {fireEvent} from "@testing-library/react-native";
3
+
4
+ import {BooleanField} from "./BooleanField";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("BooleanField", () => {
8
+ it("renders correctly with default props", () => {
9
+ const {toJSON} = renderWithTheme(<BooleanField onChange={() => {}} value={false} />);
10
+ expect(toJSON()).toMatchSnapshot();
11
+ });
12
+
13
+ it("renders with title", () => {
14
+ const {getByText, toJSON} = renderWithTheme(
15
+ <BooleanField onChange={() => {}} title="Enable notifications" value={false} />
16
+ );
17
+ expect(getByText("Enable notifications")).toBeTruthy();
18
+ expect(toJSON()).toMatchSnapshot();
19
+ });
20
+
21
+ it("renders with value true", () => {
22
+ const {toJSON} = renderWithTheme(<BooleanField onChange={() => {}} value={true} />);
23
+ expect(toJSON()).toMatchSnapshot();
24
+ });
25
+
26
+ it("renders with title variant showing Yes/No text", () => {
27
+ const {getByText} = renderWithTheme(
28
+ <BooleanField onChange={() => {}} title="Active" value={true} variant="title" />
29
+ );
30
+ expect(getByText("Yes")).toBeTruthy();
31
+ });
32
+
33
+ it("renders with title variant showing No when false", () => {
34
+ const {getByText} = renderWithTheme(
35
+ <BooleanField onChange={() => {}} title="Active" value={false} variant="title" />
36
+ );
37
+ expect(getByText("No")).toBeTruthy();
38
+ });
39
+
40
+ it("calls onChange when pressed", () => {
41
+ const handleChange = mock((_value: boolean) => {});
42
+ const {UNSAFE_getByType} = renderWithTheme(
43
+ <BooleanField onChange={handleChange} value={false} />
44
+ );
45
+ // TouchableWithoutFeedback is the pressable element
46
+ const touchable = UNSAFE_getByType("TouchableWithoutFeedback" as any);
47
+ fireEvent.press(touchable);
48
+ expect(handleChange).toHaveBeenCalledWith(true);
49
+ });
50
+
51
+ it("does not call onChange when disabled", () => {
52
+ const handleChange = mock((_value: boolean) => {});
53
+ const {UNSAFE_getByType} = renderWithTheme(
54
+ <BooleanField disabled onChange={handleChange} value={false} />
55
+ );
56
+ const touchable = UNSAFE_getByType("TouchableWithoutFeedback" as any);
57
+ fireEvent.press(touchable);
58
+ expect(handleChange).not.toHaveBeenCalled();
59
+ });
60
+
61
+ it("renders disabled state", () => {
62
+ const {toJSON} = renderWithTheme(<BooleanField disabled onChange={() => {}} value={false} />);
63
+ expect(toJSON()).toMatchSnapshot();
64
+ });
65
+
66
+ it("renders with helper text", () => {
67
+ const {getByText} = renderWithTheme(
68
+ <BooleanField helperText="Toggle to enable" onChange={() => {}} value={false} />
69
+ );
70
+ expect(getByText("Toggle to enable")).toBeTruthy();
71
+ });
72
+
73
+ it("renders with disabled helper text when disabled", () => {
74
+ const {getByText} = renderWithTheme(
75
+ <BooleanField
76
+ disabled
77
+ disabledHelperText="This setting is locked"
78
+ onChange={() => {}}
79
+ value={false}
80
+ />
81
+ );
82
+ expect(getByText("This setting is locked")).toBeTruthy();
83
+ });
84
+ });
@@ -0,0 +1,160 @@
1
+ import {describe, expect, it, mock} from "bun:test";
2
+ import {act, fireEvent, waitFor} from "@testing-library/react-native";
3
+
4
+ import {Button} from "./Button";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("Button", () => {
8
+ it("renders correctly with default props", () => {
9
+ const {toJSON} = renderWithTheme(<Button onClick={() => {}} text="Click me" />);
10
+ expect(toJSON()).toMatchSnapshot();
11
+ });
12
+
13
+ it("renders button text correctly", () => {
14
+ const {getByText} = renderWithTheme(<Button onClick={() => {}} text="Submit" />);
15
+ expect(getByText("Submit")).toBeTruthy();
16
+ });
17
+
18
+ it("renders with testID", () => {
19
+ const {getByTestId} = renderWithTheme(
20
+ <Button onClick={() => {}} testID="test-button" text="Test" />
21
+ );
22
+ expect(getByTestId("test-button")).toBeTruthy();
23
+ });
24
+
25
+ // Variant tests
26
+ it("renders primary variant", () => {
27
+ const {toJSON} = renderWithTheme(
28
+ <Button onClick={() => {}} text="Primary" variant="primary" />
29
+ );
30
+ expect(toJSON()).toMatchSnapshot();
31
+ });
32
+
33
+ it("renders secondary variant", () => {
34
+ const {toJSON} = renderWithTheme(
35
+ <Button onClick={() => {}} text="Secondary" variant="secondary" />
36
+ );
37
+ expect(toJSON()).toMatchSnapshot();
38
+ });
39
+
40
+ it("renders muted variant", () => {
41
+ const {toJSON} = renderWithTheme(<Button onClick={() => {}} text="Muted" variant="muted" />);
42
+ expect(toJSON()).toMatchSnapshot();
43
+ });
44
+
45
+ it("renders outline variant", () => {
46
+ const {toJSON} = renderWithTheme(
47
+ <Button onClick={() => {}} text="Outline" variant="outline" />
48
+ );
49
+ expect(toJSON()).toMatchSnapshot();
50
+ });
51
+
52
+ it("renders destructive variant", () => {
53
+ const {toJSON} = renderWithTheme(
54
+ <Button onClick={() => {}} text="Delete" variant="destructive" />
55
+ );
56
+ expect(toJSON()).toMatchSnapshot();
57
+ });
58
+
59
+ // Disabled state
60
+ it("renders disabled state", () => {
61
+ const {toJSON} = renderWithTheme(<Button disabled onClick={() => {}} text="Disabled" />);
62
+ expect(toJSON()).toMatchSnapshot();
63
+ });
64
+
65
+ it("applies disabled styles when disabled", () => {
66
+ const {toJSON} = renderWithTheme(<Button disabled onClick={() => {}} text="Disabled" />);
67
+ // The button should render with disabled styling
68
+ expect(toJSON()).toMatchSnapshot();
69
+ });
70
+
71
+ // Loading state
72
+ it("renders loading state", () => {
73
+ const {toJSON} = renderWithTheme(<Button loading onClick={() => {}} text="Loading" />);
74
+ expect(toJSON()).toMatchSnapshot();
75
+ });
76
+
77
+ // fullWidth
78
+ it("renders fullWidth button", () => {
79
+ const {toJSON} = renderWithTheme(<Button fullWidth onClick={() => {}} text="Full Width" />);
80
+ expect(toJSON()).toMatchSnapshot();
81
+ });
82
+
83
+ // Icon tests
84
+ it("renders with icon on left", () => {
85
+ const {toJSON} = renderWithTheme(
86
+ <Button iconName="check" onClick={() => {}} text="With Icon" />
87
+ );
88
+ expect(toJSON()).toMatchSnapshot();
89
+ });
90
+
91
+ it("renders with icon on right", () => {
92
+ const {toJSON} = renderWithTheme(
93
+ <Button iconName="arrow-right" iconPosition="right" onClick={() => {}} text="Next" />
94
+ );
95
+ expect(toJSON()).toMatchSnapshot();
96
+ });
97
+
98
+ // Click handling
99
+ it("calls onClick when pressed", async () => {
100
+ const handleClick = mock(() => Promise.resolve());
101
+ const {getByText} = renderWithTheme(<Button onClick={handleClick} text="Click" />);
102
+
103
+ await act(async () => {
104
+ fireEvent.press(getByText("Click"));
105
+ // Wait for debounce
106
+ await new Promise((resolve) => setTimeout(resolve, 100));
107
+ });
108
+
109
+ await waitFor(() => {
110
+ expect(handleClick).toHaveBeenCalled();
111
+ });
112
+ });
113
+
114
+ // Confirmation modal tests
115
+ it("renders with confirmation modal props", () => {
116
+ const {toJSON} = renderWithTheme(
117
+ <Button
118
+ confirmationText="Are you sure?"
119
+ modalSubTitle="This action cannot be undone"
120
+ modalTitle="Confirm Delete"
121
+ onClick={() => {}}
122
+ text="Delete"
123
+ withConfirmation
124
+ />
125
+ );
126
+ expect(toJSON()).toMatchSnapshot();
127
+ });
128
+
129
+ it("shows confirmation modal when withConfirmation is true and button is pressed", async () => {
130
+ const handleClick = mock(() => Promise.resolve());
131
+ const {getByText, queryByText} = renderWithTheme(
132
+ <Button
133
+ confirmationText="Are you sure you want to proceed?"
134
+ modalTitle="Confirm Action"
135
+ onClick={handleClick}
136
+ text="Press Me"
137
+ withConfirmation
138
+ />
139
+ );
140
+
141
+ await act(async () => {
142
+ fireEvent.press(getByText("Press Me"));
143
+ await new Promise((resolve) => setTimeout(resolve, 600));
144
+ });
145
+
146
+ // The confirmation modal should now be visible with the modal title
147
+ await waitFor(
148
+ () => {
149
+ expect(queryByText("Confirm Action")).toBeTruthy();
150
+ },
151
+ {timeout: 2000}
152
+ );
153
+ });
154
+
155
+ // Accessibility
156
+ it("has correct accessibility props", () => {
157
+ const {getByLabelText} = renderWithTheme(<Button onClick={() => {}} text="Accessible" />);
158
+ expect(getByLabelText("Accessible")).toBeTruthy();
159
+ });
160
+ });
@@ -0,0 +1,61 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {Card} from "./Card";
4
+ import {Text} from "./Text";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("Card", () => {
8
+ it("renders correctly with default props", () => {
9
+ const {toJSON} = renderWithTheme(
10
+ <Card>
11
+ <Text>Card content</Text>
12
+ </Card>
13
+ );
14
+ expect(toJSON()).toMatchSnapshot();
15
+ });
16
+
17
+ it("renders children correctly", () => {
18
+ const {getByText} = renderWithTheme(
19
+ <Card>
20
+ <Text>Test content</Text>
21
+ </Card>
22
+ );
23
+ expect(getByText("Test content")).toBeTruthy();
24
+ });
25
+
26
+ it("applies custom padding", () => {
27
+ const {toJSON} = renderWithTheme(
28
+ <Card padding={8}>
29
+ <Text>Content</Text>
30
+ </Card>
31
+ );
32
+ expect(toJSON()).toMatchSnapshot();
33
+ });
34
+
35
+ it("applies custom color", () => {
36
+ const {toJSON} = renderWithTheme(
37
+ <Card color="secondary">
38
+ <Text>Content</Text>
39
+ </Card>
40
+ );
41
+ expect(toJSON()).toMatchSnapshot();
42
+ });
43
+
44
+ it("passes additional Box props", () => {
45
+ const {toJSON} = renderWithTheme(
46
+ <Card gap={2} marginTop={4}>
47
+ <Text>Content</Text>
48
+ </Card>
49
+ );
50
+ expect(toJSON()).toMatchSnapshot();
51
+ });
52
+
53
+ it("renders with testID", () => {
54
+ const {getByTestId} = renderWithTheme(
55
+ <Card testID="test-card">
56
+ <Text>Content</Text>
57
+ </Card>
58
+ );
59
+ expect(getByTestId("test-card")).toBeTruthy();
60
+ });
61
+ });
package/src/Card.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import {Box} from "./Box";
2
2
  import type {BoxProps} from "./Common";
3
3
 
4
- export const Card = ({children, color = "base", padding = 4, width, ...rest}: BoxProps) => {
4
+ export const Card = ({children, color = "base", padding = 4, ...rest}: BoxProps) => {
5
5
  return (
6
6
  <Box
7
7
  color={color}
@@ -10,7 +10,6 @@ export const Card = ({children, color = "base", padding = 4, width, ...rest}: Bo
10
10
  padding={padding}
11
11
  rounding="md"
12
12
  shadow
13
- width={width}
14
13
  {...rest}
15
14
  >
16
15
  {children}