@agilant/toga-blox 1.0.134 → 1.0.135
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.
- package/dist/components/BaseInput/BaseToggle.js +1 -1
- package/dist/components/Input/Input.d.ts +1 -0
- package/dist/components/Input/Input.js +15 -14
- package/dist/components/SearchInput/SearchInput.d.ts +1 -1
- package/dist/components/SearchInput/SearchInput.js +3 -3
- package/dist/components/SearchInput/SearchInput.stories.js +1 -3
- package/dist/components/SearchInput/SearchInput.types.d.ts +3 -0
- package/dist/components/SearchInput/SearchInputDatePicker.d.ts +4 -1
- package/dist/components/SearchInput/SearchInputDatePicker.js +69 -55
- package/dist/components/SearchInput/SearchNumberInput.d.ts +4 -1
- package/dist/components/SearchInput/SearchNumberInput.js +3 -3
- package/dist/components/SearchInput/SearchTextInput.js +1 -1
- package/dist/components/TableRow/TableRow.d.ts +3 -1
- package/dist/components/TableRow/TableRow.js +18 -10
- package/dist/components/TableRow/TableRow.stories.d.ts +10 -4
- package/dist/components/TableRow/TableRow.stories.js +115 -112
- package/dist/components/ToggleButton/ToggleButton.js +33 -22
- package/dist/components/ToggleButton/ToggleButton.test.js +5 -5
- package/dist/components/ToggleButton/ToggleButton.types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -3,6 +3,6 @@ import { Controller } from "react-hook-form";
|
|
|
3
3
|
import ToggleButton from "../ToggleButton/ToggleButton";
|
|
4
4
|
const BaseToggle = (props) => {
|
|
5
5
|
const { control, valueKey, inputContainerClasses, defaultValue, toggleTextPosition = "right", toggleTextSize = "sm", toggleActiveColorBackground = "bg-blue-600", toggleInactiveColorBackground = "bg-blue-300", toggleActiveColorBorder = "border-blue-500", toggleInactiveColorBorder = "border-blue-300", toggleActiveTextColor = "text-blue-800", toggleInactiveTextColor = "text-blue-600", toggleAdditionalClasses = `w-1/4`, toggleHasDivider = false, toggleFontFamily = "font-omnes-regular", toggleActiveLabel = "Yes", toggleInactiveLabel = "No", toggleSmallToggle = true, toggleBorderStyle = true, } = props;
|
|
6
|
-
return (_jsx("div", { className: `${inputContainerClasses}`, children: _jsx(Controller, { control: control, name: valueKey, defaultValue: defaultValue, render: ({ field: { value, onChange } }) => (_jsx(ToggleButton, { initialStatus: Boolean(value), onClick: () => onChange(!value), textPosition: toggleTextPosition, textSize: toggleTextSize, activeColorBackground: toggleActiveColorBackground, inactiveColorBackground: toggleInactiveColorBackground, activeColorBorder: toggleActiveColorBorder, inactiveColorBorder: toggleInactiveColorBorder, activeTextColor: toggleActiveTextColor, inactiveTextColor: toggleInactiveTextColor, additionalClasses: toggleAdditionalClasses, hasDivider: toggleHasDivider, fontFamily: toggleFontFamily, activeLabel: toggleActiveLabel, inactiveLabel: toggleInactiveLabel, id: valueKey, smallToggle: toggleSmallToggle, borderStyle: toggleBorderStyle })) }) }));
|
|
6
|
+
return (_jsx("div", { className: `${inputContainerClasses}`, children: _jsx(Controller, { control: control, name: valueKey, defaultValue: defaultValue, render: ({ field: { value, onChange } }) => (_jsx(ToggleButton, { initialStatus: Boolean(value), onClick: () => onChange(!value), textPosition: toggleTextPosition, textSize: toggleTextSize, activeColorBackground: toggleActiveColorBackground, inactiveColorBackground: toggleInactiveColorBackground, activeColorBorder: toggleActiveColorBorder, inactiveColorBorder: toggleInactiveColorBorder, activeTextColor: toggleActiveTextColor, inactiveTextColor: toggleInactiveTextColor, additionalClasses: toggleAdditionalClasses, hasDivider: toggleHasDivider, fontFamily: toggleFontFamily, activeLabel: toggleActiveLabel, inactiveLabel: toggleInactiveLabel, id: valueKey, smallToggle: toggleSmallToggle, borderStyle: toggleBorderStyle, activeCircleColor: "", inactiveCircleColor: "" })) }) }));
|
|
7
7
|
};
|
|
8
8
|
export default BaseToggle;
|
|
@@ -6,7 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
|
6
6
|
* A properly formed forwardRef component: exactly two parameters:
|
|
7
7
|
* (props, ref). We pass `ref` to the <input ref={ref} ...>.
|
|
8
8
|
*/
|
|
9
|
-
const InputField = forwardRef(function InputField({ label, placeholder, required, 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, focusRingColor = "focus:ring-transparent", firstIconClasses, firstIconTop = "top-[8px]", }, ref) {
|
|
9
|
+
const InputField = forwardRef(function InputField({ label, placeholder, required, 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, focusRingColor = "focus:ring-transparent", firstIconClasses, firstIconTop = "top-[8px]", placeHolderColor = "placeholder:text-gray-500", }, ref) {
|
|
10
10
|
const [isFocused, setIsFocused] = useState(false);
|
|
11
11
|
const hasValue = value != null && !!value.toString().trim();
|
|
12
12
|
const isNumberInput = type === "number";
|
|
@@ -67,18 +67,19 @@ const InputField = forwardRef(function InputField({ label, placeholder, required
|
|
|
67
67
|
}
|
|
68
68
|
// Normal input mode
|
|
69
69
|
return (_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", { ref: ref, autoComplete: "", ...registerProps, className: `
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
70
|
+
${focusRingColor}
|
|
71
|
+
focus:ring-1
|
|
72
|
+
focus:outline-none
|
|
73
|
+
block w-full py-2 px-2
|
|
74
|
+
outline outline-0
|
|
75
|
+
md:w-full
|
|
76
|
+
${placeHolderColor}
|
|
77
|
+
${disabled ? "border-gray-500 focus:ring-gray-500" : ""}
|
|
78
|
+
${isValid ? "" : "border-redText focus:ring-red-500"}
|
|
79
|
+
${firstIcon ? "pl-10" : ""}
|
|
80
|
+
${secondIcon ? "pr-10" : ""}
|
|
81
|
+
${isFocused ? "" : ""}
|
|
82
|
+
${additionalClasses}
|
|
83
|
+
`, autoFocus: hasAutoFocus, placeholder: placeholder, type: type, id: id, value: formattedValue, name: name, checked: type === "checkbox" ? checked : undefined, onChange: onChange, onKeyDown: onKeyDown, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), disabled: disabled, required: required && !hasValue })] })] }));
|
|
83
84
|
});
|
|
84
85
|
export default InputField;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SearchInputProps } from "./SearchInput.types";
|
|
2
|
-
declare const SearchInput: <T extends object>({ textHighlight, inputType, dropdownIconProp, dropdownOptions, selectedDropdownOption, onDropdownOptionSelect, searchItems, setSearchItems, toggleStatus, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, onChange, selectedValue, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, handleFilter, column, setSearchCriteria, setEditingHeader, pillColor, firstIconClasses, dataPickerThemeColor, dataPickerThemeColorAccent, isBoolean, toggleColor, toggleTextColor, fontFamily, removePattern, isSearchable, hasOperator, tooltipText, hoverBgColor, clearTextHoverColor, numberTypeIcon, firstIconTop, }: SearchInputProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
declare const SearchInput: <T extends object>({ textHighlight, inputType, dropdownIconProp, dropdownOptions, selectedDropdownOption, onDropdownOptionSelect, searchItems, setSearchItems, toggleStatus, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, onChange, selectedValue, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, handleFilter, column, setSearchCriteria, setEditingHeader, pillColor, firstIconClasses, dataPickerThemeColor, dataPickerThemeColorAccent, isBoolean, toggleColor, toggleTextColor, fontFamily, removePattern, isSearchable, hasOperator, tooltipText, hoverBgColor, clearTextHoverColor, numberTypeIcon, firstIconTop, inactiveCircleColor, activeCircleColor, placeHolderColor, }: SearchInputProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export default SearchInput;
|
|
@@ -8,7 +8,7 @@ const SearchInput = ({ textHighlight = "text-sky-500", inputType = "text", dropd
|
|
|
8
8
|
name: "chevronDown",
|
|
9
9
|
weight: "bold",
|
|
10
10
|
iconClasses: "text-black",
|
|
11
|
-
}, dropdownOptions = [], selectedDropdownOption = "", onDropdownOptionSelect, searchItems = [], setSearchItems, toggleStatus = false, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, onChange, selectedValue, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, handleFilter, column, setSearchCriteria, setEditingHeader, pillColor, firstIconClasses, dataPickerThemeColor, dataPickerThemeColorAccent, isBoolean = false, toggleColor = "bg-sky-500", toggleTextColor = "text-black", fontFamily, removePattern = /^[^:]*:/, isSearchable = false, hasOperator = false, tooltipText = "Clear filters to edit operator", hoverBgColor, clearTextHoverColor, numberTypeIcon, firstIconTop, }) => {
|
|
11
|
+
}, dropdownOptions = [], selectedDropdownOption = "", onDropdownOptionSelect, searchItems = [], setSearchItems, toggleStatus = false, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, onChange, selectedValue, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, handleFilter, column, setSearchCriteria, setEditingHeader, pillColor, firstIconClasses, dataPickerThemeColor, dataPickerThemeColorAccent, isBoolean = false, toggleColor = "bg-sky-500", toggleTextColor = "text-black", fontFamily, removePattern = /^[^:]*:/, isSearchable = false, hasOperator = false, tooltipText = "Clear filters to edit operator", hoverBgColor, clearTextHoverColor, numberTypeIcon, firstIconTop, inactiveCircleColor, activeCircleColor, placeHolderColor, }) => {
|
|
12
12
|
const containerRef = useRef(null);
|
|
13
13
|
const inputRef = useRef(null);
|
|
14
14
|
useEffect(() => {
|
|
@@ -20,11 +20,11 @@ const SearchInput = ({ textHighlight = "text-sky-500", inputType = "text", dropd
|
|
|
20
20
|
case "text":
|
|
21
21
|
return (_jsx(SearchTextInput, { dropdownIconProp: dropdownIconProp, dropdownOptions: dropdownOptions, selectedDropdownOption: selectedDropdownOption, onDropdownOptionSelect: onDropdownOptionSelect, searchItems: searchItems, setSearchItems: setSearchItems, handleFilter: handleFilter, setSearchCriteria: setSearchCriteria, column: column, setEditingHeader: setEditingHeader, pillColor: pillColor, firstIconClasses: firstIconClasses, fontFamily: fontFamily, removePattern: removePattern, textHighlight: textHighlight, hasOperator: hasOperator, tooltipText: tooltipText }));
|
|
22
22
|
case "number":
|
|
23
|
-
return (_jsx(SearchNumberInput, { dropdownIconProp: dropdownIconProp, dropdownOptions: dropdownOptions, selectedDropdownOption: selectedDropdownOption, onDropdownOptionSelect: onDropdownOptionSelect, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, minValue: minValue, maxValue: maxValue, setMinValue: setMinValue, setMaxValue: setMaxValue, handleFilter: handleFilter, setSearchCriteria: setSearchCriteria, column: column, themeBgColor: dataPickerThemeColor, toggleColor: toggleColor, toggleTextColor: toggleTextColor, searchItems: searchItems, setSearchItems: setSearchItems, removePattern: removePattern, pillColor: pillColor, hasOperator: hasOperator, tooltipText: tooltipText, numberTypeIcon: numberTypeIcon, firstIconTop: firstIconTop }));
|
|
23
|
+
return (_jsx(SearchNumberInput, { dropdownIconProp: dropdownIconProp, dropdownOptions: dropdownOptions, selectedDropdownOption: selectedDropdownOption, onDropdownOptionSelect: onDropdownOptionSelect, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, minValue: minValue, maxValue: maxValue, setMinValue: setMinValue, setMaxValue: setMaxValue, handleFilter: handleFilter, setSearchCriteria: setSearchCriteria, column: column, themeBgColor: dataPickerThemeColor, toggleColor: toggleColor, toggleTextColor: toggleTextColor, searchItems: searchItems, setSearchItems: setSearchItems, removePattern: removePattern, pillColor: pillColor, hasOperator: hasOperator, tooltipText: tooltipText, numberTypeIcon: numberTypeIcon, firstIconTop: firstIconTop, inactiveCircleColor: inactiveCircleColor, activeCircleColor: activeCircleColor, placeHolderColor: placeHolderColor }));
|
|
24
24
|
case "multiSelect":
|
|
25
25
|
return (_jsx(SearchDropdownInput, { options: dropdownOptions, placeholder: "Search", additionalClasses: "", onChange: onChange, selectedValue: selectedValue, bgColor: dataPickerThemeColor, clearText: "Clear", clearTextColor: "text-sky-500", buttonText: "Filter", handleFilter: handleFilter, column: column, setSearchCriteria: setSearchCriteria, textHighlight: textHighlight, isBoolean: isBoolean, isSearchable: isSearchable, setSearchItems: setSearchItems, fontFamily: fontFamily, pillColor: pillColor, hoverBgColor: hoverBgColor, clearTextHoverColor: clearTextHoverColor }));
|
|
26
26
|
case "date":
|
|
27
|
-
return (_jsx(SearchDatePickerInput, { textHighlight: textHighlight, dropdownOptions: dropdownOptions, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, selectedDate: selectedDate, onDateSelect: onDateSelect, selectedStartDate: selectedStartDate, onStartDateSelect: onStartDateSelect, selectedEndDate: selectedEndDate, onEndDateSelect: onEndDateSelect, handleFilter: handleFilter, themeBgColor: dataPickerThemeColor, lightThemeBg: dataPickerThemeColorAccent, setSearchCriteria: setSearchCriteria, column: column, setEditingHeader: setEditingHeader, searchItems: searchItems, setSearchItems: setSearchItems, pillColor: pillColor, toggleColor: toggleColor, toggleTextColor: toggleTextColor, fontFamily: fontFamily, removePattern: removePattern, dropdownIconProp: dropdownIconProp, hasOperator: hasOperator, tooltipText: tooltipText }));
|
|
27
|
+
return (_jsx(SearchDatePickerInput, { textHighlight: textHighlight, dropdownOptions: dropdownOptions, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, selectedDate: selectedDate, onDateSelect: onDateSelect, selectedStartDate: selectedStartDate, onStartDateSelect: onStartDateSelect, selectedEndDate: selectedEndDate, onEndDateSelect: onEndDateSelect, handleFilter: handleFilter, themeBgColor: dataPickerThemeColor, lightThemeBg: dataPickerThemeColorAccent, setSearchCriteria: setSearchCriteria, column: column, setEditingHeader: setEditingHeader, searchItems: searchItems, setSearchItems: setSearchItems, pillColor: pillColor, toggleColor: toggleColor, toggleTextColor: toggleTextColor, fontFamily: fontFamily, removePattern: removePattern, dropdownIconProp: dropdownIconProp, hasOperator: hasOperator, tooltipText: tooltipText, inactiveCircleColor: inactiveCircleColor, activeCircleColor: activeCircleColor, placeHolderColor: placeHolderColor }));
|
|
28
28
|
default:
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
@@ -101,9 +101,7 @@ const Template = (args) => {
|
|
|
101
101
|
name: "dummy-name",
|
|
102
102
|
});
|
|
103
103
|
}, []);
|
|
104
|
-
return (_jsx(SearchInput, { ...args, column: mockColumn,
|
|
105
|
-
// States from the story
|
|
106
|
-
selectedDropdownOption: selectedOption, onDropdownOptionSelect: handleDropdownOptionSelect, searchItems: searchItems, setSearchItems: setSearchItems, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, minValue: minValue, maxValue: maxValue, setMinValue: setMinValue, setMaxValue: setMaxValue, onChange: handleOnChange, selectedValue: selectedValue, selectedDate: selectedDate, onDateSelect: setSelectedDate, selectedStartDate: selectedStartDate, onStartDateSelect: setSelectedStartDate, selectedEndDate: selectedEndDate, onEndDateSelect: setSelectedEndDate, setSearchCriteria: setSearchCriteria, setEditingHeader: setEditingHeader, removePattern: /^[^:]*:/, pillColor: "bg-sky-500",
|
|
104
|
+
return (_jsx(SearchInput, { ...args, column: mockColumn, selectedDropdownOption: selectedOption, onDropdownOptionSelect: handleDropdownOptionSelect, searchItems: searchItems, setSearchItems: setSearchItems, toggleStatus: toggleStatus, setToggleStatus: setToggleStatus, minValue: minValue, maxValue: maxValue, setMinValue: setMinValue, setMaxValue: setMaxValue, onChange: handleOnChange, selectedValue: selectedValue, selectedDate: selectedDate, onDateSelect: setSelectedDate, selectedStartDate: selectedStartDate, onStartDateSelect: setSelectedStartDate, selectedEndDate: selectedEndDate, onEndDateSelect: setSelectedEndDate, setSearchCriteria: setSearchCriteria, setEditingHeader: setEditingHeader, removePattern: /^[^:]*:/, pillColor: "bg-sky-500",
|
|
107
105
|
// Overwrite the dropdownOptions with our memoized version
|
|
108
106
|
dropdownOptions: stableDropdownOptions }));
|
|
109
107
|
};
|
|
@@ -34,6 +34,9 @@ export interface SearchDatePickerInputProps<T extends object> {
|
|
|
34
34
|
removePattern?: RegExp | string;
|
|
35
35
|
hasOperator?: boolean;
|
|
36
36
|
tooltipText?: string;
|
|
37
|
+
inactiveCircleColor?: string;
|
|
38
|
+
activeCircleColor?: string;
|
|
39
|
+
placeHolderColor?: string;
|
|
37
40
|
}
|
|
38
|
-
declare function SearchDatePickerInput<T extends object>({ themeBgColor, lightThemeBg, pillColor, textHighlight, dropdownOptions, dropdownIconProp, toggleStatus, setToggleStatus, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, selectedDropdownOption, onDropdownOptionSelect, buttonText, buttonColor, searchItems, setSearchItems, handleFilter, setSearchCriteria, column, setEditingHeader, localStorageKey, toggleColor, toggleTextColor, fontFamily, removePattern, hasOperator, tooltipText, }: SearchDatePickerInputProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
declare function SearchDatePickerInput<T extends object>({ themeBgColor, lightThemeBg, pillColor, textHighlight, dropdownOptions, dropdownIconProp, toggleStatus, setToggleStatus, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, selectedDropdownOption, onDropdownOptionSelect, buttonText, buttonColor, searchItems, setSearchItems, handleFilter, setSearchCriteria, column, setEditingHeader, localStorageKey, toggleColor, toggleTextColor, fontFamily, removePattern, hasOperator, tooltipText, inactiveCircleColor, activeCircleColor, placeHolderColor, }: SearchDatePickerInputProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
39
42
|
export default SearchDatePickerInput;
|
|
@@ -23,13 +23,16 @@ function parseOperatorAndDate(text) {
|
|
|
23
23
|
return { operator: "", dateStr: text };
|
|
24
24
|
}
|
|
25
25
|
/** Formats a JS Date as YYYY-MM-DD in local time */
|
|
26
|
-
function
|
|
27
|
-
if (!date)
|
|
28
|
-
return "";
|
|
29
|
-
const year = date.getFullYear();
|
|
26
|
+
function formatDateAsMonthDayYear(date) {
|
|
30
27
|
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
31
28
|
const day = date.getDate().toString().padStart(2, "0");
|
|
32
|
-
|
|
29
|
+
const year = date.getFullYear();
|
|
30
|
+
return `${month}/${day}/${year}`;
|
|
31
|
+
}
|
|
32
|
+
function formatDateAsYearMonthDay(date) {
|
|
33
|
+
if (!date)
|
|
34
|
+
return "";
|
|
35
|
+
return date.toISOString().slice(0, 10);
|
|
33
36
|
}
|
|
34
37
|
/** Attempts to parse a date string input by the user as a local date */
|
|
35
38
|
function parseUserDateInput(input) {
|
|
@@ -63,7 +66,7 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
63
66
|
iconClasses: "text-sky-500",
|
|
64
67
|
name: "chevronDown",
|
|
65
68
|
weight: "solid",
|
|
66
|
-
}, toggleStatus = false, setToggleStatus, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, selectedDropdownOption, onDropdownOptionSelect, buttonText = "Filter", buttonColor, searchItems = [], setSearchItems, handleFilter, setSearchCriteria, column, setEditingHeader, localStorageKey = "searchCriteria", toggleColor = "bg-sky-500", toggleTextColor = "text-black", fontFamily, removePattern, hasOperator, tooltipText, }) {
|
|
69
|
+
}, toggleStatus = false, setToggleStatus, selectedDate, onDateSelect, selectedStartDate, onStartDateSelect, selectedEndDate, onEndDateSelect, selectedDropdownOption, onDropdownOptionSelect, buttonText = "Filter", buttonColor, searchItems = [], setSearchItems, handleFilter, setSearchCriteria, column, setEditingHeader, localStorageKey = "searchCriteria", toggleColor = "bg-sky-500", toggleTextColor = "text-black", fontFamily, removePattern, hasOperator, tooltipText, inactiveCircleColor = "after:bg-gray-300", activeCircleColor = "peer-checked:after:bg-sky-500", placeHolderColor, }) {
|
|
67
70
|
const containerRef = useRef(null);
|
|
68
71
|
// Local operator state.
|
|
69
72
|
const [localOperator, setLocalOperator] = useState(() => {
|
|
@@ -75,15 +78,19 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
75
78
|
});
|
|
76
79
|
// Local single-date and its input value.
|
|
77
80
|
const [localDate, setLocalDate] = useState(selectedDate);
|
|
78
|
-
const [dateInputValue, setDateInputValue] = useState(selectedDate ?
|
|
81
|
+
const [dateInputValue, setDateInputValue] = useState(selectedDate ? formatDateAsMonthDayYear(selectedDate) : "");
|
|
79
82
|
// Local start/end for range mode and their input values.
|
|
80
83
|
const [localStartDate, setLocalStartDate] = useState(selectedStartDate);
|
|
81
|
-
const [startDateInputValue, setStartDateInputValue] = useState(selectedStartDate ?
|
|
84
|
+
const [startDateInputValue, setStartDateInputValue] = useState(selectedStartDate ? formatDateAsMonthDayYear(selectedStartDate) : "");
|
|
82
85
|
const [localEndDate, setLocalEndDate] = useState(selectedEndDate);
|
|
83
|
-
const [endDateInputValue, setEndDateInputValue] = useState(selectedEndDate ?
|
|
86
|
+
const [endDateInputValue, setEndDateInputValue] = useState(selectedEndDate ? formatDateAsMonthDayYear(selectedEndDate) : "");
|
|
84
87
|
const [isDatePickerOpen, setIsDatePickerOpen] = useState(false);
|
|
85
88
|
// activeInput can be "start", "end", "single" or null (when not editing)
|
|
86
89
|
const [activeInput, setActiveInput] = useState(null);
|
|
90
|
+
const handlePickerClose = () => {
|
|
91
|
+
setIsDatePickerOpen(false);
|
|
92
|
+
setActiveInput(null);
|
|
93
|
+
};
|
|
87
94
|
// Load from localStorage if there's an existing criterion for this column.
|
|
88
95
|
useEffect(() => {
|
|
89
96
|
if (!column?.id)
|
|
@@ -104,7 +111,7 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
104
111
|
const d = new Date(dateStr.trim());
|
|
105
112
|
if (!isNaN(d.getTime())) {
|
|
106
113
|
setLocalDate(d);
|
|
107
|
-
setDateInputValue(
|
|
114
|
+
setDateInputValue(formatDateAsMonthDayYear(d));
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
else if (toggleStatus && dateStr) {
|
|
@@ -114,11 +121,11 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
114
121
|
const endDate = new Date(parts[1].trim());
|
|
115
122
|
if (!isNaN(startDate.getTime())) {
|
|
116
123
|
setLocalStartDate(startDate);
|
|
117
|
-
setStartDateInputValue(
|
|
124
|
+
setStartDateInputValue(formatDateAsMonthDayYear(startDate));
|
|
118
125
|
}
|
|
119
126
|
if (!isNaN(endDate.getTime())) {
|
|
120
127
|
setLocalEndDate(endDate);
|
|
121
|
-
setEndDateInputValue(
|
|
128
|
+
setEndDateInputValue(formatDateAsMonthDayYear(endDate));
|
|
122
129
|
}
|
|
123
130
|
}
|
|
124
131
|
}
|
|
@@ -133,19 +140,19 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
133
140
|
useEffect(() => {
|
|
134
141
|
if (selectedDate && activeInput !== "single") {
|
|
135
142
|
setLocalDate(selectedDate);
|
|
136
|
-
setDateInputValue(
|
|
143
|
+
setDateInputValue(formatDateAsMonthDayYear(selectedDate));
|
|
137
144
|
}
|
|
138
145
|
}, [selectedDate, activeInput]);
|
|
139
146
|
useEffect(() => {
|
|
140
147
|
if (selectedStartDate && activeInput !== "start") {
|
|
141
148
|
setLocalStartDate(selectedStartDate);
|
|
142
|
-
setStartDateInputValue(
|
|
149
|
+
setStartDateInputValue(formatDateAsMonthDayYear(selectedStartDate));
|
|
143
150
|
}
|
|
144
151
|
}, [selectedStartDate, activeInput]);
|
|
145
152
|
useEffect(() => {
|
|
146
153
|
if (selectedEndDate && activeInput !== "end") {
|
|
147
154
|
setLocalEndDate(selectedEndDate);
|
|
148
|
-
setEndDateInputValue(
|
|
155
|
+
setEndDateInputValue(formatDateAsMonthDayYear(selectedEndDate));
|
|
149
156
|
}
|
|
150
157
|
}, [selectedEndDate, activeInput]);
|
|
151
158
|
useEffect(() => {
|
|
@@ -220,13 +227,20 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
220
227
|
const handleFilterClick = () => {
|
|
221
228
|
let finalText = "";
|
|
222
229
|
if (!toggleStatus) {
|
|
223
|
-
const dateStr = localDate
|
|
230
|
+
const dateStr = localDate
|
|
231
|
+
? formatDateAsYearMonthDay(localDate)
|
|
232
|
+
: "";
|
|
233
|
+
console.log(dateStr, "HERE");
|
|
224
234
|
finalText = localOperator.value + dateStr;
|
|
225
235
|
onDateSelect?.(localDate);
|
|
226
236
|
}
|
|
227
237
|
else {
|
|
228
|
-
const startStr = localStartDate
|
|
229
|
-
|
|
238
|
+
const startStr = localStartDate
|
|
239
|
+
? formatDateAsYearMonthDay(localStartDate)
|
|
240
|
+
: "";
|
|
241
|
+
const endStr = localEndDate
|
|
242
|
+
? formatDateAsYearMonthDay(localEndDate)
|
|
243
|
+
: "";
|
|
230
244
|
if (startStr && endStr) {
|
|
231
245
|
finalText = `${startStr} - ${endStr}`;
|
|
232
246
|
}
|
|
@@ -281,56 +295,56 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
281
295
|
}, [isDatePickerOpen]);
|
|
282
296
|
// Render the DayPicker – for both single and range modes.
|
|
283
297
|
const dayPicker = !toggleStatus
|
|
284
|
-
? isDatePickerOpen && (
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
298
|
+
? isDatePickerOpen && (_jsxs("div", { className: "absolute p-4 top-16 w-auto z-50 shadow-lg bg-white", children: [_jsx("div", { onClick: handlePickerClose, className: "hover:cursor-pointer text-right pr-3", children: getFontAwesomeIcon("x", "regular") }), _jsx(DayPicker, { mode: "single", selected: parseUserDateInput(dateInputValue) || localDate, onSelect: (day) => {
|
|
299
|
+
if (day) {
|
|
300
|
+
setLocalDate(day);
|
|
301
|
+
setDateInputValue(formatDateAsMonthDayYear(day));
|
|
302
|
+
onDateSelect?.(day);
|
|
303
|
+
}
|
|
304
|
+
setIsDatePickerOpen(false);
|
|
305
|
+
setActiveInput(null);
|
|
306
|
+
} })] }))
|
|
293
307
|
: isDatePickerOpen &&
|
|
294
|
-
activeInput && (_jsx("div", { className: "absolute p-4 top-16 w-auto z-50 shadow-lg bg-white", children: activeInput === "start" ? (_jsx(DayPicker, { mode: "single", selected: parseUserDateInput(startDateInputValue) ||
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
return (_jsxs("div", { ref: containerRef, className: "relative w-[425px] border-2 p-4", children: [_jsx("div", { className: "flex items-center justify-between h-12 mb-2", children: toggleStatus ? (_jsxs("div", { className: "flex items-center w-full", children: [activeInput === "start" ? (_jsx(Input, { type: "text", value: startDateInputValue, onChange: handleStartDateInputChange, placeholder: "mm/dd/yyy", onKeyDown: (e) => {
|
|
308
|
+
activeInput && (_jsx("div", { className: "absolute p-4 top-16 w-auto z-50 shadow-lg bg-white", children: activeInput === "start" ? (_jsxs(_Fragment, { children: [_jsx("div", { onClick: handlePickerClose, className: "hover:cursor-pointer text-right pr-3", children: getFontAwesomeIcon("x", "regular") }), _jsx(DayPicker, { mode: "single", selected: parseUserDateInput(startDateInputValue) ||
|
|
309
|
+
localStartDate, onSelect: (day) => {
|
|
310
|
+
if (day) {
|
|
311
|
+
setLocalStartDate(day);
|
|
312
|
+
setStartDateInputValue(formatDateAsMonthDayYear(day));
|
|
313
|
+
onStartDateSelect?.(day);
|
|
314
|
+
}
|
|
315
|
+
setIsDatePickerOpen(false);
|
|
316
|
+
setActiveInput(null);
|
|
317
|
+
} })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { onClick: handlePickerClose, className: "hover:cursor-pointer text-right pr-3", children: getFontAwesomeIcon("x", "regular") }), _jsx(DayPicker, { mode: "single", selected: parseUserDateInput(endDateInputValue) ||
|
|
318
|
+
localEndDate, onSelect: (day) => {
|
|
319
|
+
if (day) {
|
|
320
|
+
setLocalEndDate(day);
|
|
321
|
+
setEndDateInputValue(formatDateAsMonthDayYear(day));
|
|
322
|
+
onEndDateSelect?.(day);
|
|
323
|
+
}
|
|
324
|
+
setIsDatePickerOpen(false);
|
|
325
|
+
setActiveInput(null);
|
|
326
|
+
} })] })) }));
|
|
327
|
+
return (_jsxs("div", { ref: containerRef, className: "relative w-[425px] border-2 p-4", children: [_jsx("div", { className: "flex items-center justify-between h-12 mb-2", children: toggleStatus ? (_jsxs("div", { className: "flex items-center w-full", children: [activeInput === "start" ? (_jsx(Input, { type: "text", value: startDateInputValue, onChange: handleStartDateInputChange, placeholder: "mm/dd/yyy", placeHolderColor: placeHolderColor, onKeyDown: (e) => {
|
|
314
328
|
if (e.key === "Enter") {
|
|
315
329
|
setIsDatePickerOpen(false);
|
|
316
330
|
setActiveInput(null);
|
|
317
331
|
}
|
|
318
|
-
}, firstIcon: getFontAwesomeIcon("calendar", "regular"), required: false, additionalClasses: "border-2 px-3 py-2 flex-[2] h-10 text-left min-w-44 max-w-44", hasAutoFocus: true })) : (_jsxs("button", { onClick: openStartPicker, className: "border-2 px-3 py-2 flex-1 h-10 text-left min-w-44 max-w-44", children: [_jsx("span", { className: "pr-2", children: getFontAwesomeIcon("calendar", "regular") }), localStartDate
|
|
319
|
-
?
|
|
320
|
-
: "mm/dd/yyyy"] })), _jsx("span", { className: "mx-2", children: "to" }), activeInput === "end" ? (_jsx(Input, { type: "text", value: endDateInputValue, onChange: handleEndDateInputChange, placeholder: "mm/dd/yyy", onKeyDown: (e) => {
|
|
332
|
+
}, firstIcon: getFontAwesomeIcon("calendar", "regular"), required: false, additionalClasses: "border-2 px-3 py-2 flex-[2] h-10 text-left min-w-44 max-w-44 ", hasAutoFocus: true })) : (_jsxs("button", { onClick: openStartPicker, className: "border-2 px-3 py-2 flex-1 h-10 text-left min-w-44 max-w-44", children: [_jsx("span", { className: "pr-2", children: getFontAwesomeIcon("calendar", "regular") }), localStartDate
|
|
333
|
+
? formatDateAsMonthDayYear(localStartDate)
|
|
334
|
+
: "mm/dd/yyyy"] })), _jsx("span", { className: "mx-2", children: "to" }), activeInput === "end" ? (_jsx(Input, { type: "text", value: endDateInputValue, onChange: handleEndDateInputChange, placeholder: "mm/dd/yyy", placeHolderColor: placeHolderColor, onKeyDown: (e) => {
|
|
321
335
|
if (e.key === "Enter") {
|
|
322
336
|
setIsDatePickerOpen(false);
|
|
323
337
|
setActiveInput(null);
|
|
324
338
|
}
|
|
325
339
|
}, firstIcon: getFontAwesomeIcon("calendar", "regular"), required: false, additionalClasses: "border-2 px-3 py-2 flex-[2] h-10 text-left min-w-44 max-w-44", hasAutoFocus: true })) : (_jsxs("button", { onClick: openEndPicker, className: "border-2 px-3 py-2 flex-1 h-10 text-left min-w-44 max-w-44", children: [_jsx("span", { className: "pr-2", children: getFontAwesomeIcon("calendar", "regular") }), localEndDate
|
|
326
|
-
?
|
|
327
|
-
: "mm/dd/yyyy"] }))] })) : (_jsxs(_Fragment, { children: [_jsx(Dropdown, { options: dropdownOptions, selectedOption: localOperator, onOptionSelect: handleOperatorSelect, optionClasses: "px-4 h-full flex items-center", menuClasses: "bg-white min-w-32xw rounded-md shadow-md top-12", dropdownClasses: "border-2 border-r-0 flex-[1] h-10 w-auto", icon: dropdownIconProp, isEnabled: !hasOperator, tooltipText: tooltipText }), activeInput === "single" ? (_jsx(
|
|
340
|
+
? formatDateAsMonthDayYear(localEndDate)
|
|
341
|
+
: "mm/dd/yyyy"] }))] })) : (_jsxs(_Fragment, { children: [_jsx(Dropdown, { options: dropdownOptions, selectedOption: localOperator, onOptionSelect: handleOperatorSelect, optionClasses: "px-4 h-full flex items-center ", menuClasses: "bg-white min-w-32xw rounded-md shadow-md top-12", dropdownClasses: "border-2 border-r-0 flex-[1] h-10 w-auto min-w-44 max-w-44", icon: dropdownIconProp, isEnabled: !hasOperator, tooltipText: tooltipText }), activeInput === "single" ? (_jsx(_Fragment, { children: _jsx(Input, { type: "text", value: dateInputValue, onChange: handleSingleDateInputChange, placeholder: "mm/dd/yyy", onKeyDown: (e) => {
|
|
328
342
|
if (e.key === "Enter") {
|
|
329
343
|
setIsDatePickerOpen(false);
|
|
330
344
|
setActiveInput(null);
|
|
331
345
|
}
|
|
332
|
-
}, firstIcon: getFontAwesomeIcon("calendar", "regular"), required: false, additionalClasses: "border-2 px-3 py-2 flex-[2] h-10 text-left
|
|
333
|
-
?
|
|
346
|
+
}, firstIcon: getFontAwesomeIcon("calendar", "regular"), required: false, additionalClasses: "border-2 px-3 py-2 flex-[2] h-10 text-left ", hasAutoFocus: true, placeHolderColor: placeHolderColor }) })) : (_jsx(_Fragment, { children: _jsxs("button", { onClick: openSinglePicker, className: "border-2 px-3 py-2 flex-[2] h-10 text-left ", children: [_jsx("span", { className: "pr-2", children: getFontAwesomeIcon("calendar", "regular") }), localDate
|
|
347
|
+
? formatDateAsMonthDayYear(localDate)
|
|
334
348
|
: "mm/dd/yyyy"] }) }))] })) }), dayPicker, searchItems?.length ? (_jsx("div", { className: "flex flex-wrap bg-white py-2 px-2 mt-2 rounded-md", children: searchItems.map((item, index) => {
|
|
335
349
|
const cleanedText = getCleanedText(item, removePattern);
|
|
336
350
|
return (_jsx(Badge, { backgroundColor: pillColor, borderRadius: "rounded-full", hasRightIcon: true, icon: _jsx("div", { className: "text-white text-xxs", children: getFontAwesomeIcon("xmark", "solid") }), iconSize: "text-sm", onClick: () => {
|
|
@@ -343,6 +357,6 @@ function SearchDatePickerInput({ themeBgColor = "bg-sky-500", lightThemeBg = "bg
|
|
|
343
357
|
return filtered;
|
|
344
358
|
});
|
|
345
359
|
}, text: _jsx(Text, { color: "text-white", size: "text-sm", tag: "span", text: cleanedText }), badgeContainerClasses: `${pillColor} p-1 max-w-fit min-w-20 rounded-full flex justify-between items-center text-white text-xs px-4 border-none mr-4 mb-1`, type: "span" }, index));
|
|
346
|
-
}) })) : null, _jsxs("div", { className: "flex justify-between items-end bg-white px-2 rounded-md mt-4", children: [_jsx(ToggleButton, { initialStatus: toggleStatus, onClick: () => setToggleStatus?.(!toggleStatus), activeColorBackground: toggleColor, activeColorBorder: "border-sky-500", activeLabel: "Range", activeTextColor: toggleTextColor, additionalClasses: "flex items-center", inactiveColorBackground: "bg-gray-300", inactiveColorBorder: "border-gray-300", inactiveLabel: "Range", inactiveTextColor: "text-gray-500", pillHeight: "h-8", textPosition: "right", textSize: "text-sm", smallToggle: true, borderStyle: true }), _jsx(BaseButton, { text: buttonText, backgroundColor: themeBgColor, additionalClasses: "py-0.5 px-6 text-white", borderColor: "border-none", onClick: handleFilterClick, shape: "rounded-full" })] })] }));
|
|
360
|
+
}) })) : null, _jsxs("div", { className: "flex justify-between items-end bg-white px-2 rounded-md mt-4", children: [_jsx(ToggleButton, { initialStatus: toggleStatus, onClick: () => setToggleStatus?.(!toggleStatus), activeColorBackground: toggleColor, activeColorBorder: "border-sky-500", activeLabel: "Range", activeTextColor: toggleTextColor, additionalClasses: "flex items-center", inactiveColorBackground: "bg-gray-300", inactiveColorBorder: "border-gray-300", inactiveLabel: "Range", inactiveTextColor: "text-gray-500", pillHeight: "h-8", textPosition: "right", textSize: "text-sm", smallToggle: true, borderStyle: true, inactiveCircleColor: inactiveCircleColor, activeCircleColor: activeCircleColor }), _jsx(BaseButton, { text: buttonText, backgroundColor: themeBgColor, additionalClasses: "py-0.5 px-6 text-white", borderColor: "border-none", onClick: handleFilterClick, shape: "rounded-full" })] })] }));
|
|
347
361
|
}
|
|
348
362
|
export default SearchDatePickerInput;
|
|
@@ -49,6 +49,9 @@ type SearchNumberInputProps<T extends object> = {
|
|
|
49
49
|
weight: string;
|
|
50
50
|
};
|
|
51
51
|
firstIconTop?: string;
|
|
52
|
+
inactiveCircleColor: string;
|
|
53
|
+
activeCircleColor: string;
|
|
54
|
+
placeHolderColor?: string;
|
|
52
55
|
};
|
|
53
56
|
/**
|
|
54
57
|
* A numeric filter component that:
|
|
@@ -56,5 +59,5 @@ type SearchNumberInputProps<T extends object> = {
|
|
|
56
59
|
* 2. On Filter => either remove or store a string in localStorage
|
|
57
60
|
* 3. On mount => read any existing filter for this column, parse, and set min/max
|
|
58
61
|
*/
|
|
59
|
-
declare const SearchNumberInput: <T extends object>({ textHighlight, dropdownIconProp, dropdownOptions, selectedDropdownOption, onDropdownOptionSelect, toggleStatus, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, handleFilter, searchItems, setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey, themeBgColor, toggleColor, toggleTextColor, pillColor, fontFamily, removePattern, hasOperator, tooltipText, numberTypeIcon, firstIconTop, }: SearchNumberInputProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
62
|
+
declare const SearchNumberInput: <T extends object>({ textHighlight, dropdownIconProp, dropdownOptions, selectedDropdownOption, onDropdownOptionSelect, toggleStatus, setToggleStatus, minValue, setMinValue, maxValue, setMaxValue, handleFilter, searchItems, setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey, themeBgColor, toggleColor, toggleTextColor, pillColor, fontFamily, removePattern, hasOperator, tooltipText, numberTypeIcon, firstIconTop, inactiveCircleColor, activeCircleColor, placeHolderColor, }: SearchNumberInputProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
60
63
|
export default SearchNumberInput;
|
|
@@ -22,7 +22,7 @@ const SearchNumberInput = ({ textHighlight = "text-sky-500", dropdownIconProp =
|
|
|
22
22
|
weight: "solid",
|
|
23
23
|
}, dropdownOptions = [], selectedDropdownOption = { label: "", value: "" }, onDropdownOptionSelect, toggleStatus = false, setToggleStatus, minValue = "", setMinValue, maxValue = "", setMaxValue, handleFilter,
|
|
24
24
|
// local-storage
|
|
25
|
-
searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey = DEFAULT_STORAGE_KEY, themeBgColor = "bg-sky-500", toggleColor = "bg-sky-500", toggleTextColor = "text-black", pillColor, fontFamily, removePattern, hasOperator, tooltipText, numberTypeIcon = { icon: "x", weight: "regular" }, firstIconTop, }) => {
|
|
25
|
+
searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey = DEFAULT_STORAGE_KEY, themeBgColor = "bg-sky-500", toggleColor = "bg-sky-500", toggleTextColor = "text-black", pillColor, fontFamily, removePattern, hasOperator, tooltipText, numberTypeIcon = { icon: "x", weight: "regular" }, firstIconTop, inactiveCircleColor = "after:bg-gray-300", activeCircleColor = "peer-checked:after:bg-sky-500", placeHolderColor = "placeholder:text-gray-500", }) => {
|
|
26
26
|
const containerRef = useRef(null);
|
|
27
27
|
const inputRef = useRef(null);
|
|
28
28
|
/** Decide if we can store for this column */
|
|
@@ -162,12 +162,12 @@ searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, l
|
|
|
162
162
|
});
|
|
163
163
|
};
|
|
164
164
|
return (_jsx("div", { ref: containerRef, className: "w-[425px]", children: _jsxs("div", { className: "flex flex-col pt-4 p pb-1 border-2 border-navy-200 rounded-md", children: [_jsx("div", { className: `flex flex-[1] mx-4 ${toggleStatus ? "" : "border-2"}
|
|
165
|
-
h-full max-h-11 items-center justify-around`, children: toggleStatus ? (_jsxs("div", { className: "flex items-center", children: [_jsx(Input, { focusRingColor: "focus:ring-2 ", hasAutoFocus: true, value: minValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMinValue?.(e.target.value), additionalClasses: "min-w-[180px] max-w-[180px] h-10 text-gray flex focus:border-l-2 border-2", placeholder: "Min" }), _jsx(Text, { size: "text-md", tag: "span", text: "to", additionalClasses: "px-2" }), _jsx(Input, { focusRingColor: "focus:ring-2", value: maxValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMaxValue?.(e.target.value), additionalClasses: "min-w-[180px] max-w-[180px] h-10 text-gray flex border-2 focus:border-l-2 ", placeholder: "Max" })] })) : (
|
|
165
|
+
h-full max-h-11 items-center justify-around`, children: toggleStatus ? (_jsxs("div", { className: "flex items-center", children: [_jsx(Input, { focusRingColor: "focus:ring-2 ", hasAutoFocus: true, value: minValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMinValue?.(e.target.value), additionalClasses: "min-w-[180px] max-w-[180px] h-10 text-gray flex focus:border-l-2 border-2", placeholder: "Min", placeHolderColor: placeHolderColor }), _jsx(Text, { size: "text-md", tag: "span", text: "to", additionalClasses: "px-2" }), _jsx(Input, { focusRingColor: "focus:ring-2", value: maxValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMaxValue?.(e.target.value), additionalClasses: "min-w-[180px] max-w-[180px] h-10 text-gray flex border-2 focus:border-l-2 ", placeholder: "Max", placeHolderColor: placeHolderColor })] })) : (
|
|
166
166
|
// Single value mode
|
|
167
167
|
_jsxs(_Fragment, { children: [_jsx(Dropdown, { options: dropdownOptions, selectedOption: selectedDropdownOption || {
|
|
168
168
|
label: "",
|
|
169
169
|
value: "",
|
|
170
|
-
}, onOptionSelect: onDropdownOptionSelect, optionClasses: "px-4 h-full flex items-center", menuClasses: "bg-white min-w-32xw rounded-md shadow-md top-12", dropdownClasses: "border-0 w-auto", icon: dropdownIconProp, isEnabled: !hasOperator, tooltipText: tooltipText }), _jsx(Input, { ref: inputRef, focusRingColor: "focus:ring-transparent", hasAutoFocus: true, value: minValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMinValue?.(e.target.value), additionalClasses: "min-w-[200px] h-10 text-gray flex border-l-2 flex items-center", placeholder: "Amount", hasIcons: true, iconPosition: "both", firstIcon: _jsx("div", { children: getFontAwesomeIcon(numberTypeIcon.icon, numberTypeIcon.weight) }), firstIconTop: firstIconTop })] })) }), _jsxs("div", { className: " flex flex-[1] justify-between items-end py-1 px-4", children: [_jsx(ToggleButton, { initialStatus: toggleStatus, onClick: () => setToggleStatus?.(!toggleStatus), activeColorBackground: toggleColor, activeColorBorder: "border-sky-500", activeLabel: "Range", activeTextColor: toggleTextColor, additionalClasses: "flex items-center", inactiveColorBackground: "bg-gray-300", inactiveColorBorder: "border-gray-300", inactiveLabel: "Range", inactiveTextColor: "text-gray-500", pillHeight: "h-8", textPosition: "right", textSize: "text-sm", smallToggle: true, borderStyle: true }), _jsx(BaseButton, { text: "Filter", backgroundColor: themeBgColor, additionalClasses: "py-0.5 px-6 text-white", borderColor: "border-none", onClick: handleFilterClick, shape: "rounded-full" })] }), searchItems?.length ? (_jsx("div", { className: "border-t border-gray-300 ", children: _jsx("div", { className: "flex flex-wrap bg-white pt-2 px-4 rounded-md", children: searchItems.map((item, index) => {
|
|
170
|
+
}, onOptionSelect: onDropdownOptionSelect, optionClasses: "px-4 h-full flex items-center", menuClasses: "bg-white min-w-32xw rounded-md shadow-md top-12", dropdownClasses: "border-0 w-auto", icon: dropdownIconProp, isEnabled: !hasOperator, tooltipText: tooltipText }), _jsx(Input, { ref: inputRef, focusRingColor: "focus:ring-transparent", hasAutoFocus: true, value: minValue, iconColor: "text-navy-400", required: false, id: "", name: "", type: "number", onChange: (e) => setMinValue?.(e.target.value), additionalClasses: "min-w-[200px] h-10 text-gray flex border-l-2 flex items-center", placeholder: "Amount", placeHolderColor: placeHolderColor, hasIcons: true, iconPosition: "both", firstIcon: numberTypeIcon?.icon ? (_jsx("div", { children: getFontAwesomeIcon(numberTypeIcon.icon, numberTypeIcon.weight) })) : null, firstIconTop: firstIconTop })] })) }), _jsxs("div", { className: " flex flex-[1] justify-between items-end py-1 px-4", children: [_jsx(ToggleButton, { initialStatus: toggleStatus, onClick: () => setToggleStatus?.(!toggleStatus), activeColorBackground: toggleColor, activeColorBorder: "border-sky-500", activeLabel: "Range", activeTextColor: toggleTextColor, additionalClasses: "flex items-center", inactiveColorBackground: "bg-gray-300", inactiveColorBorder: "border-gray-300", inactiveLabel: "Range", inactiveTextColor: "text-gray-500", pillHeight: "h-8", textPosition: "right", textSize: "text-sm", smallToggle: true, borderStyle: true, activeCircleColor: activeCircleColor, inactiveCircleColor: inactiveCircleColor }), _jsx(BaseButton, { text: "Filter", backgroundColor: themeBgColor, additionalClasses: "py-0.5 px-6 text-white", borderColor: "border-none", onClick: handleFilterClick, shape: "rounded-full" })] }), searchItems?.length ? (_jsx("div", { className: "border-t border-gray-300 ", children: _jsx("div", { className: "flex flex-wrap bg-white pt-2 px-4 rounded-md ", children: searchItems.map((item, index) => {
|
|
171
171
|
const cleanedText = getCleanedText(item, removePattern);
|
|
172
172
|
return (_jsx(Badge, { backgroundColor: pillColor, borderRadius: "rounded-full", hasRightIcon: true, icon: _jsx("div", { className: "text-white text-xxs", "data-testid": "item-clear-icon", children: getFontAwesomeIcon("xmark", "solid") }), iconSize: "text-sm", mobileIconLabel: item, onClick: () => handleSearchBadgeClick(item), text: _jsx(Text, { color: "text-white", fontFamily: fontFamily, size: "text-sm", tag: "span", text: cleanedText }), badgeContainerClasses: `${pillColor} cursor-pointer p-1 max-w-fit min-w-20 rounded-full flex justify-between items-center text-white text-xs px-4 border-none mr-4 mb-1`, type: "span" }, index));
|
|
173
173
|
}) }) })) : null] }) }));
|
|
@@ -91,7 +91,7 @@ const SearchTextInput = ({ pillColor = "bg-sky-500", textHighlight = "text-sky-5
|
|
|
91
91
|
};
|
|
92
92
|
return (_jsx("div", { ref: containerRef, className: "rounded-md", children: _jsxs("div", { className: "flex flex-col border-2 border-navy-200 rounded-md", children: [_jsxs("div", { className: `flex ${searchItems.length ? "border-b-2" : ""} h-full`, children: [_jsx(Dropdown, { options: dropdownOptions, selectedOption: selectedDropdownOption || { label: "", value: "" }, onOptionSelect: onDropdownOptionSelect, optionClasses: "px-4 py-1 h-full flex items-center ", menuClasses: "bg-white min-w-32xw rounded-md shadow-md top-12", icon: dropdownIconProp, dropdownClasses: "border-0 border-r-2 w-auto ", isEnabled: !hasOperator, tooltipText: tooltipText }), _jsx(Input, { focusRingColor: "focus:ring-transparent", hasAutoFocus: true, value: getCleanedText(localSearchText, removePattern), iconColor: "text-navy-400", onKeyDown: handleKeyDown, required: false, id: "", name: "", type: "text", firstIconClasses: firstIconClasses, onChange: handleInputChange, additionalClasses: "min-w-[250px] min-h-full text-gray flex", placeholder: "Search", hasIcons: true, firstIcon: localSearchText === "" ? (_jsx(AnimatePresence, { children: _jsx(motion.div, { initial: "initial", animate: "animate", exit: "exit", className: "text-navy-400", children: getFontAwesomeIcon("search", "regular") }) })) : undefined, iconPosition: "both", secondIcon: _jsx("div", { className: "border-transparent text-white min-w-14", children: _jsx(AnimatePresence, { children: localSearchText !== "" && (_jsxs(motion.div, { className: "flex justify-between items-center min-w-4 text-navy-400 hover:cursor-pointer hover:text-primary", initial: "initial", animate: "animate", exit: "exit", children: [_jsx("div", { className: "bg-navy-50 pr-2 pl-1 text-gray-500 text-base", onClick: () => setLocalSearchText(""), "data-testid": "clear-icon", children: getFontAwesomeIcon("xmark", "regular") }), _jsx("div", { onClick: handleSubmit, className: `${textHighlight} text-base hover:text-primary`, children: getFontAwesomeIcon("search", "solid") })] })) }) }), onIconClick: () => setLocalSearchText("") })] }), searchItems?.length ? (_jsx("div", { className: "flex flex-wrap bg-white py-2 rounded-md", children: searchItems.map((item, index) => {
|
|
93
93
|
const cleanedText = getCleanedText(item, removePattern);
|
|
94
|
-
return (_jsx(Badge, { backgroundColor: pillColor, borderRadius: "rounded-full", hasRightIcon: true, icon: _jsx("div", { className: "text-white text-xxs", "data-testid": "item-clear-icon", children: getFontAwesomeIcon("xmark", "solid") }), iconSize: "text-sm", mobileIconLabel: item, onClick: () => handleSearchBadgeClick(item), text: _jsx(Text, { color: "text-white", fontFamily: fontFamily, size: "text-sm", tag: "span", text: cleanedText }), badgeContainerClasses: `${pillColor} p-1 max-w-fit min-w-20 rounded-full flex justify-between items-center text-white text-xs px-4 border-none mr-4 mb-1`, type: "span" }, index));
|
|
94
|
+
return (_jsx(Badge, { backgroundColor: pillColor, borderRadius: "rounded-full", hasRightIcon: true, icon: _jsx("div", { className: "text-white text-xxs", "data-testid": "item-clear-icon", children: getFontAwesomeIcon("xmark", "solid") }), iconSize: "text-sm", mobileIconLabel: item, onClick: () => handleSearchBadgeClick(item), text: _jsx(Text, { color: "text-white", fontFamily: fontFamily, size: "text-sm", tag: "span", text: cleanedText }), badgeContainerClasses: `${pillColor} p-1 max-w-fit min-w-20 rounded-full flex justify-between items-center text-white text-xs px-4 border-none mr-4 mb-1 mx-4`, type: "span" }, index));
|
|
95
95
|
}) })) : null] }) }));
|
|
96
96
|
};
|
|
97
97
|
export default SearchTextInput;
|
|
@@ -31,6 +31,8 @@ export interface TableRowProps<T extends DataWithUUID> {
|
|
|
31
31
|
* @param event - the click event on the <tr>
|
|
32
32
|
*/
|
|
33
33
|
onRowClick?: (index: number, rowUuid: string, event: React.MouseEvent<HTMLTableRowElement, MouseEvent>) => void;
|
|
34
|
+
/** Determines if this row should have an expandable drop down */
|
|
35
|
+
hasDropDown?: boolean;
|
|
34
36
|
}
|
|
35
|
-
declare const TableRow: <T extends DataWithUUID>({ row, prepareRow, activeIndex, globalTrimActive, rowUuid, columnInputs, activeRowColor, rowHoverClasses, onRowClick, }: TableRowProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
declare const TableRow: <T extends DataWithUUID>({ row, prepareRow, activeIndex, globalTrimActive, rowUuid, columnInputs, activeRowColor, rowHoverClasses, onRowClick, hasDropDown, }: TableRowProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
36
38
|
export default TableRow;
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment } from "react";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, useState } from "react";
|
|
3
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
3
4
|
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
|
+
const TableRow = ({ row, prepareRow, activeIndex, globalTrimActive, rowUuid, columnInputs, activeRowColor = "bg-pink-100", rowHoverClasses = "hover:bg-red-100 hover:cursor-pointer", onRowClick, hasDropDown = false, }) => {
|
|
5
6
|
prepareRow(row);
|
|
6
7
|
const isActive = activeIndex === row.index;
|
|
7
8
|
let rowClasses = `border-primary`;
|
|
8
9
|
if (isActive) {
|
|
9
10
|
rowClasses += ` activeRow ${activeRowColor}`;
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
// Local state for expansion, only used if hasDropDown is true.
|
|
13
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
14
|
+
const handleRowClick = (event) => {
|
|
15
|
+
onRowClick?.(row.index, rowUuid || "", event);
|
|
16
|
+
if (hasDropDown) {
|
|
17
|
+
setIsExpanded((prev) => !prev);
|
|
18
|
+
// TODO: Trigger API call with rowUuid, handle loading/error states.
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return (_jsxs(Fragment, { children: [_jsx("tr", { "data-testid": "table-row", className: `border-b border-b-navy-200 ${rowHoverClasses} ${rowClasses}`, ...(row.getRowProps ? row.getRowProps() : {}), onClick: handleRowClick, children: row.cells.map((cell, index) => {
|
|
22
|
+
const isLastCell = index === row.cells.length - 1;
|
|
23
|
+
const cellProps = cell.getCellProps();
|
|
24
|
+
return (_jsx(Fragment, { children: _jsx(TableCell, { cell: cell, rowUuid: rowUuid, globalTrimActive: globalTrimActive, columnInputs: columnInputs, isLastCell: isLastCell }) }, cellProps.key));
|
|
25
|
+
}) }, rowUuid), hasDropDown && (_jsx(AnimatePresence, { children: isExpanded && (_jsx("tr", { "data-testid": "expanded-row", children: _jsx("td", { colSpan: row.cells.length, className: "p-0", children: _jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.3 }, className: "overflow-hidden w-full", children: _jsx("div", { className: "h-96 w-full border flex items-center justify-center", children: _jsxs("span", { children: ["drop down - ", rowUuid] }) }) }) }) })) }))] }));
|
|
18
26
|
};
|
|
19
27
|
export default TableRow;
|
|
@@ -3,7 +3,13 @@ import TableRow from "./TableRow";
|
|
|
3
3
|
declare const meta: Meta<typeof TableRow>;
|
|
4
4
|
export default meta;
|
|
5
5
|
export declare const Default: any;
|
|
6
|
-
export declare const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export declare const MultipleRows: {
|
|
7
|
+
(): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
story: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import TableRow from "./TableRow";
|
|
3
|
-
// Sample data for testing
|
|
4
3
|
const sampleData = {
|
|
5
4
|
uuid: "12345",
|
|
6
5
|
name: "John Doe",
|
|
@@ -10,45 +9,115 @@ const sampleData = {
|
|
|
10
9
|
phone: "+1 555-123-4567",
|
|
11
10
|
status: "Active",
|
|
12
11
|
};
|
|
13
|
-
|
|
12
|
+
const sampleData2 = {
|
|
13
|
+
uuid: "67890",
|
|
14
|
+
name: "Jane Smith",
|
|
15
|
+
age: 25,
|
|
16
|
+
address: "456 Another St, Springfield, IL, 62702, United States",
|
|
17
|
+
email: "jane.smith@example.com",
|
|
18
|
+
phone: "+1 555-987-6543",
|
|
19
|
+
status: "Inactive",
|
|
20
|
+
};
|
|
21
|
+
const cellsForRow1 = [
|
|
22
|
+
{
|
|
23
|
+
value: sampleData.name,
|
|
24
|
+
render: (type) => (type === "Cell" ? sampleData.name : null),
|
|
25
|
+
getCellProps: () => ({}),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: sampleData.age,
|
|
29
|
+
render: (type) => type === "Cell" ? sampleData.age.toString() : null,
|
|
30
|
+
getCellProps: () => ({}),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
value: sampleData.address,
|
|
34
|
+
render: (type) => (type === "Cell" ? sampleData.address : null),
|
|
35
|
+
getCellProps: () => ({}),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: sampleData.email,
|
|
39
|
+
render: (type) => (type === "Cell" ? sampleData.email : null),
|
|
40
|
+
getCellProps: () => ({}),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
value: sampleData.phone,
|
|
44
|
+
render: (type) => (type === "Cell" ? sampleData.phone : null),
|
|
45
|
+
getCellProps: () => ({}),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
value: sampleData.status,
|
|
49
|
+
render: (type) => type === "Cell" ? (_jsx("span", { className: "text-green-500", children: sampleData.status })) : null,
|
|
50
|
+
getCellProps: () => ({}),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
const cellsForRow2 = [
|
|
54
|
+
{
|
|
55
|
+
value: sampleData2.name,
|
|
56
|
+
render: (type) => (type === "Cell" ? sampleData2.name : null),
|
|
57
|
+
getCellProps: () => ({}),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
value: sampleData2.age,
|
|
61
|
+
render: (type) => type === "Cell" ? sampleData2.age.toString() : null,
|
|
62
|
+
getCellProps: () => ({}),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
value: sampleData2.address,
|
|
66
|
+
render: (type) => type === "Cell" ? sampleData2.address : null,
|
|
67
|
+
getCellProps: () => ({}),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
value: sampleData2.email,
|
|
71
|
+
render: (type) => (type === "Cell" ? sampleData2.email : null),
|
|
72
|
+
getCellProps: () => ({}),
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
value: sampleData2.phone,
|
|
76
|
+
render: (type) => (type === "Cell" ? sampleData2.phone : null),
|
|
77
|
+
getCellProps: () => ({}),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
value: sampleData2.status,
|
|
81
|
+
render: (type) => type === "Cell" ? (_jsx("span", { className: "text-red-500", children: sampleData2.status })) : null,
|
|
82
|
+
getCellProps: () => ({}),
|
|
83
|
+
},
|
|
84
|
+
];
|
|
14
85
|
const mockRow = {
|
|
15
86
|
index: 0,
|
|
16
87
|
rowUuid: sampleData.uuid,
|
|
17
|
-
cells:
|
|
18
|
-
{
|
|
19
|
-
value: sampleData.name,
|
|
20
|
-
render: (type) => type === "Cell" ? sampleData.name : null,
|
|
21
|
-
getCellProps: () => ({}),
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
value: sampleData.age,
|
|
25
|
-
render: (type) => type === "Cell" ? sampleData.age.toString() : null,
|
|
26
|
-
getCellProps: () => ({}),
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
value: sampleData.address,
|
|
30
|
-
render: (type) => type === "Cell" ? sampleData.address : null,
|
|
31
|
-
getCellProps: () => ({}),
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
value: sampleData.email,
|
|
35
|
-
render: (type) => type === "Cell" ? sampleData.email : null,
|
|
36
|
-
getCellProps: () => ({}),
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
value: sampleData.phone,
|
|
40
|
-
render: (type) => type === "Cell" ? sampleData.phone : null,
|
|
41
|
-
getCellProps: () => ({}),
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
value: sampleData.status,
|
|
45
|
-
render: (type) => type === "Cell" ? (_jsx("span", { className: "text-green-500", children: sampleData.status })) : null,
|
|
46
|
-
getCellProps: () => ({}),
|
|
47
|
-
},
|
|
48
|
-
],
|
|
88
|
+
cells: cellsForRow1,
|
|
49
89
|
getRowProps: () => ({}),
|
|
90
|
+
original: sampleData,
|
|
91
|
+
id: "0",
|
|
92
|
+
values: {
|
|
93
|
+
name: sampleData.name,
|
|
94
|
+
age: sampleData.age,
|
|
95
|
+
address: sampleData.address,
|
|
96
|
+
email: sampleData.email,
|
|
97
|
+
phone: sampleData.phone,
|
|
98
|
+
status: sampleData.status,
|
|
99
|
+
},
|
|
100
|
+
subRows: [],
|
|
101
|
+
allCells: cellsForRow1,
|
|
102
|
+
};
|
|
103
|
+
const mockRow2 = {
|
|
104
|
+
index: 1,
|
|
105
|
+
rowUuid: sampleData2.uuid,
|
|
106
|
+
cells: cellsForRow2,
|
|
107
|
+
getRowProps: () => ({}),
|
|
108
|
+
original: sampleData2,
|
|
109
|
+
id: "1",
|
|
110
|
+
values: {
|
|
111
|
+
name: sampleData2.name,
|
|
112
|
+
age: sampleData2.age,
|
|
113
|
+
address: sampleData2.address,
|
|
114
|
+
email: sampleData2.email,
|
|
115
|
+
phone: sampleData2.phone,
|
|
116
|
+
status: sampleData2.status,
|
|
117
|
+
},
|
|
118
|
+
subRows: [],
|
|
119
|
+
allCells: cellsForRow2,
|
|
50
120
|
};
|
|
51
|
-
// Mock prepareRow function
|
|
52
121
|
const prepareRow = (row) => { };
|
|
53
122
|
const meta = {
|
|
54
123
|
title: "Table/TableRow",
|
|
@@ -76,7 +145,7 @@ const meta = {
|
|
|
76
145
|
},
|
|
77
146
|
rowHoverClasses: {
|
|
78
147
|
control: "text",
|
|
79
|
-
description: "CSS classes to apply when the row is hovered. Defaults to `hover:bg-
|
|
148
|
+
description: "CSS classes to apply when the row is hovered. Defaults to `hover:bg-red-100 hover:cursor-pointer`.",
|
|
80
149
|
},
|
|
81
150
|
onRowClick: {
|
|
82
151
|
control: "function",
|
|
@@ -86,21 +155,23 @@ const meta = {
|
|
|
86
155
|
control: "number",
|
|
87
156
|
description: "The index of the currently active row. If the row's index matches this value, the row will be highlighted.",
|
|
88
157
|
},
|
|
158
|
+
hasDropDown: {
|
|
159
|
+
control: "boolean",
|
|
160
|
+
description: "Determines if the row has an expandable drop down.",
|
|
161
|
+
},
|
|
89
162
|
},
|
|
90
163
|
tags: ["autodocs"],
|
|
91
164
|
parameters: {
|
|
92
165
|
layout: "centered",
|
|
93
166
|
docs: {
|
|
94
167
|
description: {
|
|
95
|
-
component: "A table row component that renders a row of data with optional hover effects, active states, and click handlers. It supports text trimming
|
|
168
|
+
component: "A table row component that renders a row of data with optional hover effects, active states, and click handlers. It supports text trimming, custom cell rendering, and an expandable drop down with Framer Motion animations.",
|
|
96
169
|
},
|
|
97
170
|
},
|
|
98
171
|
},
|
|
99
172
|
};
|
|
100
173
|
export default meta;
|
|
101
|
-
// Template for the story
|
|
102
174
|
const Template = (args) => (_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { ...args }) }) }));
|
|
103
|
-
// Default story
|
|
104
175
|
export const Default = Template.bind({});
|
|
105
176
|
Default.args = {
|
|
106
177
|
row: mockRow,
|
|
@@ -113,83 +184,15 @@ Default.args = {
|
|
|
113
184
|
Default.parameters = {
|
|
114
185
|
docs: {
|
|
115
186
|
description: {
|
|
116
|
-
story: "Default table row with text trimming enabled.
|
|
187
|
+
story: "Default table row with text trimming enabled.",
|
|
117
188
|
},
|
|
118
189
|
},
|
|
119
190
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
ActiveRow.args = {
|
|
123
|
-
...Default.args,
|
|
124
|
-
activeIndex: 0,
|
|
125
|
-
};
|
|
126
|
-
ActiveRow.parameters = {
|
|
127
|
-
docs: {
|
|
128
|
-
description: {
|
|
129
|
-
story: "Table row with an active state. The active row is highlighted to indicate selection.",
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
// Story with custom row click handler
|
|
134
|
-
export const WithRowClickHandler = Template.bind({});
|
|
135
|
-
WithRowClickHandler.args = {
|
|
136
|
-
...Default.args,
|
|
137
|
-
onRowClick: (index, rowUuid, event) => {
|
|
138
|
-
alert(`Row clicked!\nIndex: ${index}\nRow UUID: ${rowUuid}`);
|
|
139
|
-
console.log("Row clicked:", index, rowUuid, event);
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
WithRowClickHandler.parameters = {
|
|
143
|
-
docs: {
|
|
144
|
-
description: {
|
|
145
|
-
story: "Table row with a custom click handler. The `onRowClick` prop is used to handle row click events. In this example, an alert is shown when the row is clicked.",
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
// Story with disabled text trimming
|
|
150
|
-
export const NoTrimming = Template.bind({});
|
|
151
|
-
NoTrimming.args = {
|
|
152
|
-
...Default.args,
|
|
153
|
-
globalTrimActive: false, // Disable text trimming
|
|
154
|
-
};
|
|
155
|
-
NoTrimming.parameters = {
|
|
156
|
-
docs: {
|
|
157
|
-
description: {
|
|
158
|
-
story: "Table row with text trimming disabled. The full text is displayed for each cell.",
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
};
|
|
162
|
-
// Story with custom cell rendering
|
|
163
|
-
export const CustomCellRendering = Template.bind({});
|
|
164
|
-
CustomCellRendering.args = {
|
|
165
|
-
...Default.args,
|
|
166
|
-
row: {
|
|
167
|
-
...mockRow,
|
|
168
|
-
cells: [
|
|
169
|
-
{
|
|
170
|
-
value: sampleData.name,
|
|
171
|
-
id: "name",
|
|
172
|
-
render: (type) => type === "Cell" ? _jsx("strong", { children: sampleData.name }) : null,
|
|
173
|
-
getCellProps: () => ({}),
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
value: sampleData.age,
|
|
177
|
-
id: "age",
|
|
178
|
-
render: (type) => type === "Cell" ? (_jsx("span", { className: "text-blue-500", children: sampleData.age })) : null,
|
|
179
|
-
getCellProps: () => ({}),
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
value: sampleData.address,
|
|
183
|
-
render: (type) => type === "Cell" ? sampleData.address : null,
|
|
184
|
-
getCellProps: () => ({}),
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
CustomCellRendering.parameters = {
|
|
191
|
+
export const MultipleRows = () => (_jsx("table", { children: _jsxs("tbody", { children: [_jsx(TableRow, { row: mockRow, prepareRow: prepareRow, globalTrimActive: true, rowUuid: sampleData.uuid, columnInputs: [], rowHoverClasses: "hover:bg-red-100 hover:cursor-pointer", hasDropDown: true }), _jsx(TableRow, { row: mockRow2, prepareRow: prepareRow, globalTrimActive: true, rowUuid: sampleData2.uuid, columnInputs: [], rowHoverClasses: "hover:bg-red-100 hover:cursor-pointer", hasDropDown: false })] }) }));
|
|
192
|
+
MultipleRows.parameters = {
|
|
190
193
|
docs: {
|
|
191
194
|
description: {
|
|
192
|
-
story: "Table
|
|
195
|
+
story: "Table with two rows. The first row is expandable. When expanded, its slide-down section (displaying the UUID) pushes the second row down.",
|
|
193
196
|
},
|
|
194
197
|
},
|
|
195
198
|
};
|
|
@@ -6,36 +6,47 @@ const textPositionMap = {
|
|
|
6
6
|
top: "flex flex-col items-start",
|
|
7
7
|
bottom: "flex flex-col-reverse items-start",
|
|
8
8
|
};
|
|
9
|
-
const getToggleClasses = (status, smallToggle, borderStyle, activeColorBorder, inactiveColorBorder, activeColorBackground, inactiveColorBackground) => {
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
9
|
+
const getToggleClasses = (status, smallToggle, borderStyle, activeColorBorder, inactiveColorBorder, activeColorBackground, inactiveColorBackground, inactiveCircleColor, activeCircleColor) => {
|
|
10
|
+
// Base classes without a preset border
|
|
11
|
+
const baseClasses = "peer rounded-full";
|
|
12
|
+
// Build the dynamic border class based on status.
|
|
13
|
+
// The 'border' class here sets the border width.
|
|
14
|
+
const borderClasses = `border ${status ? activeColorBorder : inactiveColorBorder}`;
|
|
15
|
+
// For toggles with a border style, we use a pseudo-element for the inner circle.
|
|
16
|
+
const borderToggleClasses = `after:absolute after:left-[4px] after:top-1 after:h-3 after:w-3 after:rounded-full ${inactiveCircleColor} after:transition-all after:content-['']`;
|
|
17
|
+
const borderToggleCircleClasses = `peer-checked:after:translate-x-full peer-checked:after:border-white ${activeCircleColor}`;
|
|
18
|
+
// For background style toggles, these classes style the inner circle.
|
|
19
|
+
const smallBackgroundToggleClasses = "after:absolute after:left-[4px] after:top-1 after:h-3 after:w-3 after:rounded-full after:transition-all after:content-['']";
|
|
20
|
+
const largeBackgroundToggleClasses = "after:absolute after:left-[3px] after:top-[4.5px] after:h-[19px] after:w-[19px] after:rounded-full after:transition-all after:content-['']";
|
|
21
|
+
// Build the final classes based on toggle type and style.
|
|
22
|
+
if (smallToggle && borderStyle) {
|
|
23
|
+
return `${baseClasses} ${borderClasses} h-[1.25rem] w-[2rem] ${borderToggleClasses} ${status ? borderToggleCircleClasses : ""}`;
|
|
24
|
+
}
|
|
25
|
+
else if (smallToggle && !borderStyle) {
|
|
26
|
+
return `${baseClasses} ${borderClasses} h-[1.25rem] w-[2rem] ${smallBackgroundToggleClasses} ${status ? "peer-checked:after:translate-x-full " : ""} ${status ? activeColorBackground : inactiveColorBackground}`;
|
|
27
|
+
}
|
|
28
|
+
else if (!smallToggle && !borderStyle) {
|
|
29
|
+
return `${baseClasses} ${borderClasses} h-7 w-11 ${largeBackgroundToggleClasses} ${status ? "peer-checked:after:translate-x-full " : ""} ${status ? activeColorBackground : inactiveColorBackground}`;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Large toggle with border style.
|
|
33
|
+
return `${baseClasses} ${borderClasses} h-7 w-11 ${largeBackgroundToggleClasses} ${status ? "peer-checked:after:translate-x-full " : ""} ${status ? activeColorBackground : inactiveColorBackground}`;
|
|
27
34
|
}
|
|
28
35
|
};
|
|
29
|
-
const ToggleButton = ({ initialStatus, onClick, id, textPosition, textSize,
|
|
36
|
+
const ToggleButton = ({ initialStatus, onClick, id, textPosition, textSize,
|
|
37
|
+
// Background colors
|
|
38
|
+
activeColorBackground = "bg-red-600", inactiveColorBackground = "bg-red-200",
|
|
39
|
+
// Border colors (active is red and inactive is blue by default)
|
|
40
|
+
activeColorBorder = "border-red-600", inactiveColorBorder = "border-blue-600", activeLabel, inactiveLabel, additionalClasses, hasDisabledStatus, hasDivider, fontFamily, activeTextColor = "text-red-700", inactiveTextColor = "text-red-400", smallToggle, pillHeight, borderStyle, inactiveCircleColor = "after:bg-red-300", activeCircleColor = "peer-checked:after:bg-red-500", }) => {
|
|
30
41
|
const handleToggle = () => {
|
|
31
42
|
const newValue = !initialStatus;
|
|
32
43
|
onClick(newValue);
|
|
33
44
|
};
|
|
34
|
-
const textColor = initialStatus
|
|
45
|
+
const textColor = initialStatus ? activeTextColor : inactiveTextColor;
|
|
35
46
|
const textPositionClasses = textPositionMap[textPosition];
|
|
36
|
-
const toggleClasses = getToggleClasses(initialStatus, smallToggle, borderStyle, activeColorBorder, inactiveColorBorder, activeColorBackground, inactiveColorBackground);
|
|
47
|
+
const toggleClasses = getToggleClasses(initialStatus, smallToggle, borderStyle, activeColorBorder, inactiveColorBorder, activeColorBackground, inactiveColorBackground, inactiveCircleColor, activeCircleColor);
|
|
37
48
|
return (_jsx("div", { className: `flex justify-center ${hasDivider && textPosition === "right"
|
|
38
49
|
? "border-r-1 border-navy-200 pr-2"
|
|
39
|
-
: ""} mr-2 ${pillHeight}`, children: hasDisabledStatus ? (_jsx("div", { className: `${pillHeight}`, children: _jsx(Text, { fontFamily: fontFamily, size: textSize, color: textColor, text: initialStatus ? activeLabel : inactiveLabel }) })) : (_jsxs("div", { className: `justify-between w-full ${textPositionClasses} ${textSize} ${textColor} ${additionalClasses}
|
|
50
|
+
: ""} mr-2 ${pillHeight}`, children: hasDisabledStatus ? (_jsx("div", { className: `${pillHeight}`, children: _jsx(Text, { fontFamily: fontFamily, size: textSize, color: textColor, text: initialStatus ? activeLabel : inactiveLabel }) })) : (_jsxs("div", { className: `justify-between w-full ${textPositionClasses} ${textSize} ${textColor} ${additionalClasses}`, children: [_jsx("label", { htmlFor: id, "data-testid": "inactive-label", className: `flex justify-center pl-2 ${smallToggle ? "min-w-10" : "min-w-20"}`, children: initialStatus ? activeLabel : inactiveLabel }), _jsxs("label", { className: "relative inline-flex cursor-pointer items-center", children: [_jsx("input", { id: id, type: "checkbox", className: "peer sr-only", checked: initialStatus, onChange: handleToggle }), _jsx("div", { className: toggleClasses })] })] })) }));
|
|
40
51
|
};
|
|
41
52
|
export default ToggleButton;
|
|
@@ -25,7 +25,7 @@ describe("<ToggleButton />", () => {
|
|
|
25
25
|
id: "toggle-button",
|
|
26
26
|
};
|
|
27
27
|
beforeEach(() => {
|
|
28
|
-
render(_jsx(ToggleButton, { ...defaultProps }));
|
|
28
|
+
render(_jsx(ToggleButton, { activeCircleColor: "", inactiveCircleColor: "", ...defaultProps }));
|
|
29
29
|
});
|
|
30
30
|
// test("renders correct element for divider", () => {
|
|
31
31
|
// const { container } = render(
|
|
@@ -68,19 +68,19 @@ describe("<ToggleButton />", () => {
|
|
|
68
68
|
expect(defaultProps.onClick).toHaveBeenCalledWith(true);
|
|
69
69
|
});
|
|
70
70
|
test("renders correct classes for small toggle", () => {
|
|
71
|
-
render(_jsx(ToggleButton, { ...defaultProps, smallToggle: true }));
|
|
71
|
+
render(_jsx(ToggleButton, { activeCircleColor: "", inactiveCircleColor: "", ...defaultProps, smallToggle: true }));
|
|
72
72
|
const toggleButton = screen.getByLabelText("Inactive")
|
|
73
73
|
.nextSibling;
|
|
74
74
|
expect(toggleButton.className).toContain("h-7");
|
|
75
75
|
expect(toggleButton.className).toContain("w-11");
|
|
76
76
|
});
|
|
77
77
|
test("renders correct disabled state", () => {
|
|
78
|
-
render(_jsx(ToggleButton, { ...defaultProps, hasDisabledStatus: true }));
|
|
78
|
+
render(_jsx(ToggleButton, { activeCircleColor: "", inactiveCircleColor: "", ...defaultProps, hasDisabledStatus: true }));
|
|
79
79
|
const disabledText = screen.getAllByText("Inactive")[1]; // Target the specific occurrence
|
|
80
80
|
expect(disabledText).toBeInTheDocument();
|
|
81
81
|
});
|
|
82
82
|
test("renders correct element for divider", async () => {
|
|
83
|
-
render(_jsx(ToggleButton, { ...defaultProps, hasDivider: true, textPosition: "right" }));
|
|
83
|
+
render(_jsx(ToggleButton, { activeCircleColor: "", inactiveCircleColor: "", ...defaultProps, hasDivider: true, textPosition: "right" }));
|
|
84
84
|
const toggleContainer = screen
|
|
85
85
|
.getByLabelText("Inactive")
|
|
86
86
|
.closest("div");
|
|
@@ -92,7 +92,7 @@ describe("<ToggleButton />", () => {
|
|
|
92
92
|
}, { timeout: 2000 });
|
|
93
93
|
});
|
|
94
94
|
test("handles custom text size class", () => {
|
|
95
|
-
render(_jsx(ToggleButton, { ...defaultProps, textSize: "2xl" }));
|
|
95
|
+
render(_jsx(ToggleButton, { activeCircleColor: "", inactiveCircleColor: "", ...defaultProps, textSize: "2xl" }));
|
|
96
96
|
// Use `getByText` with a more specific query
|
|
97
97
|
const inactiveLabel = screen
|
|
98
98
|
.getAllByText("Inactive")
|