@redocly/theme 0.40.6 → 0.41.0-rc.1

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 (101) hide show
  1. package/lib/components/Dropdown/DropdownMenu.d.ts +2 -0
  2. package/lib/components/Dropdown/DropdownMenu.js +3 -1
  3. package/lib/components/Loaders/SpinnerLoader.d.ts +5 -0
  4. package/lib/components/Loaders/SpinnerLoader.js +32 -0
  5. package/lib/components/Search/FilterFields/SearchFilterFieldSelect.d.ts +12 -0
  6. package/lib/components/Search/FilterFields/SearchFilterFieldSelect.js +113 -0
  7. package/lib/components/Search/FilterFields/SearchFilterFieldTags.d.ts +10 -0
  8. package/lib/components/Search/FilterFields/SearchFilterFieldTags.js +37 -0
  9. package/lib/components/Search/Search.js +1 -1
  10. package/lib/components/Search/SearchDialog.js +103 -26
  11. package/lib/components/Search/SearchFilter.d.ts +11 -0
  12. package/lib/components/Search/SearchFilter.js +71 -0
  13. package/lib/components/Search/SearchFilterField.d.ts +11 -0
  14. package/lib/components/Search/SearchFilterField.js +43 -0
  15. package/lib/components/Search/SearchGroups.d.ts +9 -0
  16. package/lib/components/Search/SearchGroups.js +69 -0
  17. package/lib/components/Search/SearchHighlight.d.ts +1 -1
  18. package/lib/components/Search/SearchHighlight.js +28 -5
  19. package/lib/components/Search/SearchInput.d.ts +3 -2
  20. package/lib/components/Search/SearchInput.js +11 -3
  21. package/lib/components/Search/SearchItem.d.ts +2 -2
  22. package/lib/components/Search/SearchItem.js +23 -15
  23. package/lib/components/Search/variables.js +48 -2
  24. package/lib/components/Segmented/Segmented.d.ts +2 -5
  25. package/lib/components/Select/Select.d.ts +2 -36
  26. package/lib/components/Select/Select.js +110 -98
  27. package/lib/components/Select/SelectInput.d.ts +22 -0
  28. package/lib/components/Select/SelectInput.js +118 -0
  29. package/lib/components/Select/variables.js +11 -1
  30. package/lib/components/Tag/Tag.d.ts +4 -2
  31. package/lib/components/Tag/Tag.js +40 -4
  32. package/lib/components/Tag/variables.dark.js +20 -5
  33. package/lib/components/Tag/variables.js +49 -17
  34. package/lib/components/VersionPicker/VersionPicker.d.ts +2 -3
  35. package/lib/components/VersionPicker/VersionPicker.js +13 -30
  36. package/lib/core/hooks/__mocks__/index.d.ts +1 -1
  37. package/lib/core/hooks/__mocks__/index.js +1 -1
  38. package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +1 -1
  39. package/lib/core/hooks/__mocks__/use-theme-hooks.js +1 -1
  40. package/lib/core/hooks/index.d.ts +2 -1
  41. package/lib/core/hooks/index.js +2 -1
  42. package/lib/core/hooks/search/use-recent-searches.js +2 -0
  43. package/lib/core/hooks/{use-search.d.ts → search/use-search-dialog.d.ts} +1 -1
  44. package/lib/core/hooks/{use-search.js → search/use-search-dialog.js} +5 -5
  45. package/lib/core/hooks/search/use-search-filter.d.ts +9 -0
  46. package/lib/core/hooks/search/use-search-filter.js +50 -0
  47. package/lib/core/types/hooks.d.ts +16 -4
  48. package/lib/core/types/index.d.ts +1 -1
  49. package/lib/core/types/index.js +1 -1
  50. package/lib/core/types/l10n.d.ts +1 -1
  51. package/lib/core/types/search.d.ts +43 -2
  52. package/lib/core/types/select.d.ts +29 -0
  53. package/lib/core/types/{select-option.js → select.js} +1 -1
  54. package/lib/icons/ResetIcon/ResetIcon.d.ts +9 -0
  55. package/lib/icons/ResetIcon/ResetIcon.js +22 -0
  56. package/lib/icons/SettingsIcon/SettingsIcon.d.ts +9 -0
  57. package/lib/icons/SettingsIcon/SettingsIcon.js +23 -0
  58. package/lib/index.d.ts +7 -1
  59. package/lib/index.js +7 -1
  60. package/package.json +2 -2
  61. package/src/components/Dropdown/DropdownMenu.tsx +2 -1
  62. package/src/components/Filter/FilterSelect.tsx +3 -3
  63. package/src/components/Loaders/SpinnerLoader.tsx +31 -0
  64. package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +134 -0
  65. package/src/components/Search/FilterFields/SearchFilterFieldTags.tsx +61 -0
  66. package/src/components/Search/Search.tsx +2 -2
  67. package/src/components/Search/SearchDialog.tsx +168 -42
  68. package/src/components/Search/SearchFilter.tsx +90 -0
  69. package/src/components/Search/SearchFilterField.tsx +84 -0
  70. package/src/components/Search/SearchGroups.tsx +80 -0
  71. package/src/components/Search/SearchHighlight.tsx +29 -2
  72. package/src/components/Search/SearchInput.tsx +17 -3
  73. package/src/components/Search/SearchItem.tsx +38 -24
  74. package/src/components/Search/variables.ts +48 -2
  75. package/src/components/Segmented/Segmented.tsx +2 -2
  76. package/src/components/Select/Select.tsx +170 -157
  77. package/src/components/Select/SelectInput.tsx +184 -0
  78. package/src/components/Select/variables.ts +11 -1
  79. package/src/components/Tag/Tag.tsx +57 -6
  80. package/src/components/Tag/variables.dark.ts +20 -5
  81. package/src/components/Tag/variables.ts +49 -17
  82. package/src/components/VersionPicker/VersionPicker.tsx +15 -39
  83. package/src/core/hooks/__mocks__/index.ts +1 -1
  84. package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -1
  85. package/src/core/hooks/index.ts +2 -1
  86. package/src/core/hooks/search/use-recent-searches.ts +3 -0
  87. package/src/core/hooks/{use-search.ts → search/use-search-dialog.ts} +1 -1
  88. package/src/core/hooks/search/use-search-filter.ts +57 -0
  89. package/src/core/types/hooks.ts +24 -4
  90. package/src/core/types/index.ts +1 -1
  91. package/src/core/types/l10n.ts +7 -1
  92. package/src/core/types/search.ts +54 -2
  93. package/src/core/types/select.ts +31 -0
  94. package/src/icons/ResetIcon/ResetIcon.tsx +26 -0
  95. package/src/icons/SettingsIcon/SettingsIcon.tsx +30 -0
  96. package/src/index.ts +7 -1
  97. package/lib/core/types/select-option.d.ts +0 -4
  98. package/src/core/types/select-option.ts +0 -4
  99. /package/lib/components/{Loading → Loaders}/Loading.d.ts +0 -0
  100. /package/lib/components/{Loading → Loaders}/Loading.js +0 -0
  101. /package/src/components/{Loading → Loaders}/Loading.tsx +0 -0
@@ -0,0 +1,69 @@
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.SearchGroups = void 0;
30
+ const React = __importStar(require("react"));
31
+ const styled_components_1 = __importDefault(require("styled-components"));
32
+ const Tag_1 = require("../../components/Tag/Tag");
33
+ function SearchGroups({ facets, searchFilter, onFilterChange, onTopFacetsReset, }) {
34
+ const groupFacets = facets.filter((facet) => facet.isTop);
35
+ const handleGroupTagClick = (value, fieldId, active, currentValues) => {
36
+ const values = active
37
+ ? currentValues.filter((item) => item !== value)
38
+ : [...currentValues, value];
39
+ onFilterChange(fieldId, values, true);
40
+ };
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"),
43
+ React.createElement(Divider, null),
44
+ groupFacets.flatMap((facet) => facet.values.map((facetCount, index) => {
45
+ var _a;
46
+ const { value, count, isCounterVisible } = facetCount;
47
+ const currentValues = ((_a = searchFilter.find((item) => item.field === facet.field)) === null || _a === void 0 ? void 0 : _a.values) || [];
48
+ const active = currentValues === null || currentValues === void 0 ? void 0 : currentValues.includes(value);
49
+ return (React.createElement(GroupTag, { key: `${facet.field}-${index}`, onClick: () => handleGroupTagClick(value, facet.field, active, currentValues), active: active, borderless: true },
50
+ value,
51
+ " ",
52
+ isCounterVisible && React.createElement("span", null, count)));
53
+ }))));
54
+ }
55
+ exports.SearchGroups = SearchGroups;
56
+ const SearchGroupsWrapper = styled_components_1.default.div `
57
+ display: flex;
58
+ gap: 4px;
59
+ padding: var(--spacing-md);
60
+ `;
61
+ const GroupTag = (0, styled_components_1.default)(Tag_1.Tag) `
62
+ cursor: pointer;
63
+ gap: 4px;
64
+ `;
65
+ const Divider = styled_components_1.default.div `
66
+ border-right: 1px solid var(--border-color-secondary);
67
+ margin: 5px 5px 5px 0;
68
+ `;
69
+ //# sourceMappingURL=SearchGroups.js.map
@@ -1 +1 @@
1
- export declare function highlight(text: string | string[]): JSX.Element | string;
1
+ export declare function searchHighlight(text: string | string[]): JSX.Element | string;
@@ -26,19 +26,42 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.highlight = void 0;
29
+ exports.searchHighlight = void 0;
30
30
  const React = __importStar(require("react"));
31
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
- function highlight(text) {
33
- if (!Array.isArray(text))
34
- return text;
32
+ function slicer(str, arr) {
33
+ const markOpenIndex = str.indexOf('<mark>');
34
+ const markCloseIndex = str.indexOf('</mark>');
35
+ if (markOpenIndex !== -1 && markCloseIndex !== -1) {
36
+ const pre = str.slice(0, markOpenIndex);
37
+ const entry = str.slice(markOpenIndex + 6, markCloseIndex);
38
+ const suf = str.slice(markCloseIndex + 7, str.length);
39
+ return (arr = [...arr, pre, { entry }, ...slicer(suf, arr)]);
40
+ }
41
+ else
42
+ return [...arr, str];
43
+ }
44
+ function searchHighlight(text) {
45
+ if (!Array.isArray(text)) {
46
+ const arr = slicer(text, []);
47
+ if (arr.length === 1)
48
+ return text;
49
+ return (React.createElement("span", null, arr.map((item, index) => {
50
+ if (typeof item === 'object') {
51
+ return React.createElement(Highlight, { key: index }, item.entry);
52
+ }
53
+ else {
54
+ return item;
55
+ }
56
+ })));
57
+ }
35
58
  const [pre, entry, suf] = text;
36
59
  return (React.createElement("span", { "data-component-name": "Search/SearchHighlight" },
37
60
  pre,
38
61
  React.createElement(Highlight, null, entry),
39
62
  suf));
40
63
  }
41
- exports.highlight = highlight;
64
+ exports.searchHighlight = searchHighlight;
42
65
  const Highlight = styled_components_1.default.span `
43
66
  background-color: var(--search-highlight-bg-color);
44
67
  color: var(--search-highlight-text-color);
@@ -2,9 +2,10 @@ import React from 'react';
2
2
  export type SearchInputProps = {
3
3
  placeholder?: string;
4
4
  value: string;
5
- onChange(value: string): void;
5
+ onChange: (value: string) => void;
6
+ onFilterToggle: () => void;
6
7
  inputRef?: React.RefObject<HTMLInputElement>;
7
8
  isLoading: boolean;
8
9
  className?: string;
9
10
  };
10
- export declare function SearchInput({ placeholder, value, onChange, isLoading, className, }: SearchInputProps): JSX.Element;
11
+ export declare function SearchInput({ placeholder, value, onChange, onFilterToggle, isLoading, className, }: SearchInputProps): JSX.Element;
@@ -8,10 +8,11 @@ const react_1 = __importDefault(require("react"));
8
8
  const styled_components_1 = __importDefault(require("styled-components"));
9
9
  const SearchIcon_1 = require("../../icons/SearchIcon/SearchIcon");
10
10
  const Spinner_1 = require("../../icons/Spinner/Spinner");
11
- const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
12
11
  const Button_1 = require("../../components/Button/Button");
13
12
  const hooks_1 = require("../../core/hooks");
14
- function SearchInput({ placeholder, value, onChange, isLoading, className, }) {
13
+ const CloseFilledIcon_1 = require("../../icons/CloseFilledIcon/CloseFilledIcon");
14
+ const SettingsIcon_1 = require("../../icons/SettingsIcon/SettingsIcon");
15
+ function SearchInput({ placeholder, value, onChange, onFilterToggle, isLoading, className, }) {
15
16
  const { useTelemetry } = (0, hooks_1.useThemeHooks)();
16
17
  const telemetry = useTelemetry();
17
18
  const stopPropagation = (event) => event.stopPropagation();
@@ -25,7 +26,8 @@ function SearchInput({ placeholder, value, onChange, isLoading, className, }) {
25
26
  return (react_1.default.createElement(SearchInputWrapper, { "data-component-name": "Search/SearchInput", className: className },
26
27
  value && isLoading ? (react_1.default.createElement(Spinner_1.Spinner, { size: "18px", color: "--search-input-icon-color" })) : (react_1.default.createElement(SearchIcon_1.SearchIcon, { size: "18px", color: "--search-input-icon-color" })),
27
28
  react_1.default.createElement(SearchInputField, { value: value, placeholder: placeholder, onChange: handleOnChange, onClick: stopPropagation }),
28
- !!value && react_1.default.createElement(Button_1.Button, { variant: "ghost", onClick: handleOnReset, icon: react_1.default.createElement(CloseIcon_1.CloseIcon, null) })));
29
+ !!value && (react_1.default.createElement(ResetButton, { variant: "ghost", onClick: handleOnReset, icon: react_1.default.createElement(CloseFilledIcon_1.CloseFilledIcon, null) })),
30
+ react_1.default.createElement(FilterToggleButton, { icon: react_1.default.createElement(SettingsIcon_1.SettingsIcon, null), onClick: onFilterToggle })));
29
31
  }
30
32
  exports.SearchInput = SearchInput;
31
33
  const SearchInputWrapper = styled_components_1.default.div `
@@ -52,4 +54,10 @@ const SearchInputField = styled_components_1.default.input `
52
54
  color: var(--search-input-placeholder-color);
53
55
  }
54
56
  `;
57
+ const ResetButton = (0, styled_components_1.default)(Button_1.Button) `
58
+ color: var(--color-warm-grey-5);
59
+ `;
60
+ const FilterToggleButton = (0, styled_components_1.default)(Button_1.Button) `
61
+ margin-left: 0;
62
+ `;
55
63
  //# sourceMappingURL=SearchInput.js.map
@@ -1,9 +1,9 @@
1
- import type { SearchDocument } from '../../core/types';
1
+ import type { SearchItemData } from '../../core/types';
2
2
  type ActiveItem<T> = T & {
3
3
  active?: boolean;
4
4
  };
5
5
  export type SearchItemProps = {
6
- item: ActiveItem<SearchDocument>;
6
+ item: ActiveItem<SearchItemData>;
7
7
  product?: {
8
8
  name: string;
9
9
  icon?: string;
@@ -43,27 +43,33 @@ function SearchItem({ item, className, product }) {
43
43
  (_a = ref.current) === null || _a === void 0 ? void 0 : _a.focus();
44
44
  }
45
45
  }, [item.active]);
46
- const itemParam = (_a = item.parameters) === null || _a === void 0 ? void 0 : _a[0];
47
- return (react_1.default.createElement(SearchItemWrapper, { className: className, to: item.url, tabIndex: 0, innerRef: ref, "data-component-name": "Search/SearchItem" },
46
+ const { document, highlight } = item;
47
+ const parameter = highlight.parameters && highlight.parameters.length ? highlight.parameters[0] : null;
48
+ const shouldShowPath = document.path && ((_a = document.path) === null || _a === void 0 ? void 0 : _a.length) > 1;
49
+ return (react_1.default.createElement(SearchItemWrapper, { className: className, to: document.url, tabIndex: 0, innerRef: ref, "data-component-name": "Search/SearchItem" },
48
50
  react_1.default.createElement(SearchItemHeader, null,
49
51
  product && (react_1.default.createElement(SearchItemProductTag, { "data-testid": "search-item-product-tag" },
50
52
  react_1.default.createElement(Image_1.Image, { src: product.icon }),
51
53
  product.name)),
52
- item.httpVerb ? (react_1.default.createElement(SearchItemOperation, null,
53
- react_1.default.createElement(SearchItemOperationTag, { color: item.httpVerb }, item.httpVerb.toUpperCase()),
54
- item.pathName ? (0, SearchHighlight_1.highlight)(item.pathName) : null)) : null,
54
+ document.httpMethod ? (react_1.default.createElement(SearchItemOperation, null,
55
+ react_1.default.createElement(SearchItemOperationTag, { color: document.httpMethod }, document.httpMethod.toUpperCase()),
56
+ highlight.httpPath ? (0, SearchHighlight_1.searchHighlight)(highlight.httpPath) : document.httpPath)) : null,
55
57
  react_1.default.createElement(SearchItemTitleWrapper, null,
56
- react_1.default.createElement(SearchItemTitle, null, (0, SearchHighlight_1.highlight)(item.title)),
57
- item.deprecated ? react_1.default.createElement(SearchItemBadge, { deprecated: true }, "Deprecated") : null,
58
- item.badges
59
- ? item.badges.map(({ name, color }) => (react_1.default.createElement(SearchItemBadge, { color: color || 'var(--color-info-base)', key: name }, name)))
58
+ react_1.default.createElement(SearchItemTitle, null, highlight.title ? (0, SearchHighlight_1.searchHighlight)(highlight.title) : document.title),
59
+ document.deprecated ? react_1.default.createElement(SearchItemBadge, { deprecated: true }, "Deprecated") : null,
60
+ document.badges
61
+ ? document.badges.map(({ name, color }) => (react_1.default.createElement(SearchItemBadge, { color: color || 'var(--color-info-base)', key: name }, name)))
60
62
  : null),
61
- Array.isArray(item.text) ? (react_1.default.createElement(SearchItemDescription, null, (0, SearchHighlight_1.highlight)(item.text))) : null),
62
- itemParam ? (react_1.default.createElement(SearchItemPlace, null,
63
+ react_1.default.createElement(SearchItemDescription, null, highlight.text ? (0, SearchHighlight_1.searchHighlight)(highlight.text) : document.text)),
64
+ parameter ? (react_1.default.createElement(SearchItemPlace, null,
63
65
  react_1.default.createElement("div", null,
64
- `${itemParam.place} → ${((_b = itemParam.path) === null || _b === void 0 ? void 0 : _b.length) ? ((_c = itemParam.path) === null || _c === void 0 ? void 0 : _c.join(' → ')) + ' → ' : ''}`,
65
- (0, SearchHighlight_1.highlight)(itemParam.name)),
66
- react_1.default.createElement("div", null, (0, SearchHighlight_1.highlight)(itemParam.description)))) : (react_1.default.createElement(SearchItemPath, null, (_d = item.path) === null || _d === void 0 ? void 0 : _d.join(' → ')))));
66
+ (0, SearchHighlight_1.searchHighlight)(parameter.place),
67
+ ` → `,
68
+ ((_b = parameter.path) === null || _b === void 0 ? void 0 : _b.length) ? (0, SearchHighlight_1.searchHighlight)((_c = parameter.path) === null || _c === void 0 ? void 0 : _c.join(' → ')) + ' → ' : '',
69
+ (0, SearchHighlight_1.searchHighlight)(parameter.name)),
70
+ react_1.default.createElement("div", null, (0, SearchHighlight_1.searchHighlight)(parameter.description)))) : (shouldShowPath && (react_1.default.createElement(SearchItemPath, null, highlight.path && highlight.path.length
71
+ ? (0, SearchHighlight_1.searchHighlight)(highlight.path.join(' → '))
72
+ : (_d = document.path) === null || _d === void 0 ? void 0 : _d.join(' → '))))));
67
73
  }
68
74
  exports.SearchItem = SearchItem;
69
75
  const SearchItemWrapper = (0, styled_components_1.default)(Link_1.Link) `
@@ -73,7 +79,7 @@ const SearchItemWrapper = (0, styled_components_1.default)(Link_1.Link) `
73
79
  background-color: var(--search-item-bg-color);
74
80
  transition: background-color 0.3s ease;
75
81
  text-decoration: none;
76
- white-space: nowrap;
82
+ white-space: normal;
77
83
  outline: none;
78
84
  border-top: 1px solid var(--search-item-border-color);
79
85
  border-bottom: 1px solid var(--search-item-border-color);
@@ -134,6 +140,7 @@ const SearchItemPath = styled_components_1.default.div `
134
140
  font-size: var(--font-size-sm);
135
141
  line-height: var(--line-height-sm);
136
142
  font-weight: var(--font-weight-regular);
143
+ margin-top: var(--spacing-sm);
137
144
  `;
138
145
  const SearchItemPlace = styled_components_1.default.div `
139
146
  display: flex;
@@ -143,6 +150,7 @@ const SearchItemPlace = styled_components_1.default.div `
143
150
  font-size: var(--font-size-sm);
144
151
  line-height: var(--line-height-sm);
145
152
  font-weight: var(--font-weight-regular);
153
+ margin-top: var(--spacing-sm);
146
154
 
147
155
  &:first-child {
148
156
  padding-top: 0;
@@ -6,11 +6,18 @@ exports.search = (0, styled_components_1.css) `
6
6
  /**
7
7
  * @tokens Search
8
8
  */
9
- --search-modal-width: 700px;
10
- --search-modal-min-height: 530px;
9
+ --search-modal-width: 1100px;
10
+ --search-modal-min-height: 705px;
11
11
  --search-modal-bg-color: var(--modal-bg-color);
12
12
  --search-modal-box-shadow: var(--modal-box-shadow);
13
13
  --search-modal-border-radius: var(--border-radius-lg);
14
+ --search-modal-border: 1px solid var(--border-color-secondary);
15
+
16
+ --search-modal-header-bg-color: var(--bg-color-tonal); // @presenter Color
17
+ --search-modal-header-padding: var(--spacing-sm);
18
+
19
+ --search-modal-footer-padding: var(--spacing-sm);
20
+ --search-modal-footer-gap: var(--spacing-md);
14
21
 
15
22
  --search-highlight-bg-color: none; // @presenter Color
16
23
  --search-highlight-text-color: var(--color-info-base); // @presenter Color
@@ -29,6 +36,11 @@ exports.search = (0, styled_components_1.css) `
29
36
  --search-input-border: none;
30
37
  --search-input-border-radius: var(--border-radius); // @presenter BorderRadius
31
38
 
39
+ --search-group-title-padding: var(--spacing-sm);
40
+ --search-group-title-bg-color: var(--bg-color-tonal); // @presenter Color
41
+ --search-group-footer-padding: var(--spacing-sm);
42
+ --search-group-footer-text-color: var(--link-color-primary); // @presenter Color
43
+
32
44
  --search-item-text-color: var(--text-color-secondary); // @presenter Color
33
45
  --search-item-text-color-hover: var(--text-color-primary); // @presenter Color
34
46
  --search-item-title-font-size: var(--font-size-base); // @presenter FontSize
@@ -76,6 +88,40 @@ exports.search = (0, styled_components_1.css) `
76
88
  --search-suggested-item-bg-color-active: var(--layer-color); // @presenter Color
77
89
  --search-suggested-item-border-color-focused: var(--color-blue-4); // @presenter Color
78
90
 
91
+ --search-shortcuts-gap: var(--spacing-xs);
92
+
93
+ --search-message-font-size: var(--font-size-lg); // @presenter FontSize
94
+ --search-message-font-weight: var(--font-weight-regular); // @presenter FontWeight
95
+ --search-message-line-height: var(--line-height-lg); // @presenter LineHeight
96
+ --search-message-text-color: var(--text-color-secondary); // @presenter Color
97
+ --search-message-gap: var(--spacing-md);
98
+
99
+ /**
100
+ * @tokens Search filter
101
+ */
102
+ --search-filter-width: 450px;
103
+ --search-filter-bg-color: var(--search-modal-bg-color);
104
+ --search-filter-padding: var(--spacing-lg);
105
+ --search-filter-font-size: var(--font-size-base);
106
+ --search-filter-font-weight: var(--font-weight-regular);
107
+ --search-filter-line-height: var(--line-height-base);
108
+
109
+ --search-filter-header-padding: var(--spacing-md) 0;
110
+ --search-filter-header-text-color: var(--text-color-helper);
111
+ --search-filter-header-z-index: var(--z-index-raised);
112
+
113
+ --search-filter-fields-gap: var(--spacing-base);
114
+
115
+ --search-filter-field-select-option-gap: var(--spacing-unit);
116
+ --search-filter-field-select-option-text-padding: 0 0 0 var(--spacing-unit);
117
+ --search-filter-field-select-footer-padding: 0 0 0 var(--spacing-unit);
118
+ --search-filter-field-select-footer-text-color: var(--text-color-helper);
119
+
120
+ --search-filter-field-tags-gap: var(--spacing-unit);
121
+ --search-filter-field-tags-tag-margin: var(--spacing-unit) 0 0 0;
122
+
123
+ // @tokens End
124
+
79
125
  /**
80
126
  * @tokens Navbar Search Trigger
81
127
  */
@@ -1,12 +1,9 @@
1
1
  import type { ReactElement } from 'react';
2
- import type { SelectOption } from '../../core/types/select-option';
2
+ import type { SelectOption } from '../../core/types/select';
3
3
  export type SegmentedProps<T> = {
4
4
  options: SelectOption<T>[];
5
5
  value: T;
6
- onChange: ({ label, value }: {
7
- label: string;
8
- value: T;
9
- }) => void;
6
+ onChange: ({ label, value }: SelectOption<T>) => void;
10
7
  className?: string;
11
8
  size?: 'regular' | 'small';
12
9
  };
@@ -1,39 +1,5 @@
1
- import React from 'react';
2
- export type SelectProps<T = any> = {
3
- value: T;
4
- options: {
5
- element: React.ReactNode | JSX.Element | string;
6
- value: T;
7
- label?: string;
8
- }[];
9
- dataAttributes?: Record<string, string>;
10
- className?: string;
11
- withArrow?: boolean;
12
- triggerEvent?: 'click' | 'hover';
13
- onChange?: (value: any) => void;
14
- placement?: 'top' | 'bottom';
15
- alignment?: 'start' | 'end';
16
- icon?: React.ReactNode;
17
- onlyIcon?: boolean;
18
- placeholder?: string;
19
- disabled?: boolean;
20
- hideCheckmarkIcon?: boolean;
21
- dataTestId?: string;
22
- renderInput?: (props: {
23
- isOpen: boolean;
24
- }) => React.ReactElement;
25
- renderDivider?: () => React.ReactElement;
26
- };
1
+ import type { SelectProps } from '../../core/types/select';
27
2
  export declare function Select<T>(props: SelectProps<T>): JSX.Element;
28
- export declare const SelectContainer: import("styled-components").StyledComponent<"div", any, {
3
+ export declare const SelectWrapper: import("styled-components").StyledComponent<"div", any, {
29
4
  disabled?: boolean | undefined;
30
5
  }, never>;
31
- export declare const SelectInput: import("styled-components").StyledComponent<"div", any, {}, never>;
32
- export declare const SelectInputValue: import("styled-components").StyledComponent<"div", any, {}, never>;
33
- export declare const SelectList: import("styled-components").StyledComponent<"ul", any, {
34
- placement?: string | undefined;
35
- alignment?: string | undefined;
36
- }, never>;
37
- export declare const SelectListItem: import("styled-components").StyledComponent<"li", any, {
38
- selected: boolean;
39
- }, never>;
@@ -26,60 +26,124 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.SelectListItem = exports.SelectList = exports.SelectInputValue = exports.SelectInput = exports.SelectContainer = exports.Select = void 0;
29
+ exports.SelectWrapper = exports.Select = void 0;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
- const hooks_1 = require("../../core/hooks");
33
- const ChevronDownIcon_1 = require("../../icons/ChevronDownIcon/ChevronDownIcon");
34
- const ChevronUpIcon_1 = require("../../icons/ChevronUpIcon/ChevronUpIcon");
35
32
  const CheckmarkIcon_1 = require("../../icons/CheckmarkIcon/CheckmarkIcon");
33
+ const SelectInput_1 = require("../../components/Select/SelectInput");
34
+ const Dropdown_1 = require("../../components/Dropdown/Dropdown");
35
+ const DropdownMenu_1 = require("../../components/Dropdown/DropdownMenu");
36
+ const DropdownMenuItem_1 = require("../../components/Dropdown/DropdownMenuItem");
36
37
  function Select(props) {
37
- const { className, value, options, dataAttributes, withArrow = true, triggerEvent = 'click', onChange, placement, alignment, icon, onlyIcon, disabled, placeholder, hideCheckmarkIcon, renderInput, renderDivider, dataTestId = 'select', } = props;
38
- const containerRef = (0, react_1.useRef)(null);
39
- const [isOpen, setIsOpen] = (0, react_1.useState)(false);
40
- // const [selectedIdx, setSelectedIdx] = useState<React.ReactNode | string>(selected);
41
- const handleOpen = () => {
42
- setIsOpen(true);
38
+ const { className, value, options, dataAttributes, withArrow = true, triggerEvent = 'click', placement, alignment, icon, onlyIcon, disabled, placeholder, hideCheckmarkIcon, dataTestId = 'select', multiple, searchable, footer, onChange, onSearch, renderInput, renderDivider, } = props;
39
+ const getSelectedOptionsFromPropsValue = () => {
40
+ return value ? (multiple && Array.isArray(value) ? value : [value]) : [];
43
41
  };
44
- const handleClose = () => {
45
- setIsOpen(false);
42
+ const [selectedOptions, setSelectedOptions] = (0, react_1.useState)(getSelectedOptionsFromPropsValue());
43
+ const [searchValue, setSearchValue] = (0, react_1.useState)(null);
44
+ const [dropdownActive, setDropdownActive] = (0, react_1.useState)(false);
45
+ const [filteredOptions, setFilteredOptions] = (0, react_1.useState)(options);
46
+ const [stickyInputValue, setStickyInputValue] = (0, react_1.useState)(placeholder || '');
47
+ const inputId = (0, react_1.useId)();
48
+ (0, react_1.useEffect)(() => {
49
+ setFilteredOptions(options);
50
+ }, [options]);
51
+ (0, react_1.useEffect)(() => {
52
+ setSelectedOptions(getSelectedOptionsFromPropsValue());
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, [multiple, value]);
55
+ (0, react_1.useEffect)(() => {
56
+ if (onSearch) {
57
+ onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchValue);
58
+ }
59
+ else {
60
+ if (typeof searchValue === 'string') {
61
+ const filteredOptions = options.filter((option) => {
62
+ const valueForSearch = typeof option.value === 'string' ? option.value : '';
63
+ return (!valueForSearch || valueForSearch.toLowerCase().indexOf(searchValue.toLowerCase()) > -1);
64
+ });
65
+ setFilteredOptions(filteredOptions);
66
+ }
67
+ else {
68
+ setFilteredOptions(options);
69
+ }
70
+ }
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, [searchValue]);
73
+ const selectHandler = (selectedOption) => {
74
+ const newSelectedOptions = isSelected(selectedOption)
75
+ ? selectedOptions.filter((option) => option.value !== selectedOption.value)
76
+ : multiple
77
+ ? [...selectedOptions, selectedOption]
78
+ : [selectedOption];
79
+ const newSelectedValues = newSelectedOptions.length
80
+ ? multiple
81
+ ? newSelectedOptions.map((o) => o.value)
82
+ : newSelectedOptions[0].value
83
+ : multiple
84
+ ? []
85
+ : '';
86
+ setSelectedOptions(newSelectedOptions);
87
+ onChange === null || onChange === void 0 ? void 0 : onChange(newSelectedValues);
88
+ setSearchValue(null);
89
+ if (searchable) {
90
+ setDropdownActive(false);
91
+ }
92
+ if (!multiple) {
93
+ setStickyInputValue('');
94
+ }
46
95
  };
47
- const handleToggle = () => {
48
- setIsOpen(!isOpen);
96
+ const searchHandler = (e) => {
97
+ const targetValue = e.target.value;
98
+ setSearchValue(targetValue);
99
+ setDropdownActive(true);
49
100
  };
50
- const handleSelect = (value) => {
51
- // setSelectedIdx(options.findIndex(o => o.value === value));
52
- setIsOpen(false);
53
- onChange === null || onChange === void 0 ? void 0 : onChange(value);
101
+ const inputBlurHandler = (e) => {
102
+ var _a, _b;
103
+ const relatedTarget = e.relatedTarget;
104
+ const isDropdownItem = ((_a = relatedTarget === null || relatedTarget === void 0 ? void 0 : relatedTarget.attributes.getNamedItem('data-component-name')) === null || _a === void 0 ? void 0 : _a.value) ===
105
+ 'Dropdown/DropdownMenuItem';
106
+ if (!isDropdownItem) {
107
+ if (!e.relatedTarget || ((_b = e.relatedTarget) === null || _b === void 0 ? void 0 : _b.id) !== inputId) {
108
+ setDropdownActive(false);
109
+ }
110
+ setSearchValue(null);
111
+ setStickyInputValue('');
112
+ }
54
113
  };
55
- (0, hooks_1.useOutsideClick)(containerRef, handleClose);
56
- // useEffect(() => {
57
- // handleSelect(selected);
58
- // // eslint-disable-next-line react-hooks/exhaustive-deps
59
- // }, [selected]);
60
- const selectedOption = options.find((option) => option.value === value);
61
- const renderDefaultInput = () => (react_1.default.createElement(exports.SelectInput, null,
62
- !onlyIcon && (react_1.default.createElement(exports.SelectInputValue, null, (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.label) || (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.element) || placeholder)),
63
- icon,
64
- withArrow ? isOpen ? react_1.default.createElement(ChevronUpIcon_1.ChevronUpIcon, { size: "14px" }) : react_1.default.createElement(ChevronDownIcon_1.ChevronDownIcon, { size: "14px" }) : null));
65
- return (react_1.default.createElement(exports.SelectContainer, Object.assign({ "data-component-name": "Select/Select" }, dataAttributes, { disabled: disabled, "data-testid": dataTestId, className: className, ref: containerRef, onPointerEnter: triggerEvent === 'hover' ? handleOpen : undefined, onPointerLeave: triggerEvent === 'hover' ? handleClose : undefined, onClick: triggerEvent === 'click' ? handleToggle : undefined }),
66
- renderInput ? renderInput({ isOpen }) : renderDefaultInput(),
67
- isOpen && (react_1.default.createElement(exports.SelectList, { placement: placement, alignment: alignment }, options.map((option, index) => {
68
- const selected = option.value === value;
69
- return (react_1.default.createElement(react_1.default.Fragment, null,
70
- react_1.default.createElement(exports.SelectListItem, { key: index, onClick: () => handleSelect(option.value), selected: selected },
71
- typeof option.element === 'string' ? (react_1.default.createElement("div", null, option.element)) : (option.element),
72
- !hideCheckmarkIcon && selected && react_1.default.createElement(CheckmarkIcon_1.CheckmarkIcon, null)),
73
- renderDivider && index !== options.length - 1 ? renderDivider() : null));
74
- })))));
114
+ const inputFocusHandler = () => {
115
+ if (!multiple && selectedOptions.length) {
116
+ setStickyInputValue(selectedOptions[0].value);
117
+ }
118
+ };
119
+ const inputClickHandler = () => {
120
+ setDropdownActive(!dropdownActive);
121
+ };
122
+ const isSelected = (option) => {
123
+ return !!selectedOptions.find((selectOption) => selectOption.value === option.value);
124
+ };
125
+ const renderDefaultInput = () => {
126
+ return (react_1.default.createElement(SelectInput_1.SelectInput, { id: inputId, selectedOptions: selectedOptions, searchValue: searchValue, placeholder: placeholder, stickyValue: stickyInputValue, multiple: multiple, searchable: searchable, customIcon: icon, onlyIcon: onlyIcon, clearHandler: (option) => selectHandler(option), searchHandler: searchHandler, inputBlurHandler: inputBlurHandler, inputFocusHandler: inputFocusHandler, clickHandler: inputClickHandler }));
127
+ };
128
+ return (react_1.default.createElement(exports.SelectWrapper, Object.assign({ "data-component-name": "Select/Select" }, dataAttributes, { disabled: disabled, "data-testid": dataTestId, className: className }),
129
+ react_1.default.createElement(SelectDropdown, { closeOnClick: !multiple, withArrow: withArrow, trigger: renderInput ? renderInput() : renderDefaultInput(), triggerEvent: triggerEvent, placement: placement, alignment: alignment, active: searchable ? dropdownActive : undefined },
130
+ react_1.default.createElement(SelectDropdownMenu, { footer: footer }, filteredOptions.length === 0 ? (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { disabled: true }, "No results")) : (filteredOptions.map((option, index) => {
131
+ return (react_1.default.createElement(react_1.Fragment, { key: index },
132
+ react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { onAction: () => selectHandler(option), prefix: !hideCheckmarkIcon && isSelected(option) && react_1.default.createElement(CheckmarkIcon_1.CheckmarkIcon, null) }, typeof option.element === 'string' ? (react_1.default.createElement("div", null, option.element)) : (option.element)),
133
+ renderDivider && index !== options.length - 1 ? renderDivider() : null));
134
+ }) || 'No results')))));
75
135
  }
76
136
  exports.Select = Select;
77
- exports.SelectContainer = styled_components_1.default.div `
137
+ exports.SelectWrapper = styled_components_1.default.div `
138
+ display: flex;
139
+ width: 100%;
78
140
  position: relative;
79
141
  font-size: var(--select-font-size);
80
142
  font-weight: var(--select-font-weight);
81
143
  line-height: var(--select-line-height);
82
144
  border-radius: var(--select-border-radius);
145
+ border: var(--search-trigger-border-width) var(--search-trigger-border-style)
146
+ var(--search-trigger-border-color);
83
147
  color: var(--select-text-color);
84
148
  min-width: 0;
85
149
 
@@ -88,67 +152,15 @@ exports.SelectContainer = styled_components_1.default.div `
88
152
  opacity: 0.59;
89
153
  pointer-events: none;
90
154
  `}
91
- a {
92
- display: block;
93
- text-decoration: none;
94
- color: var(--select-text-color);
95
- }
96
- `;
97
- exports.SelectInput = styled_components_1.default.div `
98
- display: flex;
99
- align-items: center;
100
- justify-content: space-between;
101
- border-radius: var(--select-input-border-radius);
102
- padding: var(--select-input-padding);
103
- cursor: pointer;
104
- gap: 8px;
105
155
  `;
106
- exports.SelectInputValue = styled_components_1.default.div `
107
- pointer-events: none;
108
- min-width: 0;
109
- text-overflow: ellipsis;
110
- overflow: hidden;
111
- `;
112
- exports.SelectList = styled_components_1.default.ul `
113
- position: absolute;
114
- top: ${({ placement }) => (placement === 'top' ? 'auto' : '100%')};
115
- bottom: ${({ placement }) => (placement === 'top' ? '100%' : 'auto')};
116
- left: ${({ alignment }) => (alignment === 'start' ? '0' : 'auto')};
117
- right: ${({ alignment }) => (alignment === 'end' ? '0' : 'auto')};
118
- margin: 0;
119
- min-width: var(--select-list-min-width);
120
- max-width: var(--select-list-max-width);
121
- padding: var(--select-list-padding);
122
- background-color: var(--select-list-bg-color);
123
- border-radius: var(--select-list-border-radius);
124
- box-shadow: var(--select-list-box-shadow);
125
- list-style-type: none;
126
- cursor: pointer;
127
- white-space: nowrap;
128
- overflow: hidden;
129
- z-index: 1;
130
- `;
131
- exports.SelectListItem = styled_components_1.default.li `
132
- display: flex;
133
- align-items: center;
134
- justify-content: space-between;
135
- border-radius: var(--select-list-item-border-radius);
136
- gap: var(--select-list-item-gap);
137
- padding: var(--select-list-item-padding);
138
- ${({ selected }) => selected &&
139
- `
140
- font-weight: var(--select-list-item-font-weight-active);
141
- background-color: var(--select-list-item-bg-color-active);
142
- &:hover { background-color: var(--select-list-item-bg-color-active)};
143
- `}
144
-
145
- & > * {
146
- overflow: hidden;
147
- text-overflow: ellipsis;
148
- }
156
+ const SelectDropdown = (0, styled_components_1.default)(Dropdown_1.Dropdown) `
157
+ width: 100%;
149
158
 
150
- &:hover {
151
- background-color: var(--select-list-item-bg-color-hover);
159
+ > * {
160
+ width: 100%;
152
161
  }
153
162
  `;
163
+ const SelectDropdownMenu = (0, styled_components_1.default)(DropdownMenu_1.DropdownMenu) `
164
+ width: 100%;
165
+ `;
154
166
  //# sourceMappingURL=Select.js.map