@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
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render, screen } from "@testing-library/react";
3
+ import TableCell from "./TableCell";
4
+ import { describe, expect, it } from "vitest";
5
+ // Sample data for testing
6
+ const sampleData = {
7
+ uuid: "12345",
8
+ name: "John Doe",
9
+ age: 30,
10
+ address: "123 Main St, Springfield, IL, 62701, United States of America",
11
+ };
12
+ const defaultProps = {
13
+ globalTrimActive: true,
14
+ rowUuid: sampleData.uuid,
15
+ columnInputs: [],
16
+ cell: {
17
+ value: sampleData.address,
18
+ render: (type) => (type === "Cell" ? sampleData.address : null),
19
+ getCellProps: () => ({ key: "cell-1" }),
20
+ column: {
21
+ id: "address",
22
+ Header: "Address",
23
+ width: 200,
24
+ minWidth: 100,
25
+ maxWidth: 300,
26
+ isVisible: true,
27
+ parent: undefined,
28
+ columns: [],
29
+ getHeaderProps: () => ({ key: "header-1" }),
30
+ toggleHidden: () => { },
31
+ render: () => null,
32
+ totalLeft: 0,
33
+ totalWidth: 0,
34
+ getFooterProps: function (propGetter) {
35
+ throw new Error("Function not implemented.");
36
+ },
37
+ getToggleHiddenProps: function (userProps) {
38
+ throw new Error("Function not implemented.");
39
+ },
40
+ depth: 0,
41
+ },
42
+ row: {
43
+ original: sampleData,
44
+ index: 0,
45
+ values: { ...sampleData },
46
+ cells: [],
47
+ allCells: [],
48
+ getRowProps: () => ({ key: "row-1" }),
49
+ id: "row-1",
50
+ subRows: [],
51
+ },
52
+ },
53
+ isLastCell: false,
54
+ };
55
+ describe("TableCell Component", () => {
56
+ it("trims the text when globalTrimActive is true", () => {
57
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx("tr", { children: _jsx(TableCell, { ...defaultProps }) }) }) }));
58
+ const trimmedText = `${sampleData.address.substring(0, 30)}...`;
59
+ expect(screen.getByText(trimmedText)).toBeInTheDocument();
60
+ });
61
+ it("does not trim the text when globalTrimActive is false", () => {
62
+ const props = { ...defaultProps, globalTrimActive: false };
63
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx("tr", { children: _jsx(TableCell, { ...props }) }) }) }));
64
+ expect(screen.getByText(sampleData.address)).toBeInTheDocument();
65
+ });
66
+ it("applies different styles when isLastCell is true", () => {
67
+ const props = { ...defaultProps, isLastCell: true };
68
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx("tr", { children: _jsx(TableCell, { ...props }) }) }) }));
69
+ const cell = screen.getByRole("cell");
70
+ expect(cell).not.toHaveClass("relative overflow-hidden font-light text-sm text-left z-0 px-5");
71
+ });
72
+ it("renders without errors when cell value is not a string", () => {
73
+ const numericValueProps = {
74
+ ...defaultProps,
75
+ cell: {
76
+ ...defaultProps.cell,
77
+ value: 42,
78
+ render: (type) => (type === "Cell" ? "42" : null),
79
+ },
80
+ };
81
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx("tr", { children: _jsx(TableCell, { ...numericValueProps }) }) }) }));
82
+ expect(screen.getByText("42")).toBeInTheDocument();
83
+ });
84
+ });
@@ -0,0 +1,2 @@
1
+ export { default } from "./TableCell";
2
+ export * from "./types";
@@ -0,0 +1,2 @@
1
+ export { default } from "./TableCell";
2
+ export * from "./types";
@@ -0,0 +1,12 @@
1
+ import { Cell } from "react-table";
2
+ export interface DataWithUUID {
3
+ uuid?: string;
4
+ }
5
+ export interface TableCellProps<T extends object> {
6
+ globalTrimActive: boolean;
7
+ rowUuid?: string;
8
+ columnInputs?: string[];
9
+ rowHoverClasses?: string;
10
+ cell: Cell<T>;
11
+ isLastCell: boolean;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { TableHeaderContentProps } from "./types";
2
+ declare const TableHeaderContent: <T extends object>({ column, contentClassNames, }: TableHeaderContentProps<T>) => JSX.Element;
3
+ export default TableHeaderContent;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const TableHeaderContent = ({ column, contentClassNames = `flex items-center justify-center text-sm`, }) => {
3
+ return _jsx("div", { className: contentClassNames, children: column.render("Header") });
4
+ };
5
+ export default TableHeaderContent;
@@ -0,0 +1,6 @@
1
+ import { Meta } from "@storybook/react";
2
+ declare const _default: Meta;
3
+ export default _default;
4
+ export declare const Default: any;
5
+ export declare const ComponentHeader: any;
6
+ export declare const MultipleHeaders: any;
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { useTable } from "react-table";
4
+ import TableHeaderContent from "./TableHeaderContent";
5
+ export default {
6
+ title: "Table/TableHeaderContent",
7
+ component: TableHeaderContent,
8
+ parameters: {
9
+ layout: "centered",
10
+ controls: { hideNoControlsWarning: true },
11
+ },
12
+ };
13
+ // Basic template with configurable columns
14
+ const Template = (args) => {
15
+ const { columns } = args;
16
+ const data = useMemo(() => [], []);
17
+ const { headers } = useTable({
18
+ columns,
19
+ data,
20
+ });
21
+ return (_jsx("div", { className: "p-4 bg-gray-50 rounded-lg", children: headers.map((header, index) => (_jsx(TableHeaderContent, { column: header }, index))) }));
22
+ };
23
+ // Story demonstrating default behavior
24
+ export const Default = Template.bind({});
25
+ Default.args = {
26
+ columns: [
27
+ {
28
+ Header: "Basic Header",
29
+ accessor: "basic",
30
+ },
31
+ ],
32
+ };
33
+ // Story with component-based header
34
+ export const ComponentHeader = Template.bind({});
35
+ ComponentHeader.args = {
36
+ columns: [
37
+ {
38
+ Header: () => (_jsx("span", { className: "text-red-500", children: "\uD83D\uDD25 Custom Component" })),
39
+ accessor: "component",
40
+ },
41
+ ],
42
+ };
43
+ // Story demonstrating multiple headers
44
+ export const MultipleHeaders = Template.bind({});
45
+ MultipleHeaders.args = {
46
+ columns: [
47
+ {
48
+ Header: "First Column",
49
+ accessor: "first",
50
+ headerClassName: "bg-green-100",
51
+ },
52
+ {
53
+ Header: "Second Column",
54
+ accessor: "second",
55
+ headerClassName: "bg-purple-100",
56
+ },
57
+ {
58
+ Header: () => _jsx("div", { className: "text-yellow-600", children: "Custom Header" }),
59
+ accessor: "third",
60
+ },
61
+ ],
62
+ };
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render, screen } from "@testing-library/react";
3
+ import TableHeaderContent from "./TableHeaderContent";
4
+ import { describe, expect, test, vi } from "vitest";
5
+ describe("TableHeaderContent", () => {
6
+ test("renders header string correctly", () => {
7
+ const headerText = "Test Header";
8
+ const mockColumn = {
9
+ render: vi.fn((key) => key === "Header" ? headerText : null),
10
+ };
11
+ render(_jsx(TableHeaderContent, { column: mockColumn }));
12
+ expect(mockColumn.render).toHaveBeenCalledWith("Header");
13
+ expect(screen.getByText(headerText)).toBeInTheDocument();
14
+ });
15
+ test("renders header component correctly", () => {
16
+ const headerText = "Component Header";
17
+ const mockColumn = {
18
+ render: vi.fn((key) => key === "Header" ? _jsx("span", { children: headerText }) : null),
19
+ };
20
+ render(_jsx(TableHeaderContent, { column: mockColumn }));
21
+ expect(screen.getByText(headerText)).toBeInTheDocument();
22
+ expect(screen.getByText(headerText).tagName).toBe("SPAN");
23
+ });
24
+ test("applies default contentClassNames when none provided", () => {
25
+ const mockColumn = {
26
+ render: vi.fn(() => "Header"),
27
+ };
28
+ const { container } = render(_jsx(TableHeaderContent, { column: mockColumn }));
29
+ const div = container.firstChild;
30
+ expect(div).toHaveClass("flex", "items-center", "justify-center", "text-sm");
31
+ });
32
+ test("applies custom contentClassNames when provided", () => {
33
+ const customClass = "custom-class";
34
+ const mockColumn = {
35
+ render: vi.fn(() => "Header"),
36
+ };
37
+ const { container } = render(_jsx(TableHeaderContent, { column: mockColumn, contentClassNames: customClass }));
38
+ const div = container.firstChild;
39
+ expect(div).toHaveClass(customClass);
40
+ });
41
+ });
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ import { ColumnInstance } from "react-table";
2
+ export interface TableHeaderContentProps<T extends object> {
3
+ column: ColumnInstance<T>;
4
+ contentClassNames?: string;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { TableHeaderInputProps } from "./types";
2
+ declare const TableHeaderInput: import("react").ForwardRefExoticComponent<TableHeaderInputProps & import("react").RefAttributes<HTMLInputElement>>;
3
+ export default TableHeaderInput;
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, forwardRef } from "react";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
5
+ const TableHeaderInput = 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, register, }, ref) => {
6
+ const [isFocused, setIsFocused] = useState(false);
7
+ // Check if input value has at least one non-space character
8
+ const hasValue = value != null && !!value.toString().trim();
9
+ const isNumberInput = type === "number";
10
+ let formattedValue = isNumberInput &&
11
+ value != null &&
12
+ value.toString().trim() &&
13
+ isNaN(Number(value))
14
+ ? ""
15
+ : value;
16
+ if (formattedValue === "$NaN") {
17
+ formattedValue = "";
18
+ }
19
+ const renderFirstIcon = () => {
20
+ if (!firstIcon)
21
+ return null;
22
+ return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--first-icon absolute top-[10px] left-4 ${disabled
23
+ ? "text-gray-500"
24
+ : isValid
25
+ ? `text-${iconColor}`
26
+ : "text-redText"}`, children: firstIcon }));
27
+ };
28
+ const renderSecondIcon = () => {
29
+ if (!secondIcon)
30
+ return null;
31
+ return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--second-icon absolute top-2 right-4 ${disabled
32
+ ? "text-gray-500"
33
+ : isValid
34
+ ? `text-${iconColor}`
35
+ : "text-redText"}`, children: secondIcon }));
36
+ };
37
+ const renderIcons = () => {
38
+ switch (iconPosition) {
39
+ case "before":
40
+ return renderFirstIcon();
41
+ case "after":
42
+ return renderSecondIcon();
43
+ case "both":
44
+ return (_jsxs(_Fragment, { children: [renderFirstIcon(), renderSecondIcon()] }));
45
+ default:
46
+ return null;
47
+ }
48
+ };
49
+ // This brings in the name and 'required' from react-hook-form if provided
50
+ const registerProps = register
51
+ ? register(name || "", { required })
52
+ : {};
53
+ // If readOnly, render a div (or label, etc.)
54
+ if (isReadOnly) {
55
+ return (_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: `
56
+ border text-left focus:outline-none focus:ring-2 block w-full py-2 px-2 rounded-lg shadow-input
57
+ ${firstIcon ? "pl-10" : ""}
58
+ ${secondIcon ? "pr-10" : ""}
59
+ ${additionalClasses}
60
+ `, children: readOnlyInfo }), iconPosition === "after" && renderSecondIcon()] }));
61
+ }
62
+ // Normal editable input
63
+ return (_jsxs("div", { 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: "off", ...registerProps, ref: ref, className: `
64
+ rounded-md focused:ring-0 focus:ring-navy-500 text-navy-500 border focus:outline-none focus:ring-2
65
+ ${disabled
66
+ ? "border-gray-500 focus:ring-gray-500"
67
+ : isValid
68
+ ? "focus:ring-navy-200"
69
+ : "border-redText focus:ring-red-500"}
70
+ block w-full py-2 px-2
71
+ ${firstIcon ? "pl-10" : ""}
72
+ ${secondIcon ? "pr-10" : ""}
73
+ rounded-lg outline outline-0 outline-barelyPrimary focus:outline-4
74
+ ${additionalClasses}
75
+ ${isFocused && !disabled ? (isValid ? "" : "shadow-redText") : ""}
76
+ focus:ring-navy-200 focus:ring-2
77
+ `, 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()] })] }));
78
+ });
79
+ TableHeaderInput.displayName = "InputField";
80
+ export default TableHeaderInput;
@@ -0,0 +1,10 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import TableHeaderInput from "./TableHeaderInput";
3
+ declare const meta: Meta<typeof TableHeaderInput>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TableHeaderInput>;
6
+ export declare const BasicWithLabel: Story;
7
+ export declare const NoLabelWithIcon: Story;
8
+ export declare const IconOnRight: Story;
9
+ export declare const IconOnBothSides: Story;
10
+ export declare const ReadOnlyExample: Story;
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useForm } from "react-hook-form";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import TableHeaderInput from "./TableHeaderInput";
5
+ import { faSearch } from "@fortawesome/free-solid-svg-icons";
6
+ const meta = {
7
+ title: "Table/TableHeaderInput",
8
+ component: TableHeaderInput,
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: `
13
+ **TableHeaderInput** is a lightweight input component for use in table headers or other compact UI areas,
14
+ optionally with an icon and label. This component supports \`react-hook-form\` via the \`register\` prop.
15
+ `,
16
+ },
17
+ },
18
+ },
19
+ argTypes: {
20
+ label: {
21
+ description: "Optional text label displayed above the input.",
22
+ },
23
+ placeholder: {
24
+ description: "Text displayed when the input is empty.",
25
+ },
26
+ required: {
27
+ description: "Marks the input as required.",
28
+ },
29
+ type: {
30
+ description: "Specifies the input type (text, checkbox, email, etc.).",
31
+ },
32
+ name: {
33
+ description: "Name of the field, which also wires into `react-hook-form` when `register` is passed.",
34
+ },
35
+ firstIcon: {
36
+ description: "An icon to display on the left side of the input.",
37
+ },
38
+ secondIcon: {
39
+ description: "An icon to display on the right side of the input.",
40
+ },
41
+ register: {
42
+ description: "Pass in the `register` function from `react-hook-form`.",
43
+ },
44
+ onChange: {
45
+ description: "Change event handler for the input.",
46
+ },
47
+ },
48
+ tags: ["autodocs"],
49
+ };
50
+ export default meta;
51
+ export const BasicWithLabel = {
52
+ name: "Basic with Label",
53
+ render: () => {
54
+ const { register } = useForm();
55
+ return (_jsx("div", { style: { width: 300 }, children: _jsx(TableHeaderInput, { label: "First Name", placeholder: "Enter your name", type: "text", required: true, register: register, name: "firstName" }) }));
56
+ },
57
+ };
58
+ export const NoLabelWithIcon = {
59
+ name: "No Label, Left Icon",
60
+ render: () => {
61
+ const { register } = useForm();
62
+ return (_jsx("div", { style: { width: 300 }, children: _jsx(TableHeaderInput, { placeholder: "Search", name: "search", register: register, type: "text", firstIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), required: false }) }));
63
+ },
64
+ };
65
+ export const IconOnRight = {
66
+ name: "Icon on Right",
67
+ render: () => {
68
+ const { register } = useForm();
69
+ return (_jsx("div", { style: { width: 300 }, children: _jsx(TableHeaderInput, { placeholder: "Search anything...", name: "searchRight", register: register, type: "text", secondIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), iconPosition: "both", required: false }) }));
70
+ },
71
+ };
72
+ export const IconOnBothSides = {
73
+ name: "Icon on Both Sides",
74
+ render: () => {
75
+ const { register } = useForm();
76
+ return (_jsx("div", { style: { width: 300 }, children: _jsx(TableHeaderInput, { placeholder: "Search anything...", name: "searchRight", register: register, type: "text", firstIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), secondIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), iconPosition: "both", required: false }) }));
77
+ },
78
+ };
79
+ export const ReadOnlyExample = {
80
+ name: "Read-Only Example",
81
+ render: () => (_jsx("div", { style: { width: 300 }, children: _jsx(TableHeaderInput, { label: "Read Only Field", type: "text", isReadOnly: true, readOnlyInfo: "This is read-only text.", required: false }) })),
82
+ };
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, it, expect, vi } from "vitest";
3
+ import { render, screen, fireEvent } from "@testing-library/react";
4
+ import TableHeaderInput from "./TableHeaderInput";
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
+ import { faSearch } from "@fortawesome/free-solid-svg-icons";
7
+ describe("TableHeaderInput", () => {
8
+ it("renders label and placeholder in normal mode", () => {
9
+ render(_jsx(TableHeaderInput, { label: "First Name", placeholder: "Enter your name", name: "firstName", required: false, type: "number" }));
10
+ expect(screen.getByText("First Name")).toBeInTheDocument();
11
+ expect(screen.getByPlaceholderText("Enter your name")).toBeInTheDocument();
12
+ });
13
+ it("renders secondIcon when iconPosition is 'after'", () => {
14
+ const { container } = render(_jsx(TableHeaderInput, { placeholder: "Search", iconPosition: "after", secondIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), required: false, type: "number" }));
15
+ const secondIconSpan = container.querySelector(".input-icon--second-icon");
16
+ expect(secondIconSpan).toBeInTheDocument();
17
+ });
18
+ it("does not render an input when isReadOnly is true", () => {
19
+ render(_jsx(TableHeaderInput, { label: "Read Only", isReadOnly: true, readOnlyInfo: "This is read-only text", required: false, type: "number" }));
20
+ expect(screen.getByText("Read Only")).toBeInTheDocument();
21
+ expect(screen.getByText("This is read-only text")).toBeInTheDocument();
22
+ const input = screen.queryByRole("textbox");
23
+ expect(input).toBeNull();
24
+ });
25
+ it("renders firstIcon when iconPosition is 'before'", () => {
26
+ render(_jsx(TableHeaderInput, { placeholder: "Search", iconPosition: "before", firstIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), required: false, type: "number" }));
27
+ const icons = screen.getAllByRole("img", { hidden: true });
28
+ expect(icons).toHaveLength(1);
29
+ });
30
+ it("renders both icons when iconPosition is 'both'", () => {
31
+ render(_jsx(TableHeaderInput, { placeholder: "Search", iconPosition: "both", firstIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), secondIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), required: false, type: "number" }));
32
+ const icons = screen.getAllByRole("img", { hidden: true });
33
+ expect(icons).toHaveLength(2);
34
+ });
35
+ it("calls onIconClick when the icon is clicked", () => {
36
+ const handleIconClick = vi.fn();
37
+ render(_jsx(TableHeaderInput, { iconPosition: "before", firstIcon: _jsx(FontAwesomeIcon, { icon: faSearch }), onIconClick: handleIconClick, required: false, type: "number" }));
38
+ const iconEl = screen.getAllByRole("img", { hidden: true })[0];
39
+ fireEvent.click(iconEl);
40
+ expect(handleIconClick).toHaveBeenCalledTimes(1);
41
+ });
42
+ it("calls onChange when typing in the input", () => {
43
+ const handleChange = vi.fn();
44
+ render(_jsx(TableHeaderInput, { placeholder: "Type here", onChange: handleChange, name: "testName", type: "text", required: false }));
45
+ const inputEl = screen.getByPlaceholderText("Type here");
46
+ fireEvent.change(inputEl, { target: { value: "Hello" } });
47
+ expect(handleChange).toHaveBeenCalledTimes(1);
48
+ });
49
+ it("calls onKeyDown when a key is pressed", () => {
50
+ const handleKeyDown = vi.fn();
51
+ render(_jsx(TableHeaderInput, { placeholder: "Key test", onKeyDown: handleKeyDown, required: false, type: "number" }));
52
+ const inputEl = screen.getByPlaceholderText("Key test");
53
+ fireEvent.keyDown(inputEl, { key: "Enter", code: "Enter" });
54
+ expect(handleKeyDown).toHaveBeenCalledTimes(1);
55
+ });
56
+ it("marks input as required if `required` and no value provided", () => {
57
+ render(_jsx(TableHeaderInput, { placeholder: "Required test", required: true, type: "number" }));
58
+ const inputEl = screen.getByPlaceholderText("Required test");
59
+ expect(inputEl).toHaveAttribute("required");
60
+ });
61
+ it("does not mark input as required if value is present", () => {
62
+ render(_jsx(TableHeaderInput, { placeholder: "Required test", required: true, value: "Has Value", type: "number" }));
63
+ const inputEl = screen.getByPlaceholderText("Required test");
64
+ expect(inputEl).not.toHaveAttribute("required");
65
+ });
66
+ it("handles $NaN case for number input gracefully", () => {
67
+ render(_jsx(TableHeaderInput, { placeholder: "Number test", type: "number", value: "$NaN", required: false }));
68
+ const inputEl = screen.getByPlaceholderText("Number test");
69
+ expect(inputEl.value).toBe("");
70
+ });
71
+ it("applies invalid border classes when isValid is false", () => {
72
+ render(_jsx(TableHeaderInput, { placeholder: "Invalid test", isValid: false, required: false, type: "number" }));
73
+ const inputEl = screen.getByPlaceholderText("Invalid test");
74
+ expect(inputEl.className).toContain("border-redText");
75
+ expect(inputEl.className).toContain("focus:ring-red-500");
76
+ });
77
+ it("applies disabled classes when disabled is true", () => {
78
+ render(_jsx(TableHeaderInput, { placeholder: "Disabled test", disabled: true, required: false, type: "number" }));
79
+ const inputEl = screen.getByPlaceholderText("Disabled test");
80
+ expect(inputEl).toBeDisabled();
81
+ expect(inputEl.className).toContain("border-gray-500");
82
+ expect(inputEl.className).toContain("focus:ring-gray-500");
83
+ });
84
+ });
@@ -0,0 +1 @@
1
+ export { default } from "./TableHeaderInput";
@@ -0,0 +1 @@
1
+ export { default } from "./TableHeaderInput";
@@ -0,0 +1,30 @@
1
+ import { KeyboardEvent, ChangeEvent, ReactNode } from "react";
2
+ import { UseFormRegister } from "react-hook-form";
3
+ export interface TableHeaderInputProps {
4
+ label?: string;
5
+ value?: string | number;
6
+ readOnlyInfo?: string | JSX.Element;
7
+ iconColor?: string;
8
+ placeholder?: string;
9
+ iconPosition?: "before" | "after" | "both";
10
+ required: boolean;
11
+ firstIcon?: ReactNode | null;
12
+ secondIcon?: ReactNode | null;
13
+ hasToolTip?: boolean;
14
+ toolTipText?: string;
15
+ onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
16
+ onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
17
+ checked?: boolean extends TableHeaderInputProps["type"] ? boolean : undefined;
18
+ id?: string;
19
+ name?: string;
20
+ additionalClasses?: string;
21
+ onIconClick?: () => void;
22
+ type: "text" | "checkbox" | "radio" | "number" | "email" | "password" | "file" | "color" | "tel" | "url" | "range";
23
+ isValid?: boolean;
24
+ isReadOnly?: boolean;
25
+ hasIcons?: boolean;
26
+ labelClasses?: string;
27
+ disabled?: boolean;
28
+ hasAutoFocus?: boolean;
29
+ register?: UseFormRegister<any>;
30
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { DataWithUUID } from "../TableCell";
2
+ import TableRowProps from ".";
3
+ interface TableRowProps {
4
+ row: any;
5
+ prepareRow: (row: any) => void;
6
+ activeIndex?: number;
7
+ activeRowColor?: string;
8
+ globalTrimActive?: boolean;
9
+ rowUuid?: string;
10
+ columnInputs?: string[];
11
+ rowHoverClasses?: string;
12
+ onRowClick?: (index: number, rowUuid: string, event: React.MouseEvent) => void;
13
+ }
14
+ declare const TableRow: <T extends DataWithUUID>({ row, prepareRow, activeIndex, globalTrimActive, rowUuid, columnInputs, activeRowColor, rowHoverClasses, onRowClick, }: TableRowProps) => import("react/jsx-runtime").JSX.Element;
15
+ export default TableRow;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ import TableCell from "../TableCell";
4
+ const TableRow = ({ row, prepareRow, activeIndex, globalTrimActive, rowUuid, columnInputs, activeRowColor = "bg-pink-100", rowHoverClasses = "hover:bg-red-100 hover:cursor-pointer", onRowClick, }) => {
5
+ prepareRow(row);
6
+ const isActive = activeIndex === row.index;
7
+ let rowClasses = `border-primary`;
8
+ if (isActive) {
9
+ rowClasses += ` activeRow ${activeRowColor}`;
10
+ }
11
+ return (_jsx("tr", { "data-testid": "table-row", className: `border-b border-b-navy-200 ${rowHoverClasses} ${rowClasses}`, ...(row.getRowProps ? row.getRowProps() : {}), onClick: (event) => {
12
+ if (onRowClick) {
13
+ onRowClick(row.index, rowUuid || "", event);
14
+ }
15
+ }, children: row.cells.map((cell, index) => {
16
+ const isLastCell = index === row.cells.length - 1;
17
+ const cellProps = cell.getCellProps();
18
+ return (_jsx(Fragment, { children: _jsx(TableCell, { cell: cell, rowUuid: rowUuid, globalTrimActive: globalTrimActive, columnInputs: columnInputs, isLastCell: isLastCell }) }, cellProps.key));
19
+ }) }, rowUuid));
20
+ };
21
+ export default TableRow;
@@ -0,0 +1,9 @@
1
+ import { Meta } from "@storybook/react";
2
+ import TableRow from "./TableRow";
3
+ declare const meta: Meta<typeof TableRow>;
4
+ export default meta;
5
+ export declare const Default: any;
6
+ export declare const ActiveRow: any;
7
+ export declare const WithRowClickHandler: any;
8
+ export declare const NoTrimming: any;
9
+ export declare const CustomCellRendering: any;