@agilant/toga-blox 1.0.32 → 1.0.34

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 (144) hide show
  1. package/dist/components/Dropdown/Dropdown.d.ts +4 -0
  2. package/dist/components/Dropdown/Dropdown.js +20 -0
  3. package/dist/components/Dropdown/Dropdown.stories.d.ts +8 -0
  4. package/dist/components/Dropdown/Dropdown.stories.js +110 -0
  5. package/dist/components/Dropdown/Dropdown.test.d.ts +1 -0
  6. package/dist/components/Dropdown/Dropdown.test.js +43 -0
  7. package/dist/components/Dropdown/Dropdown.types.d.ts +15 -0
  8. package/dist/components/Dropdown/Dropdown.types.js +1 -0
  9. package/dist/components/GenericList/GenericList.d.ts +2 -15
  10. package/dist/components/GenericList/GenericList.js +64 -51
  11. package/dist/components/GenericList/GenericList.stories.d.ts +8 -35
  12. package/dist/components/GenericList/GenericList.stories.js +46 -78
  13. package/dist/components/GenericList/GenericList.test.d.ts +1 -1
  14. package/dist/components/GenericList/GenericList.test.js +112 -22
  15. package/dist/components/GenericList/index.d.ts +2 -0
  16. package/dist/components/GenericList/index.js +2 -0
  17. package/dist/components/GenericList/types.d.ts +16 -0
  18. package/dist/components/GenericList/types.js +1 -0
  19. package/dist/components/Header/Header.stories.js +2 -4
  20. package/dist/components/Input/Input.d.ts +30 -3
  21. package/dist/components/Input/Input.js +70 -48
  22. package/dist/components/Input/Input.stories.js +3 -4
  23. package/dist/components/Input/Input.test.js +74 -42
  24. package/dist/components/InputAndCheck/InputAndCheck.d.ts +47 -0
  25. package/dist/components/InputAndCheck/InputAndCheck.js +74 -0
  26. package/dist/components/InputAndCheck/InputAndCheck.stories.d.ts +9 -0
  27. package/dist/components/InputAndCheck/InputAndCheck.stories.js +201 -0
  28. package/dist/components/InputAndCheck/InputAndCheck.test.d.ts +1 -0
  29. package/dist/components/InputAndCheck/InputAndCheck.test.js +307 -0
  30. package/dist/components/InputAndCheck/index.d.ts +0 -0
  31. package/dist/components/InputAndCheck/index.js +0 -0
  32. package/dist/components/InputAndCheck/types.d.ts +35 -0
  33. package/dist/components/InputAndCheck/types.js +1 -0
  34. package/dist/components/MagnifyingIcon/MagnifyingIcon.d.ts +4 -0
  35. package/dist/components/MagnifyingIcon/MagnifyingIcon.js +60 -0
  36. package/dist/components/MagnifyingIcon/MagnifyingIcon.stories.d.ts +9 -0
  37. package/dist/components/MagnifyingIcon/MagnifyingIcon.stories.js +72 -0
  38. package/dist/components/MagnifyingIcon/MagnifyingIcon.test.d.ts +1 -0
  39. package/dist/components/MagnifyingIcon/MagnifyingIcon.test.js +101 -0
  40. package/dist/components/MagnifyingIcon/index.d.ts +2 -0
  41. package/dist/components/MagnifyingIcon/index.js +2 -0
  42. package/dist/components/MagnifyingIcon/types.d.ts +20 -0
  43. package/dist/components/MagnifyingIcon/types.js +2 -0
  44. package/dist/components/MultiSelect/MultiSelect.d.ts +4 -0
  45. package/dist/components/MultiSelect/MultiSelect.js +30 -0
  46. package/dist/components/MultiSelect/MultiSelect.stories.d.ts +10 -0
  47. package/dist/components/MultiSelect/MultiSelect.stories.js +162 -0
  48. package/dist/components/MultiSelect/MultiSelect.test.d.ts +1 -0
  49. package/dist/components/MultiSelect/MultiSelect.test.js +107 -0
  50. package/dist/components/MultiSelect/MultiSelect.types.d.ts +28 -0
  51. package/dist/components/MultiSelect/MultiSelect.types.js +1 -0
  52. package/dist/components/Page/ViewPageTemplate.stories.js +2 -3
  53. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.d.ts +3 -0
  54. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.js +72 -0
  55. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.stories.d.ts +4 -0
  56. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.stories.js +99 -0
  57. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.test.d.ts +1 -0
  58. package/dist/components/PrimaryTableHeader/PrimaryTableHeader.test.js +124 -0
  59. package/dist/components/PrimaryTableHeader/index.d.ts +0 -0
  60. package/dist/components/PrimaryTableHeader/index.js +0 -0
  61. package/dist/components/PrimaryTableHeader/types.d.ts +35 -0
  62. package/dist/components/PrimaryTableHeader/types.js +2 -0
  63. package/dist/components/SearchInput/SearchInput.d.ts +1 -2
  64. package/dist/components/SearchInput/SearchInput.js +61 -11
  65. package/dist/components/SearchInput/SearchInput.stories.d.ts +2 -4
  66. package/dist/components/SearchInput/SearchInput.stories.js +80 -93
  67. package/dist/components/SearchInput/SearchInput.types.d.ts +37 -24
  68. package/dist/components/SearchInput/SearchNumberInput.d.ts +31 -0
  69. package/dist/components/SearchInput/SearchNumberInput.js +60 -0
  70. package/dist/components/SearchInput/SearchTextInput.d.ts +24 -0
  71. package/dist/components/SearchInput/SearchTextInput.js +65 -0
  72. package/dist/components/SortArrowIcon/SortArrowIcon.d.ts +4 -0
  73. package/dist/components/SortArrowIcon/SortArrowIcon.js +12 -0
  74. package/dist/components/SortArrowIcon/SortArrowIcon.stories.d.ts +17 -0
  75. package/dist/components/SortArrowIcon/SortArrowIcon.stories.js +77 -0
  76. package/dist/components/SortArrowIcon/SortArrowIcon.test.d.ts +1 -0
  77. package/dist/components/SortArrowIcon/SortArrowIcon.test.js +44 -0
  78. package/dist/components/SortArrowIcon/index.d.ts +2 -0
  79. package/dist/components/SortArrowIcon/index.js +2 -0
  80. package/dist/components/SortArrowIcon/types.d.ts +15 -0
  81. package/dist/components/SortArrowIcon/types.js +1 -0
  82. package/dist/components/SortArrows/SortArrows.d.ts +3 -0
  83. package/dist/components/SortArrows/SortArrows.js +33 -0
  84. package/dist/components/SortArrows/SortArrows.stories.d.ts +7 -0
  85. package/dist/components/SortArrows/SortArrows.stories.js +41 -0
  86. package/dist/components/SortArrows/SortArrows.test.d.ts +1 -0
  87. package/dist/components/SortArrows/SortArrows.test.js +150 -0
  88. package/dist/components/SortArrows/index.d.ts +2 -0
  89. package/dist/components/SortArrows/index.js +2 -0
  90. package/dist/components/SortArrows/types.d.ts +21 -0
  91. package/dist/components/SortArrows/types.js +1 -0
  92. package/dist/components/SortArrows/useSortArrowsViewModel.d.ts +30 -0
  93. package/dist/components/SortArrows/useSortArrowsViewModel.js +114 -0
  94. package/dist/components/SortArrows/useSortArrowsViewModel.test.d.ts +1 -0
  95. package/dist/components/SortArrows/useSortArrowsViewModel.test.js +100 -0
  96. package/dist/components/TableCell/TableCell.d.ts +3 -0
  97. package/dist/components/TableCell/TableCell.js +13 -0
  98. package/dist/components/TableCell/TableCell.stories.d.ts +16 -0
  99. package/dist/components/TableCell/TableCell.stories.js +99 -0
  100. package/dist/components/TableCell/TableCell.test.d.ts +1 -0
  101. package/dist/components/TableCell/TableCell.test.js +84 -0
  102. package/dist/components/TableCell/index.d.ts +2 -0
  103. package/dist/components/TableCell/index.js +2 -0
  104. package/dist/components/TableCell/types.d.ts +12 -0
  105. package/dist/components/TableCell/types.js +1 -0
  106. package/dist/components/TableHeaderContent/TableHeaderContent.d.ts +3 -0
  107. package/dist/components/TableHeaderContent/TableHeaderContent.js +5 -0
  108. package/dist/components/TableHeaderContent/TableHeaderContent.stories.d.ts +6 -0
  109. package/dist/components/TableHeaderContent/TableHeaderContent.stories.js +62 -0
  110. package/dist/components/TableHeaderContent/TableHeaderContent.test.d.ts +1 -0
  111. package/dist/components/TableHeaderContent/TableHeaderContent.test.js +41 -0
  112. package/dist/components/TableHeaderContent/index.d.ts +0 -0
  113. package/dist/components/TableHeaderContent/index.js +0 -0
  114. package/dist/components/TableHeaderContent/types.d.ts +5 -0
  115. package/dist/components/TableHeaderContent/types.js +1 -0
  116. package/dist/components/TableHeaderInput/TableHeaderInput.d.ts +3 -0
  117. package/dist/components/TableHeaderInput/TableHeaderInput.js +80 -0
  118. package/dist/components/TableHeaderInput/TableHeaderInput.stories.d.ts +10 -0
  119. package/dist/components/TableHeaderInput/TableHeaderInput.stories.js +82 -0
  120. package/dist/components/TableHeaderInput/TableHeaderInput.test.d.ts +1 -0
  121. package/dist/components/TableHeaderInput/TableHeaderInput.test.js +84 -0
  122. package/dist/components/TableHeaderInput/index.d.ts +1 -0
  123. package/dist/components/TableHeaderInput/index.js +1 -0
  124. package/dist/components/TableHeaderInput/types.d.ts +30 -0
  125. package/dist/components/TableHeaderInput/types.js +1 -0
  126. package/dist/components/TableRow/TableRow.d.ts +15 -0
  127. package/dist/components/TableRow/TableRow.js +21 -0
  128. package/dist/components/TableRow/TableRow.stories.d.ts +9 -0
  129. package/dist/components/TableRow/TableRow.stories.js +195 -0
  130. package/dist/components/TableRow/TableRow.test.d.ts +1 -0
  131. package/dist/components/TableRow/TableRow.test.js +44 -0
  132. package/dist/components/TableRow/index.d.ts +2 -0
  133. package/dist/components/TableRow/index.js +2 -0
  134. package/dist/components/TableRow/types.d.ts +11 -0
  135. package/dist/components/TableRow/types.js +1 -0
  136. package/dist/components/ToggleButton/ToggleButton.d.ts +4 -0
  137. package/dist/components/ToggleButton/ToggleButton.js +41 -0
  138. package/dist/components/ToggleButton/ToggleButton.stories.d.ts +11 -0
  139. package/dist/components/ToggleButton/ToggleButton.stories.js +111 -0
  140. package/dist/components/ToggleButton/ToggleButton.test.d.ts +1 -0
  141. package/dist/components/ToggleButton/ToggleButton.test.js +106 -0
  142. package/dist/components/ToggleButton/ToggleButton.types.d.ts +22 -0
  143. package/dist/components/ToggleButton/ToggleButton.types.js +1 -0
  144. package/package.json +11 -4
@@ -1,24 +1,114 @@
1
- import { screen } from "@testing-library/react";
2
- import { describe, expect, test } from "vitest";
3
- describe("<GenericList />", () => {
4
- // beforeEach(() => {
5
- // render(
6
- // <GenericList
7
- // data={DUMMYICONDATA.DUMMYICONCOMPASSDATA}
8
- // renderItem={(item) => <DynamicIconList />}
9
- // itemHeight={20}
10
- // containerHeight={72}
11
- // listType="unordered"
12
- // containerClasses="bg-gray-100 w-36 border-2 border-teal-500"
13
- // listDirection="vertical"
14
- // hasVirtualization={false}
15
- // />
16
- // );
17
- // });
18
- test("contains correct icon images", () => {
19
- expect(screen.getByTestId("user")).toBeInTheDocument();
20
- expect(screen.getByTestId("circle-info")).toBeInTheDocument();
21
- expect(screen.getByTestId("bell")).toBeInTheDocument();
22
- expect(screen.getByTestId("cart-shopping")).toBeInTheDocument();
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createRef } from "react";
3
+ import { describe, it, expect, vi } from "vitest";
4
+ import { render, screen } from "@testing-library/react";
5
+ import userEvent from "@testing-library/user-event";
6
+ import GenericList from "./GenericList";
7
+ import "@testing-library/jest-dom";
8
+ // Sample data used in tests.
9
+ const data = Array.from({ length: 5 }, (_, index) => ({
10
+ id: index.toString(),
11
+ text: `Item ${index}`,
12
+ }));
13
+ // A simple render function for each item.
14
+ const renderItem = (item, index) => (_jsx("span", { children: item.text }));
15
+ describe("GenericList", () => {
16
+ it("renders basic list (non-virtualized)", () => {
17
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered" }));
18
+ // Ensure every item text is present.
19
+ data.forEach((item) => {
20
+ expect(screen.getByText(item.text)).toBeInTheDocument();
21
+ });
22
+ // When listType is "unordered", ListWrapper renders a <ul>.
23
+ const list = screen.getByRole("list");
24
+ // Each item is rendered in a <div> inside the <ul> so the number of children equals the number of items.
25
+ expect(list.children.length).toBe(data.length);
26
+ });
27
+ it("handles click events", async () => {
28
+ const handleClick = vi.fn();
29
+ // Render items as buttons so that clicks can be detected.
30
+ const renderItemWithClick = (item, index) => (_jsx("button", { onClick: handleClick, "data-testid": `button-${index}`, children: item.text }));
31
+ render(_jsx(GenericList, { data: data, renderItem: renderItemWithClick, itemHeight: 35, containerHeight: 200, listType: "unordered" }));
32
+ const firstButton = screen.getByTestId("button-0");
33
+ await userEvent.click(firstButton);
34
+ expect(handleClick).toHaveBeenCalled();
35
+ });
36
+ it("renders virtualized list (default direction, non-virtualized branch)", () => {
37
+ // Create many items so that virtualization kicks in.
38
+ const manyItems = Array.from({ length: 1000 }, (_, index) => ({
39
+ id: index.toString(),
40
+ text: `Item ${index}`,
41
+ }));
42
+ render(_jsx(GenericList, { data: manyItems, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", hasVirtualization: true,
43
+ // Force the virtualized branch.
44
+ isVirtualizer: false }));
45
+ // The rendered <ul> will contain one child: the virtualization container.
46
+ const list = screen.getByRole("list");
47
+ const innerContainer = list.querySelector("div");
48
+ if (!innerContainer) {
49
+ throw new Error("Virtualization container not found");
50
+ }
51
+ // Expect that the number of virtualized items is far fewer than the total.
52
+ expect(innerContainer.childElementCount).toBeLessThan(100);
53
+ });
54
+ it("renders virtualization as non-virtualized when isVirtualizer is true", () => {
55
+ // Even when virtualization is enabled, if isVirtualizer is true, the non-virtualized branch is used.
56
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", hasVirtualization: true, isVirtualizer: true }));
57
+ const list = screen.getByRole("list");
58
+ // Expect each of the 5 items to be rendered directly.
59
+ expect(list.children.length).toBe(data.length);
60
+ });
61
+ it("renders proper list elements when listType is 'none'", () => {
62
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "none" }));
63
+ // Check that every item text is present.
64
+ data.forEach((item) => {
65
+ expect(screen.getByText(item.text)).toBeInTheDocument();
66
+ });
67
+ // For listType "none", the ListWrapper renders a <div> (thus no element with role "list").
68
+ expect(screen.queryByRole("list")).toBeNull();
69
+ });
70
+ it("renders ordered list when listType is 'ordered'", () => {
71
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "ordered" }));
72
+ // For listType "ordered", ListWrapper renders an <ol>.
73
+ const list = screen.getByRole("list");
74
+ expect(list.tagName).toBe("OL");
75
+ expect(list.children.length).toBe(data.length);
76
+ });
77
+ it("handles horizontal layout", () => {
78
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", listDirection: "horizontal" }));
79
+ // With listDirection "horizontal", the container's className should include "flex" and "overflow-x-auto".
80
+ const list = screen.getByRole("list");
81
+ expect(list.className).toContain("flex");
82
+ expect(list.className).toContain("overflow-x-auto");
83
+ });
84
+ it("handles vertical layout", () => {
85
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", listDirection: "vertical" }));
86
+ // With listDirection "vertical", the container's className should include "flex" and "flex-col".
87
+ const list = screen.getByRole("list");
88
+ expect(list.className).toContain("flex");
89
+ expect(list.className).toContain("flex-col");
90
+ });
91
+ it("applies additional containerClasses", () => {
92
+ const extraClasses = "bg-red-500 p-4";
93
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", containerClasses: extraClasses }));
94
+ const list = screen.getByRole("list");
95
+ expect(list.className).toContain(extraClasses);
96
+ });
97
+ it("forwards parentRef to the container", () => {
98
+ const ref = createRef();
99
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered", parentRef: ref }));
100
+ // The ref should be attached to an element (an unordered list in this case).
101
+ expect(ref.current).not.toBeNull();
102
+ expect(ref.current?.tagName).toBe("UL");
103
+ });
104
+ // --- Additional tests to improve branch coverage ---
105
+ it("handles unknown listDirection", () => {
106
+ // Pass an unrecognized value so getListDirectionClasses returns an empty string.
107
+ render(_jsx(GenericList, { data: data, renderItem: renderItem, itemHeight: 35, containerHeight: 200, listType: "unordered",
108
+ // @ts-expect-error Passing an invalid value for testing purposes.
109
+ listDirection: "diagonal" }));
110
+ const list = screen.getByRole("list");
111
+ // The only classes should be from ListWrapper ("list-none p-0 m-0")
112
+ expect(list.className).toBe("list-none p-0 m-0");
23
113
  });
24
114
  });
@@ -0,0 +1,2 @@
1
+ export { default } from "./GenericList";
2
+ export * from "./types";
@@ -0,0 +1,2 @@
1
+ export { default } from "./GenericList";
2
+ export * from "./types";
@@ -0,0 +1,16 @@
1
+ export type GenericData = {
2
+ id: string;
3
+ [key: string]: any;
4
+ };
5
+ export type GenericListTypes<T extends GenericData> = {
6
+ data: T[];
7
+ renderItem: (item: T, index?: number) => JSX.Element;
8
+ itemHeight?: number;
9
+ containerHeight?: number;
10
+ containerClasses?: string;
11
+ listDirection?: "horizontal" | "vertical";
12
+ hasVirtualization?: boolean;
13
+ listType: "ordered" | "unordered" | "none";
14
+ parentRef?: React.RefObject<HTMLElement>;
15
+ isVirtualizer?: boolean;
16
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -4,8 +4,6 @@ import Nav from "../Nav/Nav";
4
4
  import Image from "../Image/Image";
5
5
  import Badge from "../Badge/Badge";
6
6
  import Text from "../Text/Text";
7
- import Input from "../Input/Input";
8
- import BaseButton from "../BaseButton/BaseButton";
9
7
  import { DUMMYCOMPASSNAVDATA, DUMMYNAVDATA } from "../Nav/DUMMYNAVDATA.json";
10
8
  import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
11
9
  export default {
@@ -131,7 +129,7 @@ Default.args = {
131
129
  ),
132
130
  badge: (_jsx(Badge, { type: "href", to: "#", hoverColor: "blue", borderColor: "none", mobileIcon: getFontAwesomeIcon("square-phone"), mobileIconLabel: "Contact Us", onClick: () => alert("Redirect to Contact Us page"), image: _jsx(Image, { src: "../../../assets/contact-image.png", alt: "", background: false, additionalClasses: "flex justify-center w-8 h-8 max-md:hidden" }), text: _jsxs(_Fragment, { children: [_jsx(Text, { size: "text-sm", color: "text-black", fontFamily: "font-serif", text: "Contact Us", tag: "h2", additionalClasses: "pl-2 pb-0 font-bold" }), _jsx(Text, { size: "text-xs", color: "text-black", fontFamily: "font-serif", text: "1-800-800-8000", tag: "p", additionalClasses: "pl-2 pt-0" })] }) })),
133
131
  nav: (_jsx(Nav, { navData: DUMMYNAVDATA, navBackgroundColor: "#FFFFF", parentHoverBackground: "blue", parentHoverFontColor: "white", parentHoverUnderline: true, parentHoverBorderColor: "none", parentShape: "cornered", parentBackground: "none", parentBorderColor: "none", submenuBackgroundColor: "blue", submenuHoverBackground: "white", submenuHoverBorderStyle: "bottom", submenuHoverBorderColor: "black", mobileBreakpoint: "extraLarge", accordionParentStyle: "cornered p-2 w-full border-b-2 border-b-blue-700 text-black", accordionExpandedStyle: "pl-2 py-3" })),
134
- input: (_jsx(Input, { labelVisible: false, label: undefined, inputType: "text", inputName: "search", hasPlaceholder: true, placeholder: "Search", borderColor: "gray", hasButton: true, backgroundColor: "white", additionalClasses: "bg-blue-500", button: _jsx(BaseButton, { icon: getFontAwesomeIcon("search"), backgroundColor: "blue", hoverBackground: "black", hoverFontColor: "white", additionalClasses: "h-full w-8 justify-center", shape: "none" }), inputWidth: "w-full" })),
132
+ input: _jsx(_Fragment, {}),
135
133
  logoBorderRadius: true,
136
134
  logoHoverColor: "blue",
137
135
  hasIcons: false,
@@ -188,7 +186,7 @@ Compass.args = {
188
186
  badge: (_jsx(Badge, { type: "href", to: "#", hoverColor: "green", borderColor: "none", mobileIcon: getFontAwesomeIcon("square-phone"), mobileIconLabel: "Contact Us", onClick: () => alert("Redirect to Contact Us page"), image: _jsx(Image, { src: "../../../assets/contact-image.png", alt: "", background: false, additionalClasses: "flex justify-center w-8 h-8 max-md:hidden" }), text: _jsxs(_Fragment, { children: [_jsx(Text, { size: "text-sm", color: "text-teal-700", fontFamily: "font-serif", text: "Contact Us", tag: "h2", additionalClasses: "pl-2 pb-0 font-bold" }), _jsx(Text, { size: "text-xs", color: "text-teal-700", fontFamily: "font-serif", text: "1-800-800-8000", tag: "p", additionalClasses: "pl-2 pt-0" })] }) })),
189
187
  logo: (_jsx(Image, { src: "../../../assets/compass-logo.png", alt: "Generic Company Logo.", background: false, additionalClasses: " w-40 p-2" })),
190
188
  nav: (_jsx(Nav, { navData: DUMMYCOMPASSNAVDATA, navBackgroundColor: "#FFFFF", parentHoverBackground: "none", parentHoverFontColor: "black", parentHoverUnderline: true, parentHoverBorderColor: "none", parentShape: "cornered", parentBackground: "none", parentBorderColor: "none", submenuBackgroundColor: "white", submenuHoverBackground: "green", submenuHoverBorderStyle: "top-bottom", submenuHoverBorderColor: "green", includeSubmenuImages: true, mobileBreakpoint: "extraLarge", accordionParentStyle: "cornered p-2 w-full border-b-2 border-b-teal-700 text-black", accordionExpandedStyle: "pl-2 py-3" })),
191
- input: (_jsx(Input, { labelVisible: false, label: undefined, inputType: "text", inputName: "search", borderColor: "gray", hasPlaceholder: true, placeholder: "Search", hasButton: true, backgroundColor: "white", additionalClasses: "bg-blue-500", button: _jsx(BaseButton, { icon: getFontAwesomeIcon("search"), backgroundColor: "green", hoverBackground: "black", hoverFontColor: "white", additionalClasses: "h-full w-8 justify-center", shape: "none" }), inputWidth: "w-full" })),
189
+ input: _jsx(_Fragment, {}),
192
190
  };
193
191
  export const NoSearchOrBadge = Template.bind({});
194
192
  NoSearchOrBadge.args = {
@@ -1,4 +1,31 @@
1
1
  import React from "react";
2
- import { InputTypes } from ".";
3
- declare const Input: React.FC<InputTypes>;
4
- export default Input;
2
+ interface InputFieldProps {
3
+ label?: string;
4
+ value?: string | number;
5
+ readOnlyInfo?: string | JSX.Element;
6
+ iconColor?: string;
7
+ placeholder?: string;
8
+ iconPosition?: "before" | "after" | "both";
9
+ required: boolean;
10
+ firstIcon?: JSX.Element | (() => JSX.Element | React.ReactElement) | null;
11
+ secondIcon?: JSX.Element | (() => JSX.Element | React.ReactElement) | null;
12
+ hasToolTip?: boolean;
13
+ toolTipText?: string;
14
+ onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
15
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
16
+ checked?: boolean extends InputFieldProps["type"] ? boolean : undefined;
17
+ id?: string;
18
+ name?: string;
19
+ additionalClasses?: string;
20
+ onIconClick?: () => void;
21
+ type: string;
22
+ isValid?: boolean;
23
+ isReadOnly?: boolean;
24
+ hasIcons?: boolean;
25
+ labelClasses?: string;
26
+ disabled?: boolean;
27
+ hasAutoFocus?: boolean;
28
+ focusRingColor?: string;
29
+ }
30
+ declare const InputField: React.ForwardRefExoticComponent<InputFieldProps & React.RefAttributes<unknown>>;
31
+ export default InputField;
@@ -1,51 +1,73 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
3
- import BaseButton from "../BaseButton/BaseButton";
4
- import { validateInput } from "../../utils/inputValidation";
5
- import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
6
- const Input = ({
7
- // FUNCTIONALITY
8
- hasValidation = false, errorMessage, regex, setControlledState, controlledState,
9
- // LABEL
10
- label, labelVisible = true, labelPlacement = "block",
11
- // INPUT DETAILS
12
- inputName, inputType,
13
- // PLACEHOLDER
14
- hasPlaceholder = true, placeholder,
15
- // ICONS
16
- hasLeftIcon, hasRightIcon, leftIcon, rightIcon, iconColor = "text-gray-500", iconBackgroundColor = "bg-transparent",
17
- // INPUT STYLES
18
- inputTextSize = "text-base", inputShape = "rounded-md", borderColor = "border-gray-300", backgroundColor = "bg-white", inputWidth = "w-full", errorBorder = "border-red-500", successBorder = "border-green-500",
19
- // BUTTON
20
- hasButton, button = (_jsx(BaseButton, { text: "Submit", as: "button", hoverBackground: "hover:bg-green-500", backgroundColor: "bg-red-500", icon: getFontAwesomeIcon("arrow-right"), borderColor: "border-green-500", hoverFontColor: "hover:text-black", shape: "rounded-none", additionalClasses: "h-full" })), }) => {
21
- const [isValid, setIsValid] = useState("");
22
- const [termInternal, setTermInternal] = useState("");
23
- const [inputBorderClasses, setInputBorderClasses] = useState(borderColor);
24
- const inputValue = termInternal || controlledState || "";
25
- const setTerm = setControlledState || setTermInternal;
26
- const handleBorderStyles = () => {
27
- if (isValid !== "Success" && isValid !== "") {
28
- setInputBorderClasses(errorBorder);
29
- }
30
- else if (isValid === "Success") {
31
- setInputBorderClasses(successBorder);
32
- }
33
- else if (isValid === "") {
34
- setInputBorderClasses(borderColor);
35
- }
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { useState, forwardRef } from "react";
5
+ const InputField = forwardRef(({ label, placeholder, required = false, checked, id, name, type = "text", firstIcon, secondIcon, iconPosition = "before", iconColor = "primary", isValid = true, isReadOnly = false, onChange, value, readOnlyInfo = "", toolTipText = "", hasToolTip = false, additionalClasses = "", labelClasses = "", hasAutoFocus, onIconClick, onKeyDown, disabled,
6
+ // register,
7
+ focusRingColor = "focus:ring-transparent", }) => {
8
+ const [isFocused, setIsFocused] = useState(false);
9
+ const hasValue = value != null && !!value.toString().trim(); // Check if input value has at least one non-space character
10
+ const isNumberInput = type === "number";
11
+ let formattedValue = isNumberInput &&
12
+ value != null &&
13
+ value.toString().trim() &&
14
+ isNaN(Number(value))
15
+ ? ""
16
+ : value;
17
+ if (formattedValue === "$NaN") {
18
+ formattedValue = "";
19
+ }
20
+ const renderFirstIcon = () => {
21
+ if (!firstIcon)
22
+ return null;
23
+ return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--first-icon absolute top-[8px] left-4 ${disabled
24
+ ? "text-gray-500"
25
+ : isValid
26
+ ? `text-${iconColor}`
27
+ : "text-redText"}`, children: _jsx(_Fragment, { children: firstIcon }) }));
28
+ };
29
+ const renderSecondIcon = () => {
30
+ if (!secondIcon)
31
+ return null;
32
+ return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--second-icon absolute top-2 right-4 text-${disabled
33
+ ? "text-gray-500"
34
+ : isValid
35
+ ? `text-${iconColor}`
36
+ : "text-redText"}`, children: _jsx(_Fragment, { children: secondIcon }) }));
36
37
  };
37
- const handleChange = (e) => {
38
- setTerm(e.target.value);
39
- if (hasValidation) {
40
- let validation = validateInput &&
41
- regex &&
42
- errorMessage &&
43
- validateInput(inputValue, regex, errorMessage);
44
- setIsValid(validation || "");
45
- handleBorderStyles();
38
+ const renderIcons = () => {
39
+ switch (iconPosition) {
40
+ case "before":
41
+ return renderFirstIcon();
42
+ case "after":
43
+ return renderSecondIcon();
44
+ case "both":
45
+ return (_jsxs(_Fragment, { children: [renderFirstIcon(), renderSecondIcon()] }));
46
+ default:
47
+ return null;
46
48
  }
47
49
  };
48
- return (_jsxs("div", { className: `${labelPlacement} w-full`, "data-testid": "input-container", children: [_jsx("label", { htmlFor: inputName, className: `${labelVisible ? "block" : "hidden"} pb-1 pl-1`, "data-testid": "input-label", children: label }), hasButton ? (_jsxs("div", { className: `relative ${inputWidth} flex`, children: [_jsxs("div", { className: "flex-1 relative", children: [hasLeftIcon && (_jsx("div", { className: `absolute bottom-1 left-1 flex items-center justify-center ${iconColor} ${iconBackgroundColor} h-8 w-8`, children: leftIcon })), _jsx("input", { type: inputType, placeholder: hasPlaceholder ? placeholder : undefined, name: inputName, id: inputName, onChange: handleChange, value: inputValue, "data-testid": "input-element", className: `block w-full border-2 p-2 ${inputTextSize} ${inputShape} ${backgroundColor} ${inputBorderClasses} ${hasLeftIcon ? "pl-10" : ""} ${hasRightIcon ? "pr-10" : ""}` })] }), hasButton && (_jsx("div", { className: `flex items-center justify-center ${inputShape} h-full`, "data-testid": "submit-button", children: button }))] })) : (_jsxs("div", { className: `relative ${inputWidth} flex`, children: [hasLeftIcon && (_jsx("div", { className: `absolute top-1 left-1 flex items-center justify-center ${iconColor} ${iconBackgroundColor} h-8 w-8`, children: leftIcon })), _jsx("input", { type: inputType, placeholder: hasPlaceholder ? placeholder : undefined, name: inputName, id: inputName, onChange: handleChange, value: inputValue, "data-testid": "input-element", className: `block w-full border-2 ${inputTextSize} ${inputShape} ${backgroundColor} ${inputBorderClasses} ${hasLeftIcon ? "pl-10" : ""} ${hasRightIcon ? "pr-10" : ""}` }), hasRightIcon && (_jsx("div", { className: `absolute top-1 right-1 flex items-center justify-center ${iconColor} ${iconBackgroundColor} h-8 w-8`, children: rightIcon }))] }))] }));
49
- };
50
- Input.displayName = "Memo(Input)";
51
- export default Input;
50
+ // const registerProps = register
51
+ // ? register(name || "", { required })
52
+ // : {};
53
+ return isReadOnly ? (_jsxs("div", { className: "input-wrapper relative", children: [renderIcons(), _jsxs("label", { htmlFor: id, className: `block font-light text-left mb-1 ${labelClasses} `, children: [label, hasToolTip && (_jsxs("span", { className: "pl-4 group", children: [_jsx(FontAwesomeIcon, { icon: faCircleInfo, className: "text-primary group-hover:text-blue-600" }), _jsx("span", { className: "opacity-0 group-hover:opacity-100 bg-gray-800 text-white text-sm rounded-md px-2 py-1 absolute top-[-14px]", children: toolTipText })] }))] }), _jsx("div", { className: `
54
+ text-left focus:outline-none focus:ring-2 block w-full py-2 px-2 rounded-lg shadow-input outline outline-0 outline-barelyPrimary focus:outline-4 md:w-full lg:w-full xl:w-full
55
+ ${firstIcon ? "pl-10" : ""}
56
+ ${secondIcon ? "pr-10" : ""}
57
+ ${additionalClasses}
58
+ `, children: readOnlyInfo }), iconPosition === "after" && renderSecondIcon()] })) : (_jsxs(_Fragment, { children: [label && (_jsxs("label", { htmlFor: id, className: ` block font-light text-left mb-1 ${labelClasses}`, children: [label, hasToolTip && (_jsxs("span", { className: "pl-4 group", children: [_jsx(FontAwesomeIcon, { icon: faCircleInfo, className: "text-primary group-hover:text-blue-600" }), _jsx("span", { className: "opacity-0 group-hover:opacity-100 bg-gray-800 text-white text-sm rounded-md px-2 py-1 absolute top-[-14px]", children: toolTipText })] }))] })), _jsxs("div", { className: " input-wrapper relative", children: [renderIcons(), _jsx("input", { autoComplete: "",
59
+ // {...registerProps}
60
+ className: `rounded-md focused:ring-0 ${focusRingColor} focus:ring-1
61
+ focus:outline-none
62
+ ${disabled
63
+ ? "border-gray-500 focus:ring-gray-500"
64
+ : isValid
65
+ ? ""
66
+ : "border-redText focus:ring-red-500"} block w-full py-2 px-2
67
+ ${firstIcon ? "pl-10" : ""}
68
+ ${secondIcon ? "pr-10" : ""}
69
+ rounded-lg outline outline-0 outline-barelyPrimary focus:outline-4 md:w-full lg:w-full ${additionalClasses} ${isFocused ? "hover:border-transparent" : ""} ${isFocused && !disabled
70
+ ? ` ${isValid ? "" : "shadow-redText"}`
71
+ : disabled}`, autoFocus: hasAutoFocus, placeholder: placeholder, type: type, id: id, value: formattedValue, name: name, onChange: onChange, checked: type === "checkbox" ? checked : undefined, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), disabled: disabled, required: required && !hasValue, onKeyDown: onKeyDown }), iconPosition === "after" && renderSecondIcon()] })] }));
72
+ });
73
+ export default InputField;
@@ -1,12 +1,11 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Input } from ".";
3
3
  import Text from "../Text/Text";
4
4
  import { minCharactersRegex } from "../../utils/inputValidation";
5
5
  import { withMemo } from "../../userHoc";
6
- import { arePropsEqual } from "./InputMemoTypes";
7
6
  import BaseButton from "../BaseButton/BaseButton";
8
7
  import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
9
- const MemoizedInput = withMemo(Input, arePropsEqual);
8
+ const MemoizedInput = withMemo(Input);
10
9
  export default {
11
10
  title: "Components/Input",
12
11
  component: MemoizedInput,
@@ -176,7 +175,7 @@ export default {
176
175
  layout: "centered",
177
176
  },
178
177
  };
179
- const Template = (args) => _jsx(MemoizedInput, { ...args });
178
+ const Template = (args) => _jsx(_Fragment, {});
180
179
  export const NoIcons = Template.bind({});
181
180
  NoIcons.args = {
182
181
  inputType: "search",
@@ -1,45 +1,77 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
1
  import "../../../dist/main.css";
3
- import { render, screen } from "@testing-library/react";
4
- import { describe, test, expect, beforeEach } from "vitest";
5
- import Input from "./Input";
6
- import Text from "../Text/Text";
7
- import BaseButton from "../BaseButton/BaseButton";
8
- import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
2
+ import { describe } from "vitest";
9
3
  describe("<Input /> with all props", () => {
10
- beforeEach(() => {
11
- render(_jsx(Input, { hasValidation: false,
12
- // LABEL
13
- label: _jsx(Text, { size: "text-md", color: "text-black", fontFamily: "font-serif", text: "Search for items", tag: "h2", additionalClasses: "mb-0 pb-2 pl-2" }), labelVisible: true, labelPlacement: "left",
14
- // INPUT DETAILS
15
- inputName: "search", inputType: "text",
16
- // PLACEHOLDER
17
- hasPlaceholder: true, placeholder: "Search for items",
18
- // ICONS
19
- hasLeftIcon: false, hasRightIcon: false, iconColor: "black",
20
- // INPUT STYLES
21
- inputTextSize: "medium", inputShape: "cornered", borderColor: "green", backgroundColor: "none", inputWidth: "w-96",
22
- // BUTTON
23
- hasButton: true, button: _jsx(BaseButton, { text: "Submit", as: "button", hoverBackground: "green", backgroundColor: "green", icon: getFontAwesomeIcon("arrow-right"), additionalClasses: "items-center px-4", borderColor: "green", hoverFontColor: "black", shape: "cornered" }) }));
24
- });
25
- test("renders Input component", () => {
26
- expect(screen.getByTestId("input-container")).toBeInTheDocument();
27
- expect(screen.getByTestId("input-element")).toBeInTheDocument();
28
- });
29
- test("renders correct Input label", () => {
30
- expect(screen.getByTestId("input-label")).toBeInTheDocument();
31
- expect(screen.getByTestId("input-label")).toHaveTextContent("Search for items");
32
- });
33
- test("renders correct button", () => {
34
- expect(screen.getByTestId("submit-button")).toBeInTheDocument();
35
- expect(screen.getByTestId("submit-button")).toHaveTextContent("Submit");
36
- });
37
- test("contains correct placeholder text", () => {
38
- const input = screen.getByTestId("input-element");
39
- expect(input).toHaveAttribute("placeholder", "Search for items");
40
- });
41
- test("renders correct border color class", () => {
42
- const inputElement = screen.getByTestId("input-element");
43
- expect(inputElement).toHaveClass("border-teal-500");
44
- });
4
+ // beforeEach(() => {
5
+ // render(
6
+ // <Input
7
+ // hasValidation={false}
8
+ // // LABEL
9
+ // label={
10
+ // <Text
11
+ // size="text-md"
12
+ // color="text-black"
13
+ // fontFamily="font-serif"
14
+ // text="Search for items"
15
+ // tag="h2"
16
+ // additionalClasses="mb-0 pb-2 pl-2"
17
+ // />
18
+ // }
19
+ // labelVisible={true}
20
+ // labelPlacement="left"
21
+ // // INPUT DETAILS
22
+ // inputName="search"
23
+ // inputType="text"
24
+ // // PLACEHOLDER
25
+ // hasPlaceholder={true}
26
+ // placeholder="Search for items"
27
+ // // ICONS
28
+ // hasLeftIcon={false}
29
+ // hasRightIcon={false}
30
+ // iconColor="black"
31
+ // // INPUT STYLES
32
+ // inputTextSize="medium"
33
+ // inputShape="cornered"
34
+ // borderColor="green"
35
+ // backgroundColor="none"
36
+ // inputWidth="w-96"
37
+ // // BUTTON
38
+ // hasButton={true}
39
+ // button={
40
+ // <BaseButton
41
+ // text="Submit"
42
+ // as="button"
43
+ // hoverBackground="green"
44
+ // backgroundColor="green"
45
+ // icon={getFontAwesomeIcon("arrow-right")}
46
+ // additionalClasses="items-center px-4"
47
+ // borderColor="green"
48
+ // hoverFontColor="black"
49
+ // shape="cornered"
50
+ // />
51
+ // }
52
+ // />
53
+ // );
54
+ // });
55
+ // test("renders Input component", () => {
56
+ // expect(screen.getByTestId("input-container")).toBeInTheDocument();
57
+ // expect(screen.getByTestId("input-element")).toBeInTheDocument();
58
+ // });
59
+ // test("renders correct Input label", () => {
60
+ // expect(screen.getByTestId("input-label")).toBeInTheDocument();
61
+ // expect(screen.getByTestId("input-label")).toHaveTextContent(
62
+ // "Search for items"
63
+ // );
64
+ // });
65
+ // test("renders correct button", () => {
66
+ // expect(screen.getByTestId("submit-button")).toBeInTheDocument();
67
+ // expect(screen.getByTestId("submit-button")).toHaveTextContent("Submit");
68
+ // });
69
+ // test("contains correct placeholder text", () => {
70
+ // const input = screen.getByTestId("input-element");
71
+ // expect(input).toHaveAttribute("placeholder", "Search for items");
72
+ // });
73
+ // test("renders correct border color class", () => {
74
+ // const inputElement = screen.getByTestId("input-element");
75
+ // expect(inputElement).toHaveClass("border-teal-500");
76
+ // });
45
77
  });
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import { ColumnInstance } from "react-table";
3
+ /** A single search criterion used by InputAndCheck. */
4
+ export type SearchCriterion<T extends object> = {
5
+ searchColumn: ColumnInstance<T>;
6
+ submittedSearchText: string;
7
+ };
8
+ /** The props needed by <InputAndCheck>. */
9
+ export type InputAndCheckProps<T extends object> = {
10
+ closeOutSearch: (value: number | null) => void;
11
+ setResetSearch: React.Dispatch<React.SetStateAction<boolean>>;
12
+ setEditingHeader: (value: number | null) => void;
13
+ /** The column we’re editing/searching on. */
14
+ column: ColumnInstance<T>;
15
+ /** The search criteria state we manage. */
16
+ searchCriteria: SearchCriterion<T>[];
17
+ setSearchCriteria: React.Dispatch<React.SetStateAction<SearchCriterion<T>[]>>;
18
+ /** Optional styling or icons. */
19
+ badgeColor?: string;
20
+ badgeIcon?: {
21
+ icon: string;
22
+ weight: string;
23
+ };
24
+ iconBadgeContainerClasses?: string;
25
+ searchIcon?: {
26
+ icon: string;
27
+ weight: string;
28
+ };
29
+ cancelIcon?: {
30
+ icon: string;
31
+ weight: string;
32
+ };
33
+ initialIcon?: {
34
+ icon: string;
35
+ weight: string;
36
+ };
37
+ initialIconClasses?: string;
38
+ searchIconClasses?: string;
39
+ additionalInputClasses?: string;
40
+ secondIconClasses?: string;
41
+ };
42
+ /**
43
+ * Renders an input field for column-based searching,
44
+ * maintaining local text and updating searchCriteria on submit.
45
+ */
46
+ declare function InputAndCheck<T extends object>({ closeOutSearch, setResetSearch, setEditingHeader, column, searchCriteria, setSearchCriteria, badgeColor, badgeIcon, cancelIcon, iconBadgeContainerClasses, searchIcon, searchIconClasses, additionalInputClasses, secondIconClasses, initialIcon, initialIconClasses, }: InputAndCheckProps<T>): import("react/jsx-runtime").JSX.Element;
47
+ export default InputAndCheck;