@geotab/zenith 3.13.0-beta.0 → 3.13.1-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.
Files changed (41) hide show
  1. package/README.md +7 -1
  2. package/dist/chart/lineChart/getDefaultOptions.js +7 -2
  3. package/dist/commonHelpers/hooks/usePillSize.js +2 -2
  4. package/dist/controlledPopup/controlledPopup.d.ts +4 -1
  5. package/dist/controlledPopup/controlledPopup.js +2 -2
  6. package/dist/filters/components/filtersContainer.js +64 -7
  7. package/dist/filters/components/filtersSearch.d.ts +7 -2
  8. package/dist/filters/components/filtersSearch.js +36 -72
  9. package/dist/filters/components/filtersSearchList.js +18 -35
  10. package/dist/filters/filters.d.ts +2 -0
  11. package/dist/filters/filters.js +66 -180
  12. package/dist/filters/filtersHelper.js +1 -1
  13. package/dist/groupsFilterRaw/groupsFilterRaw.js +7 -1
  14. package/dist/index.css +158 -69
  15. package/dist/inputAdornments/inputAdornments.d.ts +2 -1
  16. package/dist/inputAdornments/inputAdornments.js +2 -2
  17. package/dist/searchInputRaw/searchInputRaw.js +6 -2
  18. package/dist/searchInputRaw/types.d.ts +4 -0
  19. package/dist/utils/localization/translations/en.json +1 -0
  20. package/dist/utils/positioningUtils/calculatePosition.js +3 -1
  21. package/dist/utils/positioningUtils/normalizeVertically.js +1 -1
  22. package/esm/chart/lineChart/getDefaultOptions.js +7 -2
  23. package/esm/commonHelpers/hooks/usePillSize.js +2 -2
  24. package/esm/controlledPopup/controlledPopup.d.ts +4 -1
  25. package/esm/controlledPopup/controlledPopup.js +2 -2
  26. package/esm/filters/components/filtersContainer.js +65 -8
  27. package/esm/filters/components/filtersSearch.d.ts +7 -2
  28. package/esm/filters/components/filtersSearch.js +36 -49
  29. package/esm/filters/components/filtersSearchList.js +18 -35
  30. package/esm/filters/filters.d.ts +2 -0
  31. package/esm/filters/filters.js +67 -181
  32. package/esm/filters/filtersHelper.js +1 -1
  33. package/esm/groupsFilterRaw/groupsFilterRaw.js +7 -1
  34. package/esm/inputAdornments/inputAdornments.d.ts +2 -1
  35. package/esm/inputAdornments/inputAdornments.js +2 -2
  36. package/esm/searchInputRaw/searchInputRaw.js +6 -2
  37. package/esm/searchInputRaw/types.d.ts +4 -0
  38. package/esm/utils/localization/translations/en.json +1 -0
  39. package/esm/utils/positioningUtils/calculatePosition.js +3 -1
  40. package/esm/utils/positioningUtils/normalizeVertically.js +1 -1
  41. package/package.json +1 -1
@@ -1,17 +1,20 @@
1
1
  import { injectString } from "../../utils/localization/translationsDictionary";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useMemo } from "react";
3
+ import { useCallback, useMemo, useRef, useState } from "react";
4
4
  import { classNames } from "../../commonHelpers/classNames/classNames";
5
5
  import { Chip } from "../../chip/chip";
6
6
  import React from "react";
7
7
  import { IconFilter } from "../../icons/iconFilter";
8
8
  import { createPropsHash, createStateHash, createStateObject, getFiltersState, getNumberOfChangedFilters, stabilizeChildrenWithId } from "../filtersHelper";
9
9
  import { FiltersSavedChipComponent } from "./filtersSavedChipComponent";
10
- import { IconClose } from "../../icons/iconClose";
10
+ import { IconCloseCircle } from "../../icons/iconCloseCircle";
11
+ import { IconDisk } from "../../icons/iconDisk";
11
12
  import { useChipStatus } from "../../chip/chipStatusProvider";
12
13
  import { useLanguage } from "../../utils/localization/useLanguage";
13
14
  import { useMobile } from "../../commonHelpers/hooks/useMobile";
14
15
  import { getNewFocusableItem } from "../../utils/keyboardHelpers";
16
+ import { useFiltersSavedItems } from "./filtersSavedItemsProvider";
17
+ import { FiltersSaveModal } from "./filtersSaveModal";
15
18
  injectString("cs", "All Filters", "V\u0161echny filtry");
16
19
  injectString("da-DK", "All Filters", "Alle filtre");
17
20
  injectString("de", "All Filters", "Alle Filter");
@@ -66,6 +69,33 @@ injectString("zh-Hans", "Clear", "\u6E05\u9664");
66
69
  injectString("zh-TW", "Clear", "\u6E05\u9664");
67
70
  injectString("ro-RO", "Clear", "\u0218terge\u021Bi");
68
71
  injectString("ar", "Clear", "\u0645\u0633\u062D");
72
+ injectString("cs", "Save", "Ulo\u017Eit");
73
+ injectString("da-DK", "Save", "Spare");
74
+ injectString("de", "Save", "Speichern");
75
+ injectString("en", "Save", "Save");
76
+ injectString("es", "Save", "Guardar");
77
+ injectString("fi-FI", "Save", "S\xE4\xE4st\xE4\xE4");
78
+ injectString("fr", "Save", "Enregistrer");
79
+ injectString("fr-FR", "Save", "Enregistrer");
80
+ injectString("hu-HU", "Save", "Ment\xE9s");
81
+ injectString("id", "Save", "Simpan");
82
+ injectString("it", "Save", "Salvare");
83
+ injectString("ja", "Save", "\u4FDD\u5B58");
84
+ injectString("ko-KR", "Save", "\uC800\uC7A5");
85
+ injectString("ms", "Save", "Simpan");
86
+ injectString("nb-NO", "Save", "Lagre");
87
+ injectString("nl", "Save", "Opslaan");
88
+ injectString("pl", "Save", "Zapisz");
89
+ injectString("pt-BR", "Save", "Salvar");
90
+ injectString("pt-PT", "Save", "Guardar");
91
+ injectString("sk-SK", "Save", "Ulo\u017Ei\u0165");
92
+ injectString("sv", "Save", "Spara");
93
+ injectString("th", "Save", "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01");
94
+ injectString("tr", "Save", "Kaydet");
95
+ injectString("zh-Hans", "Save", "\u4FDD\u5B58");
96
+ injectString("zh-TW", "Save", "\u5132\u5B58");
97
+ injectString("ro-RO", "Save", "Salva\u021Bi");
98
+ injectString("ar", "Save", "\u062D\u0641\u0638");
69
99
  export const FiltersContainer = ({
70
100
  className,
71
101
  isPinned = false,
@@ -81,6 +111,11 @@ export const FiltersContainer = ({
81
111
  translate
82
112
  } = useLanguage();
83
113
  const isMobile = useMobile();
114
+ const {
115
+ onSave
116
+ } = useFiltersSavedItems();
117
+ const [saveModalOpen, setSaveModalOpen] = useState(false);
118
+ const saveChipRef = useRef(null);
84
119
  const filtersChipContainerRef = React.useRef(null);
85
120
  const numberOfChangedFilters = useMemo(() => {
86
121
  const suppressedFilters = new Set();
@@ -103,6 +138,7 @@ export const FiltersContainer = ({
103
138
  title: translate("All Filters"),
104
139
  dataRole: "dialog",
105
140
  triggerRef: filtersChipRef,
141
+ className: "zen-filters-container__all-filters-chip",
106
142
  children: "+"
107
143
  }), [numberOfChangedFilters, chipStatus, filtersClickHandler, translate, filtersChipRef]);
108
144
  const childrenSignature = useMemo(() => {
@@ -160,18 +196,39 @@ export const FiltersContainer = ({
160
196
  active: false,
161
197
  status: isPinned ? "accent" : undefined,
162
198
  onChange: handleRemovalClick,
163
- icon: IconClose
199
+ icon: IconCloseCircle
164
200
  }) : null, [isPinned, handleRemovalClick, translate, numberOfChangedFilters]);
201
+ const handleSaveChipClick = useCallback(() => {
202
+ setSaveModalOpen(true);
203
+ }, []);
204
+ const chipSaveComponent = useMemo(() => onSave ? _jsx(Chip, {
205
+ title: translate("Save"),
206
+ onClick: handleSaveChipClick,
207
+ icon: IconDisk,
208
+ isOpen: saveModalOpen,
209
+ triggerRef: saveChipRef,
210
+ className: "zen-filters-container__save-chip"
211
+ }) : null, [onSave, translate, handleSaveChipClick, saveModalOpen]);
212
+ // Order:
213
+ // Default: [filters] [+]
214
+ // Selected: [filters] [+badge] [save] [clear]
215
+ // w/ Saved: [filters] [+] [save]
216
+ const showInlineSave = Boolean(onSave && (numberOfChangedFilters > 0 || hasSavedFilters));
165
217
  const memoizedFiltersElements = useMemo(() => _jsxs(_Fragment, {
166
- children: [memoizedChildren, hasSavedFilters ? _jsx(FiltersSavedChipComponent, {}) : null, filtersChipComponent, chipRemovalComponent]
167
- }), [chipRemovalComponent, filtersChipComponent, hasSavedFilters, memoizedChildren]);
168
- return _jsx("div", {
218
+ children: [memoizedChildren, hasSavedFilters ? _jsx(FiltersSavedChipComponent, {}) : null, filtersChipComponent, showInlineSave ? chipSaveComponent : null, chipRemovalComponent]
219
+ }), [chipRemovalComponent, chipSaveComponent, filtersChipComponent, hasSavedFilters, memoizedChildren, showInlineSave]);
220
+ return _jsxs("div", {
169
221
  className: classNames(["zen-filters-container", isMobile ? "zen-filters-container--mobile" : "", className || ""]),
170
222
  onKeyDown: handleKeyDown,
171
223
  ref: filtersChipContainerRef,
172
- children: isMobile ? _jsx("div", {
224
+ children: [isMobile ? _jsx("div", {
173
225
  className: "zen-filters-container__mobile-scroll-wrapper",
174
226
  children: memoizedFiltersElements
175
- }) : memoizedFiltersElements
227
+ }) : memoizedFiltersElements, onSave ? _jsx(FiltersSaveModal, {
228
+ prioritize: isMobile,
229
+ isOpen: saveModalOpen,
230
+ onClose: setSaveModalOpen,
231
+ onSave: onSave
232
+ }) : null]
176
233
  });
177
234
  };
@@ -8,19 +8,24 @@ interface IFiltersSearch {
8
8
  onChange: (newValue: string) => void;
9
9
  onSearchKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
10
10
  onOpenPopup?: () => void;
11
+ /** Called when the clear (X) button inside the search input is clicked */
12
+ onClear?: () => void;
11
13
  searchSelection?: ISearchItem[];
12
- handleRemove?: (id: ISearchItem) => void;
13
14
  className?: string;
14
15
  ref?: RefObject<HTMLInputElement | null>;
16
+ /** Ref forwarded to the root wrapper div — used to anchor the search popup */
17
+ containerRef?: RefObject<HTMLDivElement | null>;
15
18
  ariaLabel?: string;
16
19
  role?: string | undefined;
17
20
  ariaAutocomplete?: "list" | "none" | "inline" | "both";
18
21
  ariaControls?: string;
19
22
  ariaHaspopup?: boolean | "dialog" | "menu" | "grid" | "true" | "false" | "listbox" | "tree";
20
23
  ariaExpanded?: boolean | "true" | "false";
24
+ /** When true, renders only the search icon button (input lives in the popup) */
25
+ isMobile?: boolean;
21
26
  }
22
27
  export declare const FiltersSearch: {
23
- ({ id, name, value, onChange, onSearchKeyDown, onOpenPopup, searchSelection, handleRemove, className, ariaLabel, role, ariaAutocomplete, ariaControls, ariaHaspopup, ariaExpanded, ref }: IFiltersSearch): import("react/jsx-runtime").JSX.Element;
28
+ ({ id, name, value, onChange, onSearchKeyDown, onOpenPopup, onClear, searchSelection, className, containerRef, ariaLabel, role, ariaAutocomplete, ariaControls, ariaHaspopup, ariaExpanded, isMobile, ref }: IFiltersSearch): import("react/jsx-runtime").JSX.Element;
24
29
  displayName: string;
25
30
  };
26
31
  export {};
@@ -1,62 +1,49 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useCallback, useMemo } from "react";
2
+ import { useCallback, useMemo } from "react";
3
3
  import { classNames } from "../../commonHelpers/classNames/classNames";
4
- import { NO_TYPED_SEARCH_ITEM } from "./filtersSearchList";
5
4
  import { SearchInputRaw } from "../../searchInputRaw/searchInputRaw";
6
5
  import { Pill } from "../../pill/pill";
7
- import { useMobile } from "../../commonHelpers/hooks/useMobile";
8
- export const FiltersSearch = ({ id, name, value, onChange, onSearchKeyDown, onOpenPopup, searchSelection, handleRemove, className, ariaLabel, role, ariaAutocomplete, ariaControls, ariaHaspopup, ariaExpanded, ref }) => {
9
- const isWithPills = Boolean(searchSelection && handleRemove);
10
- const divider = "_divider_";
11
- const isMobile = useMobile();
12
- const memoizedPillsArray = React.useMemo(() => {
13
- if (!isWithPills || !searchSelection || searchSelection.length === 0) {
14
- return [];
15
- }
16
- const pillsArray = [];
17
- searchSelection.forEach(item => {
18
- pillsArray.push({
19
- id: `${item.type || NO_TYPED_SEARCH_ITEM}${divider}${item.id}`,
20
- name: item.name
21
- });
22
- });
23
- return pillsArray;
24
- }, [isWithPills, searchSelection]);
25
- const onRemove = useCallback((removedId) => {
26
- const [type, itemId] = removedId.split(divider);
27
- const item = searchSelection === null || searchSelection === void 0 ? void 0 : searchSelection.find(el => el.id === itemId);
28
- if (item) {
29
- handleRemove === null || handleRemove === void 0 ? void 0 : handleRemove(Object.assign(Object.assign({}, item), { type: type === NO_TYPED_SEARCH_ITEM ? undefined : type }));
30
- }
31
- }, [handleRemove, searchSelection]);
32
- const handleSearchClick = useCallback(e => {
33
- var _a, _b, _c;
34
- if (((_a = e.target) === null || _a === void 0 ? void 0 : _a.dataset.name) === "IconClose" ||
35
- e.target.classList.contains("zen-pill-non-actionable__close-button") ||
36
- ((_b = e.target) === null || _b === void 0 ? void 0 : _b.parentElement.classList.contains("zen-pill-non-actionable__close-button")) ||
37
- ((_c = e.target) === null || _c === void 0 ? void 0 : _c.parentElement.dataset.name) === "IconClose") {
6
+ import { IconSearch } from "../../icons/iconSearch";
7
+ export const FiltersSearch = ({ id, name, value, onChange, onSearchKeyDown, onOpenPopup, onClear, searchSelection, className, containerRef, ariaLabel, role, ariaAutocomplete, ariaControls, ariaHaspopup, ariaExpanded, isMobile, ref }) => {
8
+ var _a;
9
+ const selectionCount = (_a = searchSelection === null || searchSelection === void 0 ? void 0 : searchSelection.length) !== null && _a !== void 0 ? _a : 0;
10
+ const handleSearchClick = useCallback((e) => {
11
+ var _a, _b;
12
+ const target = e.target;
13
+ if (target.classList.contains("zen-search-input__close-button") ||
14
+ ((_a = target.parentElement) === null || _a === void 0 ? void 0 : _a.classList.contains("zen-search-input__close-button")) ||
15
+ target.dataset.name === "IconClose" ||
16
+ ((_b = target.parentElement) === null || _b === void 0 ? void 0 : _b.dataset.name) === "IconClose") {
38
17
  return;
39
18
  }
40
19
  onOpenPopup === null || onOpenPopup === void 0 ? void 0 : onOpenPopup();
41
20
  }, [onOpenPopup]);
21
+ const selectionLabel = selectionCount > 99 ? "+99" : String(selectionCount);
42
22
  const selectedPills = useMemo(() => {
43
- if (memoizedPillsArray.length === 0) {
23
+ if (selectionCount === 0) {
44
24
  return [];
45
25
  }
46
- if (isMobile) {
47
- return memoizedPillsArray.length
48
- ? [
49
- _jsx(Pill, { type: "info", className: "zen-filters-search__selected-item zen-filters-search__selected-item--more", children: `+${memoizedPillsArray.length}` }, `${memoizedPillsArray.length}_${memoizedPillsArray.map(pill => pill.name).join("_")}`)
50
- ]
51
- : [];
52
- }
53
- const pillsForRender = [
54
- { id: memoizedPillsArray[0].id, name: memoizedPillsArray[0].name },
55
- memoizedPillsArray.length > 1 ? { id: "more_pills", name: `+${memoizedPillsArray.length - 1}` } : undefined
56
- ].filter(Boolean);
57
- return pillsForRender.map((pill, ind) => (_jsx(Pill, { type: "info", onClose: ind === 0 ? onRemove.bind(null, pill.id) : undefined, className: classNames(["zen-filters-search__selected-item", ind !== 0 ? "zen-filters-search__selected-item--more" : ""]), children: pill.name }, `${pill.id}_${pill.name}`)));
58
- }, [memoizedPillsArray, onRemove, isMobile]);
59
- const searchComponent = useMemo(() => (_jsx(SearchInputRaw, { id: id, ref: ref, placeholder: name, onChange: onChange, onKeyDown: onSearchKeyDown, value: value, role: role, ariaLabel: ariaLabel, ariaExpanded: ariaExpanded === undefined ? undefined : ariaExpanded === "true" || ariaExpanded === true, ariaHaspopup: ariaHaspopup, ariaControls: ariaControls, ariaAutocomplete: ariaAutocomplete, className: classNames(["zen-filters-search__search-input", "zen-filters__search", className || ""]) })), [id, ref, name, onChange, onSearchKeyDown, value, className, role, ariaLabel, ariaExpanded, ariaHaspopup, ariaControls, ariaAutocomplete]);
60
- return (_jsxs("div", { className: classNames(["zen-filters-search", className || "", isMobile ? "zen-filters-search--mobile" : ""]), onClick: handleSearchClick, children: [searchComponent, selectedPills.length > 0 && _jsx("div", { className: "zen-filters-search__selected", children: selectedPills })] }));
26
+ return [
27
+ _jsx(Pill, { type: "info", className: "zen-filters-search__selected-item zen-filters-search__selected-item--more", children: selectionLabel }, selectionCount)
28
+ ];
29
+ }, [selectionCount, selectionLabel]);
30
+ const searchComponent = useMemo(() => (_jsx(SearchInputRaw, { id: id, ref: ref, placeholder: name, onChange: onChange, onClear: onClear, onKeyDown: onSearchKeyDown, value: value, role: role, ariaLabel: ariaLabel, ariaExpanded: ariaExpanded === undefined ? undefined : ariaExpanded === "true" || ariaExpanded === true, ariaHaspopup: ariaHaspopup, ariaControls: ariaControls, ariaAutocomplete: ariaAutocomplete, className: classNames(["zen-filters-search__search-input", "zen-filters__search", className || ""]) })), [
31
+ id,
32
+ ref,
33
+ name,
34
+ onChange,
35
+ onClear,
36
+ onSearchKeyDown,
37
+ value,
38
+ className,
39
+ role,
40
+ ariaLabel,
41
+ ariaExpanded,
42
+ ariaHaspopup,
43
+ ariaControls,
44
+ ariaAutocomplete
45
+ ]);
46
+ const mobileTrigger = useMemo(() => (_jsx("button", { type: "button", className: "zen-filters-search__mobile-trigger", onClick: handleSearchClick, "aria-haspopup": ariaHaspopup, "aria-controls": ariaControls, "aria-expanded": ariaExpanded === undefined ? undefined : ariaExpanded === "true" || ariaExpanded === true, "aria-label": ariaLabel || name, children: _jsx(IconSearch, { className: "zen-filters-search__mobile-trigger-icon", size: "large" }) })), [handleSearchClick, ariaHaspopup, ariaControls, ariaExpanded, ariaLabel, name]);
47
+ return (_jsxs("div", { ref: containerRef, className: classNames(["zen-filters-search", isMobile ? "zen-filters-search--mobile" : "", className || ""]), onClick: isMobile ? undefined : handleSearchClick, children: [isMobile ? mobileTrigger : searchComponent, selectedPills.length > 0 && _jsx("div", { className: "zen-filters-search__selected", children: selectedPills })] }));
61
48
  };
62
49
  FiltersSearch.displayName = "FiltersSearch";
@@ -126,33 +126,6 @@ injectString("zh-Hans", "Currently selected", "Currently selected");
126
126
  injectString("zh-TW", "Currently selected", "Currently selected");
127
127
  injectString("ro-RO", "Currently selected", "Selec\u021Bie curent\u0103");
128
128
  injectString("ar", "Currently selected", "\u0627\u0644\u0645\u062D\u062F\u062F \u062D\u0627\u0644\u064A\u0627\u064B");
129
- injectString("cs", "View history", "View history");
130
- injectString("da-DK", "View history", "View history");
131
- injectString("de", "View history", "View history");
132
- injectString("en", "View history", "View history");
133
- injectString("es", "View history", "View history");
134
- injectString("fi-FI", "View history", "View history");
135
- injectString("fr", "View history", "View history");
136
- injectString("fr-FR", "View history", "View history");
137
- injectString("hu-HU", "View history", "View history");
138
- injectString("id", "View history", "View history");
139
- injectString("it", "View history", "View history");
140
- injectString("ja", "View history", "View history");
141
- injectString("ko-KR", "View history", "View history");
142
- injectString("ms", "View history", "View history");
143
- injectString("nb-NO", "View history", "View history");
144
- injectString("nl", "View history", "View history");
145
- injectString("pl", "View history", "View history");
146
- injectString("pt-BR", "View history", "View history");
147
- injectString("pt-PT", "View history", "Ver hist\xF3rico");
148
- injectString("sk-SK", "View history", "View history");
149
- injectString("sv", "View history", "View history");
150
- injectString("th", "View history", "View history");
151
- injectString("tr", "View history", "View history");
152
- injectString("zh-Hans", "View history", "View history");
153
- injectString("zh-TW", "View history", "View history");
154
- injectString("ro-RO", "View history", "Vede\u021Bi istoricul");
155
- injectString("ar", "View history", "\u0639\u0631\u0636 \u0627\u0644\u0633\u062C\u0644");
156
129
  injectString("cs", "Clear", "Vymazat");
157
130
  injectString("da-DK", "Clear", "Ryd");
158
131
  injectString("de", "Clear", "L\xF6schen");
@@ -385,15 +358,25 @@ export const FiltersSearchList = ({
385
358
  var _a;
386
359
  setRemovedItems(prev => [...prev, itemId]);
387
360
  onRemoveRecentSearchItem && onRemoveRecentSearchItem([itemId]);
361
+ const remaining = recentItems.filter(item => item.id !== itemId && !removedItems.includes(item.id));
362
+ if (remaining.length === 0) {
363
+ changeMode("");
364
+ return;
365
+ }
388
366
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
389
367
  const firstItem = (_a = searchListRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(FOCUSABLE_SELECTOR);
390
368
  firstItem === null || firstItem === void 0 ? void 0 : firstItem.focus();
391
- }, [onRemoveRecentSearchItem, searchListRef]);
369
+ }, [onRemoveRecentSearchItem, searchListRef, recentItems, removedItems, changeMode]);
392
370
  const handleRemoveAll = useCallback(() => {
393
371
  setRemovedItems(recentItems.map(item => item.id));
394
372
  onRemoveRecentSearchItem && onRemoveRecentSearchItem(recentItems.map(item => item.id));
395
373
  changeMode(getCurrentMode());
396
374
  }, [recentItems, onRemoveRecentSearchItem, changeMode, getCurrentMode]);
375
+ const handleViewAll = useCallback(() => {
376
+ setRemovedItems(recentItems.map(item => item.id));
377
+ onRemoveRecentSearchItem && onRemoveRecentSearchItem(recentItems.map(item => item.id));
378
+ changeMode("");
379
+ }, [recentItems, onRemoveRecentSearchItem, changeMode]);
397
380
  const memoizedSearchItemClick = useCallback((itemId, itemType) => () => {
398
381
  const currentSearchItem = onlyOneType && !itemType ? searchItems.find(item => item.id === itemId) : searchItems.find(item => item.id === itemId && item.type === itemType);
399
382
  currentSearchItem && handleSearchItemClick && handleSearchItemClick(currentSearchItem);
@@ -522,10 +505,10 @@ export const FiltersSearchList = ({
522
505
  children: [_jsx("div", {
523
506
  className: "zen-filters-search-list__header-title",
524
507
  children: currentMode === "recent" ? translate("Recent searches") : translate("Currently selected")
525
- }), currentMode === "recent" && recentItems.length > resultsToShow.length && _jsx(Button, {
508
+ }), currentMode === "recent" && _jsx(Button, {
526
509
  type: "tertiary",
527
- onClick: changeMode.bind(null, "history"),
528
- children: translate("View history")
510
+ onClick: handleViewAll,
511
+ children: translate("Clear all")
529
512
  }), currentMode === "selected" && resultsToShow.length > 0 && _jsx(Button, {
530
513
  type: "tertiary",
531
514
  onClick: memoizedClearSelectedItems,
@@ -570,17 +553,17 @@ export const FiltersSearchList = ({
570
553
  type: "tertiary",
571
554
  onClick: handleRemoveAll,
572
555
  children: translate("Clear all")
573
- }) : null, currentMode === "recent" && recentItems.length > resultsToShow.length ? _jsx(Button, {
556
+ }) : null, currentMode === "recent" ? _jsx(Button, {
574
557
  type: "tertiary",
575
- onClick: changeMode.bind(null, "history"),
576
- children: translate("View history")
558
+ onClick: handleViewAll,
559
+ children: translate("Clear all")
577
560
  }) : null, currentMode === "selected" && resultsToShow.length > 0 && (searchSelection || []).length > 0 ? _jsx(Button, {
578
561
  type: "tertiary",
579
562
  onClick: memoizedClearSelectedItemsForApplyMode,
580
563
  children: translate("Clear")
581
564
  }) : null]
582
565
  });
583
- }, [changeMode, currentMode, handleRemoveAll, applyButtonHandler, memoizedClearSelectedItemsForApplyMode, recentItems.length, resultsToShow.length, translate, isInitialSearchSelectionState, searchSelection]);
566
+ }, [currentMode, handleRemoveAll, handleViewAll, applyButtonHandler, memoizedClearSelectedItemsForApplyMode, resultsToShow.length, translate, isInitialSearchSelectionState, searchSelection]);
584
567
  const searchHeaderContent = applyButtonHandler ? getHeaderTitles() : getSearchHeaderContent();
585
568
  return _jsxs(_Fragment, {
586
569
  children: [_jsxs("div", {
@@ -40,6 +40,8 @@ export interface IFiltersSearchTypesItem {
40
40
  export interface IFiltersBase extends IZenComponentProps {
41
41
  searchTypes?: IFiltersSearchTypesItem[] | IFiltersSearchTypesItem;
42
42
  onToggleView?: (isOpen: boolean) => void;
43
+ /** Placeholder text for the search input. Defaults to "Find in page" when empty or undefined. */
44
+ searchPlaceholder?: string;
43
45
  }
44
46
  export interface IFiltersWithKeyword {
45
47
  keyword: string;