@geotab/zenith 1.26.4 → 1.26.5-beta.0
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/README.md +6 -0
- package/dist/absolute/absolute.js +2 -2
- package/dist/chip/chip.d.ts +35 -0
- package/dist/chip/chip.js +105 -0
- package/dist/chip/chipStatusProvider.d.ts +9 -0
- package/dist/chip/chipStatusProvider.js +13 -0
- package/dist/chip/utils/getChipStateClassName.d.ts +2 -0
- package/dist/chip/utils/getChipStateClassName.js +32 -0
- package/dist/chip/utils/useChip.d.ts +10 -0
- package/dist/chip/utils/useChip.js +24 -0
- package/dist/commonHelpers/hooks/useDebouncedMemo.d.ts +2 -0
- package/dist/commonHelpers/hooks/useDebouncedMemo.js +26 -0
- package/dist/commonStyles/shadows/shadows.less +4 -0
- package/dist/dateRange/dateRange.d.ts +2 -1
- package/dist/dateRange/dateRange.js +6 -2
- package/dist/dropdown/dropdown.d.ts +18 -3
- package/dist/dropdown/dropdown.js +63 -31
- package/dist/dropdown/dropdownHelper.d.ts +1 -1
- package/dist/dropdown/dropdownHelper.js +7 -3
- package/dist/dropdown/dropdownList.d.ts +1 -0
- package/dist/dropdown/dropdownList.js +2 -2
- package/dist/dropdown/dropdownPopup.d.ts +1 -0
- package/dist/dropdown/dropdownPopup.js +2 -2
- package/dist/dropdown/stateReducer/stateAction.d.ts +9 -1
- package/dist/dropdown/stateReducer/stateActionType.d.ts +1 -0
- package/dist/dropdown/stateReducer/stateActionType.js +1 -0
- package/dist/dropdown/stateReducer/stateReducer.js +35 -0
- package/dist/dropdown/useDropdownState.d.ts +7 -0
- package/dist/dropdown/useDropdownState.js +10 -0
- package/dist/filters/components/filtersChip.d.ts +9 -0
- package/dist/filters/components/filtersChip.js +28 -0
- package/dist/filters/components/filtersContainer.d.ts +12 -0
- package/dist/filters/components/filtersContainer.js +77 -0
- package/dist/filters/components/filtersCustom.d.ts +13 -0
- package/dist/filters/components/filtersCustom.js +15 -0
- package/dist/filters/components/filtersDateRange.d.ts +33 -0
- package/dist/filters/components/filtersDateRange.js +27 -0
- package/dist/filters/components/filtersDropdown.d.ts +32 -0
- package/dist/filters/components/filtersDropdown.js +42 -0
- package/dist/filters/components/filtersGroups.d.ts +14 -0
- package/dist/filters/components/filtersGroups.js +28 -0
- package/dist/filters/components/filtersItem.d.ts +25 -0
- package/dist/filters/components/filtersItem.js +23 -0
- package/dist/filters/components/filtersModal.d.ts +17 -0
- package/dist/filters/components/filtersModal.js +107 -0
- package/dist/filters/components/filtersModalItem.d.ts +9 -0
- package/dist/filters/components/filtersModalItem.js +74 -0
- package/dist/filters/components/filtersRange.d.ts +11 -0
- package/dist/filters/components/filtersRange.js +27 -0
- package/dist/filters/components/filtersSaveModal.d.ts +7 -0
- package/dist/filters/components/filtersSaveModal.js +53 -0
- package/dist/filters/components/filtersSavedChipComponent.d.ts +2 -0
- package/dist/filters/components/filtersSavedChipComponent.js +66 -0
- package/dist/filters/components/filtersSavedItemsProvider.d.ts +19 -0
- package/dist/filters/components/filtersSavedItemsProvider.js +13 -0
- package/dist/filters/components/filtersSearch.d.ts +16 -0
- package/dist/filters/components/filtersSearch.js +64 -0
- package/dist/filters/components/filtersSearchItemData.d.ts +16 -0
- package/dist/filters/components/filtersSearchItemData.js +42 -0
- package/dist/filters/components/filtersSearchList.d.ts +30 -0
- package/dist/filters/components/filtersSearchList.js +75 -0
- package/dist/filters/components/filtersSelect.d.ts +30 -0
- package/dist/filters/components/filtersSelect.js +51 -0
- package/dist/filters/components/filtersSelectListItem.d.ts +15 -0
- package/dist/filters/components/filtersSelectListItem.js +14 -0
- package/dist/filters/filters.d.ts +99 -0
- package/dist/filters/filters.js +246 -0
- package/dist/filters/filtersHelper.d.ts +40 -0
- package/dist/filters/filtersHelper.js +226 -0
- package/dist/filters/filtersHooks.d.ts +19 -0
- package/dist/filters/filtersHooks.js +25 -0
- package/dist/filtersBar/components/filtersBarDropdownWithCheckbox/filtersBarDropdownWithCheckbox.d.ts +5 -3
- package/dist/groupsFilter/groupsFilter.d.ts +10 -1
- package/dist/groupsFilter/groupsFilter.js +40 -11
- package/dist/header/components/collapsedItemsControl/collapsedItemsControl.js +7 -4
- package/dist/header/headerMenu.d.ts +1 -0
- package/dist/header/headerMenu.js +11 -4
- package/dist/index.css +3453 -2649
- package/dist/index.d.ts +18 -3
- package/dist/index.js +55 -15
- package/dist/layout/layout.js +5 -0
- package/dist/list/list.d.ts +1 -1
- package/dist/list/list.js +3 -2
- package/dist/modal/modal.d.ts +11 -1
- package/dist/modal/modal.js +8 -5
- package/dist/nav/nav.d.ts +1 -0
- package/dist/nav/nav.js +21 -7
- package/dist/nav/navHeader/navHeader.js +1 -1
- package/dist/nav/navItem/navItem.d.ts +4 -2
- package/dist/nav/navItem/navItem.js +25 -10
- package/dist/nav/navMobileBar/navMobileBar.d.ts +11 -0
- package/dist/nav/navMobileBar/navMobileBar.js +33 -0
- package/dist/nav/navSection/navSection.js +52 -1
- package/dist/nav/storyHelpers/storyDecorator.js +2 -1
- package/dist/nav/utils/navUtils.d.ts +6 -1
- package/dist/nav/utils/navUtils.js +48 -1
- package/dist/pageHeader/pageHeader.d.ts +16 -0
- package/dist/pageHeader/pageHeader.js +21 -0
- package/dist/pageHeader/pageHeaderActions.d.ts +10 -0
- package/dist/pageHeader/pageHeaderActions.js +35 -0
- package/dist/pageHeader/pageHeaderButton.d.ts +16 -0
- package/dist/pageHeader/pageHeaderButton.js +26 -0
- package/dist/pageHeader/pageHeaderFilters.d.ts +13 -0
- package/dist/pageHeader/pageHeaderFilters.js +7 -0
- package/dist/pageHeader/pageHeaderHelpers.d.ts +4 -0
- package/dist/pageHeader/pageHeaderHelpers.js +62 -0
- package/dist/pageHeader/pageHeaderMenu.d.ts +9 -0
- package/dist/pageHeader/pageHeaderMenu.js +9 -0
- package/dist/pillBox/components/pillBoxItem.js +1 -1
- package/dist/pillBox/pillBox.d.ts +1 -0
- package/dist/pillBox/pillBox.js +2 -2
- package/dist/range/range.d.ts +2 -1
- package/dist/range/range.js +11 -2
- package/dist/tabs/tabs.d.ts +1 -2
- package/dist/utils/localization/translations/en-json.d.ts +18 -0
- package/dist/utils/localization/translations/en-json.js +19 -1
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FiltersSearchList = exports.KEYWORD_TYPE = exports.KEYWORD_ID = exports.NO_TYPED_SEARCH_ITEM = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const list_1 = require("../../list/list");
|
|
7
|
+
const useLanguage_1 = require("../../utils/localization/useLanguage");
|
|
8
|
+
const button_1 = require("../../button/button");
|
|
9
|
+
const textIconButton_1 = require("../../textIconButton/textIconButton");
|
|
10
|
+
const iconChevronLeft_1 = require("../../icons/iconChevronLeft");
|
|
11
|
+
const textIconButton_2 = require("../../textIconButton/textIconButton");
|
|
12
|
+
const filtersSearchItemData_1 = require("./filtersSearchItemData");
|
|
13
|
+
const useMobile_1 = require("../../commonHelpers/hooks/useMobile");
|
|
14
|
+
const useDrive_1 = require("../../utils/theme/useDrive");
|
|
15
|
+
const classNames_1 = require("../../commonHelpers/classNames/classNames");
|
|
16
|
+
const filtersHelper_1 = require("../filtersHelper");
|
|
17
|
+
exports.NO_TYPED_SEARCH_ITEM = "noTypedSearchItem";
|
|
18
|
+
exports.KEYWORD_ID = "keywordId";
|
|
19
|
+
exports.KEYWORD_TYPE = "keyword";
|
|
20
|
+
const FiltersSearchList = ({ searchValue, searchData, recentSearches, searchSelection, handleSearchItemClick, onRemoveRecentSearchItem, handleRecentSearchItemClick, getIconByType }) => {
|
|
21
|
+
const { translate } = (0, useLanguage_1.useLanguage)();
|
|
22
|
+
const isSearchMode = Boolean(handleSearchItemClick && searchSelection);
|
|
23
|
+
const isMobile = (0, useMobile_1.useMobile)();
|
|
24
|
+
const isDrive = (0, useDrive_1.useDrive)();
|
|
25
|
+
const [removedItems, setRemovedItems] = (0, react_1.useState)([]);
|
|
26
|
+
const [historyMode, setHistoryMode] = (0, react_1.useState)(false);
|
|
27
|
+
const waitingItemsLimit = 5;
|
|
28
|
+
const isRecentSearchesMode = Boolean(recentSearches && handleRecentSearchItemClick && onRemoveRecentSearchItem);
|
|
29
|
+
// Handle React Query errors
|
|
30
|
+
(0, react_1.useEffect)(() => {
|
|
31
|
+
if (isSearchMode && (searchData === null || searchData === void 0 ? void 0 : searchData.error)) {
|
|
32
|
+
console.error("Failed to fetch search results. Error:", searchData.error);
|
|
33
|
+
}
|
|
34
|
+
}, [isSearchMode, searchData === null || searchData === void 0 ? void 0 : searchData.error]);
|
|
35
|
+
// Reset history mode when search value changes
|
|
36
|
+
(0, react_1.useEffect)(() => {
|
|
37
|
+
if (historyMode && searchValue) {
|
|
38
|
+
setHistoryMode(false);
|
|
39
|
+
}
|
|
40
|
+
}, [historyMode, searchValue]);
|
|
41
|
+
const searchItems = (0, react_1.useMemo)(() => isSearchMode ? (searchData === null || searchData === void 0 ? void 0 : searchData.data) || [] : [], [isSearchMode, searchData === null || searchData === void 0 ? void 0 : searchData.data]);
|
|
42
|
+
const recentItems = (0, react_1.useMemo)(() => isRecentSearchesMode ? (recentSearches === null || recentSearches === void 0 ? void 0 : recentSearches.data) || [] : [], [isRecentSearchesMode, recentSearches === null || recentSearches === void 0 ? void 0 : recentSearches.data]);
|
|
43
|
+
const isLoading = searchValue && isSearchMode && (searchData === null || searchData === void 0 ? void 0 : searchData.isLoading) || (isRecentSearchesMode ? recentSearches === null || recentSearches === void 0 ? void 0 : recentSearches.isLoading : false) || false;
|
|
44
|
+
const changeMode = (0, react_1.useCallback)(() => {
|
|
45
|
+
setHistoryMode(prev => !prev);
|
|
46
|
+
setRemovedItems([]);
|
|
47
|
+
// Note: In React Query implementation, the parent component should handle
|
|
48
|
+
// refetching data when switching between modes
|
|
49
|
+
}, []);
|
|
50
|
+
const handleRemove = (0, react_1.useCallback)((itemId) => () => {
|
|
51
|
+
setRemovedItems(prev => [...prev, itemId]);
|
|
52
|
+
onRemoveRecentSearchItem && onRemoveRecentSearchItem([itemId]);
|
|
53
|
+
}, [onRemoveRecentSearchItem]);
|
|
54
|
+
const handleRemoveAll = (0, react_1.useCallback)(() => {
|
|
55
|
+
setRemovedItems(recentItems.map(item => item.id));
|
|
56
|
+
onRemoveRecentSearchItem && onRemoveRecentSearchItem(recentItems.map(item => item.id));
|
|
57
|
+
changeMode();
|
|
58
|
+
}, [onRemoveRecentSearchItem, recentItems, changeMode]);
|
|
59
|
+
const memoizedSearchItemClick = (0, react_1.useCallback)((itemId, itemType) => () => {
|
|
60
|
+
const currentSearchItem = searchItems.find(item => item.id === itemId && item.type === itemType);
|
|
61
|
+
currentSearchItem && handleSearchItemClick && handleSearchItemClick(currentSearchItem);
|
|
62
|
+
}, [handleSearchItemClick, searchItems]);
|
|
63
|
+
const memoizedRecentSearchItemClick = (0, react_1.useCallback)((itemId, itemType) => () => {
|
|
64
|
+
const currentSearchItem = recentItems.find(item => item.id === itemId && item.type === itemType);
|
|
65
|
+
currentSearchItem && handleRecentSearchItemClick && handleRecentSearchItemClick(currentSearchItem);
|
|
66
|
+
}, [handleRecentSearchItemClick, recentItems]);
|
|
67
|
+
const memoizedRecentDataArr = (0, react_1.useMemo)(() => recentItems.filter(item => !removedItems.includes(item.id)).reverse(), [recentItems, removedItems]);
|
|
68
|
+
const memoizedRecentData = (0, react_1.useMemo)(() => (historyMode ? memoizedRecentDataArr : (searchValue && isSearchMode ? [] : memoizedRecentDataArr.slice(0, waitingItemsLimit))).map(item => ((0, jsx_runtime_1.jsx)(filtersSearchItemData_1.FiltersSearchItemData, { id: item.id, name: item.name, isActive: false, secondary: item.description, onClose: handleRemove(item.id), onClick: memoizedRecentSearchItemClick(item.id, item.type || exports.NO_TYPED_SEARCH_ITEM), icon: getIconByType(item.type), isMobile: isMobile, isDrive: isDrive }, `recent-${item.id}`))), [historyMode, memoizedRecentDataArr, searchValue, isSearchMode, handleRemove, memoizedRecentSearchItemClick, getIconByType, isMobile, isDrive]);
|
|
69
|
+
const memoizedSearchData = (0, react_1.useMemo)(() => historyMode || !searchValue && isRecentSearchesMode ? [] : searchItems.slice(0, filtersHelper_1.MAX_TOTAL_RESULTS).map(item => ((0, jsx_runtime_1.jsx)(filtersSearchItemData_1.FiltersSearchItemData, { id: item.id, name: item.name, isActive: isSearchMode ? searchSelection.filter(el => el.id === item.id).some(el => el.type === (item.type || exports.NO_TYPED_SEARCH_ITEM)) || false : false, secondary: item.description, onClose: undefined, onClick: isSearchMode ? memoizedSearchItemClick(item.id, item.type || exports.NO_TYPED_SEARCH_ITEM) : undefined, icon: getIconByType(item.type), isMobile: isMobile, isDrive: isDrive }, `search-${item.id}-${item.type || exports.NO_TYPED_SEARCH_ITEM}`))), [historyMode, searchValue, isRecentSearchesMode, searchItems, isSearchMode, searchSelection, memoizedSearchItemClick, getIconByType, isMobile, isDrive]);
|
|
70
|
+
const resultsToShow = (0, react_1.useMemo)(() => isRecentSearchesMode ? [...memoizedRecentData, ...memoizedSearchData]
|
|
71
|
+
: memoizedSearchData, [isRecentSearchesMode, memoizedRecentData, memoizedSearchData]);
|
|
72
|
+
return (0, jsx_runtime_1.jsxs)("div", { className: "zen-filters-search-list", children: [searchValue ? null : (0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-filters-search-list__header", isDrive ? (isMobile ? "zen-filters-search-list__header--drive" : "zen-filters-search-list__header--drive-tablet") : ""]), children: [historyMode ? (0, jsx_runtime_1.jsx)(textIconButton_1.TextIconButton, { className: "zen-filters-search-list__header-back-button", title: translate("Back"), type: "tertiary", onClick: changeMode, icon: iconChevronLeft_1.IconChevronLeft, iconPosition: textIconButton_2.ButtonIconPosition.Start })
|
|
73
|
+
: null, isRecentSearchesMode ? (0, jsx_runtime_1.jsx)("div", { className: "zen-filters-search-list__header-title", children: translate("Recent searches") }) : null, historyMode || !isRecentSearchesMode ? null : (0, jsx_runtime_1.jsx)(button_1.Button, { type: "tertiary", onClick: changeMode, children: translate("View history") }), historyMode && isRecentSearchesMode ? (0, jsx_runtime_1.jsx)(button_1.Button, { type: "tertiary", onClick: handleRemoveAll, children: translate("Clear all") }) : null] }), (0, jsx_runtime_1.jsx)(list_1.List, { className: "zen-filters-search-list__data", isLoading: isLoading, type: "data", waitingItems: waitingItemsLimit, children: resultsToShow })] });
|
|
74
|
+
};
|
|
75
|
+
exports.FiltersSearchList = FiltersSearchList;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { IFiltersSearchTypesSubItem } from "../filters";
|
|
3
|
+
import "./filtersSelect.less";
|
|
4
|
+
export interface IFiltersSelectItems {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
subItems?: IFiltersSearchTypesSubItem[];
|
|
8
|
+
}
|
|
9
|
+
interface IFiltersSelectProps {
|
|
10
|
+
items?: IFiltersSelectItems[];
|
|
11
|
+
}
|
|
12
|
+
export interface IFiltersSelect extends IFiltersSelectProps {
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
value: IFiltersSearchType;
|
|
16
|
+
onChange: (newValue: IFiltersSearchType) => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const ALL_SELECT_OPTION_ID: string;
|
|
20
|
+
export interface IFiltersSearchType {
|
|
21
|
+
[name: string]: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
export declare const FiltersSelectDisplayName = "FiltersSelect";
|
|
24
|
+
export declare const getFiltersSearchTypeAllOption: () => IFiltersSearchType;
|
|
25
|
+
export declare const getAllOption: (translate: (key: string) => string) => {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
export declare const FiltersSelect: React.FC<IFiltersSelect>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FiltersSelect = exports.getAllOption = exports.getFiltersSearchTypeAllOption = exports.FiltersSelectDisplayName = exports.ALL_SELECT_OPTION_ID = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const classNames_1 = require("../../commonHelpers/classNames/classNames");
|
|
7
|
+
const useLanguage_1 = require("../../utils/localization/useLanguage");
|
|
8
|
+
const useUniqueId_1 = require("../../commonHelpers/useUniqueId");
|
|
9
|
+
const filtersSelectListItem_1 = require("./filtersSelectListItem");
|
|
10
|
+
exports.ALL_SELECT_OPTION_ID = "All";
|
|
11
|
+
exports.FiltersSelectDisplayName = "FiltersSelect";
|
|
12
|
+
const getFiltersSearchTypeAllOption = () => ({
|
|
13
|
+
[exports.ALL_SELECT_OPTION_ID]: undefined
|
|
14
|
+
});
|
|
15
|
+
exports.getFiltersSearchTypeAllOption = getFiltersSearchTypeAllOption;
|
|
16
|
+
const getAllOption = (translate) => ({
|
|
17
|
+
id: exports.ALL_SELECT_OPTION_ID,
|
|
18
|
+
name: translate("All")
|
|
19
|
+
});
|
|
20
|
+
exports.getAllOption = getAllOption;
|
|
21
|
+
const FiltersSelect = ({ value, name, onChange, id, items, className }) => {
|
|
22
|
+
const { translate } = (0, useLanguage_1.useLanguage)();
|
|
23
|
+
const [activeId, setActiveId] = (0, react_1.useState)("");
|
|
24
|
+
const filtersSelectListId = (0, useUniqueId_1.useUniqueId)();
|
|
25
|
+
const filteredItems = (0, react_1.useMemo)(() => (items === null || items === void 0 ? void 0 : items.filter(el => el.id !== exports.ALL_SELECT_OPTION_ID)) || [], [items]);
|
|
26
|
+
const preparedItems = (0, react_1.useMemo)(() => [
|
|
27
|
+
(0, exports.getAllOption)(translate),
|
|
28
|
+
...filteredItems
|
|
29
|
+
], [translate, filteredItems]);
|
|
30
|
+
const handleExpandableItemClick = (0, react_1.useCallback)((clickedId) => () => {
|
|
31
|
+
if (activeId === clickedId) {
|
|
32
|
+
setActiveId("");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
setActiveId(clickedId);
|
|
36
|
+
onChange({ [clickedId]: undefined });
|
|
37
|
+
}, [activeId, onChange]);
|
|
38
|
+
const handleItemClick = (0, react_1.useCallback)((clickedId, parentId) => () => {
|
|
39
|
+
if (parentId) {
|
|
40
|
+
onChange({ [parentId]: clickedId });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setActiveId("");
|
|
44
|
+
onChange(Object.keys(value).includes(clickedId) ? (0, exports.getFiltersSearchTypeAllOption)() : { [clickedId]: undefined });
|
|
45
|
+
}, [onChange, value]);
|
|
46
|
+
const selectListComponent = (0, react_1.useMemo)(() => preparedItems.map(el => el.subItems ?
|
|
47
|
+
(0, jsx_runtime_1.jsx)(filtersSelectListItem_1.FiltersSelectListExpandableItem, { id: `${filtersSelectListId}-${el.id}`, name: el.name, isActive: el.id === activeId, className: (0, classNames_1.classNames)([value.hasOwnProperty(el.id) ? "zen-filters-select__list-item--active" : ""]), onClick: handleExpandableItemClick(el.id), content: el.id === activeId ? el.subItems.map(subEl => (0, jsx_runtime_1.jsx)(filtersSelectListItem_1.FiltersSelectListItem, { className: (0, classNames_1.classNames)(["zen-filters-select__sub-item"]), id: `${filtersSelectListId}-${el.id}-${subEl.id}`, name: subEl.name, isActive: value[el.id] === subEl.id, onClick: handleItemClick(subEl.id, el.id) }, `${el.id}-${subEl.id}`)) : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}) }, el.id) : (0, jsx_runtime_1.jsx)(filtersSelectListItem_1.FiltersSelectListItem, { id: `${filtersSelectListId}-${el.id}`, name: el.name, isActive: Object.keys(value).includes(el.id), onClick: handleItemClick(el.id) }, el.id)), [activeId, filtersSelectListId, handleExpandableItemClick, handleItemClick, preparedItems, value]);
|
|
48
|
+
return (0, jsx_runtime_1.jsxs)("div", { className: "zen-filters-select", children: [id && name ? (0, jsx_runtime_1.jsx)("div", { className: "zen-filters-select__label", id: id, children: name }) : null, (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-filters-select__list", className || ""]), children: selectListComponent })] });
|
|
49
|
+
};
|
|
50
|
+
exports.FiltersSelect = FiltersSelect;
|
|
51
|
+
exports.FiltersSelect.displayName = exports.FiltersSelectDisplayName;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const FiltersSelectListItem: ({ id, name, isActive, onClick, className }: {
|
|
2
|
+
id: any;
|
|
3
|
+
name: any;
|
|
4
|
+
isActive: any;
|
|
5
|
+
onClick: any;
|
|
6
|
+
className?: string | undefined;
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const FiltersSelectListExpandableItem: ({ id, name, content, isActive, onClick, className }: {
|
|
9
|
+
id: any;
|
|
10
|
+
name: any;
|
|
11
|
+
content: any;
|
|
12
|
+
isActive: any;
|
|
13
|
+
onClick: any;
|
|
14
|
+
className?: string | undefined;
|
|
15
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FiltersSelectListExpandableItem = exports.FiltersSelectListItem = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const classNames_1 = require("../../commonHelpers/classNames/classNames");
|
|
6
|
+
const useUniqueId_1 = require("../../commonHelpers/useUniqueId");
|
|
7
|
+
const iconChevronBottom_1 = require("../../icons/iconChevronBottom");
|
|
8
|
+
const FiltersSelectListItem = ({ id, name, isActive, onClick, className = "" }) => (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("button", { type: "button", className: (0, classNames_1.classNames)(["zen-filters-select__list-item", isActive ? "zen-filters-select__list-item--active" : "", className]), id: id, onClick: onClick, children: name }) });
|
|
9
|
+
exports.FiltersSelectListItem = FiltersSelectListItem;
|
|
10
|
+
const FiltersSelectListExpandableItem = ({ id, name, content, isActive, onClick, className = "" }) => {
|
|
11
|
+
const ariaControlsId = (0, useUniqueId_1.useUniqueId)();
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", "aria-expanded": isActive, "aria-controls": ariaControlsId, className: (0, classNames_1.classNames)(["zen-filters-select__list-item", isActive ? "zen-filters-select__list-item--active" : "", className]), id: id, onClick: onClick, children: [name, (0, jsx_runtime_1.jsx)(iconChevronBottom_1.IconChevronBottom, { size: "large", className: (0, classNames_1.classNames)(["zen-filters-select__item-icon", isActive ? "zen-filters-select__item-icon--rotated" : ""]) })] }), (0, jsx_runtime_1.jsx)("div", { id: ariaControlsId, "aria-labelledby": id, role: "region", className: (0, classNames_1.classNames)(["zen-filters-select__item-content", content ? "" : "zen-filters-select__item-content--hidden"]), children: content })] }));
|
|
13
|
+
};
|
|
14
|
+
exports.FiltersSelectListExpandableItem = FiltersSelectListExpandableItem;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import "./filters.less";
|
|
2
|
+
import { IZenComponentProps } from "./../commonHelpers/zenComponent";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { IFiltersSearchType } from "./components/filtersSelect";
|
|
5
|
+
import { TFiltersComponentsItemState } from "./components/filtersItem";
|
|
6
|
+
import { IFiltersDropdown, TFiltersDropdownAllStates } from "./components/filtersDropdown";
|
|
7
|
+
import { IFiltersGroups } from "./components/filtersGroups";
|
|
8
|
+
import { IFiltersRange } from "./components/filtersRange";
|
|
9
|
+
import { IFiltersChip } from "./components/filtersChip";
|
|
10
|
+
import { FiltersDateRange } from "./components/filtersDateRange";
|
|
11
|
+
import { IRecentSearchItem, IRecentSearchItemWithoutId, ISearchItem } from "./components/filtersSearchList";
|
|
12
|
+
import { IIcon } from "../icons/icon";
|
|
13
|
+
export interface ISavedFilters {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
state: Record<string, TFiltersComponentsItemState>;
|
|
17
|
+
}
|
|
18
|
+
export interface ISaveFilter {
|
|
19
|
+
name: string;
|
|
20
|
+
state: Record<string, TFiltersComponentsItemState>;
|
|
21
|
+
}
|
|
22
|
+
export interface IFetchState<T> {
|
|
23
|
+
data: T | undefined;
|
|
24
|
+
isLoading: boolean;
|
|
25
|
+
error: Error | null;
|
|
26
|
+
}
|
|
27
|
+
export interface IFiltersSearchTypesSubItem {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
}
|
|
31
|
+
export interface IFiltersSearchTypesItem {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
subItems?: IFiltersSearchTypesSubItem[];
|
|
35
|
+
icon?: React.FC<IIcon>;
|
|
36
|
+
data: IFetchState<ISearchItem[]>;
|
|
37
|
+
relevance?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface IFiltersBase extends IZenComponentProps {
|
|
40
|
+
keyword: string;
|
|
41
|
+
setKeyword: (newKeyword: string) => void;
|
|
42
|
+
searchTypes?: IFiltersSearchTypesItem[] | IFiltersSearchTypesItem;
|
|
43
|
+
searchType: IFiltersSearchType;
|
|
44
|
+
setSearchType: (newType: IFiltersSearchType) => void;
|
|
45
|
+
onToggleView?: (isOpen: boolean) => void;
|
|
46
|
+
}
|
|
47
|
+
export interface IFiltersWithRecentSearches {
|
|
48
|
+
recentSearches: IFetchState<IRecentSearchItem[]>;
|
|
49
|
+
onSaveRecentSearch: (item: IRecentSearchItemWithoutId) => void;
|
|
50
|
+
onRemoveRecentSearchItem: (itemIds: string[]) => void;
|
|
51
|
+
}
|
|
52
|
+
export interface IFiltersWithSearchSelection {
|
|
53
|
+
searchSelection: ISearchItem[];
|
|
54
|
+
setSearchSelection: (items: ISearchItem[]) => void;
|
|
55
|
+
}
|
|
56
|
+
export interface IFiltersWithPin {
|
|
57
|
+
isPinned: boolean;
|
|
58
|
+
onPinChange: (isPinned: boolean) => void;
|
|
59
|
+
}
|
|
60
|
+
export interface IFiltersWithSavedFilters {
|
|
61
|
+
savedFilters: IFetchState<ISavedFilters[]>;
|
|
62
|
+
onRemoveSavedFilter: (filterId: string) => void;
|
|
63
|
+
onSaveFilter: (newFilter: ISaveFilter) => Promise<string>;
|
|
64
|
+
}
|
|
65
|
+
export interface IFiltersWithExternalState {
|
|
66
|
+
allFiltersState: Record<string, TFiltersComponentsItemState>;
|
|
67
|
+
setAllFiltersState: (newState: Partial<Record<string, TFiltersComponentsItemState>>) => void;
|
|
68
|
+
}
|
|
69
|
+
export interface IFilters extends IFiltersBase, Partial<IFiltersWithRecentSearches>, Partial<IFiltersWithSearchSelection>, Partial<IFiltersWithPin>, Partial<IFiltersWithSavedFilters>, Partial<IFiltersWithExternalState> {
|
|
70
|
+
}
|
|
71
|
+
/** Base filters with only required functionality */
|
|
72
|
+
export type IFiltersBasic = IFiltersBase;
|
|
73
|
+
/** Filters with external modal state management */
|
|
74
|
+
export type IFiltersWithModal = IFiltersBase & IFiltersWithExternalState;
|
|
75
|
+
/** Filters with pin/unpin functionality */
|
|
76
|
+
export type IFiltersWithPinning = IFiltersBase & IFiltersWithPin;
|
|
77
|
+
/** Filters with recent searches history */
|
|
78
|
+
export type IFiltersWithRecent = IFiltersBase & IFiltersWithRecentSearches;
|
|
79
|
+
/** Filters with saved filters functionality */
|
|
80
|
+
export type IFiltersWithSaved = IFiltersBase & IFiltersWithSavedFilters;
|
|
81
|
+
/** Filters with search selection functionality */
|
|
82
|
+
export type TFiltersWithSearchSelection = IFiltersBase & IFiltersWithSearchSelection;
|
|
83
|
+
/** Complex combinations */
|
|
84
|
+
/** Filters with both modal state and pinning */
|
|
85
|
+
export type IFiltersWithModalAndPin = IFiltersBase & IFiltersWithExternalState & IFiltersWithPin;
|
|
86
|
+
/** Filters with both recent searches and saved filters */
|
|
87
|
+
export type IFiltersWithRecentAndSaved = IFiltersBase & IFiltersWithRecentSearches & IFiltersWithSavedFilters;
|
|
88
|
+
/** Complete filters interface with all features enabled */
|
|
89
|
+
export type IFiltersComplete = IFiltersBase & IFiltersWithRecentSearches & TFiltersWithSearchSelection & IFiltersWithPin & IFiltersWithSavedFilters & IFiltersWithExternalState;
|
|
90
|
+
export declare const FiltersDisplayName = "Filters";
|
|
91
|
+
interface IFiltersComponents {
|
|
92
|
+
Chip: React.FC<IFiltersChip>;
|
|
93
|
+
DateRange: typeof FiltersDateRange;
|
|
94
|
+
Dropdown: React.FC<IFiltersDropdown<TFiltersDropdownAllStates>>;
|
|
95
|
+
Groups: React.FC<IFiltersGroups>;
|
|
96
|
+
Range: React.FC<IFiltersRange>;
|
|
97
|
+
}
|
|
98
|
+
export declare const Filters: React.FC<IFilters> & IFiltersComponents;
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Filters = exports.FiltersDisplayName = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const headerHelpers_1 = require("../header/headerHelpers");
|
|
10
|
+
const react_2 = __importDefault(require("react"));
|
|
11
|
+
const filtersSelect_1 = require("./components/filtersSelect");
|
|
12
|
+
const classNames_1 = require("../commonHelpers/classNames/classNames");
|
|
13
|
+
const textIconButton_1 = require("../textIconButton/textIconButton");
|
|
14
|
+
const iconChevronDownSmall_1 = require("../icons/iconChevronDownSmall");
|
|
15
|
+
const useLanguage_1 = require("../utils/localization/useLanguage");
|
|
16
|
+
const controlledPopup_1 = require("../controlledPopup/controlledPopup");
|
|
17
|
+
const filtersContainer_1 = require("./components/filtersContainer");
|
|
18
|
+
const filtersItem_1 = require("./components/filtersItem");
|
|
19
|
+
const filtersDropdown_1 = require("./components/filtersDropdown");
|
|
20
|
+
const filtersGroups_1 = require("./components/filtersGroups");
|
|
21
|
+
const filtersRange_1 = require("./components/filtersRange");
|
|
22
|
+
const filtersChip_1 = require("./components/filtersChip");
|
|
23
|
+
const filtersDateRange_1 = require("./components/filtersDateRange");
|
|
24
|
+
const filtersModal_1 = require("./components/filtersModal");
|
|
25
|
+
const filtersSearchList_1 = require("./components/filtersSearchList");
|
|
26
|
+
const chipStatusProvider_1 = require("../chip/chipStatusProvider");
|
|
27
|
+
const filtersSavedItemsProvider_1 = require("./components/filtersSavedItemsProvider");
|
|
28
|
+
const filtersHelper_1 = require("./filtersHelper");
|
|
29
|
+
const filtersSearch_1 = require("./components/filtersSearch");
|
|
30
|
+
const useUniqueId_1 = require("../commonHelpers/useUniqueId");
|
|
31
|
+
const isElementsEqual_1 = require("../utils/compareElementsUtils/isElementsEqual");
|
|
32
|
+
const iconFilter_1 = require("../icons/iconFilter");
|
|
33
|
+
exports.FiltersDisplayName = "Filters";
|
|
34
|
+
const Filters = ({ className, children, isPinned, onPinChange, keyword, setKeyword, searchTypes, searchType, setSearchType, allFiltersState, setAllFiltersState, onToggleView, searchSelection, setSearchSelection, recentSearches, onRemoveRecentSearchItem, onSaveRecentSearch, savedFilters, onRemoveSavedFilter, onSaveFilter }) => {
|
|
35
|
+
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
36
|
+
const isSavedFiltersMode = Boolean(savedFilters && onRemoveSavedFilter && onSaveFilter);
|
|
37
|
+
const isPinMode = Boolean(typeof isPinned === "boolean" && onPinChange);
|
|
38
|
+
const isRecentSearchesMode = Boolean(recentSearches && onRemoveRecentSearchItem && onSaveRecentSearch);
|
|
39
|
+
const uniqueKey = (0, useUniqueId_1.useUniqueId)();
|
|
40
|
+
const [isModalOpen, setIsModalOpen] = (0, react_1.useState)(false);
|
|
41
|
+
const triggerRef = react_2.default.useRef(null);
|
|
42
|
+
const searchTriggerRef = react_2.default.useRef(null);
|
|
43
|
+
const prevIsOpenRef = react_2.default.useRef(isOpen);
|
|
44
|
+
const [savedFiltersStates, setSavedFiltersStates] = (0, react_1.useState)(new Map());
|
|
45
|
+
const { translate } = (0, useLanguage_1.useLanguage)();
|
|
46
|
+
const searchTypesArray = (0, react_1.useMemo)(() => (0, filtersHelper_1.getArrayOfElements)(searchTypes), [searchTypes]);
|
|
47
|
+
const searchTypesMap = (0, react_1.useMemo)(() => {
|
|
48
|
+
const map = new Map();
|
|
49
|
+
searchTypesArray.forEach(el => {
|
|
50
|
+
map.set(el.id, el.name);
|
|
51
|
+
});
|
|
52
|
+
return map;
|
|
53
|
+
}, [searchTypesArray]);
|
|
54
|
+
const searchTypesToSelect = (0, react_1.useMemo)(() => searchTypesArray.map(el => ({ id: el.id, name: el.name, subItems: el.subItems ? [...el.subItems] : undefined })), [searchTypesArray]);
|
|
55
|
+
const filters = (0, react_1.useMemo)(() => {
|
|
56
|
+
const childrenArray = (0, headerHelpers_1.getArrayOfChildren)(children);
|
|
57
|
+
return (0, filtersItem_1.getAllowedFilters)(childrenArray);
|
|
58
|
+
}, [children]);
|
|
59
|
+
(0, react_1.useEffect)(() => {
|
|
60
|
+
if (!isSavedFiltersMode) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const error = savedFilters.error;
|
|
64
|
+
if (error) {
|
|
65
|
+
console.error("Failed to fetch saved filters. Error:", error);
|
|
66
|
+
}
|
|
67
|
+
else if (savedFilters && savedFilters.data) {
|
|
68
|
+
setSavedFiltersStates(new Map(savedFilters.data.map(item => [item.name, { id: item.id, state: item.state }])));
|
|
69
|
+
}
|
|
70
|
+
}, [isSavedFiltersMode, savedFilters]);
|
|
71
|
+
const handleSaveRecentSearch = (0, react_1.useCallback)((searchValue) => {
|
|
72
|
+
if (!onSaveRecentSearch) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!(searchSelection === null || searchSelection === void 0 ? void 0 : searchSelection.length) && !searchValue) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const entries = searchSelection || [];
|
|
79
|
+
const keywordEntry = searchValue ? { id: filtersSearchList_1.KEYWORD_ID, name: searchValue, type: filtersSearchList_1.KEYWORD_TYPE } : entries.find((item) => item.id === filtersSearchList_1.KEYWORD_ID);
|
|
80
|
+
const preparedItemsArray = [...entries].filter(el => el.id !== filtersSearchList_1.KEYWORD_ID).map(el => (Object.assign(Object.assign({}, el), { type: el.type || filtersSearchList_1.NO_TYPED_SEARCH_ITEM })));
|
|
81
|
+
const isTyped = preparedItemsArray.length ? preparedItemsArray.every(el => el.type === preparedItemsArray[0].type) : false;
|
|
82
|
+
if (keywordEntry) {
|
|
83
|
+
preparedItemsArray.push(Object.assign(Object.assign({}, keywordEntry), { type: filtersSearchList_1.KEYWORD_TYPE }));
|
|
84
|
+
}
|
|
85
|
+
const newRecentSearchNamesArr = preparedItemsArray.filter(el => el.id !== filtersSearchList_1.KEYWORD_ID).map(el => el.name || el.id);
|
|
86
|
+
keywordEntry && newRecentSearchNamesArr.push(`\%${keywordEntry.name}\%`);
|
|
87
|
+
const newRecentSearchName = newRecentSearchNamesArr.join(", ");
|
|
88
|
+
const newRecentSearch = { name: newRecentSearchName, type: isTyped ? preparedItemsArray[0].type : filtersSearchList_1.NO_TYPED_SEARCH_ITEM,
|
|
89
|
+
description: Array.from(new Set(entries.filter(el => el.type && el.type !== filtersSearchList_1.NO_TYPED_SEARCH_ITEM && el.type !== filtersSearchList_1.KEYWORD_TYPE)
|
|
90
|
+
.map(el => searchTypesMap.get(el.type) || el))).join(", "),
|
|
91
|
+
itemsArray: [...preparedItemsArray] };
|
|
92
|
+
onSaveRecentSearch(Object.assign({}, newRecentSearch));
|
|
93
|
+
}, [onSaveRecentSearch, searchSelection, searchTypesMap]);
|
|
94
|
+
const handleSearchFocus = (0, react_1.useCallback)(() => {
|
|
95
|
+
if (!isOpen) {
|
|
96
|
+
setIsOpen(true);
|
|
97
|
+
}
|
|
98
|
+
}, [isOpen]);
|
|
99
|
+
(0, react_1.useEffect)(() => {
|
|
100
|
+
var _a;
|
|
101
|
+
isOpen && ((_a = searchTriggerRef.current) === null || _a === void 0 ? void 0 : _a.focus());
|
|
102
|
+
}, [isOpen, searchTriggerRef]);
|
|
103
|
+
(0, react_1.useEffect)(() => {
|
|
104
|
+
if (!isOpen && prevIsOpenRef.current) {
|
|
105
|
+
prevIsOpenRef.current = false;
|
|
106
|
+
isRecentSearchesMode && handleSaveRecentSearch();
|
|
107
|
+
}
|
|
108
|
+
if (isOpen) {
|
|
109
|
+
prevIsOpenRef.current = true;
|
|
110
|
+
}
|
|
111
|
+
}, [isOpen, isRecentSearchesMode, handleSaveRecentSearch]);
|
|
112
|
+
const selectState = (0, react_1.useMemo)(() => Object.keys(searchType), [searchType]);
|
|
113
|
+
const onSearchItemClick = (0, react_1.useCallback)((item) => {
|
|
114
|
+
if (!(searchSelection && setSearchSelection)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const typeKey = item.type || filtersSearchList_1.NO_TYPED_SEARCH_ITEM;
|
|
118
|
+
const currentItem = searchSelection.find(el => el.id === item.id && (el.type || filtersSearchList_1.NO_TYPED_SEARCH_ITEM) === typeKey);
|
|
119
|
+
if (currentItem) {
|
|
120
|
+
const newValue = searchSelection.filter(el => !(el.id === currentItem.id && (el.type || filtersSearchList_1.NO_TYPED_SEARCH_ITEM) === typeKey));
|
|
121
|
+
setSearchSelection(newValue);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
setSearchSelection([...searchSelection, item]);
|
|
125
|
+
}
|
|
126
|
+
}, [searchSelection, setSearchSelection]);
|
|
127
|
+
const handleTriggerClick = (0, react_1.useCallback)(() => {
|
|
128
|
+
setIsOpen(prevState => !prevState);
|
|
129
|
+
}, []);
|
|
130
|
+
const handleModalState = (0, react_1.useCallback)(() => {
|
|
131
|
+
onToggleView && onToggleView(!isModalOpen);
|
|
132
|
+
setIsModalOpen(val => !val);
|
|
133
|
+
}, [isModalOpen, onToggleView]);
|
|
134
|
+
const handleOpenChange = (0, react_1.useCallback)((open) => {
|
|
135
|
+
setIsOpen(open);
|
|
136
|
+
}, []);
|
|
137
|
+
const handleModalApply = (0, react_1.useCallback)((state) => {
|
|
138
|
+
filters.forEach((filter) => {
|
|
139
|
+
const newState = state[filter.props.id];
|
|
140
|
+
if (filter.props.id && state.hasOwnProperty(filter.props.id) && filter.props.onChange) {
|
|
141
|
+
filter.props.onChange(newState);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}, [filters]);
|
|
145
|
+
const handleSaveFilters = (0, react_1.useCallback)((filterName, filterState) => {
|
|
146
|
+
const stateForSave = filterState || (0, filtersHelper_1.createStateObject)(filters, "state");
|
|
147
|
+
onSaveFilter && onSaveFilter({ name: filterName, state: stateForSave }).then((id) => {
|
|
148
|
+
setSavedFiltersStates(prevStates => new Map(prevStates).set(filterName, { state: stateForSave, id: id }));
|
|
149
|
+
}).catch(error => {
|
|
150
|
+
console.error("Could not save the following filter configuration:", "name", filterName, "state", stateForSave, "Error:", error);
|
|
151
|
+
});
|
|
152
|
+
}, [filters, onSaveFilter]);
|
|
153
|
+
const handleRecentSearchItemClick = (0, react_1.useCallback)((item) => {
|
|
154
|
+
const newSearchSelection = item.itemsArray;
|
|
155
|
+
const newItemSearch = item.itemsArray.find(el => el.id === filtersSearchList_1.KEYWORD_ID);
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
157
|
+
if (newSearchSelection) {
|
|
158
|
+
setSearchSelection === null || setSearchSelection === void 0 ? void 0 : setSearchSelection([...newSearchSelection]);
|
|
159
|
+
}
|
|
160
|
+
newItemSearch && setKeyword(newItemSearch.name);
|
|
161
|
+
setIsOpen(false);
|
|
162
|
+
}, [setKeyword, setSearchSelection]);
|
|
163
|
+
const handlePinChange = (0, react_1.useCallback)(() => {
|
|
164
|
+
onPinChange && onPinChange(!isPinned);
|
|
165
|
+
}, [onPinChange, isPinned]);
|
|
166
|
+
const getIconByType = (0, react_1.useCallback)((type) => {
|
|
167
|
+
if (!type) {
|
|
168
|
+
return iconFilter_1.IconFilter;
|
|
169
|
+
}
|
|
170
|
+
const foundType = searchTypesArray.find((item) => item.id === type);
|
|
171
|
+
return foundType && foundType.icon ? foundType.icon : iconFilter_1.IconFilter;
|
|
172
|
+
}, [searchTypesArray]);
|
|
173
|
+
const memoizedSelect = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(filtersSelect_1.FiltersSelect, { id: `filtersSelect_${uniqueKey}`,
|
|
174
|
+
// name={translate("Search by")}
|
|
175
|
+
value: searchType, onChange: setSearchType, items: searchTypesToSelect }), [searchType, searchTypesToSelect, setSearchType, uniqueKey]);
|
|
176
|
+
const memoizedSearch = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(filtersSearch_1.FiltersSearch, { id: `filtersSearch_${uniqueKey}`, ref: isOpen ? searchTriggerRef : null, name: translate("Search page"), value: keyword, onChange: setKeyword, onSearchKeyDown: isRecentSearchesMode ? handleSaveRecentSearch : undefined, handleSearchFocus: handleSearchFocus, handleRemove: onSearchItemClick, searchSelection: searchSelection, className: "zen-filters-popup__search-with-pills" }), [uniqueKey, isOpen, translate, keyword, setKeyword, isRecentSearchesMode, handleSaveRecentSearch, handleSearchFocus, onSearchItemClick, searchSelection]);
|
|
177
|
+
const allOption = (0, react_1.useMemo)(() => (0, filtersSelect_1.getAllOption)(translate), [translate]);
|
|
178
|
+
const selectTrigger = (0, react_1.useMemo)(() => {
|
|
179
|
+
var _a;
|
|
180
|
+
return (0, jsx_runtime_1.jsx)(textIconButton_1.TextIconButton, { className: "zen-filters__select-trigger", iconClasses: "zen-filters__select-trigger-icon", contentClasses: "zen-filters__select-trigger-content", onClick: handleTriggerClick, icon: iconChevronDownSmall_1.IconChevronDownSmall, iconPosition: "end", children: !isOpen ? selectState[0] === filtersSelect_1.ALL_SELECT_OPTION_ID ? allOption.name :
|
|
181
|
+
(_a = searchTypesArray.find((item) => item.id === selectState[0])) === null || _a === void 0 ? void 0 : _a.name : translate("Search by") });
|
|
182
|
+
}, [handleTriggerClick, selectState, isOpen, allOption.name, translate, searchTypesArray]);
|
|
183
|
+
const combinedData = (0, filtersHelper_1.useCombineData)(searchTypesArray);
|
|
184
|
+
const memoizedPopup = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(controlledPopup_1.ControlledPopup, { paddingY: -28, isOpen: isOpen, className: (0, classNames_1.classNames)(["zen-filters-popup"]), onOpenChange: handleOpenChange, useTrapFocusWithTrigger: "withTrigger", alignment: "bottom", shouldHoldScroll: true, triggerRef: triggerRef, ariaLabel: translate("Setting conditions"), recalculateOnScroll: true, children: (0, jsx_runtime_1.jsxs)("div", { className: "zen-filters-popup__content", children: [(0, jsx_runtime_1.jsxs)("div", { className: "zen-filters-popup__left-panel", children: [selectTrigger, memoizedSelect] }), (0, jsx_runtime_1.jsxs)("div", { className: "zen-filters-popup__right-panel", children: [memoizedSearch, (0, jsx_runtime_1.jsx)(filtersSearchList_1.FiltersSearchList, { searchValue: keyword, searchData: combinedData, searchSelection: searchSelection, getIconByType: getIconByType, handleSearchItemClick: onSearchItemClick, recentSearches: isRecentSearchesMode ? recentSearches : undefined, onRemoveRecentSearchItem: isRecentSearchesMode ? onRemoveRecentSearchItem : undefined, handleRecentSearchItemClick: isRecentSearchesMode ? handleRecentSearchItemClick : undefined })] })] }) }), [isOpen, handleOpenChange, selectTrigger, memoizedSelect, memoizedSearch, keyword, combinedData, searchSelection, getIconByType, onSearchItemClick, isRecentSearchesMode, recentSearches, translate, onRemoveRecentSearchItem, handleRecentSearchItemClick]);
|
|
185
|
+
const filtersForRender = (0, react_1.useMemo)(() => filters.filter(el => typeof el.props.visible === "boolean" ? el.props.visible
|
|
186
|
+
: el.props.visible === undefined ? false : el.props.visible(Array.from(selectState), undefined)), [filters, selectState]);
|
|
187
|
+
// The modal has a full set of filters, so we need to calculate the number of changed filters based on all filters, not just the visible ones
|
|
188
|
+
const filtersForCalculation = (0, react_1.useMemo)(() => {
|
|
189
|
+
const stateObj = (0, filtersHelper_1.createStateObject)(filters, "state");
|
|
190
|
+
return filters.filter(el => typeof el.props.visible === "boolean" ? el.props.visible
|
|
191
|
+
: el.props.visible === undefined ? true : (el.props.visible(Array.from(selectState), stateObj) || el.props.visible(Array.from(selectState))));
|
|
192
|
+
}, [filters, selectState]);
|
|
193
|
+
const hasSavedFilters = savedFiltersStates.size > 0;
|
|
194
|
+
const memoizedFiltersContainer = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(filtersContainer_1.FiltersContainer, { filtersClickHandler: handleModalState, filtersForCalculation: filtersForCalculation, isPinned: isPinMode ? isPinned : undefined, onPinChange: isPinMode ? onPinChange : undefined, hasSavedFilters: hasSavedFilters, children: filtersForRender }), [handleModalState, filtersForCalculation, isPinMode, isPinned, onPinChange, hasSavedFilters, filtersForRender]);
|
|
195
|
+
const tabItems = (0, react_1.useMemo)(() => searchTypesArray.map((item) => ({ id: item.id, name: item.name })), [searchTypesArray]);
|
|
196
|
+
const memoizedModal = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(filtersModal_1.FiltersModal, { isOpen: isModalOpen, onApply: handleModalApply, onClose: handleModalState, onPin: isPinMode ? handlePinChange : undefined, isPinned: isPinMode ? isPinned : undefined, filters: filters, tabItems: tabItems, externalModalState: allFiltersState, setExternalModalState: setAllFiltersState }), [isModalOpen, handleModalApply, handleModalState, handlePinChange, isPinned, isPinMode, filters, tabItems, allFiltersState, setAllFiltersState]);
|
|
197
|
+
const memoizedStatus = (0, react_1.useMemo)(() => isPinned && isPinMode ? "accent" : undefined, [isPinned, isPinMode]);
|
|
198
|
+
const memoizedSavedFiltersItems = (0, react_1.useMemo)(() => new Set(savedFiltersStates.keys()), [savedFiltersStates]);
|
|
199
|
+
const memoizedSavedFiltersActive = (0, react_1.useMemo)(() => {
|
|
200
|
+
const activeSet = new Set();
|
|
201
|
+
const currentState = (0, filtersHelper_1.createStateObject)(filters, "state");
|
|
202
|
+
Array.from(savedFiltersStates.keys()).forEach(key => {
|
|
203
|
+
var _a;
|
|
204
|
+
const savedState = (_a = savedFiltersStates.get(key)) === null || _a === void 0 ? void 0 : _a.state;
|
|
205
|
+
if (savedState) {
|
|
206
|
+
if ((0, isElementsEqual_1.isElementsEqual)(currentState, savedState)) {
|
|
207
|
+
activeSet.add(key);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return activeSet;
|
|
212
|
+
}, [savedFiltersStates, filters]);
|
|
213
|
+
const removeSavedFiltersState = (0, react_1.useCallback)((item) => {
|
|
214
|
+
var _a;
|
|
215
|
+
setSavedFiltersStates((prev) => {
|
|
216
|
+
const newState = new Map(prev);
|
|
217
|
+
newState.delete(item);
|
|
218
|
+
return newState;
|
|
219
|
+
});
|
|
220
|
+
const filterId = (_a = savedFiltersStates.get(item)) === null || _a === void 0 ? void 0 : _a.id;
|
|
221
|
+
if (filterId) {
|
|
222
|
+
onRemoveSavedFilter && onRemoveSavedFilter(filterId);
|
|
223
|
+
}
|
|
224
|
+
}, [onRemoveSavedFilter, savedFiltersStates]);
|
|
225
|
+
const applySavedFiltersState = (0, react_1.useCallback)((item) => {
|
|
226
|
+
var _a;
|
|
227
|
+
const newState = (_a = savedFiltersStates.get(item)) === null || _a === void 0 ? void 0 : _a.state;
|
|
228
|
+
if (newState) {
|
|
229
|
+
filters.forEach((filter) => {
|
|
230
|
+
const stateForFilter = newState[filter.props.id];
|
|
231
|
+
if (filter.props.id && newState.hasOwnProperty(filter.props.id) && filter.props.onChange) {
|
|
232
|
+
filter.props.onChange(stateForFilter);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}, [filters, savedFiltersStates]);
|
|
237
|
+
return (0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-filters", className || ""]), children: [isOpen ? null : (0, jsx_runtime_1.jsxs)("div", { className: "zen-filters__main-row", children: [selectTrigger, memoizedSearch] }), (0, jsx_runtime_1.jsx)("div", { className: "zen-filters__trigger", ref: triggerRef, role: "button", tabIndex: 0, "aria-label": translate("Open search") }), (0, jsx_runtime_1.jsx)(filtersSavedItemsProvider_1.FiltersSavedItemsProvider, { items: memoizedSavedFiltersItems, active: memoizedSavedFiltersActive, onRemove: isSavedFiltersMode ? removeSavedFiltersState : undefined, onApply: isSavedFiltersMode ? applySavedFiltersState : undefined, onSave: isSavedFiltersMode ? handleSaveFilters : undefined, children: (0, jsx_runtime_1.jsx)(chipStatusProvider_1.ChipStatusProvider, { status: memoizedStatus, children: memoizedFiltersContainer }) }), memoizedPopup, isModalOpen ? (0, jsx_runtime_1.jsx)(filtersSavedItemsProvider_1.FiltersSavedItemsProvider, { items: memoizedSavedFiltersItems, active: memoizedSavedFiltersActive, onRemove: isSavedFiltersMode ? removeSavedFiltersState : undefined, onApply: isSavedFiltersMode ? applySavedFiltersState : undefined, onSave: isSavedFiltersMode ? handleSaveFilters : undefined, children: (0, jsx_runtime_1.jsx)(chipStatusProvider_1.ChipStatusProvider, { status: memoizedStatus, children: memoizedModal }) }) : null] });
|
|
238
|
+
};
|
|
239
|
+
exports.Filters = Filters;
|
|
240
|
+
exports.Filters.Chip = filtersChip_1.FiltersChip;
|
|
241
|
+
exports.Filters.DateRange = filtersDateRange_1.FiltersDateRange;
|
|
242
|
+
exports.Filters.Dropdown = filtersDropdown_1.FiltersDropdown;
|
|
243
|
+
exports.Filters.Groups = filtersGroups_1.FiltersGroups;
|
|
244
|
+
exports.Filters.Range = filtersRange_1.FiltersRange;
|
|
245
|
+
// Filters.Custom = FiltersCustom;
|
|
246
|
+
exports.Filters.displayName = exports.FiltersDisplayName;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { TFiltersDropdownAllStates } from "./components/filtersDropdown";
|
|
4
|
+
import { IFiltersSearchTypesItem } from "./filters";
|
|
5
|
+
import { ISearchItem } from "./components/filtersSearchList";
|
|
6
|
+
export declare const createStateHash: (state: unknown) => string;
|
|
7
|
+
export declare const createPropsHash: (props: Record<string, unknown>) => string;
|
|
8
|
+
export declare const stabilizeChildrenWithId: (children: React.ReactNode) => (React.ReactElement | null)[];
|
|
9
|
+
export type TDropdownState = "base" | "withCheckbox" | "fullSelection" | "fullSelectionWithCheckbox";
|
|
10
|
+
export declare const getDropdownStateType: (dropdownState: TFiltersDropdownAllStates) => "base" | "fullSelectionWithCheckbox" | "fullSelection" | "withCheckbox";
|
|
11
|
+
export declare const prepareDefaultDropdownState: (type: TDropdownState) => never[] | {
|
|
12
|
+
selected: never[];
|
|
13
|
+
isAllSelected: boolean;
|
|
14
|
+
isChecked: boolean;
|
|
15
|
+
} | {
|
|
16
|
+
selected: never[];
|
|
17
|
+
isChecked: boolean;
|
|
18
|
+
isAllSelected?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
selected: never[];
|
|
21
|
+
isAllSelected: boolean;
|
|
22
|
+
isChecked?: undefined;
|
|
23
|
+
};
|
|
24
|
+
export declare const getChildren: (children?: ReactElement | (null | ReactElement)[]) => (ReactElement<any, string | React.JSXElementConstructor<any>> | null)[];
|
|
25
|
+
export declare const getFiltersState: (children: ReactElement | ReactElement[]) => {};
|
|
26
|
+
export declare const createStateObject: (children: ReactElement | ReactElement[], field: "state" | "defaultState") => {};
|
|
27
|
+
export declare function getNumberOfChangedFilters(state: object): number;
|
|
28
|
+
export declare const getTotalChangedNumber: (selectState: string[], filters: ReactElement[], isModalCondition: boolean) => number;
|
|
29
|
+
export declare const serializeEntriesToId: (entries: {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
type?: string;
|
|
33
|
+
}[]) => string;
|
|
34
|
+
export declare const MAX_TOTAL_RESULTS = 500;
|
|
35
|
+
export declare const useCombineData: (searchTypes: IFiltersSearchTypesItem[]) => {
|
|
36
|
+
data: ISearchItem[];
|
|
37
|
+
isLoading: boolean;
|
|
38
|
+
error: Error | null;
|
|
39
|
+
};
|
|
40
|
+
export declare function getArrayOfElements<T>(elem: T | T[] | undefined): T[];
|