@redocly/theme 0.42.2 → 0.43.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 (112) 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 +109 -27
  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 +1 -1
  20. package/lib/components/Search/SearchInput.js +5 -2
  21. package/lib/components/Search/SearchItem.d.ts +2 -2
  22. package/lib/components/Search/SearchItem.js +24 -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 +136 -98
  27. package/lib/components/Select/SelectInput.d.ts +23 -0
  28. package/lib/components/Select/SelectInput.js +129 -0
  29. package/lib/components/Select/variables.js +12 -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 +2 -1
  37. package/lib/core/hooks/__mocks__/index.js +2 -1
  38. package/lib/core/hooks/__mocks__/search/use-search-filter.d.ts +9 -0
  39. package/lib/core/hooks/__mocks__/search/use-search-filter.js +14 -0
  40. package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +6 -1
  41. package/lib/core/hooks/__mocks__/use-theme-hooks.js +6 -1
  42. package/lib/core/hooks/index.d.ts +2 -1
  43. package/lib/core/hooks/index.js +2 -1
  44. package/lib/core/hooks/search/use-recent-searches.js +2 -0
  45. package/lib/core/hooks/{use-search.d.ts → search/use-search-dialog.d.ts} +1 -1
  46. package/lib/core/hooks/{use-search.js → search/use-search-dialog.js} +5 -5
  47. package/lib/core/hooks/search/use-search-filter.d.ts +9 -0
  48. package/lib/core/hooks/search/use-search-filter.js +50 -0
  49. package/lib/core/types/hooks.d.ts +17 -4
  50. package/lib/core/types/index.d.ts +1 -1
  51. package/lib/core/types/index.js +1 -1
  52. package/lib/core/types/l10n.d.ts +1 -2
  53. package/lib/core/types/search.d.ts +42 -2
  54. package/lib/core/types/select.d.ts +31 -0
  55. package/lib/core/types/{select-option.js → select.js} +1 -1
  56. package/lib/core/utils/index.d.ts +1 -0
  57. package/lib/core/utils/index.js +1 -0
  58. package/lib/core/utils/text-trimmer.d.ts +1 -0
  59. package/lib/core/utils/text-trimmer.js +16 -0
  60. package/lib/icons/ResetIcon/ResetIcon.d.ts +9 -0
  61. package/lib/icons/ResetIcon/ResetIcon.js +22 -0
  62. package/lib/icons/SettingsIcon/SettingsIcon.d.ts +9 -0
  63. package/lib/icons/SettingsIcon/SettingsIcon.js +23 -0
  64. package/lib/index.d.ts +8 -1
  65. package/lib/index.js +8 -1
  66. package/lib/markdoc/components/Cards/Card.js +6 -6
  67. package/package.json +3 -3
  68. package/src/components/Dropdown/DropdownMenu.tsx +2 -1
  69. package/src/components/Filter/FilterSelect.tsx +3 -3
  70. package/src/components/Loaders/SpinnerLoader.tsx +31 -0
  71. package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +135 -0
  72. package/src/components/Search/FilterFields/SearchFilterFieldTags.tsx +61 -0
  73. package/src/components/Search/Search.tsx +2 -2
  74. package/src/components/Search/SearchDialog.tsx +183 -41
  75. package/src/components/Search/SearchFilter.tsx +90 -0
  76. package/src/components/Search/SearchFilterField.tsx +84 -0
  77. package/src/components/Search/SearchGroups.tsx +81 -0
  78. package/src/components/Search/SearchHighlight.tsx +29 -2
  79. package/src/components/Search/SearchInput.tsx +9 -3
  80. package/src/components/Search/SearchItem.tsx +39 -24
  81. package/src/components/Search/variables.ts +48 -2
  82. package/src/components/Segmented/Segmented.tsx +2 -2
  83. package/src/components/Select/Select.tsx +208 -157
  84. package/src/components/Select/SelectInput.tsx +201 -0
  85. package/src/components/Select/variables.ts +12 -1
  86. package/src/components/Tag/Tag.tsx +57 -6
  87. package/src/components/Tag/variables.dark.ts +20 -5
  88. package/src/components/Tag/variables.ts +49 -17
  89. package/src/components/VersionPicker/VersionPicker.tsx +15 -39
  90. package/src/core/hooks/__mocks__/index.ts +2 -1
  91. package/src/core/hooks/__mocks__/search/use-search-filter.ts +10 -0
  92. package/src/core/hooks/__mocks__/use-theme-hooks.ts +6 -1
  93. package/src/core/hooks/index.ts +2 -1
  94. package/src/core/hooks/search/use-recent-searches.ts +3 -0
  95. package/src/core/hooks/{use-search.ts → search/use-search-dialog.ts} +1 -1
  96. package/src/core/hooks/search/use-search-filter.ts +57 -0
  97. package/src/core/types/hooks.ts +25 -4
  98. package/src/core/types/index.ts +1 -1
  99. package/src/core/types/l10n.ts +110 -38
  100. package/src/core/types/search.ts +53 -2
  101. package/src/core/types/select.ts +33 -0
  102. package/src/core/utils/index.ts +1 -0
  103. package/src/core/utils/text-trimmer.ts +7 -0
  104. package/src/icons/ResetIcon/ResetIcon.tsx +26 -0
  105. package/src/icons/SettingsIcon/SettingsIcon.tsx +30 -0
  106. package/src/index.ts +8 -1
  107. package/src/markdoc/components/Cards/Card.tsx +15 -15
  108. package/lib/core/types/select-option.d.ts +0 -4
  109. package/src/core/types/select-option.ts +0 -4
  110. /package/lib/components/{Loading → Loaders}/Loading.d.ts +0 -0
  111. /package/lib/components/{Loading → Loaders}/Loading.js +0 -0
  112. /package/src/components/{Loading → Loaders}/Loading.tsx +0 -0
@@ -0,0 +1,31 @@
1
+ import type React from 'react';
2
+ export type SelectOption<T> = {
3
+ value: T;
4
+ element?: React.ReactNode | JSX.Element | string;
5
+ label?: string;
6
+ };
7
+ export type SelectProps<T = any> = {
8
+ value?: SelectOption<T> | SelectOption<T>[] | T | T[];
9
+ options: SelectOption<T>[];
10
+ multiple?: boolean;
11
+ searchable?: boolean;
12
+ clearable?: boolean;
13
+ dataAttributes?: Record<string, string>;
14
+ className?: string;
15
+ withArrow?: boolean;
16
+ triggerEvent?: 'click' | 'hover';
17
+ placement?: 'top' | 'bottom';
18
+ alignment?: 'start' | 'end';
19
+ onlyIcon?: boolean;
20
+ placeholder?: string;
21
+ disabled?: boolean;
22
+ hideCheckmarkIcon?: boolean;
23
+ checkmarkIconPosition?: 'start' | 'end';
24
+ dataTestId?: string;
25
+ icon?: React.ReactNode;
26
+ footer?: React.ReactNode;
27
+ onChange?: (value: T | T[]) => void;
28
+ renderInput?: () => React.ReactElement;
29
+ renderDivider?: () => React.ReactElement;
30
+ onSearch?: (value: T | null) => void;
31
+ };
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=select-option.js.map
3
+ //# sourceMappingURL=select.js.map
@@ -24,3 +24,4 @@ export * from '../../core/utils/format-date-without-timezone';
24
24
  export * from '../../core/utils/details';
25
25
  export * from '../../core/utils/get-navbar-element';
26
26
  export * from '../../core/utils/with-load-progress';
27
+ export * from '../../core/utils/text-trimmer';
@@ -40,4 +40,5 @@ __exportStar(require("../../core/utils/format-date-without-timezone"), exports);
40
40
  __exportStar(require("../../core/utils/details"), exports);
41
41
  __exportStar(require("../../core/utils/get-navbar-element"), exports);
42
42
  __exportStar(require("../../core/utils/with-load-progress"), exports);
43
+ __exportStar(require("../../core/utils/text-trimmer"), exports);
43
44
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export declare function trimText(text: string | string[], maxLength?: number): string | string[];
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trimText = void 0;
4
+ function trimText(text, maxLength = 150) {
5
+ if (typeof text === 'string') {
6
+ if (text.length <= maxLength) {
7
+ return text;
8
+ }
9
+ else
10
+ return `${text.slice(0, maxLength)}...`;
11
+ }
12
+ else
13
+ return text;
14
+ }
15
+ exports.trimText = trimText;
16
+ //# sourceMappingURL=text-trimmer.js.map
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { IconProps } from '../../icons/types';
3
+ export declare const ResetIcon: import("styled-components").StyledComponent<(props: IconProps) => React.JSX.Element, any, {
4
+ 'data-component-name': string;
5
+ } & {
6
+ color?: string | undefined;
7
+ size?: string | undefined;
8
+ className?: string | undefined;
9
+ } & React.SVGProps<SVGSVGElement>, "data-component-name">;
@@ -0,0 +1,22 @@
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.ResetIcon = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const styled_components_1 = __importDefault(require("styled-components"));
9
+ const utils_1 = require("../../core/utils");
10
+ const Icon = (props) => (react_1.default.createElement("svg", Object.assign({ viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, props),
11
+ react_1.default.createElement("path", { d: "M9 14C10.1867 14 11.3467 13.6481 12.3334 12.9888C13.3201 12.3295 14.0892 11.3925 14.5433 10.2961C14.9974 9.19975 15.1162 7.99335 14.8847 6.82946C14.6532 5.66558 14.0818 4.59648 13.2426 3.75736C12.4035 2.91825 11.3344 2.3468 10.1705 2.11529C9.00666 1.88378 7.80026 2.0026 6.7039 2.45673C5.60754 2.91085 4.67047 3.67989 4.01118 4.66658C3.35189 5.65328 3 6.81331 3 8V11.1L1.2 9.3L0.5 10L3.5 13L6.5 10L5.8 9.3L4 11.1V8C4 7.0111 4.29324 6.0444 4.84265 5.22215C5.39206 4.39991 6.17295 3.75904 7.08658 3.38061C8.00021 3.00217 9.00555 2.90315 9.97545 3.09608C10.9454 3.289 11.8363 3.76521 12.5355 4.46447C13.2348 5.16373 13.711 6.05465 13.9039 7.02455C14.0969 7.99446 13.9978 8.99979 13.6194 9.91342C13.241 10.8271 12.6001 11.6079 11.7779 12.1574C10.9556 12.7068 9.98891 13 9 13V14Z", fill: "#1A1C21" })));
12
+ exports.ResetIcon = (0, styled_components_1.default)(Icon).attrs(() => ({
13
+ 'data-component-name': 'icons/ResetIcon/ResetIcon',
14
+ })) `
15
+ path {
16
+ fill: ${({ color }) => (0, utils_1.getCssColorVariable)(color)};
17
+ }
18
+
19
+ height: ${({ size }) => size || '16px'};
20
+ width: ${({ size }) => size || '16px'};
21
+ `;
22
+ //# sourceMappingURL=ResetIcon.js.map
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { IconProps } from '../../icons/types';
3
+ export declare const SettingsIcon: import("styled-components").StyledComponent<(props: IconProps) => React.JSX.Element, any, {
4
+ 'data-component-name': string;
5
+ } & {
6
+ color?: string | undefined;
7
+ size?: string | undefined;
8
+ className?: string | undefined;
9
+ } & React.SVGProps<SVGSVGElement>, "data-component-name">;
@@ -0,0 +1,23 @@
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.SettingsIcon = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const styled_components_1 = __importDefault(require("styled-components"));
9
+ const utils_1 = require("../../core/utils");
10
+ const Icon = (props) => (react_1.default.createElement("svg", Object.assign({ viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, props),
11
+ react_1.default.createElement("path", { d: "M15.875 2.5H13.5687C13.2875 1.20625 12.1625 0.25 10.8125 0.25C9.4625 0.25 8.3375 1.20625 8.05625 2.5H0.125V3.625H8.05625C8.3375 4.91875 9.4625 5.875 10.8125 5.875C12.1625 5.875 13.2875 4.91875 13.5687 3.625H15.875V2.5ZM10.8125 4.75C9.85625 4.75 9.125 4.01875 9.125 3.0625C9.125 2.10625 9.85625 1.375 10.8125 1.375C11.7688 1.375 12.5 2.10625 12.5 3.0625C12.5 4.01875 11.7688 4.75 10.8125 4.75Z", fill: "#22242B" }),
12
+ react_1.default.createElement("path", { d: "M0.125 11.5H2.43125C2.7125 12.7937 3.8375 13.75 5.1875 13.75C6.5375 13.75 7.6625 12.7937 7.94375 11.5H15.875V10.375H7.94375C7.6625 9.08125 6.5375 8.125 5.1875 8.125C3.8375 8.125 2.7125 9.08125 2.43125 10.375H0.125V11.5ZM5.1875 9.25C6.14375 9.25 6.875 9.98125 6.875 10.9375C6.875 11.8938 6.14375 12.625 5.1875 12.625C4.23125 12.625 3.5 11.8938 3.5 10.9375C3.5 9.98125 4.23125 9.25 5.1875 9.25Z", fill: "#22242B" })));
13
+ exports.SettingsIcon = (0, styled_components_1.default)(Icon).attrs(() => ({
14
+ 'data-component-name': 'icons/SettingsIcon/SettingsIcon',
15
+ })) `
16
+ path {
17
+ fill: ${({ color }) => (0, utils_1.getCssColorVariable)(color)};
18
+ }
19
+
20
+ height: ${({ size }) => size || '16px'};
21
+ width: ${({ size }) => size || '16px'};
22
+ `;
23
+ //# sourceMappingURL=SettingsIcon.js.map
package/lib/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export * from './components/Badge/Badge';
11
11
  export * from './components/Dropdown/Dropdown';
12
12
  export * from './components/Dropdown/DropdownMenu';
13
13
  export * from './components/Dropdown/DropdownMenuItem';
14
- export * from './components/Loading/Loading';
14
+ export * from './components/Loaders/Loading';
15
15
  export * from './components/Link/Link';
16
16
  export * from './components/Portal/Portal';
17
17
  export * from './components/Segmented/Segmented';
@@ -112,6 +112,11 @@ export * from './components/Search/SearchShortcut';
112
112
  export * from './components/Search/SearchTrigger';
113
113
  export * from './components/Search/SearchRecent';
114
114
  export * from './components/Search/SearchSuggestedPages';
115
+ export * from './components/Search/SearchGroups';
116
+ export * from './components/Search/SearchFilter';
117
+ export * from './components/Search/SearchFilterField';
118
+ export * from './components/Search/FilterFields/SearchFilterFieldSelect';
119
+ export * from './components/Search/FilterFields/SearchFilterFieldTags';
115
120
  export * from './icons/ArrowRightIcon/ArrowRightIcon';
116
121
  export * from './icons/ArrowUpRightIcon/ArrowUpRightIcon';
117
122
  export * from './icons/ArrowLeftIcon/ArrowLeftIcon';
@@ -126,6 +131,7 @@ export * from './icons/FolderAddIcon/FolderAddIcon';
126
131
  export * from './icons/FolderIcon/FolderIcon';
127
132
  export * from './icons/FolderMoveToIcon/FolderMoveToIcon';
128
133
  export * from './icons/SelectIcon/SelectIcon';
134
+ export * from './icons/SettingsIcon/SettingsIcon';
129
135
  export * from './icons/CloseIcon/CloseIcon';
130
136
  export * from './icons/CloseOutlineIcon/CloseOutlineIcon';
131
137
  export * from './icons/CloseFilledIcon/CloseFilledIcon';
@@ -173,6 +179,7 @@ export * from './icons/MobileSidebarIcon/MobileSidebarIcon';
173
179
  export * from './icons/CopyLinkIcon/CopyLinkIcon';
174
180
  export * from './icons/OverflowMenuHorizontalIcon/OverflowMenuHorizontalIcon';
175
181
  export * from './icons/RenewIcon/RenewIcon';
182
+ export * from './icons/ResetIcon/ResetIcon';
176
183
  export * from './icons/WarningAltIcon/WarningAltIcon';
177
184
  export * from './icons/MoonIcon/MoonIcon';
178
185
  export * from './icons/SunIcon/SunIcon';
package/lib/index.js CHANGED
@@ -41,7 +41,7 @@ __exportStar(require("./components/Badge/Badge"), exports);
41
41
  __exportStar(require("./components/Dropdown/Dropdown"), exports);
42
42
  __exportStar(require("./components/Dropdown/DropdownMenu"), exports);
43
43
  __exportStar(require("./components/Dropdown/DropdownMenuItem"), exports);
44
- __exportStar(require("./components/Loading/Loading"), exports);
44
+ __exportStar(require("./components/Loaders/Loading"), exports);
45
45
  __exportStar(require("./components/Link/Link"), exports);
46
46
  __exportStar(require("./components/Portal/Portal"), exports);
47
47
  __exportStar(require("./components/Segmented/Segmented"), exports);
@@ -163,6 +163,11 @@ __exportStar(require("./components/Search/SearchShortcut"), exports);
163
163
  __exportStar(require("./components/Search/SearchTrigger"), exports);
164
164
  __exportStar(require("./components/Search/SearchRecent"), exports);
165
165
  __exportStar(require("./components/Search/SearchSuggestedPages"), exports);
166
+ __exportStar(require("./components/Search/SearchGroups"), exports);
167
+ __exportStar(require("./components/Search/SearchFilter"), exports);
168
+ __exportStar(require("./components/Search/SearchFilterField"), exports);
169
+ __exportStar(require("./components/Search/FilterFields/SearchFilterFieldSelect"), exports);
170
+ __exportStar(require("./components/Search/FilterFields/SearchFilterFieldTags"), exports);
166
171
  /* Icons */
167
172
  __exportStar(require("./icons/ArrowRightIcon/ArrowRightIcon"), exports);
168
173
  __exportStar(require("./icons/ArrowUpRightIcon/ArrowUpRightIcon"), exports);
@@ -178,6 +183,7 @@ __exportStar(require("./icons/FolderAddIcon/FolderAddIcon"), exports);
178
183
  __exportStar(require("./icons/FolderIcon/FolderIcon"), exports);
179
184
  __exportStar(require("./icons/FolderMoveToIcon/FolderMoveToIcon"), exports);
180
185
  __exportStar(require("./icons/SelectIcon/SelectIcon"), exports);
186
+ __exportStar(require("./icons/SettingsIcon/SettingsIcon"), exports);
181
187
  __exportStar(require("./icons/CloseIcon/CloseIcon"), exports);
182
188
  __exportStar(require("./icons/CloseOutlineIcon/CloseOutlineIcon"), exports);
183
189
  __exportStar(require("./icons/CloseFilledIcon/CloseFilledIcon"), exports);
@@ -225,6 +231,7 @@ __exportStar(require("./icons/MobileSidebarIcon/MobileSidebarIcon"), exports);
225
231
  __exportStar(require("./icons/CopyLinkIcon/CopyLinkIcon"), exports);
226
232
  __exportStar(require("./icons/OverflowMenuHorizontalIcon/OverflowMenuHorizontalIcon"), exports);
227
233
  __exportStar(require("./icons/RenewIcon/RenewIcon"), exports);
234
+ __exportStar(require("./icons/ResetIcon/ResetIcon"), exports);
228
235
  __exportStar(require("./icons/WarningAltIcon/WarningAltIcon"), exports);
229
236
  __exportStar(require("./icons/MoonIcon/MoonIcon"), exports);
230
237
  __exportStar(require("./icons/SunIcon/SunIcon"), exports);
@@ -17,10 +17,10 @@ function Card({ title, image, icon, iconRawContent, imagePosition = 'start', lay
17
17
  const alignItems = align === 'center' ? 'center' : align === 'end' ? 'flex-end' : 'flex-start';
18
18
  const textAlign = align === 'center' ? 'center' : align === 'end' ? 'right' : 'left';
19
19
  iconVariant = iconVariant !== null && iconVariant !== void 0 ? iconVariant : (variant === 'ghost' ? 'filled' : 'ghost');
20
- return (react_1.default.createElement(CardWrapper, { as: to ? Link_1.Link : 'div', to: to, "aria-labelledby": cardTitleId, variant: variant, layout: layout, isCardLink: !!to },
20
+ return (react_1.default.createElement(CardWrapper, { as: to ? Link_1.Link : 'div', to: to, "aria-labelledby": cardTitleId, "$variant": variant, "$layout": layout, "$isCardLink": !!to },
21
21
  react_1.default.createElement(react_1.default.Fragment, null,
22
22
  image ? react_1.default.createElement(CardImage_1.CardImage, { src: image, alt: title, position: imagePosition }) : null,
23
- react_1.default.createElement(CardContentWrapper, { layout: layout, alignItems: alignItems, textAlign: textAlign, hasImage: image !== undefined },
23
+ react_1.default.createElement(CardContentWrapper, { "$layout": layout, "$alignItems": alignItems, "$textAlign": textAlign, "$hasImage": image !== undefined },
24
24
  icon && react_1.default.createElement(CardIcon_1.CardIcon, { variant: iconVariant, src: icon, rawContent: iconRawContent }),
25
25
  react_1.default.createElement(ContentWrapper, null,
26
26
  react_1.default.createElement(Title, { id: cardTitleId, "$isCardLink": !!to, "$justifyContent": justifyContent },
@@ -31,13 +31,13 @@ function Card({ title, image, icon, iconRawContent, imagePosition = 'start', lay
31
31
  exports.Card = Card;
32
32
  const CardContentWrapper = styled_components_1.default.div `
33
33
  display: flex;
34
- flex-direction: ${({ layout }) => (layout === 'horizontal' ? 'row' : 'column')};
34
+ flex-direction: ${({ $layout }) => ($layout === 'horizontal' ? 'row' : 'column')};
35
35
  gap: var(--card-icon-gap);
36
- align-items: ${({ alignItems }) => alignItems};
37
- text-align: ${({ textAlign }) => textAlign};
36
+ align-items: ${({ $alignItems }) => $alignItems};
37
+ text-align: ${({ $textAlign }) => $textAlign};
38
38
  flex-grow: 1;
39
39
  padding: var(--card-padding);
40
- height: ${({ hasImage }) => (hasImage ? 'auto' : '100%')};
40
+ height: ${({ $hasImage }) => ($hasImage ? 'auto' : '100%')};
41
41
  `;
42
42
  const ContentWrapper = styled_components_1.default.div `
43
43
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.42.2",
3
+ "version": "0.43.0",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -88,7 +88,7 @@
88
88
  "tsconfig-paths": "4.2.0",
89
89
  "tsconfig-paths-webpack-plugin": "3.5.2",
90
90
  "typescript": "5.2.2",
91
- "webpack": "5.91.0"
91
+ "webpack": "5.94.0"
92
92
  },
93
93
  "dependencies": {
94
94
  "copy-to-clipboard": "^3.3.3",
@@ -99,7 +99,7 @@
99
99
  "timeago.js": "^4.0.2",
100
100
  "i18next": "^22.4.12",
101
101
  "nprogress": "^0.2.0",
102
- "@redocly/config": "0.11.0"
102
+ "@redocly/config": "0.12.0"
103
103
  },
104
104
  "scripts": {
105
105
  "start": "npm-run-all --parallel storybook storybook:tokens:watch",
@@ -7,7 +7,7 @@ import type { DropdownMenuItemProps } from '@redocly/theme/components/Dropdown/D
7
7
  import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
8
8
 
9
9
  export type DropdownMenuProps =
10
- | { className?: string; role?: string } & (
10
+ | { className?: string; role?: string; footer?: React.ReactNode } & (
11
11
  | {
12
12
  items: DropdownMenuItemProps[];
13
13
  }
@@ -37,6 +37,7 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element {
37
37
  role={props.role || 'menu'}
38
38
  >
39
39
  {content}
40
+ {props.footer || null}
40
41
  </DropdownMenuWrapper>
41
42
  );
42
43
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
- import type { FilterProps } from '@redocly/theme/core/types';
4
+ import type { FilterProps, SelectProps, SelectOption } from '@redocly/theme/core/types';
5
5
 
6
6
  import { FilterOption } from '@redocly/theme/components/Filter/FilterOption';
7
7
  import { FilterOptionLabel } from '@redocly/theme/components/Filter/FilterOptionLabel';
@@ -15,7 +15,7 @@ export function FilterSelect({ filter, filterValuesCasing }: FilterProps): JSX.E
15
15
  const { useTranslate } = useThemeHooks();
16
16
  const { translate } = useTranslate();
17
17
 
18
- let selectOptions: { value: string; element: React.ReactNode }[] = [];
18
+ let selectOptions: SelectOption<string>[] = [];
19
19
 
20
20
  const defaultOptionCount = filter.filteredOptions.reduce((acc, option) => acc + option.count, 0);
21
21
 
@@ -64,7 +64,7 @@ const FilterSelectWrapper = styled.div`
64
64
  gap: var(--filter-select-wrapper-gap);
65
65
  `;
66
66
 
67
- const StyledSelect = styled(Select)`
67
+ const StyledSelect = styled(Select)<SelectProps>`
68
68
  --select-list-max-width: var(--filter-select-max-width);
69
69
 
70
70
  min-height: var(--filter-select-min-height);
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ export type LoadingProps = {
5
+ color: string;
6
+ size: string;
7
+ };
8
+
9
+ export function SpinnerLoader({ color, size }: LoadingProps): JSX.Element {
10
+ return <Spinner color={color} size={size} />;
11
+ }
12
+
13
+ const Spinner = styled.div<{ color: string; size: string }>`
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
+ `;
@@ -0,0 +1,135 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { SearchFacet, SearchFacetCount, SearchFilterItem } from '@redocly/theme/core/types';
5
+
6
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
7
+ import { Select } from '@redocly/theme/components/Select/Select';
8
+ import { CounterTag } from '@redocly/theme/components/Tags/CounterTag';
9
+
10
+ type SearchFilterFieldSelectProps = {
11
+ className?: string;
12
+ facet: SearchFacet;
13
+ filter: SearchFilterItem[];
14
+ query: string;
15
+ selectedValues: string[];
16
+ onChange: (value: string | string[]) => void;
17
+ };
18
+
19
+ export function SearchFilterFieldSelect({
20
+ facet,
21
+ filter,
22
+ query,
23
+ selectedValues,
24
+ onChange,
25
+ }: SearchFilterFieldSelectProps) {
26
+ const MAX_SELECT_OPTIONS = 20;
27
+ const { useFacetQuery, useTranslate } = useThemeHooks();
28
+ const { translate } = useTranslate();
29
+ const { searchFacet, setSearchFacet, setSearchFacetQuery } = useFacetQuery(facet.field);
30
+ const [selectOptions, setSelectOptions] = useState<any[]>([]);
31
+ const isMultiple = facet.type === 'multi-select';
32
+
33
+ useEffect(() => {
34
+ setSelectOptions(getSelectOptions());
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ }, [searchFacet, facet]);
37
+
38
+ const onSearch = (value: string | null) => {
39
+ if (value === null) {
40
+ setSearchFacet(null);
41
+ setSearchFacetQuery(null);
42
+ } else if (typeof value === 'string') {
43
+ setSearchFacetQuery({
44
+ query,
45
+ filter,
46
+ facetQuery: value,
47
+ });
48
+ }
49
+ };
50
+
51
+ const getSelectOptions = () => {
52
+ return searchFacet
53
+ ? searchFacet.values.map(facetValueToSelectOption)
54
+ : facet.values.map(facetValueToSelectOption);
55
+ };
56
+
57
+ const facetValueToSelectOption = (facetValue?: SearchFacetCount | string) => {
58
+ if (!facetValue) {
59
+ return { element: null, value: '' };
60
+ }
61
+ if (typeof facetValue === 'string') {
62
+ return {
63
+ element: (
64
+ <FilterSelectOptionWrapper>
65
+ <FilterSelectOptionText>{facetValue}</FilterSelectOptionText>
66
+ </FilterSelectOptionWrapper>
67
+ ),
68
+ value: facetValue,
69
+ };
70
+ } else {
71
+ const { value, count, isCounterVisible } = facetValue as SearchFacetCount;
72
+ return {
73
+ element: (
74
+ <FilterSelectOptionWrapper>
75
+ <FilterSelectOptionText>{value}</FilterSelectOptionText>
76
+ {isCounterVisible && <CounterTag>{count}</CounterTag>}
77
+ </FilterSelectOptionWrapper>
78
+ ),
79
+ value: value,
80
+ };
81
+ }
82
+ };
83
+
84
+ return (
85
+ <Select
86
+ value={
87
+ selectedValues.length
88
+ ? isMultiple
89
+ ? selectedValues.map((value) => facetValueToSelectOption(value))
90
+ : facetValueToSelectOption(selectedValues[0])
91
+ : undefined
92
+ }
93
+ options={selectOptions}
94
+ onChange={onChange}
95
+ placeholder={`${translate(
96
+ 'theme.search.filter.field.placeholder',
97
+ 'Search',
98
+ )} ${facet.name.toLowerCase()}...`}
99
+ alignment="start"
100
+ multiple={isMultiple}
101
+ searchable={true}
102
+ footer={
103
+ selectOptions.length === MAX_SELECT_OPTIONS ? (
104
+ <FilterSelectFooter>Search to show more items...</FilterSelectFooter>
105
+ ) : null
106
+ }
107
+ onSearch={onSearch}
108
+ checkmarkIconPosition="start"
109
+ />
110
+ );
111
+ }
112
+
113
+ const FilterSelectOptionWrapper = styled.div`
114
+ width: 100%;
115
+ display: flex;
116
+ justify-content: space-between;
117
+ align-items: center;
118
+ gap: var(--search-filter-field-select-option-gap);
119
+ `;
120
+
121
+ const FilterSelectOptionText = styled.span`
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ white-space: nowrap;
125
+ width: 100%;
126
+ padding: var(--search-filter-field-select-option-text-padding);
127
+ `;
128
+
129
+ const FilterSelectFooter = styled.div`
130
+ display: flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ padding: var(--search-filter-field-select-footer-padding);
134
+ color: var(--search-filter-field-select-footer-text-color);
135
+ `;
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { SearchFacet, SearchFacetCount } from '@redocly/theme/core/types';
5
+
6
+ import { Tag, type TagProps } from '@redocly/theme/components/Tag/Tag';
7
+
8
+ type SearchFilterFieldTagsProps = {
9
+ className?: string;
10
+ facet: SearchFacet;
11
+ selectedValues: string[];
12
+ onChange: (value: string | string[]) => void;
13
+ };
14
+
15
+ export function SearchFilterFieldTags({
16
+ className,
17
+ facet,
18
+ selectedValues,
19
+ onChange,
20
+ }: SearchFilterFieldTagsProps) {
21
+ return (
22
+ <FilterTagsWrapper
23
+ data-component-name="Search/FilterFields/SearchFilterFieldTags"
24
+ className={className}
25
+ >
26
+ {facet.values.map((facetCount, index) => {
27
+ const { value, count, isCounterVisible } = facetCount as SearchFacetCount;
28
+ const active = selectedValues.includes(value);
29
+ return (
30
+ <FilterTagWrapper
31
+ key={`${count}-${index}`}
32
+ color={value}
33
+ onClick={() => {
34
+ const values = active
35
+ ? selectedValues.filter((item) => item !== value)
36
+ : [...selectedValues, value];
37
+ onChange(values);
38
+ }}
39
+ active={active}
40
+ borderless
41
+ >
42
+ {value} {isCounterVisible && <span>{count}</span>}
43
+ </FilterTagWrapper>
44
+ );
45
+ })}
46
+ </FilterTagsWrapper>
47
+ );
48
+ }
49
+
50
+ const FilterTagsWrapper = styled.div`
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: var(--search-filter-field-tags-gap);
54
+ `;
55
+
56
+ const FilterTagWrapper = styled(Tag)<{ color: TagProps['color'] }>`
57
+ text-transform: uppercase;
58
+ cursor: pointer;
59
+ ${({ color }) => color && `background-color: var(--tag-operation-bg-color-${color});`}
60
+ margin: var(--search-filter-field-tags-tag-margin);
61
+ `;
@@ -3,14 +3,14 @@ import styled from 'styled-components';
3
3
 
4
4
  import { SearchTrigger } from '@redocly/theme/components/Search/SearchTrigger';
5
5
  import { SearchDialog } from '@redocly/theme/components/Search/SearchDialog';
6
- import { useSearch } from '@redocly/theme/core/hooks';
6
+ import { useSearchDialog } from '@redocly/theme/core/hooks';
7
7
 
8
8
  export type SearchProps = {
9
9
  className?: string;
10
10
  };
11
11
 
12
12
  export function Search({ className }: SearchProps): JSX.Element {
13
- const { isOpen, onOpen, onClose } = useSearch();
13
+ const { isOpen, onOpen, onClose } = useSearchDialog();
14
14
 
15
15
  return (
16
16
  <SearchWrapper data-component-name="Search/Search" className={className}>