@agilant/toga-blox 1.0.109 → 1.0.111

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.
@@ -9,7 +9,6 @@ const Dropdown = ({ options, selectedOption, onOptionSelect, optionClasses = "fl
9
9
  }, selectedOptionBgColor = "bg-gray-50", optionHoverBgColor = "hover:bg-gray-50", }) => {
10
10
  const [showMenu, setShowMenu] = useState(false);
11
11
  const toggleMenu = () => setShowMenu(!showMenu);
12
- console.log(options, "DROP DOWN OPTIONS");
13
12
  return (_jsxs("div", { className: `flex items-center justify-between relative min-w-40 ${dropdownClasses}`, children: [_jsxs("div", { onClick: toggleMenu, className: "flex cursor-pointer items-center group h-full", children: [_jsx("div", { className: `font-bold ${optionClasses} bg-white`, children: selectedOption.label }), _jsx("div", { className: `transform transition-transform duration-200 mx-1 px-1 rounded-full relative ${icon.iconClasses} ${showMenu ? "rotate-180" : "rotate-0"}`, "data-testid": "dropdown-icon", children: getFontAwesomeIcon(icon.name) })] }), showMenu && (_jsx(AnimatePresence, { children: showMenu && (_jsx(motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, className: `absolute top-0 z-10 right-0 left-0 ${menuClasses}`, children: _jsx("ul", { children: options.map((option) => (_jsxs("li", { className: `text-left px-4 py-2 cursor-pointer border-b bg-white ${option.value ===
14
13
  selectedOption.value
15
14
  ? `${selectedOptionBgColor} font-semibold`
@@ -14,7 +14,7 @@ interface InputFieldProps {
14
14
  toolTipText?: string;
15
15
  onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
16
16
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
17
- checked?: boolean extends InputFieldProps["type"] ? boolean : undefined;
17
+ checked?: boolean;
18
18
  id?: string;
19
19
  name?: string;
20
20
  additionalClasses?: string;
@@ -30,5 +30,9 @@ interface InputFieldProps {
30
30
  focusRingColor?: string;
31
31
  firstIconClasses?: string;
32
32
  }
33
- declare const InputField: React.ForwardRefExoticComponent<InputFieldProps & React.RefAttributes<unknown>>;
33
+ /**
34
+ * A properly formed forwardRef component: exactly two parameters:
35
+ * (props, ref). We pass `ref` to the <input ref={ref} ...>.
36
+ */
37
+ declare const InputField: React.ForwardRefExoticComponent<InputFieldProps & React.RefAttributes<HTMLInputElement>>;
34
38
  export default InputField;
@@ -1,10 +1,14 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useState } from "react";
2
3
  import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
3
4
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
- import { useState, forwardRef } from "react";
5
- const InputField = forwardRef(({ label, placeholder, required = false, checked, id, name, type = "text", firstIcon, secondIcon, iconPosition = "before", iconColor = "primary", isValid = true, isReadOnly = false, onChange, value, readOnlyInfo = "", toolTipText = "", hasToolTip = false, additionalClasses = "", labelClasses = "", hasAutoFocus, onIconClick, onKeyDown, disabled, register, focusRingColor = "focus:ring-transparent", firstIconClasses, }) => {
5
+ /**
6
+ * A properly formed forwardRef component: exactly two parameters:
7
+ * (props, ref). We pass `ref` to the <input ref={ref} ...>.
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, }, ref) {
6
10
  const [isFocused, setIsFocused] = useState(false);
7
- const hasValue = value != null && !!value.toString().trim(); // Check if input value has at least one non-space character
11
+ const hasValue = value != null && !!value.toString().trim();
8
12
  const isNumberInput = type === "number";
9
13
  let formattedValue = isNumberInput &&
10
14
  value != null &&
@@ -12,9 +16,14 @@ const InputField = forwardRef(({ label, placeholder, required = false, checked,
12
16
  isNaN(Number(value))
13
17
  ? ""
14
18
  : value;
19
+ // Example: sometimes number formatting can produce "NaN":
15
20
  if (formattedValue === "$NaN") {
16
21
  formattedValue = "";
17
22
  }
23
+ const registerProps = register
24
+ ? register(name || "", { required })
25
+ : {};
26
+ // Render icons
18
27
  const renderFirstIcon = () => {
19
28
  if (!firstIcon)
20
29
  return null;
@@ -22,16 +31,18 @@ const InputField = forwardRef(({ label, placeholder, required = false, checked,
22
31
  ? "text-gray-500"
23
32
  : isValid
24
33
  ? `text-${iconColor}`
25
- : "text-redText"}`, children: _jsx(_Fragment, { children: firstIcon }) }));
34
+ : "text-redText"}`, children: typeof firstIcon === "function" ? firstIcon() : firstIcon }));
26
35
  };
27
36
  const renderSecondIcon = () => {
28
37
  if (!secondIcon)
29
38
  return null;
30
- return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--second-icon absolute top-2 right-4 text-${disabled
39
+ return (_jsx("span", { onClick: onIconClick, className: `input-icon input-icon--second-icon absolute top-2 right-4 ${disabled
31
40
  ? "text-gray-500"
32
41
  : isValid
33
42
  ? `text-${iconColor}`
34
- : "text-redText"}`, children: _jsx(_Fragment, { children: secondIcon }) }));
43
+ : "text-redText"}`, children: typeof secondIcon === "function"
44
+ ? secondIcon()
45
+ : secondIcon }));
35
46
  };
36
47
  const renderIcons = () => {
37
48
  switch (iconPosition) {
@@ -45,25 +56,29 @@ const InputField = forwardRef(({ label, placeholder, required = false, checked,
45
56
  return null;
46
57
  }
47
58
  };
48
- const registerProps = register
49
- ? register(name || "", { required })
50
- : {};
51
- return isReadOnly ? (_jsxs("div", { className: "input-wrapper relative", children: [renderIcons(), _jsxs("label", { htmlFor: id, className: `block font-light text-left mb-1 ${labelClasses} `, children: [label, hasToolTip && (_jsxs("span", { className: "pl-4 group", children: [_jsx(FontAwesomeIcon, { icon: faCircleInfo, className: "text-primary group-hover:text-blue-600" }), _jsx("span", { className: "opacity-0 group-hover:opacity-100 bg-gray-800 text-white text-sm rounded-md px-2 py-1 absolute top-[-14px]", children: toolTipText })] }))] }), _jsx("div", { className: `
52
- text-left focus:outline-none focus:ring-2 block w-full py-2 px-2 rounded-lg shadow-input outline outline-0 outline-barelyPrimary focus:outline-4 md:w-full lg:w-full xl:w-full
53
- ${firstIcon ? "pl-10" : ""}
54
- ${secondIcon ? "pr-10" : ""}
55
- ${additionalClasses}
56
- `, children: readOnlyInfo }), iconPosition === "after" && renderSecondIcon()] })) : (_jsxs(_Fragment, { children: [label && (_jsxs("label", { htmlFor: id, className: ` block font-light text-left mb-1 ${labelClasses}`, children: [label, hasToolTip && (_jsxs("span", { className: "pl-4 group", children: [_jsx(FontAwesomeIcon, { icon: faCircleInfo, className: "text-primary group-hover:text-blue-600" }), _jsx("span", { className: "opacity-0 group-hover:opacity-100 bg-gray-800 text-white text-sm rounded-md px-2 py-1 absolute top-[-14px]", children: toolTipText })] }))] })), _jsxs("div", { className: " input-wrapper relative", children: [renderIcons(), _jsx("input", { autoComplete: "", ...registerProps, className: `focused:ring-0 ${focusRingColor} focus:ring-1
57
- focus:outline-none
58
- ${disabled
59
- ? "border-gray-500 focus:ring-gray-500"
60
- : isValid
61
- ? ""
62
- : "border-redText focus:ring-red-500"} block w-full py-2 px-2
63
- ${firstIcon ? "pl-10" : ""}
64
- ${secondIcon ? "pr-10" : ""}
65
- outline outline-0 outline-barelyPrimary focus:outline-4 md:w-full lg:w-full ${isFocused ? "hover:border-transparent" : ""} ${isFocused && !disabled
66
- ? ` ${isValid ? "" : "shadow-redText"}`
67
- : disabled} ${additionalClasses}`, 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()] })] }));
59
+ // If it's read-only, we show readOnlyInfo instead of an actual <input>
60
+ if (isReadOnly) {
61
+ 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: `
62
+ text-left focus:outline-none focus:ring-2 block w-full py-2 px-2 rounded-lg
63
+ ${firstIcon ? "pl-10" : ""}
64
+ ${secondIcon ? "pr-10" : ""}
65
+ ${additionalClasses}
66
+ `, children: readOnlyInfo })] }));
67
+ }
68
+ // Normal input mode
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
+ ${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
+ ${disabled ? "border-gray-500 focus:ring-gray-500" : ""}
77
+ ${isValid ? "" : "border-redText focus:ring-red-500"}
78
+ ${firstIcon ? "pl-10" : ""}
79
+ ${secondIcon ? "pr-10" : ""}
80
+ ${isFocused ? "hover:border-transparent" : ""}
81
+ ${additionalClasses}
82
+ `, 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 })] })] }));
68
83
  });
69
84
  export default InputField;
@@ -5,15 +5,48 @@ const MultiSelectInput = ({ id, name, options = [], selectedValue = [], onChange
5
5
  text: "Select...",
6
6
  icon: "",
7
7
  iconStyle: "regular",
8
- }, isSearchable = true, isOpen, hasSelectAll = false, disabled = false, isLoading = false, onMenuToggle, overrideStrings, className, width = "w-72", isBoolean = false, otherProps, }) => {
8
+ }, isSearchable = true, isOpen, hasSelectAll = false, disabled = false, isLoading = false, onMenuToggle, overrideStrings, className, width = "w-72", isBoolean = false, otherProps, setInputSearchValue, }) => {
9
+ // Convert your incoming options to the shape expected by react-multi-select-component
9
10
  const multiSelectOptions = options.map((option) => ({
10
11
  label: option.name,
11
12
  value: option.value,
12
13
  }));
14
+ // Convert the "selectedValue" prop similarly
13
15
  const multiSelectValue = selectedValue.map((item) => ({
14
16
  label: item.name,
15
17
  value: item.value,
16
18
  }));
19
+ function filterOptions(baseOptions, searchText) {
20
+ const footer = baseOptions.find((option) => option.value === "__footer__");
21
+ if (!searchText) {
22
+ // If the parent is already 0, don't set it again
23
+ setInputSearchValue?.((prevCount) => {
24
+ if (prevCount !== 0)
25
+ return 0;
26
+ return prevCount; // no change => no re-render
27
+ });
28
+ return baseOptions;
29
+ }
30
+ // Normal filter
31
+ const filtered = baseOptions.filter((option) => {
32
+ if (option.value === "__footer__")
33
+ return false;
34
+ return option.label
35
+ .toLowerCase()
36
+ .includes(searchText.toLowerCase());
37
+ });
38
+ // Only update if it's different from current
39
+ setInputSearchValue?.((prevCount) => {
40
+ const newCount = filtered.length;
41
+ if (newCount !== prevCount)
42
+ return newCount;
43
+ return prevCount;
44
+ });
45
+ if (footer) {
46
+ return [...filtered, footer];
47
+ }
48
+ return filtered;
49
+ }
17
50
  const valueRenderer = (selected, _options) => {
18
51
  if (!selected || selected.length === 0) {
19
52
  return (_jsxs("span", { className: "flex items-center gap-2 text-gray-500", children: [placeholder?.icon
@@ -28,6 +61,7 @@ const MultiSelectInput = ({ id, name, options = [], selectedValue = [], onChange
28
61
  const handleSelectionChange = (selectedOptions) => {
29
62
  let finalSelection = selectedOptions;
30
63
  if (isBoolean && selectedOptions.length > 0) {
64
+ // If isBoolean is true, only allow one selection (last one clicked)
31
65
  finalSelection = [selectedOptions[selectedOptions.length - 1]];
32
66
  }
33
67
  const mapped = finalSelection.map((opt) => ({
@@ -36,8 +70,8 @@ const MultiSelectInput = ({ id, name, options = [], selectedValue = [], onChange
36
70
  }));
37
71
  onChange(mapped);
38
72
  };
39
- return (_jsx("div", { className: width, children: _jsx(MultiSelect, { id: id, name: name, className: className, options: multiSelectOptions, value: multiSelectValue, onChange: handleSelectionChange, disableSearch: !isSearchable || isBoolean, isOpen: isOpen, hasSelectAll: hasSelectAll, disabled: disabled, isLoading: isLoading, onMenuToggle: onMenuToggle, overrideStrings: {
73
+ return (_jsx("div", { className: `${width} `, children: _jsx(MultiSelect, { id: id, name: name, className: className, options: multiSelectOptions, value: multiSelectValue, onChange: handleSelectionChange, disableSearch: !isSearchable || isBoolean, isOpen: isOpen, hasSelectAll: hasSelectAll, disabled: disabled, isLoading: isLoading, onMenuToggle: onMenuToggle, overrideStrings: {
40
74
  ...overrideStrings,
41
- }, labelledBy: "Select", valueRenderer: valueRenderer, ...otherProps }) }));
75
+ }, labelledBy: "Select", valueRenderer: valueRenderer, filterOptions: filterOptions, ...otherProps }) }));
42
76
  };
43
77
  export default MultiSelectInput;
@@ -30,4 +30,5 @@ export interface MultiSelectInputProps {
30
30
  width?: string;
31
31
  isBoolean?: boolean;
32
32
  otherProps?: any;
33
+ setInputSearchValue?: React.Dispatch<React.SetStateAction<number>>;
33
34
  }
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { MultiSelectInputProps, OptionType } from "../MultiSelect/MultiSelect.types";
2
+ import { OptionType } from "../MultiSelect/MultiSelect.types";
3
3
  interface SearchDropdownInputProps {
4
4
  options?: OptionType[];
5
5
  selectedValue?: OptionType[];
@@ -18,9 +18,8 @@ interface SearchDropdownInputProps {
18
18
  [key: string]: any;
19
19
  };
20
20
  setEditingHeader?: React.Dispatch<React.SetStateAction<any>>;
21
- /** localStorage key used to store the entire “searchCriteria” array */
22
21
  localStorageKey?: string;
23
- otherProps?: MultiSelectInputProps["otherProps"];
22
+ otherProps?: any;
24
23
  additionalClasses?: string;
25
24
  clearText?: string;
26
25
  clearTextColor?: string;
@@ -28,6 +27,8 @@ interface SearchDropdownInputProps {
28
27
  buttonColor?: string;
29
28
  isBoolean?: boolean;
30
29
  isSearchable?: boolean;
30
+ fontFamily?: string;
31
+ pillColor?: string;
31
32
  }
32
33
  declare const SearchDropdownInput: React.FC<SearchDropdownInputProps>;
33
34
  export default SearchDropdownInput;
@@ -1,11 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect } from "react";
3
- import MultiSelectInput from "../MultiSelect/MultiSelect";
2
+ import { useEffect, useState } from "react";
3
+ import MultiSelectInput from "../MultiSelect/MultiSelect"; // Adjust path as needed
4
4
  import updateLocalStorage from "../../utils/updateLocalStorage";
5
+ import Badge from "../Badge";
6
+ import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
7
+ import Text from "../Text";
5
8
  const DEFAULT_STORAGE_KEY = "searchCriteria";
6
- const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, placeholder = "Select", disabled = false, hasSelectAll = true, bgColor = "bg-sky-500", textHighlight = "text-sky-700", handleFilter, searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, clearText = "Clear", clearTextColor = "text-sky-500", buttonText = "Filter", buttonColor = "bg-sky-500", localStorageKey = DEFAULT_STORAGE_KEY, isBoolean = false, isSearchable, ...rest }) => {
7
- // Are we able to store filters for this column?
9
+ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, placeholder = "Select", disabled = false, hasSelectAll = true, bgColor = "bg-sky-500", textHighlight = "text-sky-700", handleFilter, searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, clearText = "Clear", clearTextColor = "text-sky-500", buttonText = "Filter", buttonColor = "bg-sky-500", localStorageKey = DEFAULT_STORAGE_KEY, isBoolean = false, isSearchable, fontFamily, pillColor, ...rest }) => {
8
10
  const canStore = !!column?.id && !!setSearchCriteria;
11
+ // IMPORTANT: Start at 0, not options.length.
12
+ // This is the # of items matched by the child's filter, updated live.
13
+ const [filteredCount, setFilteredCount] = useState(0);
14
+ // On mount, read localStorage if we have a stored selection for this column
9
15
  useEffect(() => {
10
16
  if (!canStore)
11
17
  return;
@@ -14,7 +20,7 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
14
20
  return;
15
21
  try {
16
22
  const parsed = JSON.parse(stored);
17
- const existing = parsed.find((c) => c.searchColumn?.id === column.id);
23
+ const existing = parsed.find((c) => c.searchColumn?.id === column?.id);
18
24
  if (existing && setSearchItems) {
19
25
  const raw = existing.submittedSearchText;
20
26
  setSearchItems([raw]);
@@ -36,6 +42,7 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
36
42
  onChange,
37
43
  options,
38
44
  ]);
45
+ // Called when user clicks the "Filter" button in the footer
39
46
  const handleFooterFilter = () => {
40
47
  const actualSelections = selectedValue.filter((opt) => opt.value !== "__footer__" && opt.label !== "Select All");
41
48
  const selectedLabels = actualSelections
@@ -47,15 +54,17 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
47
54
  return;
48
55
  }
49
56
  if (isEmpty) {
57
+ // Remove from local storage
50
58
  setSearchCriteria?.((prev) => {
51
- const newCriteria = prev.filter((c) => c.searchColumn.id !== column.id);
59
+ const newCriteria = prev.filter((c) => c.searchColumn.id !== column?.id);
52
60
  updateLocalStorage(newCriteria, localStorageKey);
53
61
  return newCriteria;
54
62
  });
55
63
  }
56
64
  else {
65
+ // Store to local storage
57
66
  setSearchCriteria?.((prev) => {
58
- const filtered = prev.filter((c) => c.searchColumn.id !== column.id);
67
+ const filtered = prev.filter((c) => c.searchColumn.id !== column?.id);
59
68
  const newCriteria = [
60
69
  ...filtered,
61
70
  {
@@ -70,11 +79,12 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
70
79
  setEditingHeader?.(null);
71
80
  handleFilter?.();
72
81
  };
82
+ // Called when user clicks Clear
73
83
  const handleClear = () => {
74
84
  onChange([]);
75
85
  if (canStore) {
76
86
  setSearchCriteria?.((prev) => {
77
- const newCriteria = prev.filter((c) => c.searchColumn.id !== column.id);
87
+ const newCriteria = prev.filter((c) => c.searchColumn.id !== column?.id);
78
88
  updateLocalStorage(newCriteria, localStorageKey);
79
89
  return newCriteria;
80
90
  });
@@ -82,18 +92,20 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
82
92
  setEditingHeader?.(null);
83
93
  }
84
94
  };
95
+ // We add a “footer” item to place a Filter button, etc., at the bottom
85
96
  const footerOption = [{ name: "", value: "__footer__" }];
86
97
  const extendedOptions = [...options, ...footerOption];
98
+ // Custom item renderer referencing the parent's filteredCount
87
99
  const itemRenderer = ({ option, checked, disabled, onClick }) => {
88
100
  if (option.value === "__footer__") {
89
- return (_jsxs("div", { className: "footer px-4 py-2 flex justify-between ", children: [_jsx("div", { role: "button", className: `${textHighlight}`, onClick: handleClear, children: "Clear" }), _jsx("button", { type: "button", className: `${bgColor} text-white px-3 py-1 rounded bg-red-500`, onClick: (e) => {
101
+ return (_jsxs("div", { className: "\n footer\n px-4 py-2\n flex justify-between items-center\n text-gray-300\n border-t border-gray-300\n ", children: [filteredCount === 0 ? (_jsx("div", { onClick: handleClear, className: `${textHighlight} cursor-pointer`, children: clearText })) : (_jsxs("div", { children: [filteredCount, " Results"] })), _jsx("button", { type: "button", className: `${bgColor} ${fontFamily} text-white px-3 py-1 rounded-full`, onClick: (e) => {
90
102
  e.stopPropagation();
91
103
  handleFooterFilter();
92
104
  }, children: buttonText })] }));
93
105
  }
94
- // If it's the "Select All" item
106
+ // If it's the "Select All" item => do something special here
95
107
  if (option.label === "Select All") {
96
- return (_jsxs("label", { className: "select-all-item", style: {
108
+ return (_jsxs("label", { className: "select-all-item flex justify-between items-center px-4 cursor-pointer", style: {
97
109
  display: "flex",
98
110
  alignItems: "center",
99
111
  padding: "0.5rem 1rem",
@@ -104,17 +116,24 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
104
116
  }, onClick: (e) => {
105
117
  e.stopPropagation();
106
118
  onClick(e);
107
- }, children: [_jsx("input", { type: "checkbox", checked: checked, readOnly: true, disabled: disabled }), _jsx("span", { style: { marginLeft: "0.5rem" }, children: option.label })] }));
119
+ }, children: [_jsxs("div", { children: [_jsx("input", { type: "checkbox", checked: checked, readOnly: true, disabled: disabled }), _jsx("span", { style: { marginLeft: "0.5rem" }, children: option.label })] }), selectedValue.length > 0 && (
120
+ // Example badge if you want a count
121
+ _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", onClick: () => console.log("Select All Badge clicked"), text: _jsx(Text, { color: "text-white", fontFamily: fontFamily, size: "text-sm", tag: "span", text: `${selectedValue.length} picked` }), badgeContainerClasses: `${pillColor} p-1 max-w-fit rounded-full flex justify-between items-center text-white text-xs px-4 border-none`, type: "span" }, option.value))] }));
108
122
  }
123
+ // Normal item
109
124
  return (_jsxs("div", { className: "item px-4 py-1 cursor-pointer flex items-center", onClick: (e) => onClick(option, e), children: [_jsx("input", { type: "checkbox", checked: checked, readOnly: true, disabled: disabled }), _jsx("span", { className: "ml-2", children: option.label })] }));
110
125
  };
111
126
  return (_jsx(MultiSelectInput, { options: extendedOptions, selectedValue: selectedValue, onChange: onChange, placeholder: {
112
127
  text: placeholder,
113
128
  icon: "magnifyingGlass",
114
129
  iconStyle: "regular",
115
- }, disabled: disabled, hasSelectAll: isBoolean ? false : true, otherProps: {
130
+ }, disabled: disabled, hasSelectAll: isBoolean ? false : hasSelectAll,
131
+ // Provide our custom item renderer
132
+ otherProps: {
116
133
  ItemRenderer: itemRenderer,
117
134
  ...rest.otherProps,
118
- }, isBoolean: isBoolean, isSearchable: isSearchable, ...rest }));
135
+ }, isBoolean: isBoolean, isSearchable: isSearchable,
136
+ // The child calls this to update how many items are matched by the current search
137
+ setInputSearchValue: setFilteredCount, ...rest }));
119
138
  };
120
139
  export default SearchDropdownInput;
@@ -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, }) => {
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, }) => {
12
12
  const containerRef = useRef(null);
13
13
  const inputRef = useRef(null);
14
14
  useEffect(() => {
@@ -21,9 +21,9 @@ const SearchInput = ({ textHighlight = "text-sky-500", inputType = "text", dropd
21
21
  //will remove the filter options from the badge shown in the input
22
22
  removePattern: removePattern, textHighlight: textHighlight }));
23
23
  case "number":
24
- 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 }));
24
+ 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 }));
25
25
  case "multiSelect":
26
- 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 }));
26
+ 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 }));
27
27
  case "date":
28
28
  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 }));
29
29
  default:
@@ -1,6 +1,9 @@
1
1
  import { Meta } from "@storybook/react";
2
2
  declare const _default: Meta;
3
3
  export default _default;
4
+ /**
5
+ * 5) Create different stories from the template.
6
+ */
4
7
  export declare const Default: any;
5
8
  export declare const TextInput: any;
6
9
  export declare const NumberInput: any;
@@ -1,10 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import SearchInput from "./SearchInput";
3
- import { useState } from "react";
3
+ import { useState, useCallback, useMemo } from "react";
4
+ // 1) Provide a stable "mock column"
4
5
  const mockColumn = {
5
6
  id: "mockColumn",
6
7
  Header: "Mock Column",
7
8
  };
9
+ // 2) We define stable arrays for the controls to avoid re-creating them
10
+ const textDropdownOptions = [
11
+ { label: "Starts with", value: "startsWith" },
12
+ { label: "Ends with", value: "endsWith" },
13
+ { label: "Exactly", value: "exactly" },
14
+ { label: "Includes", value: "includes" },
15
+ { label: "Excludes", value: "excludes" },
16
+ ];
17
+ const multiSelectOptions = [
18
+ { uuid: "1", name: "Option 1", value: "option1" },
19
+ { uuid: "2", name: "Option 2", value: "option2" },
20
+ { uuid: "3", name: "Option 3", value: "option3" },
21
+ ];
22
+ // 3) Standard default export
8
23
  export default {
9
24
  title: "Components/SearchInput",
10
25
  component: SearchInput,
@@ -39,7 +54,13 @@ export default {
39
54
  },
40
55
  parameters: { layout: "centered" },
41
56
  };
57
+ /**
58
+ * 4) Our template story
59
+ * - We store state for things like selectedValue, searchItems, etc.
60
+ * - We memoize certain arrays & callbacks to avoid re-creating them every render.
61
+ */
42
62
  const Template = (args) => {
63
+ // 4A) State for various input behaviors
43
64
  const [selectedOption, setSelectedOption] = useState(args.selectedDropdownOption);
44
65
  const [searchItems, setSearchItems] = useState([]);
45
66
  const [toggleStatus, setToggleStatus] = useState(false);
@@ -55,39 +76,44 @@ const Template = (args) => {
55
76
  const [searchCriteria, setSearchCriteria] = useState([]);
56
77
  // For controlling "editingHeader"
57
78
  const [editingHeader, setEditingHeader] = useState(0);
58
- // Log current state to verify updates.
79
+ // Just for debugging. Remove if it triggers too many logs:
59
80
  console.log("Template render: editingHeader =", editingHeader);
60
81
  console.log("Template render: searchCriteria =", searchCriteria);
61
- // For multiSelect changes (or other input changes)
62
- const handleOnChange = (newSelected) => {
82
+ /**
83
+ * 4B) Memoize your arrays & callbacks
84
+ * If the user passes them in as story args, that might be stable enough,
85
+ * but we can do it again here just in case.
86
+ */
87
+ const stableDropdownOptions = useMemo(() => args.dropdownOptions || [], [args.dropdownOptions]);
88
+ const handleOnChange = useCallback((newSelected) => {
63
89
  setSelectedValue(newSelected);
90
+ // If the story user provided an onChange, call it
64
91
  args.onChange?.(newSelected);
65
92
  console.log("Selected items:", newSelected);
66
- };
67
- return (_jsx(SearchInput, { ...args, column: mockColumn,
68
- // Our local states
69
- selectedDropdownOption: selectedOption, onDropdownOptionSelect: (option) =>
93
+ }, [args]);
94
+ const handleDropdownOptionSelect = useCallback((option) => {
70
95
  // Transform the received object into an OptionType.
71
96
  setSelectedOption({
72
97
  uuid: "dummy-id", // You can generate or pass a real uuid here.
73
98
  label: option.label,
74
99
  value: option.value,
75
100
  name: "dummy-name",
76
- }), 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,
77
- // Keep handleFilter from the args or provide a custom
78
- handleFilter: args.handleFilter }));
101
+ });
102
+ }, []);
103
+ return (_jsx(SearchInput, { ...args, column: mockColumn,
104
+ // States from the story
105
+ 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",
106
+ // Overwrite the dropdownOptions with our memoized version
107
+ dropdownOptions: stableDropdownOptions }));
79
108
  };
109
+ /**
110
+ * 5) Create different stories from the template.
111
+ */
80
112
  export const Default = Template.bind({});
81
113
  Default.args = {
82
114
  inputType: "text",
83
115
  handleFilter: () => console.log("Filter applied"),
84
- dropdownOptions: [
85
- { label: "Starts with", value: "startsWith" },
86
- { label: "Ends with", value: "endsWith" },
87
- { label: "Exactly", value: "exactly" },
88
- { label: "Includes", value: "includes" },
89
- { label: "Excludes", value: "excludes" },
90
- ],
116
+ dropdownOptions: textDropdownOptions,
91
117
  selectedDropdownOption: { label: "Starts with", value: "startsWith" },
92
118
  };
93
119
  export const TextInput = Template.bind({});
@@ -101,13 +127,8 @@ TextInput.args = {
101
127
  name: "chevronDown",
102
128
  weight: "solid",
103
129
  },
104
- dropdownOptions: [
105
- "Starts with",
106
- "Ends with",
107
- "Exactly",
108
- "Includes",
109
- "Excludes",
110
- ],
130
+ // Use a stable array for the story
131
+ dropdownOptions: textDropdownOptions,
111
132
  selectedDropdownOption: { label: "Starts with", value: "startsWith" },
112
133
  };
113
134
  export const NumberInput = Template.bind({});
@@ -133,11 +154,8 @@ DropdownInput.args = {
133
154
  inputType: "multiSelect",
134
155
  handleFilter: () => console.log("Filter applied"),
135
156
  placeholder: "Search",
136
- dropdownOptions: [
137
- { uuid: "1", name: "Option 1", value: "option1" },
138
- { uuid: "2", name: "Option 2", value: "option2" },
139
- { uuid: "3", name: "Option 3", value: "option3" },
140
- ],
157
+ // Provide stable array of multiSelect items
158
+ dropdownOptions: multiSelectOptions,
141
159
  selectedValue: [],
142
160
  isSearchable: true,
143
161
  hasSelectAll: true,
@@ -178,20 +196,9 @@ DatePickerInput.args = {
178
196
  ],
179
197
  selectedDropdownOption: { label: "Starts with", value: "startsWith" },
180
198
  onDropdownOptionSelect: (option) => console.log(`Option selected: ${option}`),
181
- /**
182
- * IMPORTANT:
183
- * DO NOT override 'searchItems' or 'setSearchItems' with no-ops
184
- * or you lose the local state from the Template.
185
- *
186
- * DO NOT pass toggleStatus, setToggleStatus as no-ops, or you won't see range toggling.
187
- *
188
- * Keep them out so we use the Template's state-based hooking.
189
- */
190
- // Theming for DayPicker
191
199
  themeBgColor: "bg-sky-500",
192
200
  lightThemeBg: "bg-sky-100",
193
201
  toggleTextColor: "text-green-500",
194
202
  toggleColor: "bg-green-500",
195
- // If you want local-storage logic for date filtering:
196
- column: { id: "dateColumn" }, // real or mock
203
+ column: { id: "dateColumn" },
197
204
  };
@@ -40,6 +40,8 @@ type SearchNumberInputProps<T extends object> = {
40
40
  themeBgColor?: string;
41
41
  toggleColor?: string;
42
42
  toggleTextColor?: string;
43
+ removePattern?: RegExp | string;
44
+ fontFamily?: string;
43
45
  };
44
46
  /**
45
47
  * A numeric filter component that:
@@ -47,5 +49,5 @@ type SearchNumberInputProps<T extends object> = {
47
49
  * 2. On Filter => either remove or store a string in localStorage
48
50
  * 3. On mount => read any existing filter for this column, parse, and set min/max
49
51
  */
50
- 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, }: SearchNumberInputProps<T>) => import("react/jsx-runtime").JSX.Element;
52
+ 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, }: SearchNumberInputProps<T>) => import("react/jsx-runtime").JSX.Element;
51
53
  export default SearchNumberInput;
@@ -1,10 +1,14 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useCallback } from "react";
3
3
  import { Input } from "../Input";
4
4
  import Dropdown from "../Dropdown/Dropdown";
5
5
  import ToggleButton from "../ToggleButton/ToggleButton";
6
6
  import BaseButton from "../BaseButton";
7
7
  import Text from "../Text";
8
+ import { getFontAwesomeIcon } from "../../utils/getFontAwesomeIcon";
9
+ import { getCleanedText } from "../../utils/getCleanedText";
10
+ import Badge from "../Badge";
11
+ import updateLocalStorage from "../../utils/updateLocalStorage";
8
12
  const DEFAULT_STORAGE_KEY = "searchCriteria";
9
13
  /**
10
14
  * A numeric filter component that:
@@ -18,7 +22,7 @@ const SearchNumberInput = ({ textHighlight = "text-sky-500", dropdownIconProp =
18
22
  weight: "solid",
19
23
  }, dropdownOptions = [], selectedDropdownOption = { label: "", value: "" }, onDropdownOptionSelect, toggleStatus = false, setToggleStatus, minValue = "", setMinValue, maxValue = "", setMaxValue, handleFilter,
20
24
  // local-storage
21
- searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey = DEFAULT_STORAGE_KEY, themeBgColor = "bg-sky-500", toggleColor = "bg-sky-500", toggleTextColor = "text-black", }) => {
25
+ searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, localStorageKey = DEFAULT_STORAGE_KEY, themeBgColor = "bg-sky-500", toggleColor = "bg-sky-500", toggleTextColor = "text-black", pillColor, fontFamily, removePattern, }) => {
22
26
  const containerRef = useRef(null);
23
27
  const inputRef = useRef(null);
24
28
  /** Decide if we can store for this column */
@@ -147,12 +151,25 @@ searchItems = [], setSearchItems, setSearchCriteria, column, setEditingHeader, l
147
151
  // Let the parent know a filter was applied
148
152
  handleFilter?.();
149
153
  };
150
- return (_jsx("div", { ref: containerRef, className: "w-[425px]", children: _jsxs("div", { className: "flex flex-col p-4 h-[130px] border-2 border-navy-200 rounded-md", children: [_jsx("div", { className: `flex flex-[1] ${toggleStatus ? "" : "border-2"}
151
- h-full max-h-11 items-center justify-around`, children: toggleStatus ? (_jsxs(_Fragment, { 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" })] })) : (
154
+ const handleSearchBadgeClick = (item) => {
155
+ const newSearchItems = searchItems.filter((ele) => ele !== item);
156
+ setSearchItems && setSearchItems(newSearchItems);
157
+ setSearchCriteria((prev) => {
158
+ const newCriteria = prev.filter((crit) => crit.submittedSearchText !== item);
159
+ updateLocalStorage(newCriteria, localStorageKey);
160
+ console.log("Removed badge criterion, newCriteria:", newCriteria);
161
+ return newCriteria;
162
+ });
163
+ };
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" })] })) : (
152
166
  // Single value mode
153
167
  _jsxs(_Fragment, { children: [_jsx(Dropdown, { options: dropdownOptions, selectedOption: selectedDropdownOption || {
154
168
  label: "",
155
169
  value: "",
156
- }, onOptionSelect: onDropdownOptionSelect, optionClasses: "px-4 h-full flex items-center", menuClasses: "bg-white w-min-[150px] top-[-8px] left-[-2px]", dropdownClasses: "border-0 w-auto", icon: dropdownIconProp }), _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 ", placeholder: "Amount", hasIcons: true, iconPosition: "both" })] })) }), _jsxs("div", { className: "flex flex-[1] justify-between items-end bg-white px-2", 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: false, borderStyle: false }), _jsx(BaseButton, { text: "Filter", backgroundColor: themeBgColor, additionalClasses: "py-1.5 px-6 text-white", borderColor: "border-none", onClick: handleFilterClick, shape: "rounded-full" })] })] }) }));
170
+ }, onOptionSelect: onDropdownOptionSelect, optionClasses: "px-4 h-full flex items-center", menuClasses: "bg-white w-min-[150px] top-[-8px] left-[-2px]", dropdownClasses: "border-0 w-auto", icon: dropdownIconProp }), _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 ", placeholder: "Amount", hasIcons: true, iconPosition: "both" })] })) }), _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: false, borderStyle: false }), _jsx(BaseButton, { text: "Filter", backgroundColor: themeBgColor, additionalClasses: "py-1.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
+ const cleanedText = getCleanedText(item, removePattern);
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
+ }) }) })) : null] }) }));
157
174
  };
158
175
  export default SearchNumberInput;
@@ -91,9 +91,7 @@ const SearchTextInput = ({ pillColor = "bg-sky-500", textHighlight = "text-sky-5
91
91
  };
92
92
  return (_jsx("div", { ref: containerRef, className: "w-[425px]", 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", icon: dropdownIconProp, dropdownClasses: "border-0 border-r-2 w-auto " }), _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-9", 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", onClick: () => setLocalSearchText(""), "data-testid": "clear-icon", children: getFontAwesomeIcon("xmark", "regular") }), _jsx("div", { className: `${textHighlight} text-sm hover:text-primary`, children: getFontAwesomeIcon("search", "solid") })] })) }) }), onIconClick: () => setLocalSearchText("") })] }), searchItems?.length ? (_jsx("div", { className: "flex flex-wrap bg-white py-2 px-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",
95
- // Render only the cleaned text
96
- 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`, type: "span" }, index));
97
95
  }) })) : null] }) }));
98
96
  };
99
97
  export default SearchTextInput;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agilant/toga-blox",
3
3
  "private": false,
4
- "version": "1.0.109",
4
+ "version": "1.0.111",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",