@redocly/theme 0.47.1 → 0.48.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 (36) hide show
  1. package/lib/components/Feedback/Mood.d.ts +2 -2
  2. package/lib/components/Feedback/Mood.js +6 -6
  3. package/lib/components/Feedback/Rating.d.ts +2 -2
  4. package/lib/components/Feedback/Rating.js +6 -6
  5. package/lib/components/Feedback/Scale.d.ts +2 -2
  6. package/lib/components/Feedback/Scale.js +6 -6
  7. package/lib/components/Feedback/Sentiment.d.ts +2 -2
  8. package/lib/components/Feedback/Sentiment.js +6 -6
  9. package/lib/components/Search/SearchDialog.js +8 -8
  10. package/lib/components/Search/SearchFilter.d.ts +3 -2
  11. package/lib/components/Search/SearchFilter.js +2 -2
  12. package/lib/components/Search/SearchFilterField.d.ts +3 -2
  13. package/lib/components/Search/SearchFilterField.js +2 -2
  14. package/lib/components/Search/SearchGroups.d.ts +5 -4
  15. package/lib/components/Search/SearchGroups.js +3 -3
  16. package/lib/core/hooks/__mocks__/search/use-search-filter.d.ts +1 -1
  17. package/lib/core/hooks/__mocks__/search/use-search-filter.js +1 -1
  18. package/lib/core/hooks/search/use-search-filter.d.ts +2 -2
  19. package/lib/core/hooks/search/use-search-filter.js +5 -5
  20. package/lib/core/types/hooks.d.ts +1 -0
  21. package/lib/core/types/l10n.d.ts +1 -1
  22. package/lib/core/types/search.d.ts +1 -2
  23. package/package.json +2 -2
  24. package/src/components/Feedback/Mood.tsx +9 -10
  25. package/src/components/Feedback/Rating.tsx +9 -10
  26. package/src/components/Feedback/Scale.tsx +9 -10
  27. package/src/components/Feedback/Sentiment.tsx +9 -10
  28. package/src/components/Search/SearchDialog.tsx +11 -6
  29. package/src/components/Search/SearchFilter.tsx +6 -3
  30. package/src/components/Search/SearchFilterField.tsx +4 -2
  31. package/src/components/Search/SearchGroups.tsx +13 -8
  32. package/src/core/hooks/__mocks__/search/use-search-filter.ts +1 -1
  33. package/src/core/hooks/search/use-search-filter.ts +9 -5
  34. package/src/core/types/hooks.ts +1 -0
  35. package/src/core/types/l10n.ts +2 -2
  36. package/src/core/types/search.ts +1 -2
@@ -1,4 +1,4 @@
1
- import type { AnonymousUserEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
1
+ import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
2
2
  export declare enum MOOD_STATES {
3
3
  SATISFIED = "satisfied",
4
4
  NEUTRAL = "neutral",
@@ -25,7 +25,7 @@ export type MoodProps = {
25
25
  neutral?: ReasonsSettingsSchema;
26
26
  dissatisfied?: ReasonsSettingsSchema;
27
27
  };
28
- anonymousUserEmail?: AnonymousUserEmailSettings;
28
+ optionalEmail?: OptionalEmailSettings;
29
29
  };
30
30
  className?: string;
31
31
  };
@@ -46,7 +46,7 @@ var MOOD_STATES;
46
46
  MOOD_STATES["DISSATISFIED"] = "dissatisfied";
47
47
  })(MOOD_STATES || (exports.MOOD_STATES = MOOD_STATES = {}));
48
48
  function Mood({ settings, onSubmit, className }) {
49
- const { label, submitText, comment: commentSettings, reasons: reasonsSettings, anonymousUserEmail: anonymousUserEmailSettings, } = settings || {};
49
+ const { label, submitText, comment: commentSettings, reasons: reasonsSettings, optionalEmail: optionalEmailSettings, } = settings || {};
50
50
  const [score, setScore] = React.useState('');
51
51
  const [isSubmitted, setIsSubmitted] = React.useState(false);
52
52
  const [comment, setComment] = React.useState('');
@@ -109,7 +109,7 @@ function Mood({ settings, onSubmit, className }) {
109
109
  const displayReasons = checkIfShouldDisplayReasons(score);
110
110
  const displayComment = !!(score && !(commentSettings === null || commentSettings === void 0 ? void 0 : commentSettings.hide));
111
111
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
112
- const displayFeedbackEmail = !!score && (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.enabled) && !userData.isAuthenticated;
112
+ const displayFeedbackEmail = !!score && !(optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.hide) && !userData.isAuthenticated;
113
113
  const onSubmitMoodForm = () => {
114
114
  onSubmit({
115
115
  score: remapScore(score),
@@ -160,10 +160,10 @@ function Mood({ settings, onSubmit, className }) {
160
160
  }, onChange: setReasons })),
161
161
  displayComment && (React.createElement(Comment_1.Comment, { standAlone: false, onSubmit: ({ comment }) => setComment(comment), settings: { label: renderCommentLabel(score) } })))),
162
162
  displayFeedbackEmail && (React.createElement(StyledFormOptionalFields, null,
163
- React.createElement(Label, { "data-translation-key": "feedback.settings.anonymousUserEmail.label" }, (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.label) ||
164
- translate('feedback.settings.anonymousUserEmail.label', 'Your email (optional, for follow-up)')),
165
- React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.placeholder) ||
166
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com'), type: "email", required: !!email }))),
163
+ React.createElement(Label, { "data-translation-key": "feedback.settings.optionalEmail.label" }, (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.label) ||
164
+ translate('feedback.settings.optionalEmail.label', 'Your email (optional, for follow-up)')),
165
+ React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.placeholder) ||
166
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com'), type: "email", required: !!email }))),
167
167
  displaySubmitBnt && (React.createElement(ButtonsContainer, null,
168
168
  React.createElement(Button_1.Button, { onClick: onCancelMoodForm, variant: "text", size: "small" }, "Cancel"),
169
169
  React.createElement(Button_1.Button, { type: "submit", variant: "secondary", size: "small" }, "Submit"))))));
@@ -1,4 +1,4 @@
1
- import type { AnonymousUserEmailSettings } from '@redocly/config';
1
+ import type { OptionalEmailSettings } from '@redocly/config';
2
2
  export declare const FEEDBACK_MAX_RATING = 5;
3
3
  export type RatingProps = {
4
4
  onSubmit: (value: {
@@ -21,7 +21,7 @@ export type RatingProps = {
21
21
  component?: string;
22
22
  items: string[];
23
23
  };
24
- anonymousUserEmail?: AnonymousUserEmailSettings;
24
+ optionalEmail?: OptionalEmailSettings;
25
25
  };
26
26
  className?: string;
27
27
  };
@@ -39,7 +39,7 @@ const Stars_1 = require("../../components/Feedback/Stars");
39
39
  const Button_1 = require("../../components/Button/Button");
40
40
  exports.FEEDBACK_MAX_RATING = 5;
41
41
  function Rating({ settings, onSubmit, className }) {
42
- const { label, submitText, comment: commentSettings, reasons: reasonsSettings, anonymousUserEmail: anonymousUserEmailSettings, } = settings || {};
42
+ const { label, submitText, comment: commentSettings, reasons: reasonsSettings, optionalEmail: optionalEmailSettings, } = settings || {};
43
43
  const [isSubmitted, setIsSubmitted] = React.useState(false);
44
44
  const [score, setScore] = React.useState(0);
45
45
  const [reasons, setReasons] = React.useState([]);
@@ -71,7 +71,7 @@ function Rating({ settings, onSubmit, className }) {
71
71
  const displayReasons = !!(score && reasonsSettings && !reasonsSettings.hide);
72
72
  const displayComment = !!(score && !(commentSettings === null || commentSettings === void 0 ? void 0 : commentSettings.hide));
73
73
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
74
- const displayFeedbackEmail = !!score && (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.enabled) && !userData.isAuthenticated;
74
+ const displayFeedbackEmail = !!score && !(optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.hide) && !userData.isAuthenticated;
75
75
  (0, react_1.useEffect)(() => {
76
76
  if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
77
77
  onSubmitRatingForm();
@@ -102,10 +102,10 @@ function Rating({ settings, onSubmit, className }) {
102
102
  translate('feedback.settings.comment.label', 'Please share your feedback with us.'),
103
103
  } })))),
104
104
  displayFeedbackEmail && (React.createElement(StyledFormOptionalFields, null,
105
- React.createElement(Label, { "data-translation-key": "feedback.settings.anonymousUserEmail.label" }, (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.label) ||
106
- translate('feedback.settings.anonymousUserEmail.label', 'Your email (optional, for follow-up)')),
107
- React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.placeholder) ||
108
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com'), type: "email", required: !!email }))),
105
+ React.createElement(Label, { "data-translation-key": "feedback.settings.optionalEmail.label" }, (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.label) ||
106
+ translate('feedback.settings.optionalEmail.label', 'Your email (optional, for follow-up)')),
107
+ React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.placeholder) ||
108
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com'), type: "email", required: !!email }))),
109
109
  displaySubmitBnt && (React.createElement(ButtonsContainer, null,
110
110
  React.createElement(Button_1.Button, { onClick: onCancelRatingForm, variant: "text", size: "small" }, "Cancel"),
111
111
  React.createElement(Button_1.Button, { onClick: onSubmitRatingForm, variant: "secondary", size: "small" }, "Submit"))))));
@@ -1,4 +1,4 @@
1
- import type { AnonymousUserEmailSettings } from '@redocly/config';
1
+ import type { OptionalEmailSettings } from '@redocly/config';
2
2
  export declare const MAX_SCALE = 10;
3
3
  export type ScaleProps = {
4
4
  onSubmit: (value: {
@@ -23,7 +23,7 @@ export type ScaleProps = {
23
23
  component?: string;
24
24
  items: string[];
25
25
  };
26
- anonymousUserEmail?: AnonymousUserEmailSettings;
26
+ optionalEmail?: OptionalEmailSettings;
27
27
  };
28
28
  className?: string;
29
29
  };
@@ -39,7 +39,7 @@ const Reasons_1 = require("../../components/Feedback/Reasons");
39
39
  const Button_1 = require("../../components/Button/Button");
40
40
  exports.MAX_SCALE = 10;
41
41
  function Scale({ settings, onSubmit, className }) {
42
- const { label, submitText, leftScaleLabel, rightScaleLabel, comment: commentSettings, reasons: reasonsSettings, anonymousUserEmail: anonymousUserEmailSettings, } = settings || {};
42
+ const { label, submitText, leftScaleLabel, rightScaleLabel, comment: commentSettings, reasons: reasonsSettings, optionalEmail: optionalEmailSettings, } = settings || {};
43
43
  const [score, setScore] = React.useState(0);
44
44
  const [isSubmitted, setIsSubmitted] = React.useState(false);
45
45
  const [comment, setComment] = React.useState('');
@@ -59,7 +59,7 @@ function Scale({ settings, onSubmit, className }) {
59
59
  const displayReasons = !!score && reasonsSettings && !reasonsSettings.hide;
60
60
  const displayComment = !!(score && !(commentSettings === null || commentSettings === void 0 ? void 0 : commentSettings.hide));
61
61
  const displaySubmitBnt = !!score && (displayReasons || displayComment);
62
- const displayFeedbackEmail = !!score && (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.enabled) && !userData.isAuthenticated;
62
+ const displayFeedbackEmail = !!score && !(optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.hide) && !userData.isAuthenticated;
63
63
  const handleCancel = () => {
64
64
  setScore(0);
65
65
  setComment('');
@@ -109,10 +109,10 @@ function Scale({ settings, onSubmit, className }) {
109
109
  translate('feedback.settings.comment.label', 'Please share your feedback with us.'),
110
110
  } }))),
111
111
  displayFeedbackEmail && (React.createElement(StyledFormOptionalFields, null,
112
- React.createElement(Label, { "data-translation-key": "feedback.settings.anonymousUserEmail.label" }, (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.label) ||
113
- translate('feedback.settings.anonymousUserEmail.label', 'Your email (optional, for follow-up)')),
114
- React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.placeholder) ||
115
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com'), type: "email", required: !!email }))),
112
+ React.createElement(Label, { "data-translation-key": "feedback.settings.optionalEmail.label" }, (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.label) ||
113
+ translate('feedback.settings.optionalEmail.label', 'Your email (optional, for follow-up)')),
114
+ React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.placeholder) ||
115
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com'), type: "email", required: !!email }))),
116
116
  displaySubmitBnt && (React.createElement(ButtonsContainer, null,
117
117
  React.createElement(Button_1.Button, { "data-translation-key": "feedback.settings.comment.cancel", onClick: handleCancel, variant: "text", size: "small" }, translate('feedback.settings.comment.cancel', 'Cancel')),
118
118
  React.createElement(Button_1.Button, { "data-translation-key": "feedback.settings.scale.send", type: "submit", variant: "secondary", size: "small" }, translate('feedback.settings.scale.send', 'Submit')))))));
@@ -1,4 +1,4 @@
1
- import type { ReasonsSettingsSchema, AnonymousUserEmailSettings } from '@redocly/config';
1
+ import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
2
2
  export type SentimentProps = {
3
3
  onSubmit: (value: {
4
4
  score: number;
@@ -18,7 +18,7 @@ export type SentimentProps = {
18
18
  like?: ReasonsSettingsSchema;
19
19
  dislike?: ReasonsSettingsSchema;
20
20
  };
21
- anonymousUserEmail?: AnonymousUserEmailSettings;
21
+ optionalEmail?: OptionalEmailSettings;
22
22
  };
23
23
  className?: string;
24
24
  };
@@ -38,7 +38,7 @@ const Button_1 = require("../../components/Button/Button");
38
38
  const ThumbDownIcon_1 = require("../../icons/ThumbDownIcon/ThumbDownIcon");
39
39
  const ThumbUpIcon_1 = require("../../icons/ThumbUpIcon/ThumbUpIcon");
40
40
  function Sentiment({ settings, onSubmit, className }) {
41
- const { label, submitText, comment: commentSettings, reasons: reasonsSettings, anonymousUserEmail: anonymousUserEmailSettings, } = settings || {};
41
+ const { label, submitText, comment: commentSettings, reasons: reasonsSettings, optionalEmail: optionalEmailSettings, } = settings || {};
42
42
  const [isSubmitted, setIsSubmitted] = React.useState(false);
43
43
  const [score, setScore] = React.useState(0);
44
44
  const [comment, setComment] = React.useState('');
@@ -74,7 +74,7 @@ function Sentiment({ settings, onSubmit, className }) {
74
74
  const displayReasons = checkIfShouldDisplayReasons(score);
75
75
  const displayComment = !!(score && !(commentSettings === null || commentSettings === void 0 ? void 0 : commentSettings.hide));
76
76
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
77
- const displayFeedbackEmail = !!score && (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.enabled) && !userData.isAuthenticated;
77
+ const displayFeedbackEmail = !!score && !(optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.hide) && !userData.isAuthenticated;
78
78
  const commentLabel = score === 1
79
79
  ? (commentSettings && commentSettings.likeLabel) ||
80
80
  translate('feedback.settings.comment.likeLabel', 'What was most helpful?')
@@ -141,10 +141,10 @@ function Sentiment({ settings, onSubmit, className }) {
141
141
  }, onChange: setReasons })),
142
142
  displayComment && (React.createElement(Comment_1.Comment, { standAlone: false, onSubmit: ({ comment }) => setComment(comment), settings: { label: commentLabel } })))),
143
143
  displayFeedbackEmail && (React.createElement(StyledFormOptionalFields, null,
144
- React.createElement(Label, { "data-translation-key": "feedback.settings.anonymousUserEmail.label" }, (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.label) ||
145
- translate('feedback.settings.anonymousUserEmail.label', 'Your email (optional, for follow-up)')),
146
- React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (anonymousUserEmailSettings === null || anonymousUserEmailSettings === void 0 ? void 0 : anonymousUserEmailSettings.placeholder) ||
147
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com'), type: "email", required: !!email }))),
144
+ React.createElement(Label, { "data-translation-key": "feedback.settings.optionalEmail.label" }, (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.label) ||
145
+ translate('feedback.settings.optionalEmail.label', 'Your email (optional, for follow-up)')),
146
+ React.createElement(EmailInput, { onChange: onEmailChange, placeholder: (optionalEmailSettings === null || optionalEmailSettings === void 0 ? void 0 : optionalEmailSettings.placeholder) ||
147
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com'), type: "email", required: !!email }))),
148
148
  displaySubmitBnt && (React.createElement(ButtonsContainer, null,
149
149
  React.createElement(Button_1.Button, { onClick: onCancelSentimentForm, variant: "text", size: "small" }, "Cancel"),
150
150
  React.createElement(Button_1.Button, { onClick: onSubmitSentimentForm, variant: "secondary", size: "small" }, "Submit"))))));
@@ -52,8 +52,8 @@ function SearchDialog({ onClose, className }) {
52
52
  const [product, setProduct] = (0, react_1.useState)(currentProduct);
53
53
  const [mode, setMode] = (0, react_1.useState)('search');
54
54
  const autoSearchDisabled = mode !== 'search';
55
- const { query, setQuery, filter, setFilter, items, isSearchLoading, facets, setLoadMore, advancedSearch, askAi, } = useSearch(product === null || product === void 0 ? void 0 : product.name, autoSearchDisabled);
56
- const { isFilterOpen, onFilterToggle, onFilterChange, onFilterReset, onFacetReset, onTopFacetsReset, } = (0, hooks_1.useSearchFilter)(filter, setFilter);
55
+ const { query, setQuery, filter, setFilter, items, isSearchLoading, facets, setLoadMore, advancedSearch, askAi, groupField, } = useSearch(product === null || product === void 0 ? void 0 : product.name, autoSearchDisabled);
56
+ const { isFilterOpen, onFilterToggle, onFilterChange, onFilterReset, onFacetReset, onQuickFilterReset, } = (0, hooks_1.useSearchFilter)(filter, setFilter);
57
57
  const aiSearch = useAiSearch({ filter });
58
58
  const modalRef = (0, react_1.useRef)(null);
59
59
  const { translate } = useTranslate();
@@ -80,10 +80,10 @@ function SearchDialog({ onClose, className }) {
80
80
  return react_1.default.createElement(SearchItem_1.SearchItem, { key: `${index}-${item.document.id}`, item: item, product: itemProduct });
81
81
  };
82
82
  const showLoadMore = (groupKey, currentCount = 0) => {
83
- const topFacet = facets.find((facet) => facet.isTop);
83
+ const groupFacet = facets.find((facet) => facet.field === groupField);
84
84
  let needLoadMore = false;
85
- if (topFacet) {
86
- const groupValue = topFacet.values.find((value) => {
85
+ if (groupFacet) {
86
+ const groupValue = groupFacet.values.find((value) => {
87
87
  if (typeof value === 'object') {
88
88
  return value.value === groupKey;
89
89
  }
@@ -124,11 +124,11 @@ function SearchDialog({ onClose, className }) {
124
124
  showSearchFilterButton && (react_1.default.createElement(SearchFilterToggleButton, { icon: react_1.default.createElement(SettingsIcon_1.SettingsIcon, null), onClick: onFilterToggle }))))),
125
125
  react_1.default.createElement(SearchDialogBody, null, mode === 'search' ? (react_1.default.createElement(react_1.default.Fragment, null,
126
126
  react_1.default.createElement(SearchDialogBodyMainView, null,
127
- react_1.default.createElement(SearchGroups_1.SearchGroups, { facets: facets, searchFilter: filter, onFilterChange: onFilterChange, onTopFacetsReset: onTopFacetsReset }),
127
+ react_1.default.createElement(SearchGroups_1.SearchGroups, { facets: facets, searchFilter: filter, onFilterChange: onFilterChange, onQuickFilterReset: onQuickFilterReset, groupField: groupField }),
128
128
  showResults ? (items && Object.keys(items).some((key) => { var _a; return (_a = items[key]) === null || _a === void 0 ? void 0 : _a.length; }) ? (Object.keys(items).map((key) => {
129
129
  var _a, _b, _c;
130
130
  return ((_a = items[key]) === null || _a === void 0 ? void 0 : _a.length) ? (react_1.default.createElement(react_1.Fragment, { key: key },
131
- react_1.default.createElement(SearchGroupTitle, null, key), (_b = items[key]) === null || _b === void 0 ? void 0 :
131
+ react_1.default.createElement(SearchGroupTitle, { "data-testid": "search-group-title" }, key), (_b = items[key]) === null || _b === void 0 ? void 0 :
132
132
  _b.map(mapItem),
133
133
  showLoadMore(key, ((_c = items[key]) === null || _c === void 0 ? void 0 : _c.length) || 0) && (react_1.default.createElement(SearchGroupFooter, { "data-translation-key": "search.showMore", onClick: () => { var _a; return setLoadMore({ groupKey: key, offset: ((_a = items[key]) === null || _a === void 0 ? void 0 : _a.length) || 0 }); } }, translate('search.showMore', 'Show more'))))) : null;
134
134
  })) : isSearchLoading ? (react_1.default.createElement(SearchMessage, null,
@@ -138,7 +138,7 @@ function SearchDialog({ onClose, className }) {
138
138
  react_1.default.createElement(SearchRecent_1.SearchRecent, { onSelect: setQuery }),
139
139
  react_1.default.createElement(SearchSuggestedPages_1.SearchSuggestedPages, null)))),
140
140
  advancedSearch && mode === 'search' && isFilterOpen && (react_1.default.createElement(SearchDialogBodyFilterView, null,
141
- react_1.default.createElement(SearchFilter_1.SearchFilter, { facets: facets, filter: filter, query: query, onFilterChange: onFilterChange, onFilterReset: onFilterReset, onFacetReset: onFacetReset }))))) : (react_1.default.createElement(SearchAiResponse_1.SearchAiResponse, { question: aiSearch.question, isGeneratingResponse: aiSearch.isGeneratingResponse, response: aiSearch.response, resources: aiSearch.resources }))),
141
+ react_1.default.createElement(SearchFilter_1.SearchFilter, { facets: facets, filter: filter, query: query, quickFilterFields: [groupField], onFilterChange: onFilterChange, onFilterReset: onFilterReset, onFacetReset: onFacetReset }))))) : (react_1.default.createElement(SearchAiResponse_1.SearchAiResponse, { question: aiSearch.question, isGeneratingResponse: aiSearch.isGeneratingResponse, response: aiSearch.response, resources: aiSearch.resources }))),
142
142
  mode === 'search' && (react_1.default.createElement(SearchDialogFooter, null,
143
143
  react_1.default.createElement(SearchShortcuts, null,
144
144
  react_1.default.createElement(SearchShortcut_1.SearchShortcut, { "data-translation-key": "search.keys.navigate", combination: "Tab", text: translate('search.keys.navigate', 'to navigate') }),
@@ -4,8 +4,9 @@ export type SearchFilterProps = {
4
4
  facets: SearchFacet[];
5
5
  filter: SearchFilterItem[];
6
6
  query: string;
7
- onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
7
+ quickFilterFields: string[];
8
+ onFilterChange: (field: string, value: string | string[], isQuickFilter?: boolean) => void;
8
9
  onFilterReset: () => void;
9
10
  onFacetReset: (field: string) => void;
10
11
  };
11
- export declare function SearchFilter({ className, facets, filter, query, onFilterChange, onFilterReset, onFacetReset, }: SearchFilterProps): JSX.Element;
12
+ export declare function SearchFilter({ className, facets, filter, query, quickFilterFields, onFilterChange, onFilterReset, onFacetReset, }: SearchFilterProps): JSX.Element;
@@ -33,14 +33,14 @@ const Button_1 = require("../../components/Button/Button");
33
33
  const CleanIcon_1 = require("../../icons/CleanIcon/CleanIcon");
34
34
  const SearchFilterField_1 = require("../../components/Search/SearchFilterField");
35
35
  const hooks_1 = require("../../core/hooks");
36
- function SearchFilter({ className, facets, filter, query, onFilterChange, onFilterReset, onFacetReset, }) {
36
+ function SearchFilter({ className, facets, filter, query, quickFilterFields, onFilterChange, onFilterReset, onFacetReset, }) {
37
37
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
38
38
  const { translate } = useTranslate();
39
39
  return (React.createElement(SearchFilterWrapper, { "data-component-name": "Search/SearchFilter", className: className },
40
40
  React.createElement(SearchFilterHeader, null,
41
41
  React.createElement("span", { "data-translation-key": "search.filter.title" }, translate('search.filter.title', 'Advanced filter')),
42
42
  React.createElement(Button_1.Button, { "data-translation-key": "search.filter.reset", onClick: onFilterReset, variant: "ghost", icon: React.createElement(CleanIcon_1.CleanIcon, null) }, translate('search.filter.reset', 'Reset filters'))),
43
- React.createElement(SearchFilterFields, null, facets.map((facet, index) => (React.createElement(SearchFilterField_1.SearchFilterField, { key: `${facet.field}-${index}`, facet: facet, onFilterChange: onFilterChange, onFacetReset: onFacetReset, filter: filter, query: query }))))));
43
+ React.createElement(SearchFilterFields, null, facets.map((facet, index) => (React.createElement(SearchFilterField_1.SearchFilterField, { key: `${facet.field}-${index}`, facet: facet, filter: filter, query: query, quickFilterFields: quickFilterFields, onFilterChange: onFilterChange, onFacetReset: onFacetReset }))))));
44
44
  }
45
45
  const SearchFilterWrapper = styled_components_1.default.div `
46
46
  width: var(--search-filter-width);
@@ -4,8 +4,9 @@ type SearchFilterFieldProps = {
4
4
  facet: SearchFacet;
5
5
  filter: SearchFilterItem[];
6
6
  query: string;
7
- onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
7
+ quickFilterFields: string[];
8
+ onFilterChange: (field: string, value: string | string[], isQuickFilter?: boolean) => void;
8
9
  onFacetReset: (filed: string) => void;
9
10
  };
10
- export declare function SearchFilterField({ className, facet, filter, query, onFilterChange, onFacetReset, }: SearchFilterFieldProps): JSX.Element;
11
+ export declare function SearchFilterField({ className, facet, filter, query, quickFilterFields, onFilterChange, onFacetReset, }: SearchFilterFieldProps): JSX.Element;
11
12
  export {};
@@ -11,13 +11,13 @@ const ResetIcon_1 = require("../../icons/ResetIcon/ResetIcon");
11
11
  const hooks_1 = require("../../core/hooks");
12
12
  const SearchFilterFieldSelect_1 = require("../../components/Search/FilterFields/SearchFilterFieldSelect");
13
13
  const SearchFilterFieldTags_1 = require("../../components/Search/FilterFields/SearchFilterFieldTags");
14
- function SearchFilterField({ className, facet, filter, query, onFilterChange, onFacetReset, }) {
14
+ function SearchFilterField({ className, facet, filter, query, quickFilterFields, onFilterChange, onFacetReset, }) {
15
15
  var _a;
16
16
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
17
17
  const { translate } = useTranslate();
18
18
  const selectedValues = ((_a = filter.find((item) => item.field === facet.field)) === null || _a === void 0 ? void 0 : _a.values) || [];
19
19
  const onChange = (value) => {
20
- onFilterChange(facet.field, value, facet.isTop);
20
+ onFilterChange(facet.field, value, facet.field in quickFilterFields);
21
21
  };
22
22
  const onReset = () => {
23
23
  onFacetReset(facet.field);
@@ -1,9 +1,10 @@
1
- import type { SearchFacet, SearchFilterItem } from '../../index.js';
1
+ import { type SearchFacet, type SearchFilterItem } from '../../core/types';
2
2
  type SearchGroupsProps = {
3
3
  facets: SearchFacet[];
4
4
  searchFilter: SearchFilterItem[];
5
- onFilterChange: (field: string, value: string[], isTop?: boolean) => void;
6
- onTopFacetsReset: () => void;
5
+ groupField: string;
6
+ onFilterChange: (field: string, value: string[], isQuickFilter?: boolean) => void;
7
+ onQuickFilterReset: () => void;
7
8
  };
8
- export declare function SearchGroups({ facets, searchFilter, onFilterChange, onTopFacetsReset, }: SearchGroupsProps): JSX.Element;
9
+ export declare function SearchGroups({ facets, searchFilter, groupField, onFilterChange, onQuickFilterReset, }: SearchGroupsProps): JSX.Element;
9
10
  export {};
@@ -30,8 +30,8 @@ exports.SearchGroups = SearchGroups;
30
30
  const React = __importStar(require("react"));
31
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
32
  const Tag_1 = require("../../components/Tag/Tag");
33
- function SearchGroups({ facets, searchFilter, onFilterChange, onTopFacetsReset, }) {
34
- const groupFacets = facets.filter((facet) => facet.isTop);
33
+ function SearchGroups({ facets, searchFilter, groupField, onFilterChange, onQuickFilterReset, }) {
34
+ const groupFacets = facets.filter((facet) => facet.field === groupField);
35
35
  const handleGroupTagClick = (value, fieldId, active, currentValues) => {
36
36
  const values = active
37
37
  ? currentValues.filter((item) => item !== value)
@@ -39,7 +39,7 @@ function SearchGroups({ facets, searchFilter, onFilterChange, onTopFacetsReset,
39
39
  onFilterChange(fieldId, values, true);
40
40
  };
41
41
  return (React.createElement(SearchGroupsWrapper, null,
42
- React.createElement(GroupTag, { borderless: true, active: !searchFilter.some((item) => item.isTop), onClick: () => searchFilter.some((item) => item.isTop) && onTopFacetsReset() }, "All"),
42
+ React.createElement(GroupTag, { borderless: true, active: !searchFilter.some((item) => item.isQuickFilter), onClick: () => searchFilter.some((item) => item.isQuickFilter) && onQuickFilterReset() }, "All"),
43
43
  React.createElement(Divider, null),
44
44
  groupFacets.flatMap((facet) => facet.values.map((facetCount, index) => {
45
45
  var _a;
@@ -4,5 +4,5 @@ export declare const useSearchFilter: jest.Mock<{
4
4
  onFilterChange: () => void;
5
5
  onFilterToggle: () => void;
6
6
  onFilterReset: () => void;
7
- onTopFacetsReset: () => void;
7
+ onQuickFilterReset: () => void;
8
8
  }, [], any>;
@@ -8,7 +8,7 @@ exports.useSearchFilter = jest.fn(() => {
8
8
  onFilterChange: () => { },
9
9
  onFilterToggle: () => { },
10
10
  onFilterReset: () => { },
11
- onTopFacetsReset: () => { },
11
+ onQuickFilterReset: () => { },
12
12
  };
13
13
  });
14
14
  //# sourceMappingURL=use-search-filter.js.map
@@ -1,9 +1,9 @@
1
1
  import type { SearchFilterItem } from '../../../core/types';
2
2
  export declare function useSearchFilter(filter: SearchFilterItem[], setFilter: React.Dispatch<React.SetStateAction<SearchFilterItem[]>>): {
3
3
  onFacetReset: (field: string) => void;
4
- onTopFacetsReset: () => void;
5
- onFilterChange: (field: string, value: string | string[] | undefined, isTop?: boolean) => void;
4
+ onFilterChange: (field: string, value: string | string[] | undefined, isQuickFilter?: boolean) => void;
6
5
  onFilterReset: () => void;
7
6
  onFilterToggle: () => void;
7
+ onQuickFilterReset: () => void;
8
8
  isFilterOpen: boolean;
9
9
  };
@@ -7,7 +7,7 @@ function useSearchFilter(filter, setFilter) {
7
7
  const onFilterToggle = (0, react_1.useCallback)(() => {
8
8
  setIsFilterOpen(!isFilterOpen);
9
9
  }, [isFilterOpen]);
10
- const onFilterChange = (field, value, isTop) => {
10
+ const onFilterChange = (field, value, isQuickFilter) => {
11
11
  const values = value ? (Array.isArray(value) ? value : [value]) : [];
12
12
  const _filter = [...filter];
13
13
  const fieldIndex = _filter.findIndex((filter) => filter.field === field);
@@ -18,16 +18,16 @@ function useSearchFilter(filter, setFilter) {
18
18
  else {
19
19
  if (!values.length)
20
20
  return;
21
- _filter.push({ field, values, isTop });
21
+ _filter.push({ field, values, isQuickFilter });
22
22
  }
23
23
  setFilter(_filter.filter((item) => item.values.length));
24
24
  };
25
25
  const onFilterReset = () => {
26
26
  setFilter([]);
27
27
  };
28
- const onTopFacetsReset = () => {
28
+ const onQuickFilterReset = () => {
29
29
  const _filter = [...filter];
30
- setFilter(_filter.filter((item) => !item.isTop));
30
+ setFilter(_filter.filter((item) => !item.isQuickFilter));
31
31
  };
32
32
  const onFacetReset = (field) => {
33
33
  const _filter = [...filter];
@@ -39,10 +39,10 @@ function useSearchFilter(filter, setFilter) {
39
39
  };
40
40
  return {
41
41
  onFacetReset,
42
- onTopFacetsReset,
43
42
  onFilterChange,
44
43
  onFilterReset,
45
44
  onFilterToggle,
45
+ onQuickFilterReset,
46
46
  isFilterOpen,
47
47
  };
48
48
  }
@@ -54,6 +54,7 @@ export type ThemeHooks = {
54
54
  items: Record<string, SearchItemData[] | null>;
55
55
  isSearchLoading: boolean;
56
56
  facets: SearchFacet[];
57
+ groupField: string;
57
58
  setLoadMore: React.Dispatch<React.SetStateAction<{
58
59
  groupKey: string;
59
60
  offset: number;
@@ -1,5 +1,5 @@
1
1
  import type { TOptions } from 'i18next';
2
- export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.aiButton' | 'search.ai.label' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.notFound.title' | 'page.notFound.description' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeLayout' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.settings.reasons.send' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.anonymousUserEmail.placeholder' | 'feedback.settings.anonymousUserEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'page.nextButton' | 'page.previousButton' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.deprecated' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.noResponseExample' | 'openapi.noRequestPayload' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.scopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.implementedInterfaces' | 'graphql.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'codeWalkthrough.download' | 'codeWalkthrough.preview';
2
+ export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.aiButton' | 'search.ai.label' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.notFound.title' | 'page.notFound.description' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeLayout' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.settings.reasons.send' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.optionalEmail.placeholder' | 'feedback.settings.optionalEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'page.nextButton' | 'page.previousButton' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.deprecated' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.noResponseExample' | 'openapi.noRequestPayload' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.scopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.implementedInterfaces' | 'graphql.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'codeWalkthrough.download' | 'codeWalkthrough.preview';
3
3
  export type Locale = {
4
4
  code: string;
5
5
  name: string;
@@ -51,7 +51,6 @@ export type SearchFacet = {
51
51
  field: string;
52
52
  type: SearchFacetType;
53
53
  values: string[] | SearchFacetCount[];
54
- isTop?: boolean;
55
54
  index?: number;
56
55
  };
57
56
  export type SearchFacetCount = {
@@ -68,5 +67,5 @@ export type SearchFacetType = 'input' | 'multi-select' | 'select' | 'switch' | '
68
67
  export type SearchFilterItem = {
69
68
  field: string;
70
69
  values: string[];
71
- isTop?: boolean;
70
+ isQuickFilter?: boolean;
72
71
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.47.1",
3
+ "version": "0.48.0",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -86,7 +86,7 @@
86
86
  "timeago.js": "4.0.2",
87
87
  "i18next": "22.4.15",
88
88
  "nprogress": "0.2.0",
89
- "@redocly/config": "0.19.4"
89
+ "@redocly/config": "0.20.0"
90
90
  },
91
91
  "scripts": {
92
92
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
5
+ import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { Reasons } from '@redocly/theme/components/Feedback/Reasons';
@@ -41,7 +41,7 @@ export type MoodProps = {
41
41
  neutral?: ReasonsSettingsSchema;
42
42
  dissatisfied?: ReasonsSettingsSchema;
43
43
  };
44
- anonymousUserEmail?: AnonymousUserEmailSettings;
44
+ optionalEmail?: OptionalEmailSettings;
45
45
  };
46
46
  className?: string;
47
47
  };
@@ -52,7 +52,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
52
52
  submitText,
53
53
  comment: commentSettings,
54
54
  reasons: reasonsSettings,
55
- anonymousUserEmail: anonymousUserEmailSettings,
55
+ optionalEmail: optionalEmailSettings,
56
56
  } = settings || {};
57
57
  const [score, setScore] = React.useState('');
58
58
  const [isSubmitted, setIsSubmitted] = React.useState(false);
@@ -131,8 +131,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
131
131
  const displayReasons = checkIfShouldDisplayReasons(score);
132
132
  const displayComment = !!(score && !commentSettings?.hide);
133
133
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
134
- const displayFeedbackEmail =
135
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
134
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
136
135
 
137
136
  const onSubmitMoodForm = () => {
138
137
  onSubmit({
@@ -241,18 +240,18 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
241
240
 
242
241
  {displayFeedbackEmail && (
243
242
  <StyledFormOptionalFields>
244
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
245
- {anonymousUserEmailSettings?.label ||
243
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
244
+ {optionalEmailSettings?.label ||
246
245
  translate(
247
- 'feedback.settings.anonymousUserEmail.label',
246
+ 'feedback.settings.optionalEmail.label',
248
247
  'Your email (optional, for follow-up)',
249
248
  )}
250
249
  </Label>
251
250
  <EmailInput
252
251
  onChange={onEmailChange}
253
252
  placeholder={
254
- anonymousUserEmailSettings?.placeholder ||
255
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
253
+ optionalEmailSettings?.placeholder ||
254
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
256
255
  }
257
256
  type="email"
258
257
  required={!!email}
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings } from '@redocly/config';
5
+ import type { OptionalEmailSettings } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { Reasons } from '@redocly/theme/components/Feedback/Reasons';
@@ -35,7 +35,7 @@ export type RatingProps = {
35
35
  component?: string;
36
36
  items: string[];
37
37
  };
38
- anonymousUserEmail?: AnonymousUserEmailSettings;
38
+ optionalEmail?: OptionalEmailSettings;
39
39
  };
40
40
  className?: string;
41
41
  };
@@ -46,7 +46,7 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
46
46
  submitText,
47
47
  comment: commentSettings,
48
48
  reasons: reasonsSettings,
49
- anonymousUserEmail: anonymousUserEmailSettings,
49
+ optionalEmail: optionalEmailSettings,
50
50
  } = settings || {};
51
51
  const [isSubmitted, setIsSubmitted] = React.useState(false);
52
52
  const [score, setScore] = React.useState(0);
@@ -83,8 +83,7 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
83
83
  const displayReasons = !!(score && reasonsSettings && !reasonsSettings.hide);
84
84
  const displayComment = !!(score && !commentSettings?.hide);
85
85
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
86
- const displayFeedbackEmail =
87
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
86
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
88
87
 
89
88
  useEffect(() => {
90
89
  if (score && !displayComment && !displayReasons && !displayFeedbackEmail) {
@@ -154,18 +153,18 @@ export function Rating({ settings, onSubmit, className }: RatingProps): JSX.Elem
154
153
 
155
154
  {displayFeedbackEmail && (
156
155
  <StyledFormOptionalFields>
157
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
158
- {anonymousUserEmailSettings?.label ||
156
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
157
+ {optionalEmailSettings?.label ||
159
158
  translate(
160
- 'feedback.settings.anonymousUserEmail.label',
159
+ 'feedback.settings.optionalEmail.label',
161
160
  'Your email (optional, for follow-up)',
162
161
  )}
163
162
  </Label>
164
163
  <EmailInput
165
164
  onChange={onEmailChange}
166
165
  placeholder={
167
- anonymousUserEmailSettings?.placeholder ||
168
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
166
+ optionalEmailSettings?.placeholder ||
167
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
169
168
  }
170
169
  type="email"
171
170
  required={!!email}
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { AnonymousUserEmailSettings } from '@redocly/config';
5
+ import type { OptionalEmailSettings } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { breakpoints } from '@redocly/theme/core/utils';
@@ -37,7 +37,7 @@ export type ScaleProps = {
37
37
  component?: string;
38
38
  items: string[];
39
39
  };
40
- anonymousUserEmail?: AnonymousUserEmailSettings;
40
+ optionalEmail?: OptionalEmailSettings;
41
41
  };
42
42
  className?: string;
43
43
  };
@@ -50,7 +50,7 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
50
50
  rightScaleLabel,
51
51
  comment: commentSettings,
52
52
  reasons: reasonsSettings,
53
- anonymousUserEmail: anonymousUserEmailSettings,
53
+ optionalEmail: optionalEmailSettings,
54
54
  } = settings || {};
55
55
  const [score, setScore] = React.useState(0);
56
56
  const [isSubmitted, setIsSubmitted] = React.useState(false);
@@ -85,8 +85,7 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
85
85
  const displayReasons = !!score && reasonsSettings && !reasonsSettings.hide;
86
86
  const displayComment = !!(score && !commentSettings?.hide);
87
87
  const displaySubmitBnt = !!score && (displayReasons || displayComment);
88
- const displayFeedbackEmail =
89
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
88
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
90
89
 
91
90
  const handleCancel = () => {
92
91
  setScore(0);
@@ -179,18 +178,18 @@ export function Scale({ settings, onSubmit, className }: ScaleProps): JSX.Elemen
179
178
 
180
179
  {displayFeedbackEmail && (
181
180
  <StyledFormOptionalFields>
182
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
183
- {anonymousUserEmailSettings?.label ||
181
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
182
+ {optionalEmailSettings?.label ||
184
183
  translate(
185
- 'feedback.settings.anonymousUserEmail.label',
184
+ 'feedback.settings.optionalEmail.label',
186
185
  'Your email (optional, for follow-up)',
187
186
  )}
188
187
  </Label>
189
188
  <EmailInput
190
189
  onChange={onEmailChange}
191
190
  placeholder={
192
- anonymousUserEmailSettings?.placeholder ||
193
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
191
+ optionalEmailSettings?.placeholder ||
192
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
194
193
  }
195
194
  type="email"
196
195
  required={!!email}
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
3
  import styled from 'styled-components';
4
4
 
5
- import type { ReasonsSettingsSchema, AnonymousUserEmailSettings } from '@redocly/config';
5
+ import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
7
7
 
8
8
  import { Reasons } from '@redocly/theme/components/Feedback/Reasons';
@@ -32,7 +32,7 @@ export type SentimentProps = {
32
32
  like?: ReasonsSettingsSchema;
33
33
  dislike?: ReasonsSettingsSchema;
34
34
  };
35
- anonymousUserEmail?: AnonymousUserEmailSettings;
35
+ optionalEmail?: OptionalEmailSettings;
36
36
  };
37
37
  className?: string;
38
38
  };
@@ -43,7 +43,7 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
43
43
  submitText,
44
44
  comment: commentSettings,
45
45
  reasons: reasonsSettings,
46
- anonymousUserEmail: anonymousUserEmailSettings,
46
+ optionalEmail: optionalEmailSettings,
47
47
  } = settings || {};
48
48
  const [isSubmitted, setIsSubmitted] = React.useState(false);
49
49
  const [score, setScore] = React.useState(0);
@@ -87,8 +87,7 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
87
87
  const displayReasons = checkIfShouldDisplayReasons(score);
88
88
  const displayComment = !!(score && !commentSettings?.hide);
89
89
  const displaySubmitBnt = !!(score && (displayReasons || displayComment));
90
- const displayFeedbackEmail =
91
- !!score && anonymousUserEmailSettings?.enabled && !userData.isAuthenticated;
90
+ const displayFeedbackEmail = !!score && !optionalEmailSettings?.hide && !userData.isAuthenticated;
92
91
 
93
92
  const commentLabel =
94
93
  score === 1
@@ -214,18 +213,18 @@ export function Sentiment({ settings, onSubmit, className }: SentimentProps): JS
214
213
 
215
214
  {displayFeedbackEmail && (
216
215
  <StyledFormOptionalFields>
217
- <Label data-translation-key="feedback.settings.anonymousUserEmail.label">
218
- {anonymousUserEmailSettings?.label ||
216
+ <Label data-translation-key="feedback.settings.optionalEmail.label">
217
+ {optionalEmailSettings?.label ||
219
218
  translate(
220
- 'feedback.settings.anonymousUserEmail.label',
219
+ 'feedback.settings.optionalEmail.label',
221
220
  'Your email (optional, for follow-up)',
222
221
  )}
223
222
  </Label>
224
223
  <EmailInput
225
224
  onChange={onEmailChange}
226
225
  placeholder={
227
- anonymousUserEmailSettings?.placeholder ||
228
- translate('feedback.settings.anonymousUserEmail.placeholder', 'username@mail.com')
226
+ optionalEmailSettings?.placeholder ||
227
+ translate('feedback.settings.optionalEmail.placeholder', 'yourname@example.com')
229
228
  }
230
229
  type="email"
231
230
  required={!!email}
@@ -44,6 +44,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
44
44
  setLoadMore,
45
45
  advancedSearch,
46
46
  askAi,
47
+ groupField,
47
48
  } = useSearch(product?.name, autoSearchDisabled);
48
49
  const {
49
50
  isFilterOpen,
@@ -51,7 +52,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
51
52
  onFilterChange,
52
53
  onFilterReset,
53
54
  onFacetReset,
54
- onTopFacetsReset,
55
+ onQuickFilterReset,
55
56
  } = useSearchFilter(filter, setFilter);
56
57
  const aiSearch = useAiSearch({ filter });
57
58
 
@@ -83,10 +84,10 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
83
84
  };
84
85
 
85
86
  const showLoadMore = (groupKey: string, currentCount: number = 0) => {
86
- const topFacet = facets.find((facet) => facet.isTop);
87
+ const groupFacet = facets.find((facet) => facet.field === groupField);
87
88
  let needLoadMore = false;
88
- if (topFacet) {
89
- const groupValue = topFacet.values.find((value) => {
89
+ if (groupFacet) {
90
+ const groupValue = groupFacet.values.find((value) => {
90
91
  if (typeof value === 'object') {
91
92
  return value.value === groupKey;
92
93
  } else return false;
@@ -170,14 +171,17 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
170
171
  facets={facets}
171
172
  searchFilter={filter}
172
173
  onFilterChange={onFilterChange}
173
- onTopFacetsReset={onTopFacetsReset}
174
+ onQuickFilterReset={onQuickFilterReset}
175
+ groupField={groupField}
174
176
  />
175
177
  {showResults ? (
176
178
  items && Object.keys(items).some((key) => items[key]?.length) ? (
177
179
  Object.keys(items).map((key) =>
178
180
  items[key]?.length ? (
179
181
  <Fragment key={key}>
180
- <SearchGroupTitle>{key}</SearchGroupTitle>
182
+ <SearchGroupTitle data-testid="search-group-title">
183
+ {key}
184
+ </SearchGroupTitle>
181
185
  {items[key]?.map(mapItem)}
182
186
  {showLoadMore(key, items[key]?.length || 0) && (
183
187
  <SearchGroupFooter
@@ -215,6 +219,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
215
219
  facets={facets}
216
220
  filter={filter}
217
221
  query={query}
222
+ quickFilterFields={[groupField]}
218
223
  onFilterChange={onFilterChange}
219
224
  onFilterReset={onFilterReset}
220
225
  onFacetReset={onFacetReset}
@@ -13,7 +13,8 @@ export type SearchFilterProps = {
13
13
  facets: SearchFacet[];
14
14
  filter: SearchFilterItem[];
15
15
  query: string;
16
- onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
16
+ quickFilterFields: string[];
17
+ onFilterChange: (field: string, value: string | string[], isQuickFilter?: boolean) => void;
17
18
  onFilterReset: () => void;
18
19
  onFacetReset: (field: string) => void;
19
20
  };
@@ -23,6 +24,7 @@ export function SearchFilter({
23
24
  facets,
24
25
  filter,
25
26
  query,
27
+ quickFilterFields,
26
28
  onFilterChange,
27
29
  onFilterReset,
28
30
  onFacetReset,
@@ -50,10 +52,11 @@ export function SearchFilter({
50
52
  <SearchFilterField
51
53
  key={`${facet.field}-${index}`}
52
54
  facet={facet}
53
- onFilterChange={onFilterChange}
54
- onFacetReset={onFacetReset}
55
55
  filter={filter}
56
56
  query={query}
57
+ quickFilterFields={quickFilterFields}
58
+ onFilterChange={onFilterChange}
59
+ onFacetReset={onFacetReset}
57
60
  />
58
61
  ))}
59
62
  </SearchFilterFields>
@@ -14,7 +14,8 @@ type SearchFilterFieldProps = {
14
14
  facet: SearchFacet;
15
15
  filter: SearchFilterItem[];
16
16
  query: string;
17
- onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
17
+ quickFilterFields: string[];
18
+ onFilterChange: (field: string, value: string | string[], isQuickFilter?: boolean) => void;
18
19
  onFacetReset: (filed: string) => void;
19
20
  };
20
21
 
@@ -23,6 +24,7 @@ export function SearchFilterField({
23
24
  facet,
24
25
  filter,
25
26
  query,
27
+ quickFilterFields,
26
28
  onFilterChange,
27
29
  onFacetReset,
28
30
  }: SearchFilterFieldProps): JSX.Element {
@@ -31,7 +33,7 @@ export function SearchFilterField({
31
33
  const selectedValues = filter.find((item) => item.field === facet.field)?.values || [];
32
34
 
33
35
  const onChange = (value: string | string[]) => {
34
- onFilterChange(facet.field, value, facet.isTop);
36
+ onFilterChange(facet.field, value, facet.field in quickFilterFields);
35
37
  };
36
38
 
37
39
  const onReset = () => {
@@ -1,24 +1,29 @@
1
1
  import * as React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
- import type { SearchFacet, SearchFacetCount, SearchFilterItem } from '@redocly/theme';
5
-
4
+ import {
5
+ type SearchFacet,
6
+ type SearchFacetCount,
7
+ type SearchFilterItem,
8
+ } from '@redocly/theme/core/types';
6
9
  import { Tag } from '@redocly/theme/components/Tag/Tag';
7
10
 
8
11
  type SearchGroupsProps = {
9
12
  facets: SearchFacet[];
10
13
  searchFilter: SearchFilterItem[];
11
- onFilterChange: (field: string, value: string[], isTop?: boolean) => void;
12
- onTopFacetsReset: () => void;
14
+ groupField: string;
15
+ onFilterChange: (field: string, value: string[], isQuickFilter?: boolean) => void;
16
+ onQuickFilterReset: () => void;
13
17
  };
14
18
 
15
19
  export function SearchGroups({
16
20
  facets,
17
21
  searchFilter,
22
+ groupField,
18
23
  onFilterChange,
19
- onTopFacetsReset,
24
+ onQuickFilterReset,
20
25
  }: SearchGroupsProps): JSX.Element {
21
- const groupFacets = facets.filter((facet) => facet.isTop);
26
+ const groupFacets = facets.filter((facet) => facet.field === groupField);
22
27
 
23
28
  const handleGroupTagClick = (
24
29
  value: string,
@@ -36,8 +41,8 @@ export function SearchGroups({
36
41
  <SearchGroupsWrapper>
37
42
  <GroupTag
38
43
  borderless
39
- active={!searchFilter.some((item) => item.isTop)}
40
- onClick={() => searchFilter.some((item) => item.isTop) && onTopFacetsReset()}
44
+ active={!searchFilter.some((item) => item.isQuickFilter)}
45
+ onClick={() => searchFilter.some((item) => item.isQuickFilter) && onQuickFilterReset()}
41
46
  >
42
47
  All
43
48
  </GroupTag>
@@ -5,6 +5,6 @@ export const useSearchFilter = jest.fn(() => {
5
5
  onFilterChange: () => {},
6
6
  onFilterToggle: () => {},
7
7
  onFilterReset: () => {},
8
- onTopFacetsReset: () => {},
8
+ onQuickFilterReset: () => {},
9
9
  };
10
10
  });
@@ -12,7 +12,11 @@ export function useSearchFilter(
12
12
  setIsFilterOpen(!isFilterOpen);
13
13
  }, [isFilterOpen]);
14
14
 
15
- const onFilterChange = (field: string, value: string | string[] | undefined, isTop?: boolean) => {
15
+ const onFilterChange = (
16
+ field: string,
17
+ value: string | string[] | undefined,
18
+ isQuickFilter?: boolean,
19
+ ) => {
16
20
  const values = value ? (Array.isArray(value) ? value : [value]) : [];
17
21
 
18
22
  const _filter = [...filter];
@@ -22,7 +26,7 @@ export function useSearchFilter(
22
26
  _filter[fieldIndex].values = values;
23
27
  } else {
24
28
  if (!values.length) return;
25
- _filter.push({ field, values, isTop });
29
+ _filter.push({ field, values, isQuickFilter });
26
30
  }
27
31
 
28
32
  setFilter(_filter.filter((item) => item.values.length));
@@ -32,9 +36,9 @@ export function useSearchFilter(
32
36
  setFilter([]);
33
37
  };
34
38
 
35
- const onTopFacetsReset = () => {
39
+ const onQuickFilterReset = () => {
36
40
  const _filter = [...filter];
37
- setFilter(_filter.filter((item) => !item.isTop));
41
+ setFilter(_filter.filter((item) => !item.isQuickFilter));
38
42
  };
39
43
 
40
44
  const onFacetReset = (field: string) => {
@@ -48,10 +52,10 @@ export function useSearchFilter(
48
52
 
49
53
  return {
50
54
  onFacetReset,
51
- onTopFacetsReset,
52
55
  onFilterChange,
53
56
  onFilterReset,
54
57
  onFilterToggle,
58
+ onQuickFilterReset,
55
59
  isFilterOpen,
56
60
  };
57
61
  }
@@ -66,6 +66,7 @@ export type ThemeHooks = {
66
66
  items: Record<string, SearchItemData[] | null>;
67
67
  isSearchLoading: boolean;
68
68
  facets: SearchFacet[];
69
+ groupField: string;
69
70
  setLoadMore: React.Dispatch<
70
71
  React.SetStateAction<
71
72
  | {
@@ -129,8 +129,8 @@ export type TranslationKey =
129
129
  | 'feedback.sentiment.thumbDown'
130
130
  | 'feedback.settings.leftScaleLabel'
131
131
  | 'feedback.settings.rightScaleLabel'
132
- | 'feedback.settings.anonymousUserEmail.placeholder'
133
- | 'feedback.settings.anonymousUserEmail.label'
132
+ | 'feedback.settings.optionalEmail.placeholder'
133
+ | 'feedback.settings.optionalEmail.label'
134
134
  | 'codeSnippet.report.buttonText'
135
135
  | 'codeSnippet.report.tooltipText'
136
136
  | 'codeSnippet.report.label'
@@ -48,7 +48,6 @@ export type SearchFacet = {
48
48
  field: string;
49
49
  type: SearchFacetType;
50
50
  values: string[] | SearchFacetCount[];
51
- isTop?: boolean;
52
51
  index?: number;
53
52
  };
54
53
 
@@ -76,5 +75,5 @@ export type SearchFacetType =
76
75
  export type SearchFilterItem = {
77
76
  field: string;
78
77
  values: string[];
79
- isTop?: boolean;
78
+ isQuickFilter?: boolean;
80
79
  };