@agilant/toga-blox 1.0.119 → 1.0.120
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.
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// ===================== SearchDropdownInput.tsx =====================
|
|
3
2
|
import { useEffect, useState } from "react";
|
|
4
3
|
import MultiSelectInput from "../MultiSelect/MultiSelect";
|
|
5
4
|
import updateLocalStorage from "../../utils/updateLocalStorage";
|
|
6
5
|
const DEFAULT_STORAGE_KEY = "searchCriteria";
|
|
7
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, fontFamily, pillColor, ...rest }) => {
|
|
8
7
|
const canStore = !!column?.id && !!setSearchCriteria;
|
|
9
|
-
// We'll track how many items are visible in the child, for the "Filter" footer
|
|
10
8
|
const [filteredCount, setFilteredCount] = useState(0);
|
|
11
9
|
// --------------------------------------------------------------------
|
|
12
|
-
//
|
|
10
|
+
// On mount, read from localStorage to see previously selected items
|
|
13
11
|
// --------------------------------------------------------------------
|
|
14
12
|
useEffect(() => {
|
|
15
13
|
if (!canStore)
|
|
16
|
-
return;
|
|
14
|
+
return;
|
|
17
15
|
const stored = localStorage.getItem(localStorageKey);
|
|
18
16
|
if (!stored)
|
|
19
17
|
return;
|
|
20
18
|
try {
|
|
21
19
|
const parsed = JSON.parse(stored);
|
|
20
|
+
// see if there's a criterion for this specific column ID
|
|
22
21
|
const existing = parsed.find((c) => c.searchColumn?.id === column?.id);
|
|
23
22
|
if (existing && setSearchItems) {
|
|
23
|
+
// e.g. "fulfilled,pendingApproval"
|
|
24
24
|
const raw = existing.submittedSearchText;
|
|
25
|
-
setSearchItems([raw]);
|
|
26
|
-
//
|
|
27
|
-
// If you might have colons, handle that too:
|
|
25
|
+
setSearchItems([raw]);
|
|
26
|
+
// Split by comma. If you sometimes store colons, handle that:
|
|
28
27
|
const delimiter = raw.includes(":") ? ":" : ",";
|
|
29
28
|
const storedValues = raw.split(delimiter).map((s) => s.trim());
|
|
30
|
-
//
|
|
29
|
+
// Match them to your full list of options
|
|
31
30
|
const matched = options.filter((o) => storedValues.includes(o.value));
|
|
31
|
+
// Re-check these items
|
|
32
32
|
onChange(matched);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -39,15 +39,15 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
|
|
|
39
39
|
canStore,
|
|
40
40
|
column?.id,
|
|
41
41
|
localStorageKey,
|
|
42
|
-
setSearchItems,
|
|
43
|
-
onChange,
|
|
44
42
|
options,
|
|
43
|
+
onChange,
|
|
44
|
+
setSearchItems,
|
|
45
45
|
]);
|
|
46
|
-
// Called when user clicks the
|
|
46
|
+
// Called when user clicks the Filter button in the multiSelect footer
|
|
47
47
|
const handleFooterFilter = () => {
|
|
48
|
-
//
|
|
48
|
+
// We skip any special "footer" or "Select All" item
|
|
49
49
|
const actualSelections = selectedValue.filter((opt) => opt.value !== "__footer__" && opt.label !== "Select All");
|
|
50
|
-
//
|
|
50
|
+
// Store them in localStorage as a comma-joined string
|
|
51
51
|
const selectedLabels = actualSelections
|
|
52
52
|
.map((opt) => opt.value)
|
|
53
53
|
.join(",");
|
|
@@ -57,7 +57,7 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
|
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
if (isEmpty) {
|
|
60
|
-
//
|
|
60
|
+
// user cleared everything, remove from localStorage
|
|
61
61
|
setSearchCriteria?.((prev) => {
|
|
62
62
|
const newCriteria = prev.filter((c) => c.searchColumn.id !== column?.id);
|
|
63
63
|
updateLocalStorage(newCriteria, localStorageKey);
|
|
@@ -65,16 +65,14 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
|
-
//
|
|
68
|
+
// store new criterion
|
|
69
69
|
setSearchCriteria?.((prev) => {
|
|
70
70
|
const filtered = prev.filter((c) => c.searchColumn.id !== column?.id);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
];
|
|
71
|
+
const newCriterion = {
|
|
72
|
+
searchColumn: column,
|
|
73
|
+
submittedSearchText: selectedLabels, // e.g. "fulfilled,pendingApproval"
|
|
74
|
+
};
|
|
75
|
+
const newCriteria = [...filtered, newCriterion];
|
|
78
76
|
updateLocalStorage(newCriteria, localStorageKey);
|
|
79
77
|
return newCriteria;
|
|
80
78
|
});
|
|
@@ -82,7 +80,7 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
|
|
|
82
80
|
setEditingHeader?.(null);
|
|
83
81
|
handleFilter?.();
|
|
84
82
|
};
|
|
85
|
-
// Called when user clicks Clear
|
|
83
|
+
// Called when user clicks "Clear"
|
|
86
84
|
const handleClear = () => {
|
|
87
85
|
onChange([]);
|
|
88
86
|
if (canStore) {
|
|
@@ -95,18 +93,18 @@ const SearchDropdownInput = ({ options = [], selectedValue = [], onChange, place
|
|
|
95
93
|
setEditingHeader?.(null);
|
|
96
94
|
}
|
|
97
95
|
};
|
|
98
|
-
//
|
|
96
|
+
// We add a "footer" pseudo-option so we can place a Filter button, etc. at the bottom
|
|
99
97
|
const footerOption = [{ name: "", value: "__footer__" }];
|
|
100
98
|
const extendedOptions = [...options, ...footerOption];
|
|
101
|
-
//
|
|
99
|
+
// Provide a custom item renderer so we can handle the "Footer" row
|
|
102
100
|
const itemRenderer = ({ option, checked, disabled, onClick }) => {
|
|
103
101
|
if (option.value === "__footer__") {
|
|
104
|
-
return (_jsxs("div", { className: "footer
|
|
102
|
+
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) => {
|
|
105
103
|
e.stopPropagation();
|
|
106
104
|
handleFooterFilter();
|
|
107
105
|
}, children: buttonText })] }));
|
|
108
106
|
}
|
|
109
|
-
//
|
|
107
|
+
// "Select All" if you want to implement that
|
|
110
108
|
if (option.label === "Select All") {
|
|
111
109
|
// ...
|
|
112
110
|
}
|