@redocly/theme 0.40.6 → 0.41.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Dropdown/DropdownMenu.d.ts +2 -0
- package/lib/components/Dropdown/DropdownMenu.js +3 -1
- package/lib/components/Loaders/SpinnerLoader.d.ts +5 -0
- package/lib/components/Loaders/SpinnerLoader.js +32 -0
- package/lib/components/Search/FilterFields/SearchFilterFieldSelect.d.ts +12 -0
- package/lib/components/Search/FilterFields/SearchFilterFieldSelect.js +113 -0
- package/lib/components/Search/FilterFields/SearchFilterFieldTags.d.ts +10 -0
- package/lib/components/Search/FilterFields/SearchFilterFieldTags.js +37 -0
- package/lib/components/Search/Search.js +1 -1
- package/lib/components/Search/SearchDialog.js +103 -26
- package/lib/components/Search/SearchFilter.d.ts +11 -0
- package/lib/components/Search/SearchFilter.js +71 -0
- package/lib/components/Search/SearchFilterField.d.ts +11 -0
- package/lib/components/Search/SearchFilterField.js +43 -0
- package/lib/components/Search/SearchGroups.d.ts +9 -0
- package/lib/components/Search/SearchGroups.js +69 -0
- package/lib/components/Search/SearchHighlight.d.ts +1 -1
- package/lib/components/Search/SearchHighlight.js +28 -5
- package/lib/components/Search/SearchInput.d.ts +3 -2
- package/lib/components/Search/SearchInput.js +11 -3
- package/lib/components/Search/SearchItem.d.ts +2 -2
- package/lib/components/Search/SearchItem.js +23 -15
- package/lib/components/Search/variables.js +48 -2
- package/lib/components/Segmented/Segmented.d.ts +2 -5
- package/lib/components/Select/Select.d.ts +2 -36
- package/lib/components/Select/Select.js +134 -98
- package/lib/components/Select/SelectInput.d.ts +23 -0
- package/lib/components/Select/SelectInput.js +129 -0
- package/lib/components/Select/variables.js +11 -1
- package/lib/components/Tag/Tag.d.ts +4 -2
- package/lib/components/Tag/Tag.js +40 -4
- package/lib/components/Tag/variables.dark.js +20 -5
- package/lib/components/Tag/variables.js +49 -17
- package/lib/components/VersionPicker/VersionPicker.d.ts +2 -3
- package/lib/components/VersionPicker/VersionPicker.js +13 -30
- package/lib/core/hooks/__mocks__/index.d.ts +1 -1
- package/lib/core/hooks/__mocks__/index.js +1 -1
- package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +1 -1
- package/lib/core/hooks/__mocks__/use-theme-hooks.js +1 -1
- package/lib/core/hooks/index.d.ts +2 -1
- package/lib/core/hooks/index.js +2 -1
- package/lib/core/hooks/search/use-recent-searches.js +2 -0
- package/lib/core/hooks/{use-search.d.ts → search/use-search-dialog.d.ts} +1 -1
- package/lib/core/hooks/{use-search.js → search/use-search-dialog.js} +5 -5
- package/lib/core/hooks/search/use-search-filter.d.ts +9 -0
- package/lib/core/hooks/search/use-search-filter.js +50 -0
- package/lib/core/types/hooks.d.ts +16 -4
- package/lib/core/types/index.d.ts +1 -1
- package/lib/core/types/index.js +1 -1
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/types/search.d.ts +43 -2
- package/lib/core/types/select.d.ts +30 -0
- package/lib/core/types/{select-option.js → select.js} +1 -1
- package/lib/icons/ResetIcon/ResetIcon.d.ts +9 -0
- package/lib/icons/ResetIcon/ResetIcon.js +22 -0
- package/lib/icons/SettingsIcon/SettingsIcon.d.ts +9 -0
- package/lib/icons/SettingsIcon/SettingsIcon.js +23 -0
- package/lib/index.d.ts +7 -1
- package/lib/index.js +7 -1
- package/package.json +2 -2
- package/src/components/Dropdown/DropdownMenu.tsx +2 -1
- package/src/components/Filter/FilterSelect.tsx +3 -3
- package/src/components/Loaders/SpinnerLoader.tsx +31 -0
- package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +134 -0
- package/src/components/Search/FilterFields/SearchFilterFieldTags.tsx +61 -0
- package/src/components/Search/Search.tsx +2 -2
- package/src/components/Search/SearchDialog.tsx +168 -42
- package/src/components/Search/SearchFilter.tsx +90 -0
- package/src/components/Search/SearchFilterField.tsx +84 -0
- package/src/components/Search/SearchGroups.tsx +80 -0
- package/src/components/Search/SearchHighlight.tsx +29 -2
- package/src/components/Search/SearchInput.tsx +17 -3
- package/src/components/Search/SearchItem.tsx +38 -24
- package/src/components/Search/variables.ts +48 -2
- package/src/components/Segmented/Segmented.tsx +2 -2
- package/src/components/Select/Select.tsx +200 -157
- package/src/components/Select/SelectInput.tsx +201 -0
- package/src/components/Select/variables.ts +11 -1
- package/src/components/Tag/Tag.tsx +57 -6
- package/src/components/Tag/variables.dark.ts +20 -5
- package/src/components/Tag/variables.ts +49 -17
- package/src/components/VersionPicker/VersionPicker.tsx +15 -39
- package/src/core/hooks/__mocks__/index.ts +1 -1
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -1
- package/src/core/hooks/index.ts +2 -1
- package/src/core/hooks/search/use-recent-searches.ts +3 -0
- package/src/core/hooks/{use-search.ts → search/use-search-dialog.ts} +1 -1
- package/src/core/hooks/search/use-search-filter.ts +57 -0
- package/src/core/types/hooks.ts +24 -4
- package/src/core/types/index.ts +1 -1
- package/src/core/types/l10n.ts +7 -1
- package/src/core/types/search.ts +54 -2
- package/src/core/types/select.ts +32 -0
- package/src/icons/ResetIcon/ResetIcon.tsx +26 -0
- package/src/icons/SettingsIcon/SettingsIcon.tsx +30 -0
- package/src/index.ts +7 -1
- package/lib/core/types/select-option.d.ts +0 -4
- package/src/core/types/select-option.ts +0 -4
- /package/lib/components/{Loading → Loaders}/Loading.d.ts +0 -0
- /package/lib/components/{Loading → Loaders}/Loading.js +0 -0
- /package/src/components/{Loading → Loaders}/Loading.tsx +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import type { ReactNode } from 'react';
|
|
2
3
|
import type { DropdownMenuItemProps } from '../../components/Dropdown/DropdownMenuItem';
|
|
3
4
|
export type DropdownMenuProps = {
|
|
4
5
|
className?: string;
|
|
5
6
|
role?: string;
|
|
7
|
+
footer?: React.ReactNode;
|
|
6
8
|
} & ({
|
|
7
9
|
items: DropdownMenuItemProps[];
|
|
8
10
|
} | {
|
|
@@ -15,7 +15,9 @@ function DropdownMenu(props) {
|
|
|
15
15
|
if ('items' in props) {
|
|
16
16
|
content = props.items.map((item, idx) => (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, Object.assign({ key: idx }, item), item.content)));
|
|
17
17
|
}
|
|
18
|
-
return (react_1.default.createElement(DropdownMenuWrapper, { "data-component-name": "Dropdown/DropdownMenu", "data-testid": "dropdown-menu", className: props.className, role: props.role || 'menu' },
|
|
18
|
+
return (react_1.default.createElement(DropdownMenuWrapper, { "data-component-name": "Dropdown/DropdownMenu", "data-testid": "dropdown-menu", className: props.className, role: props.role || 'menu' },
|
|
19
|
+
content,
|
|
20
|
+
props.footer || null));
|
|
19
21
|
}
|
|
20
22
|
exports.DropdownMenu = DropdownMenu;
|
|
21
23
|
const DropdownMenuWrapper = styled_components_1.default.ul `
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SpinnerLoader = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
function SpinnerLoader({ color, size }) {
|
|
10
|
+
return react_1.default.createElement(Spinner, { color: color, size: size });
|
|
11
|
+
}
|
|
12
|
+
exports.SpinnerLoader = SpinnerLoader;
|
|
13
|
+
const Spinner = styled_components_1.default.div `
|
|
14
|
+
width: ${({ size }) => size};
|
|
15
|
+
height: ${({ size }) => size};
|
|
16
|
+
border: 3px solid ${({ color }) => color};
|
|
17
|
+
border-bottom-color: transparent;
|
|
18
|
+
border-radius: 50%;
|
|
19
|
+
display: inline-block;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
animation: rotation 1s linear infinite;
|
|
22
|
+
|
|
23
|
+
@keyframes rotation {
|
|
24
|
+
0% {
|
|
25
|
+
transform: rotate(0deg);
|
|
26
|
+
}
|
|
27
|
+
100% {
|
|
28
|
+
transform: rotate(360deg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
//# sourceMappingURL=SpinnerLoader.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SearchFacet, SearchFilterItem } from '../../../core/types';
|
|
3
|
+
type SearchFilterFieldSelectProps = {
|
|
4
|
+
className?: string;
|
|
5
|
+
facet: SearchFacet;
|
|
6
|
+
filter: SearchFilterItem[];
|
|
7
|
+
query: string;
|
|
8
|
+
selectedValues: string[];
|
|
9
|
+
onChange: (value: string | string[]) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function SearchFilterFieldSelect({ facet, filter, query, selectedValues, onChange, }: SearchFilterFieldSelectProps): React.JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.SearchFilterFieldSelect = void 0;
|
|
30
|
+
const react_1 = __importStar(require("react"));
|
|
31
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
|
+
const hooks_1 = require("../../../core/hooks");
|
|
33
|
+
const Select_1 = require("../../../components/Select/Select");
|
|
34
|
+
const CounterTag_1 = require("../../../components/Tags/CounterTag");
|
|
35
|
+
function SearchFilterFieldSelect({ facet, filter, query, selectedValues, onChange, }) {
|
|
36
|
+
const MAX_SELECT_OPTIONS = 20;
|
|
37
|
+
const { useFacetQuery, useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
38
|
+
const { translate } = useTranslate();
|
|
39
|
+
const { searchFacet, setSearchFacet, setSearchFacetQuery } = useFacetQuery(facet.field);
|
|
40
|
+
const [selectOptions, setSelectOptions] = (0, react_1.useState)([]);
|
|
41
|
+
const isMultiple = facet.type === 'multi-select';
|
|
42
|
+
(0, react_1.useEffect)(() => {
|
|
43
|
+
setSelectOptions(getSelectOptions());
|
|
44
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
+
}, [searchFacet, facet]);
|
|
46
|
+
const onSearch = (value) => {
|
|
47
|
+
if (value === null) {
|
|
48
|
+
setSearchFacet(null);
|
|
49
|
+
setSearchFacetQuery(null);
|
|
50
|
+
}
|
|
51
|
+
else if (typeof value === 'string') {
|
|
52
|
+
setSearchFacetQuery({
|
|
53
|
+
query,
|
|
54
|
+
filter,
|
|
55
|
+
facetQuery: value,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const getSelectOptions = () => {
|
|
60
|
+
return searchFacet
|
|
61
|
+
? searchFacet.values.map(facetValueToSelectOption)
|
|
62
|
+
: facet.values.map(facetValueToSelectOption);
|
|
63
|
+
};
|
|
64
|
+
const facetValueToSelectOption = (facetValue) => {
|
|
65
|
+
if (!facetValue) {
|
|
66
|
+
return { element: null, value: '' };
|
|
67
|
+
}
|
|
68
|
+
if (typeof facetValue === 'string') {
|
|
69
|
+
return {
|
|
70
|
+
element: (react_1.default.createElement(FilterSelectOptionWrapper, null,
|
|
71
|
+
react_1.default.createElement(FilterSelectOptionText, null, facetValue))),
|
|
72
|
+
value: facetValue,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const { value, count, isCounterVisible } = facetValue;
|
|
77
|
+
return {
|
|
78
|
+
element: (react_1.default.createElement(FilterSelectOptionWrapper, null,
|
|
79
|
+
react_1.default.createElement(FilterSelectOptionText, null, value),
|
|
80
|
+
isCounterVisible && react_1.default.createElement(CounterTag_1.CounterTag, null, count))),
|
|
81
|
+
value: value,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return (react_1.default.createElement(Select_1.Select, { value: selectedValues.length
|
|
86
|
+
? isMultiple
|
|
87
|
+
? selectedValues.map((value) => facetValueToSelectOption(value))
|
|
88
|
+
: facetValueToSelectOption(selectedValues[0])
|
|
89
|
+
: undefined, options: selectOptions, onChange: onChange, placeholder: `${translate('theme.search.filter.field.placeholder', 'Search')} ${facet.name.toLowerCase()}...`, alignment: "start", multiple: isMultiple, searchable: true, footer: selectOptions.length === MAX_SELECT_OPTIONS ? (react_1.default.createElement(FilterSelectFooter, null, "Search to show more items...")) : null, onSearch: onSearch }));
|
|
90
|
+
}
|
|
91
|
+
exports.SearchFilterFieldSelect = SearchFilterFieldSelect;
|
|
92
|
+
const FilterSelectOptionWrapper = styled_components_1.default.div `
|
|
93
|
+
width: 100%;
|
|
94
|
+
display: flex;
|
|
95
|
+
justify-content: space-between;
|
|
96
|
+
align-items: center;
|
|
97
|
+
gap: var(--search-filter-field-select-option-gap);
|
|
98
|
+
`;
|
|
99
|
+
const FilterSelectOptionText = styled_components_1.default.span `
|
|
100
|
+
overflow: hidden;
|
|
101
|
+
text-overflow: ellipsis;
|
|
102
|
+
white-space: nowrap;
|
|
103
|
+
width: 100%;
|
|
104
|
+
padding: var(--search-filter-field-select-option-text-padding);
|
|
105
|
+
`;
|
|
106
|
+
const FilterSelectFooter = styled_components_1.default.div `
|
|
107
|
+
display: flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
justify-content: center;
|
|
110
|
+
padding: var(--search-filter-field-select-footer-padding);
|
|
111
|
+
color: var(--search-filter-field-select-footer-text-color);
|
|
112
|
+
`;
|
|
113
|
+
//# sourceMappingURL=SearchFilterFieldSelect.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SearchFacet } from '../../../core/types';
|
|
3
|
+
type SearchFilterFieldTagsProps = {
|
|
4
|
+
className?: string;
|
|
5
|
+
facet: SearchFacet;
|
|
6
|
+
selectedValues: string[];
|
|
7
|
+
onChange: (value: string | string[]) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare function SearchFilterFieldTags({ className, facet, selectedValues, onChange, }: SearchFilterFieldTagsProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SearchFilterFieldTags = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const Tag_1 = require("../../../components/Tag/Tag");
|
|
10
|
+
function SearchFilterFieldTags({ className, facet, selectedValues, onChange, }) {
|
|
11
|
+
return (react_1.default.createElement(FilterTagsWrapper, { "data-component-name": "Search/FilterFields/SearchFilterFieldTags", className: className }, facet.values.map((facetCount, index) => {
|
|
12
|
+
const { value, count, isCounterVisible } = facetCount;
|
|
13
|
+
const active = selectedValues.includes(value);
|
|
14
|
+
return (react_1.default.createElement(FilterTagWrapper, { key: `${count}-${index}`, color: value, onClick: () => {
|
|
15
|
+
const values = active
|
|
16
|
+
? selectedValues.filter((item) => item !== value)
|
|
17
|
+
: [...selectedValues, value];
|
|
18
|
+
onChange(values);
|
|
19
|
+
}, active: active, borderless: true },
|
|
20
|
+
value,
|
|
21
|
+
" ",
|
|
22
|
+
isCounterVisible && react_1.default.createElement("span", null, count)));
|
|
23
|
+
})));
|
|
24
|
+
}
|
|
25
|
+
exports.SearchFilterFieldTags = SearchFilterFieldTags;
|
|
26
|
+
const FilterTagsWrapper = styled_components_1.default.div `
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-wrap: wrap;
|
|
29
|
+
gap: var(--search-filter-field-tags-gap);
|
|
30
|
+
`;
|
|
31
|
+
const FilterTagWrapper = (0, styled_components_1.default)(Tag_1.Tag) `
|
|
32
|
+
text-transform: uppercase;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
${({ color }) => color && `background-color: var(--tag-operation-bg-color-${color});`}
|
|
35
|
+
margin: var(--search-filter-field-tags-tag-margin);
|
|
36
|
+
`;
|
|
37
|
+
//# sourceMappingURL=SearchFilterFieldTags.js.map
|
|
@@ -10,7 +10,7 @@ const SearchTrigger_1 = require("../../components/Search/SearchTrigger");
|
|
|
10
10
|
const SearchDialog_1 = require("../../components/Search/SearchDialog");
|
|
11
11
|
const hooks_1 = require("../../core/hooks");
|
|
12
12
|
function Search({ className }) {
|
|
13
|
-
const { isOpen, onOpen, onClose } = (0, hooks_1.
|
|
13
|
+
const { isOpen, onOpen, onClose } = (0, hooks_1.useSearchDialog)();
|
|
14
14
|
return (react_1.default.createElement(SearchWrapper, { "data-component-name": "Search/Search", className: className },
|
|
15
15
|
react_1.default.createElement(SearchTrigger_1.SearchTrigger, { onClick: onOpen }),
|
|
16
16
|
isOpen && react_1.default.createElement(SearchDialog_1.SearchDialog, { onClose: onClose })));
|
|
@@ -39,12 +39,16 @@ const SearchSuggestedPages_1 = require("../../components/Search/SearchSuggestedP
|
|
|
39
39
|
const hooks_1 = require("../../core/hooks");
|
|
40
40
|
const Tag_1 = require("../../components/Tag/Tag");
|
|
41
41
|
const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
|
|
42
|
+
const SearchFilter_1 = require("../../components/Search/SearchFilter");
|
|
43
|
+
const SearchGroups_1 = require("../../components/Search/SearchGroups");
|
|
44
|
+
const SpinnerLoader_1 = require("../../components/Loaders/SpinnerLoader");
|
|
42
45
|
function SearchDialog({ onClose, className }) {
|
|
43
|
-
const { useTranslate, useCurrentProduct,
|
|
46
|
+
const { useTranslate, useCurrentProduct, useSearch, useProducts } = (0, hooks_1.useThemeHooks)();
|
|
44
47
|
const products = useProducts();
|
|
45
48
|
const currentProduct = useCurrentProduct();
|
|
46
49
|
const [product, setProduct] = (0, react_1.useState)(currentProduct);
|
|
47
|
-
const { query, setQuery, items,
|
|
50
|
+
const { query, setQuery, filter, setFilter, items, isSearchLoading, facets, setLoadMore } = useSearch(product === null || product === void 0 ? void 0 : product.name);
|
|
51
|
+
const { isFilterOpen, onFilterToggle, onFilterChange, onFilterReset, onFacetReset, onTopFacetsReset, } = (0, hooks_1.useSearchFilter)(filter, setFilter);
|
|
48
52
|
const modalRef = (0, react_1.useRef)(null);
|
|
49
53
|
const { translate } = useTranslate();
|
|
50
54
|
(0, hooks_1.useDialogHotKeys)(modalRef, onClose);
|
|
@@ -59,29 +63,64 @@ function SearchDialog({ onClose, className }) {
|
|
|
59
63
|
};
|
|
60
64
|
const mapItem = (item) => {
|
|
61
65
|
let itemProduct;
|
|
62
|
-
if (!product && item.product) {
|
|
63
|
-
const resolvedProduct = products.find((product) => { var _a; return product.slug.match(`/${(_a = item.product) === null || _a === void 0 ? void 0 : _a.folder}/`); });
|
|
66
|
+
if (!product && item.document.product) {
|
|
67
|
+
const resolvedProduct = products.find((product) => { var _a; return product.slug.match(`/${(_a = item.document.product) === null || _a === void 0 ? void 0 : _a.folder}/`); });
|
|
64
68
|
itemProduct = resolvedProduct
|
|
65
69
|
? { name: resolvedProduct.name, icon: resolvedProduct.icon }
|
|
66
70
|
: undefined;
|
|
67
71
|
}
|
|
68
|
-
return react_1.default.createElement(SearchItem_1.SearchItem, { key: item.id, item: item, product: itemProduct });
|
|
72
|
+
return react_1.default.createElement(SearchItem_1.SearchItem, { key: item.document.id, item: item, product: itemProduct });
|
|
69
73
|
};
|
|
74
|
+
const showLoadMore = (groupKey, currentCount = 0) => {
|
|
75
|
+
const topFacet = facets.find((facet) => facet.isTop);
|
|
76
|
+
let needLoadMore = false;
|
|
77
|
+
if (topFacet) {
|
|
78
|
+
const groupValue = topFacet.values.find((value) => {
|
|
79
|
+
if (typeof value === 'object') {
|
|
80
|
+
return value.value === groupKey;
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
return false;
|
|
84
|
+
});
|
|
85
|
+
needLoadMore = groupValue ? groupValue.count > currentCount : false;
|
|
86
|
+
}
|
|
87
|
+
return needLoadMore;
|
|
88
|
+
};
|
|
89
|
+
const showResults = !!((filter && filter.length) || query);
|
|
70
90
|
return (react_1.default.createElement(SearchOverlay, { "data-component-name": "Search/SearchDialog", ref: modalRef, onClick: handleOverlayClick, className: (0, utils_1.concatClassNames)('overlay', className) },
|
|
71
91
|
react_1.default.createElement(SearchDialogWrapper, { className: "scroll-lock", role: "dialog" },
|
|
72
92
|
react_1.default.createElement(SearchDialogHeader, null,
|
|
73
|
-
react_1.default.createElement(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
react_1.default.createElement(
|
|
93
|
+
product && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
94
|
+
react_1.default.createElement(SearchProductTag, { color: "product" },
|
|
95
|
+
product.name,
|
|
96
|
+
react_1.default.createElement(CloseIcon_1.CloseIcon, { onClick: () => setProduct(undefined), color: "--icon-color-additional" })))),
|
|
97
|
+
react_1.default.createElement(SearchInput_1.SearchInput, { value: query, onChange: setQuery, onFilterToggle: onFilterToggle, placeholder: translate('theme.search.label', 'Search docs...'), isLoading: isSearchLoading, "data-translation-key": "theme.search.label" })),
|
|
98
|
+
react_1.default.createElement(SearchDialogBody, null,
|
|
99
|
+
react_1.default.createElement(SearchDialogBodyMainView, null,
|
|
100
|
+
react_1.default.createElement(SearchGroups_1.SearchGroups, { facets: facets, searchFilter: filter, onFilterChange: onFilterChange, onTopFacetsReset: onTopFacetsReset }),
|
|
101
|
+
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) => {
|
|
102
|
+
var _a, _b, _c;
|
|
103
|
+
return ((_a = items[key]) === null || _a === void 0 ? void 0 : _a.length) ? (react_1.default.createElement(react_1.Fragment, { key: key },
|
|
104
|
+
react_1.default.createElement(SearchGroupTitle, null, key), (_b = items[key]) === null || _b === void 0 ? void 0 :
|
|
105
|
+
_b.map(mapItem),
|
|
106
|
+
showLoadMore(key, ((_c = items[key]) === null || _c === void 0 ? void 0 : _c.length) || 0) && (react_1.default.createElement(SearchGroupFooter, { "data-translation-key": "theme.search.showMore", onClick: () => { var _a; return setLoadMore({ groupKey: key, offset: ((_a = items[key]) === null || _a === void 0 ? void 0 : _a.length) || 0 }); } }, translate('theme.search.showMore', 'Show more'))))) : null;
|
|
107
|
+
})) : isSearchLoading ? (react_1.default.createElement(SearchMessage, null,
|
|
108
|
+
react_1.default.createElement(SpinnerLoader_1.SpinnerLoader, { size: "26px", color: "var(--search-input-icon-color)" }),
|
|
109
|
+
translate('theme.search.loading', 'Loading...'))) : (react_1.default.createElement(SearchMessage, { "data-translation-key": "theme.search.noResults" },
|
|
110
|
+
react_1.default.createElement("b", null, translate('theme.search.noResults.title', 'No results')),
|
|
111
|
+
translate('theme.search.noResults.description', 'Prease, try with a different query.')))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
112
|
+
react_1.default.createElement(SearchRecent_1.SearchRecent, { onSelect: setQuery }),
|
|
113
|
+
react_1.default.createElement(SearchSuggestedPages_1.SearchSuggestedPages, null)))),
|
|
114
|
+
isFilterOpen && (react_1.default.createElement(SearchDialogBodyFilterView, null,
|
|
115
|
+
react_1.default.createElement(SearchFilter_1.SearchFilter, { facets: facets, filter: filter, query: query, onFilterChange: onFilterChange, onFilterReset: onFilterReset, onFacetReset: onFacetReset })))),
|
|
80
116
|
react_1.default.createElement(SearchDialogFooter, null,
|
|
81
117
|
react_1.default.createElement(SearchShortcuts, null,
|
|
82
118
|
react_1.default.createElement(SearchShortcut_1.SearchShortcut, { "data-translation-key": "theme.search.keys.navigate", combination: "Tab", text: translate('theme.search.keys.navigate', 'to navigate') }),
|
|
83
119
|
react_1.default.createElement(SearchShortcut_1.SearchShortcut, { "data-translation-key": "theme.search.keys.select", combination: "\u23CE", text: translate('theme.search.keys.select', 'to select') }),
|
|
84
120
|
react_1.default.createElement(SearchShortcut_1.SearchShortcut, { "data-translation-key": "theme.search.keys.exit", combination: "Esc", text: translate('theme.search.keys.exit', 'to exit') })),
|
|
121
|
+
isSearchLoading && (react_1.default.createElement(SearchLoading, null,
|
|
122
|
+
react_1.default.createElement(SpinnerLoader_1.SpinnerLoader, { size: "16px", color: "var(--search-input-icon-color)" }),
|
|
123
|
+
translate('theme.search.loading', 'Loading...'))),
|
|
85
124
|
react_1.default.createElement(SearchCancelButton, { "data-translation-key": "theme.search.cancel", variant: "secondary", size: "small", onClick: onClose }, translate('theme.search.cancel', 'Cancel'))))));
|
|
86
125
|
}
|
|
87
126
|
exports.SearchDialog = SearchDialog;
|
|
@@ -100,7 +139,6 @@ const SearchOverlay = styled_components_1.default.div `
|
|
|
100
139
|
const SearchDialogWrapper = styled_components_1.default.div `
|
|
101
140
|
display: flex;
|
|
102
141
|
flex-direction: column;
|
|
103
|
-
justify-content: space-between;
|
|
104
142
|
overflow: auto;
|
|
105
143
|
width: 100vw;
|
|
106
144
|
height: 100vh;
|
|
@@ -116,47 +154,65 @@ const SearchDialogWrapper = styled_components_1.default.div `
|
|
|
116
154
|
max-height: 95vh;
|
|
117
155
|
height: auto;
|
|
118
156
|
resize: both;
|
|
119
|
-
min-width: 300px;
|
|
120
|
-
min-height: 200px;
|
|
121
157
|
}
|
|
122
158
|
`;
|
|
123
159
|
const SearchDialogHeader = styled_components_1.default.header `
|
|
124
160
|
display: flex;
|
|
125
161
|
align-items: center;
|
|
126
|
-
border-bottom:
|
|
127
|
-
background-color: var(--search-
|
|
128
|
-
padding: var(--
|
|
162
|
+
border-bottom: var(--search-modal-border);
|
|
163
|
+
background-color: var(--search-modal-header-bg-color);
|
|
164
|
+
padding: var(--search-modal-header-padding);
|
|
129
165
|
`;
|
|
130
166
|
const SearchDialogBody = styled_components_1.default.div `
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: row;
|
|
131
169
|
flex-grow: 1;
|
|
132
|
-
overflow-y: scroll;
|
|
133
|
-
overscroll-behavior: contain;
|
|
134
170
|
|
|
135
171
|
@media screen and (min-width: ${utils_1.breakpoints.small}) {
|
|
136
172
|
height: var(--search-modal-min-height);
|
|
137
173
|
}
|
|
138
174
|
`;
|
|
175
|
+
const SearchDialogBodyMainView = styled_components_1.default.div `
|
|
176
|
+
flex: 2;
|
|
177
|
+
flex-grow: 2;
|
|
178
|
+
overflow-y: scroll;
|
|
179
|
+
overscroll-behavior: contain;
|
|
180
|
+
border-right: var(--search-modal-border);
|
|
181
|
+
`;
|
|
182
|
+
const SearchDialogBodyFilterView = styled_components_1.default.div `
|
|
183
|
+
overflow: scroll;
|
|
184
|
+
`;
|
|
139
185
|
const SearchDialogFooter = styled_components_1.default.footer `
|
|
140
|
-
|
|
141
|
-
|
|
186
|
+
display: flex;
|
|
187
|
+
gap: var(--search-modal-footer-gap);
|
|
188
|
+
padding: var(--search-modal-footer-padding);
|
|
189
|
+
border-top: var(--search-modal-border);
|
|
142
190
|
`;
|
|
143
191
|
const SearchShortcuts = styled_components_1.default.div `
|
|
144
192
|
display: none;
|
|
145
193
|
justify-content: flex-start;
|
|
146
194
|
align-items: center;
|
|
147
|
-
gap: var(--
|
|
195
|
+
gap: var(--search-shortcuts-gap);
|
|
148
196
|
|
|
149
197
|
@media screen and (min-width: ${utils_1.breakpoints.small}) {
|
|
150
198
|
display: flex;
|
|
151
199
|
}
|
|
152
200
|
`;
|
|
153
201
|
const SearchMessage = styled_components_1.default.div `
|
|
154
|
-
|
|
155
|
-
|
|
202
|
+
display: flex;
|
|
203
|
+
height: 40%;
|
|
204
|
+
justify-content: center;
|
|
205
|
+
align-items: center;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
font-size: var(--search-message-font-size);
|
|
208
|
+
font-weight: var(--search-message-font-weight);
|
|
209
|
+
line-height: var(--search-message-line-height);
|
|
210
|
+
color: var(--search-message-text-color);
|
|
211
|
+
gap: var(--search-message-gap);
|
|
156
212
|
`;
|
|
157
213
|
const SearchProductTag = (0, styled_components_1.default)(Tag_1.Tag) `
|
|
158
214
|
--tag-border-radius: var(--border-radius);
|
|
159
|
-
|
|
215
|
+
border: none;
|
|
160
216
|
margin: var(--spacing-xs) var(--spacing-sm) !important;
|
|
161
217
|
`;
|
|
162
218
|
const SearchCancelButton = (0, styled_components_1.default)(Button_1.Button) `
|
|
@@ -166,4 +222,25 @@ const SearchCancelButton = (0, styled_components_1.default)(Button_1.Button) `
|
|
|
166
222
|
display: none;
|
|
167
223
|
}
|
|
168
224
|
`;
|
|
225
|
+
const SearchGroupTitle = styled_components_1.default.div `
|
|
226
|
+
border-bottom: var(--search-modal-border);
|
|
227
|
+
padding: var(--search-group-title-padding);
|
|
228
|
+
background-color: var(--search-group-title-bg-color);
|
|
229
|
+
`;
|
|
230
|
+
const SearchGroupFooter = styled_components_1.default.div `
|
|
231
|
+
display: flex;
|
|
232
|
+
justify-content: center;
|
|
233
|
+
padding: var(--search-group-footer-padding);
|
|
234
|
+
color: var(--search-group-footer-text-color);
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
`;
|
|
237
|
+
const SearchLoading = styled_components_1.default.div `
|
|
238
|
+
display: none;
|
|
239
|
+
align-items: center;
|
|
240
|
+
gap: var(--spacing-xs);
|
|
241
|
+
|
|
242
|
+
@media screen and (min-width: ${utils_1.breakpoints.small}) {
|
|
243
|
+
display: flex;
|
|
244
|
+
}
|
|
245
|
+
`;
|
|
169
246
|
//# sourceMappingURL=SearchDialog.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SearchFilterItem, SearchFacet } from '../../core/types';
|
|
2
|
+
export type SearchFilterProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
facets: SearchFacet[];
|
|
5
|
+
filter: SearchFilterItem[];
|
|
6
|
+
query: string;
|
|
7
|
+
onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
|
|
8
|
+
onFilterReset: () => void;
|
|
9
|
+
onFacetReset: (field: string) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function SearchFilter({ className, facets, filter, query, onFilterChange, onFilterReset, onFacetReset, }: SearchFilterProps): JSX.Element;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.SearchFilter = void 0;
|
|
30
|
+
const React = __importStar(require("react"));
|
|
31
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
|
+
const Button_1 = require("../../components/Button/Button");
|
|
33
|
+
const CleanIcon_1 = require("../../icons/CleanIcon/CleanIcon");
|
|
34
|
+
const SearchFilterField_1 = require("../../components/Search/SearchFilterField");
|
|
35
|
+
const hooks_1 = require("../../core/hooks");
|
|
36
|
+
function SearchFilter({ className, facets, filter, query, onFilterChange, onFilterReset, onFacetReset, }) {
|
|
37
|
+
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
38
|
+
const { translate } = useTranslate();
|
|
39
|
+
return (React.createElement(SearchFilterWrapper, { "data-component-name": "Search/SearchFilter", className: className },
|
|
40
|
+
React.createElement(SearchFilterHeader, null,
|
|
41
|
+
React.createElement("span", { "data-translation-key": "theme.search.filter.title" }, translate('theme.search.filter.title', 'Advanced filter')),
|
|
42
|
+
React.createElement(Button_1.Button, { "data-translation-key": "theme.search.filter.reset", onClick: onFilterReset, variant: "ghost", icon: React.createElement(CleanIcon_1.CleanIcon, null) }, translate('theme.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 }))))));
|
|
44
|
+
}
|
|
45
|
+
exports.SearchFilter = SearchFilter;
|
|
46
|
+
const SearchFilterWrapper = styled_components_1.default.div `
|
|
47
|
+
width: var(--search-filter-width);
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
padding: var(--search-filter-padding);
|
|
51
|
+
font-size: var(--search-filter-font-size);
|
|
52
|
+
font-weight: var(--search-filter-font-weight);
|
|
53
|
+
line-height: var(--search-filter-line-height);
|
|
54
|
+
`;
|
|
55
|
+
const SearchFilterHeader = styled_components_1.default.div `
|
|
56
|
+
position: sticky;
|
|
57
|
+
top: 0px;
|
|
58
|
+
display: flex;
|
|
59
|
+
justify-content: space-between;
|
|
60
|
+
align-items: center;
|
|
61
|
+
padding: var(--search-filter-header-padding);
|
|
62
|
+
color: var(--search-filter-header-text-color);
|
|
63
|
+
background-color: var(--search-filter-bg-color);
|
|
64
|
+
z-index: var(--search-filter-header-z-index);
|
|
65
|
+
`;
|
|
66
|
+
const SearchFilterFields = styled_components_1.default.div `
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: var(--search-filter-fields-gap);
|
|
70
|
+
`;
|
|
71
|
+
//# sourceMappingURL=SearchFilter.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SearchFacet, SearchFilterItem } from '../../core/types';
|
|
2
|
+
type SearchFilterFieldProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
facet: SearchFacet;
|
|
5
|
+
filter: SearchFilterItem[];
|
|
6
|
+
query: string;
|
|
7
|
+
onFilterChange: (field: string, value: string | string[], isTop?: boolean) => void;
|
|
8
|
+
onFacetReset: (filed: string) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare function SearchFilterField({ className, facet, filter, query, onFilterChange, onFacetReset, }: SearchFilterFieldProps): JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SearchFilterField = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const Button_1 = require("../../components/Button/Button");
|
|
10
|
+
const ResetIcon_1 = require("../../icons/ResetIcon/ResetIcon");
|
|
11
|
+
const core_1 = require("../../core");
|
|
12
|
+
const SearchFilterFieldSelect_1 = require("../../components/Search/FilterFields/SearchFilterFieldSelect");
|
|
13
|
+
const SearchFilterFieldTags_1 = require("../../components/Search/FilterFields/SearchFilterFieldTags");
|
|
14
|
+
function SearchFilterField({ className, facet, filter, query, onFilterChange, onFacetReset, }) {
|
|
15
|
+
var _a;
|
|
16
|
+
const { useTranslate } = (0, core_1.useThemeHooks)();
|
|
17
|
+
const { translate } = useTranslate();
|
|
18
|
+
const selectedValues = ((_a = filter.find((item) => item.field === facet.field)) === null || _a === void 0 ? void 0 : _a.values) || [];
|
|
19
|
+
const onChange = (value) => {
|
|
20
|
+
onFilterChange(facet.field, value, facet.isTop);
|
|
21
|
+
};
|
|
22
|
+
const onReset = () => {
|
|
23
|
+
onFacetReset(facet.field);
|
|
24
|
+
};
|
|
25
|
+
return (react_1.default.createElement(FilterFieldWrapper, { "data-component-name": "Search/SearchFilterField", className: className },
|
|
26
|
+
react_1.default.createElement(FilterFieldLabel, null,
|
|
27
|
+
facet.name,
|
|
28
|
+
selectedValues.length > 0 && (react_1.default.createElement(Button_1.Button, { "data-translation-key": "theme.search.filter.field.reset", icon: react_1.default.createElement(ResetIcon_1.ResetIcon, null), variant: "ghost", size: "small", onClick: onReset }, translate('theme.search.filter.field.reset', 'Reset')))),
|
|
29
|
+
['select', 'multi-select'].includes(facet.type) && (react_1.default.createElement(SearchFilterFieldSelect_1.SearchFilterFieldSelect, { facet: facet, filter: filter, query: query, selectedValues: selectedValues, onChange: onChange })),
|
|
30
|
+
facet.type === 'tags' && (react_1.default.createElement(SearchFilterFieldTags_1.SearchFilterFieldTags, { facet: facet, selectedValues: selectedValues, onChange: onChange }))));
|
|
31
|
+
}
|
|
32
|
+
exports.SearchFilterField = SearchFilterField;
|
|
33
|
+
const FilterFieldWrapper = styled_components_1.default.div `
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
gap: 4px;
|
|
37
|
+
`;
|
|
38
|
+
const FilterFieldLabel = styled_components_1.default.div `
|
|
39
|
+
display: flex;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
align-items: center;
|
|
42
|
+
`;
|
|
43
|
+
//# sourceMappingURL=SearchFilterField.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type SearchFacet, type SearchFilterItem } from '../../index.js';
|
|
2
|
+
type SearchGroupsProps = {
|
|
3
|
+
facets: SearchFacet[];
|
|
4
|
+
searchFilter: SearchFilterItem[];
|
|
5
|
+
onFilterChange: (field: string, value: string[], isTop?: boolean) => void;
|
|
6
|
+
onTopFacetsReset: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function SearchGroups({ facets, searchFilter, onFilterChange, onTopFacetsReset, }: SearchGroupsProps): JSX.Element;
|
|
9
|
+
export {};
|