@redocly/theme 0.56.0-next.6 → 0.56.0-next.8

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 (50) hide show
  1. package/lib/components/Breadcrumbs/Breadcrumbs.js +1 -1
  2. package/lib/components/Button/Button.js +1 -0
  3. package/lib/components/Catalog/CatalogCardView/CatalogCard.js +5 -2
  4. package/lib/components/Catalog/CatalogEntity/CatalogEntityInfoBar.d.ts +2 -1
  5. package/lib/components/Catalog/CatalogEntity/CatalogEntityInfoBar.js +6 -2
  6. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +18 -1
  7. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.js +1 -1
  8. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/GitProperty.js +1 -1
  9. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.js +1 -0
  10. package/lib/components/Catalog/CatalogEntityTypeTag.js +3 -1
  11. package/lib/components/Catalog/CatalogTableView/CatalogDomainsCell.js +1 -0
  12. package/lib/components/Catalog/CatalogTableView/CatalogOwnersCell.js +1 -0
  13. package/lib/components/Catalog/CatalogTableView/CatalogTableHeaderCell.js +1 -5
  14. package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.js +7 -7
  15. package/lib/components/Catalog/CatalogTableView/CatalogTagsCell.js +1 -0
  16. package/lib/components/Catalog/CatalogTagsWithTooltip.js +1 -1
  17. package/lib/components/Catalog/variables.js +8 -3
  18. package/lib/components/CodeBlock/CodeBlock.js +1 -0
  19. package/lib/components/CodeBlock/CodeBlockControls.js +25 -4
  20. package/lib/components/Feedback/Feedback.js +1 -1
  21. package/lib/components/Filter/FilterCheckboxes.js +3 -2
  22. package/lib/components/Image/Image.js +2 -0
  23. package/lib/components/Search/SearchDialog.js +2 -2
  24. package/lib/core/types/catalog.d.ts +4 -0
  25. package/lib/core/types/telemetry.d.ts +5 -20
  26. package/package.json +1 -1
  27. package/src/components/Breadcrumbs/Breadcrumbs.tsx +1 -1
  28. package/src/components/Button/Button.tsx +1 -0
  29. package/src/components/Catalog/CatalogCardView/CatalogCard.tsx +5 -2
  30. package/src/components/Catalog/CatalogEntity/CatalogEntityInfoBar.tsx +8 -2
  31. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +38 -2
  32. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.tsx +5 -1
  33. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/GitProperty.tsx +1 -1
  34. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.tsx +1 -0
  35. package/src/components/Catalog/CatalogEntityTypeTag.tsx +4 -1
  36. package/src/components/Catalog/CatalogTableView/CatalogDomainsCell.tsx +1 -0
  37. package/src/components/Catalog/CatalogTableView/CatalogOwnersCell.tsx +1 -0
  38. package/src/components/Catalog/CatalogTableView/CatalogTableHeaderCell.tsx +1 -6
  39. package/src/components/Catalog/CatalogTableView/CatalogTableViewRow.tsx +12 -11
  40. package/src/components/Catalog/CatalogTableView/CatalogTagsCell.tsx +1 -0
  41. package/src/components/Catalog/CatalogTagsWithTooltip.tsx +6 -1
  42. package/src/components/Catalog/variables.ts +8 -3
  43. package/src/components/CodeBlock/CodeBlock.tsx +1 -0
  44. package/src/components/CodeBlock/CodeBlockControls.tsx +33 -5
  45. package/src/components/Feedback/Feedback.tsx +1 -1
  46. package/src/components/Filter/FilterCheckboxes.tsx +7 -2
  47. package/src/components/Image/Image.tsx +2 -0
  48. package/src/components/Search/SearchDialog.tsx +2 -2
  49. package/src/core/types/catalog.ts +4 -0
  50. package/src/core/types/telemetry.ts +5 -13
@@ -25,7 +25,7 @@ function Breadcrumbs(props) {
25
25
  payload: {
26
26
  link: breadcrumb.link,
27
27
  position: idx + 1,
28
- total_breadcrumbs: breadcrumbs.length,
28
+ totalBreadcrumbs: breadcrumbs.length,
29
29
  },
30
30
  });
31
31
  } }),
@@ -82,6 +82,7 @@ const StyledButton = styled_components_1.default.button.attrs((props) => ({
82
82
  background-color: var(--button-bg-color);
83
83
  border: var(--button-border-width) var(--button-border-style) var(--button-border-color);
84
84
  box-shadow: var(--button-box-shadow);
85
+ backdrop-filter: var(--button-backdrop-filter, none);
85
86
 
86
87
  font-weight: var(--button-font-weight);
87
88
  font-size: var(--button-font-size);
@@ -42,6 +42,7 @@ function CatalogCard({ entity, catalogConfig }) {
42
42
  backgroundColor: 'var(--catalog-card-icon-bg-color)',
43
43
  },
44
44
  icon: react_1.default.createElement(GraphIcon_1.GraphIcon, { color: "var(--color-green-8)" }),
45
+ textTransform: 'none',
45
46
  } })),
46
47
  react_1.default.createElement(MetadataColumn, null,
47
48
  react_1.default.createElement(MetadataLabel, null, "Owners:"),
@@ -51,6 +52,7 @@ function CatalogCard({ entity, catalogConfig }) {
51
52
  backgroundColor: 'var(--catalog-card-icon-bg-color)',
52
53
  borderRadius: 'var(--border-radius-xl)',
53
54
  },
55
+ textTransform: 'none',
54
56
  } })))),
55
57
  react_1.default.createElement(Divider, null),
56
58
  react_1.default.createElement(CardFooter, null,
@@ -61,6 +63,7 @@ function CatalogCard({ entity, catalogConfig }) {
61
63
  },
62
64
  borderless: true,
63
65
  color: 'grey',
66
+ textTransform: 'none',
64
67
  }, itemsToShow: 3 }),
65
68
  react_1.default.createElement(ArrowCircle, null,
66
69
  react_1.default.createElement(ArrowRightIcon_1.ArrowRightIcon, { size: "16px" }),
@@ -120,6 +123,7 @@ const CardContent = styled_components_1.default.div `
120
123
  padding: var(--catalog-card-padding-vertical) var(--catalog-card-padding-horizontal);
121
124
  `;
122
125
  const CardFooter = styled_components_1.default.div `
126
+ height: var(--catalog-card-footer-height);
123
127
  display: flex;
124
128
  align-items: center;
125
129
  justify-content: space-between;
@@ -131,8 +135,7 @@ const Divider = styled_components_1.default.div `
131
135
  background-color: var(--catalog-card-divider-color);
132
136
  `;
133
137
  const CatalogCardWrapper = styled_components_1.default.div `
134
- min-height: var(--catalog-card-min-height);
135
- height: 100%;
138
+ height: var(--catalog-card-height);
136
139
  color: var(--catalog-card-text-color);
137
140
  font-size: var(--catalog-card-font-size);
138
141
  font-weight: var(--catalog-card-font-weight);
@@ -4,5 +4,6 @@ export type CatalogEntityInfoBarProps = {
4
4
  rightContent?: ReactNode;
5
5
  withSeparator?: boolean;
6
6
  hoverEffect?: boolean;
7
+ isCodeBlock?: boolean;
7
8
  };
8
- export declare function CatalogEntityInfoBar({ leftContent, rightContent, withSeparator, hoverEffect, }: CatalogEntityInfoBarProps): JSX.Element;
9
+ export declare function CatalogEntityInfoBar({ leftContent, rightContent, withSeparator, hoverEffect, isCodeBlock, }: CatalogEntityInfoBarProps): JSX.Element;
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CatalogEntityInfoBar = CatalogEntityInfoBar;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const styled_components_1 = __importDefault(require("styled-components"));
9
- function CatalogEntityInfoBar({ leftContent, rightContent, withSeparator = true, hoverEffect = true, }) {
9
+ function CatalogEntityInfoBar({ leftContent, rightContent, withSeparator = true, hoverEffect = true, isCodeBlock = false, }) {
10
10
  return (react_1.default.createElement(InfoBarWrapper, { "data-component-name": "Catalog/CatalogEntity/CatalogEntityInfoBar", hoverEffect: hoverEffect },
11
11
  react_1.default.createElement(LeftColumn, { withSeparator: withSeparator }, leftContent),
12
- rightContent && react_1.default.createElement(RightColumn, null, rightContent)));
12
+ rightContent && react_1.default.createElement(RightColumn, { isCodeBlock: isCodeBlock }, rightContent)));
13
13
  }
14
14
  const InfoBarWrapper = styled_components_1.default.div `
15
15
  display: grid;
@@ -42,6 +42,9 @@ const LeftColumn = styled_components_1.default.div `
42
42
  justify-self: start;
43
43
  text-align: left;
44
44
  border-right: ${({ withSeparator }) => withSeparator ? '1px solid var(--border-color-primary)' : 'none'};
45
+ height: 100%;
46
+ display: flex;
47
+ align-items: center;
45
48
  `;
46
49
  const RightColumn = styled_components_1.default.div `
47
50
  color: var(--catalog-metadata-value-color);
@@ -49,5 +52,6 @@ const RightColumn = styled_components_1.default.div `
49
52
  grid-area: right;
50
53
  justify-self: end;
51
54
  text-align: right;
55
+ width: ${({ isCodeBlock }) => (isCodeBlock ? '100%' : 'auto')};
52
56
  `;
53
57
  //# sourceMappingURL=CatalogEntityInfoBar.js.map
@@ -41,10 +41,20 @@ exports.CatalogEntityMetadata = CatalogEntityMetadata;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const styled_components_1 = __importDefault(require("styled-components"));
43
43
  const ChevronDownIcon_1 = require("../../../icons/ChevronDownIcon/ChevronDownIcon");
44
+ const JsonViewer_1 = require("../../../components/JsonViewer/JsonViewer");
44
45
  const utils_1 = require("../../../core/utils");
45
46
  const hooks_1 = require("../../../core/hooks");
46
47
  const CatalogEntityInfoBar_1 = require("../../../components/Catalog/CatalogEntity/CatalogEntityInfoBar");
47
48
  const MAX_INITIAL_ITEMS = 4;
49
+ function renderMetadataValue(value) {
50
+ if ((0, utils_1.isPlainObject)(value)) {
51
+ return react_1.default.createElement(JsonViewerWrapper, { data: value, expandLevel: 3, hideHeader: true });
52
+ }
53
+ if (Array.isArray(value)) {
54
+ return (react_1.default.createElement(ArrayWrapper, null, value.map((item, index) => (react_1.default.createElement("div", { key: index }, (0, utils_1.isPlainObject)(item) ? (react_1.default.createElement(JsonViewerWrapper, { data: item, expandLevel: 3, hideHeader: true })) : (react_1.default.createElement("span", null, String(item))))))));
55
+ }
56
+ return react_1.default.createElement("span", null, String(value));
57
+ }
48
58
  function CatalogEntityMetadata({ entity }) {
49
59
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
50
60
  const { translate } = useTranslate();
@@ -60,12 +70,15 @@ function CatalogEntityMetadata({ entity }) {
60
70
  react_1.default.createElement(Heading, null, translate('catalog.entity.metadata.title')),
61
71
  visibleMetadata.map(([key, value]) => (react_1.default.createElement(CatalogEntityInfoBar_1.CatalogEntityInfoBar, { key: key, leftContent: react_1.default.createElement(Label, null,
62
72
  (0, utils_1.capitalize)(key),
63
- ":"), rightContent: react_1.default.createElement(Value, null, value), hoverEffect: false }))),
73
+ ":"), rightContent: react_1.default.createElement(Value, null, renderMetadataValue(value)), hoverEffect: false, isCodeBlock: (0, utils_1.isPlainObject)(value) || Array.isArray(value) }))),
64
74
  hasMoreItems && (react_1.default.createElement(ShowMoreButton, { onClick: () => setIsOn(!isOn) },
65
75
  isOn ? 'Show less' : 'Show more',
66
76
  " ",
67
77
  react_1.default.createElement(ChevronIcon, { "$isExpanded": isOn })))));
68
78
  }
79
+ const JsonViewerWrapper = (0, styled_components_1.default)(JsonViewer_1.JsonViewer) `
80
+ text-align: left;
81
+ `;
69
82
  const MetadataWrapper = styled_components_1.default.div `
70
83
  display: flex;
71
84
  flex-direction: column;
@@ -83,6 +96,10 @@ const Value = styled_components_1.default.span `
83
96
  color: var(--catalog-metadata-value-color);
84
97
  font-weight: var(--font-weight-medium);
85
98
  `;
99
+ const ArrayWrapper = styled_components_1.default.div `
100
+ display: flex;
101
+ flex-direction: column;
102
+ `;
86
103
  const Heading = styled_components_1.default.h2 `
87
104
  margin-bottom: var(--spacing-base);
88
105
  margin-top: 0;
@@ -14,6 +14,6 @@ function ContactProperty({ entity }) {
14
14
  return (react_1.default.createElement("div", { "data-component-name": "Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty" },
15
15
  react_1.default.createElement(CatalogEntityPropertyCard_1.CatalogEntityPropertyCard, { header: react_1.default.createElement(react_1.default.Fragment, null,
16
16
  react_1.default.createElement(SlackIcon_1.SlackIcon, null),
17
- "Slack channels"), content: react_1.default.createElement(react_1.default.Fragment, null, channels === null || channels === void 0 ? void 0 : channels.map((channel) => (react_1.default.createElement(Tag_1.Tag, { key: channel.name, style: { backgroundColor: 'var(--bg-color)' } }, channel.name)))) })));
17
+ "Slack channels"), content: react_1.default.createElement(react_1.default.Fragment, null, channels === null || channels === void 0 ? void 0 : channels.map((channel) => (react_1.default.createElement(Tag_1.Tag, { key: channel.name, textTransform: "none", style: { backgroundColor: 'var(--bg-color)' } }, channel.name)))) })));
18
18
  }
19
19
  //# sourceMappingURL=ContactProperty.js.map
@@ -17,7 +17,7 @@ function GitProperty({ entity }) {
17
17
  "Repositories"), content: react_1.default.createElement(react_1.default.Fragment, null, git === null || git === void 0 ? void 0 : git.map((repo) => {
18
18
  const url = new URL(repo);
19
19
  const repoName = (0, utils_1.removeLeadingSlash)(url.pathname);
20
- return (react_1.default.createElement(Tag_1.Tag, { key: repo, style: { backgroundColor: 'var(--bg-color)' } }, repoName));
20
+ return (react_1.default.createElement(Tag_1.Tag, { key: repo, textTransform: "none", style: { backgroundColor: 'var(--bg-color)' } }, repoName));
21
21
  })) })));
22
22
  }
23
23
  //# sourceMappingURL=GitProperty.js.map
@@ -19,6 +19,7 @@ function TagsProperty({ entity }) {
19
19
  },
20
20
  borderless: true,
21
21
  color: 'grey',
22
+ textTransform: 'none',
22
23
  } }), hoverEffect: false })));
23
24
  }
24
25
  //# sourceMappingURL=TagsProperty.js.map
@@ -8,6 +8,7 @@ exports.CatalogEntityTypeTag = CatalogEntityTypeTag;
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const styled_components_1 = __importDefault(require("styled-components"));
10
10
  const Tag_1 = require("../../components/Tag/Tag");
11
+ const CatalogHighlight_1 = require("../../components/Catalog/CatalogHighlight");
11
12
  const entityTagColorMap = {
12
13
  service: 'blue',
13
14
  domain: 'grass',
@@ -26,7 +27,8 @@ const getEntityTagColor = (type) => {
26
27
  };
27
28
  exports.getEntityTagColor = getEntityTagColor;
28
29
  function CatalogEntityTypeTag({ entityType }) {
29
- return (react_1.default.createElement(EntityTypeTagWrapper, { entityType: entityType }, entityType));
30
+ return (react_1.default.createElement(EntityTypeTagWrapper, { entityType: entityType },
31
+ react_1.default.createElement(CatalogHighlight_1.CatalogHighlight, null, entityType)));
30
32
  }
31
33
  const EntityTypeTagWrapper = (0, styled_components_1.default)(Tag_1.Tag) `
32
34
  font-size: var(--font-size-base);
@@ -14,6 +14,7 @@ function CatalogDomainsCell({ domains }) {
14
14
  backgroundColor: 'transparent',
15
15
  borderRadius: 'var(--border-radius-xl)',
16
16
  },
17
+ textTransform: 'none',
17
18
  } })));
18
19
  }
19
20
  //# sourceMappingURL=CatalogDomainsCell.js.map
@@ -14,6 +14,7 @@ function CatalogOwnersCell({ owners }) {
14
14
  backgroundColor: 'transparent',
15
15
  borderRadius: 'var(--border-radius-xl)',
16
16
  },
17
+ textTransform: 'none',
17
18
  } })));
18
19
  }
19
20
  //# sourceMappingURL=CatalogOwnersCell.js.map
@@ -41,7 +41,7 @@ const CatalogTableHeaderCell = ({ column, handleSortClick, isColumnSorted, setSo
41
41
  });
42
42
  return (react_1.default.createElement(TableHeaderCellWrapper, { key: column.key, "data-component-name": "Catalog/CatalogTableView/CatalogTableHeaderCell", onClick: handleCellClick, "$sortable": Boolean(column.sortable && sortKey) },
43
43
  react_1.default.createElement(HeaderContent, null,
44
- react_1.default.createElement(HeaderTitle, null, column.title),
44
+ react_1.default.createElement("span", null, column.title),
45
45
  column.sortable && sortKey && (react_1.default.createElement(SortIndicator, null,
46
46
  react_1.default.createElement(SortArrow, { "$isActive": isUpActive },
47
47
  react_1.default.createElement(CaretUpIcon_1.CaretUpIcon, { size: "9px", color: isUpActive
@@ -65,12 +65,8 @@ const TableHeaderCellWrapper = styled_components_1.default.div `
65
65
  const HeaderContent = styled_components_1.default.div `
66
66
  display: flex;
67
67
  align-items: center;
68
- justify-content: space-between;
69
68
  width: 100%;
70
69
  `;
71
- const HeaderTitle = styled_components_1.default.span `
72
- flex: 1;
73
- `;
74
70
  const SortIndicator = styled_components_1.default.div `
75
71
  display: flex;
76
72
  flex-direction: column;
@@ -12,6 +12,7 @@ const CatalogEntityCell_1 = require("../../../components/Catalog/CatalogTableVie
12
12
  const CatalogTagsCell_1 = require("../../../components/Catalog/CatalogTableView/CatalogTagsCell");
13
13
  const useCatalogTableViewRow_1 = require("../../../core/hooks/catalog/useCatalogTableViewRow");
14
14
  const CatalogEntityTypeTag_1 = require("../../../components/Catalog/CatalogEntityTypeTag");
15
+ const Link_1 = require("../../Link/Link");
15
16
  const baseColumns = [
16
17
  {
17
18
  key: 'entity',
@@ -66,16 +67,15 @@ const CatalogTableViewRow = ({ entity, entitiesCatalogConfig, catalogConfig, col
66
67
  catalogConfig,
67
68
  entitiesCatalogConfig,
68
69
  });
69
- const handleRowClick = () => {
70
- window.location.assign(getEntityDetailsLink());
71
- };
72
- return (react_1.default.createElement(TableRow, { key: entity.id, columnsWidths: columns.map((column) => column.width || '1fr'), columnsMinWidths: columns.map((column) => column.minWidth || 'auto'), onClick: () => handleRowClick() }, columns.map((column) => (react_1.default.createElement(TableCell, { key: column.key, className: column.key === 'entity' ? '' : 'tooltip-cell-container' }, column.render(entity))))));
70
+ return (react_1.default.createElement(TableRow, { key: entity.id, "$columnsWidths": columns.map((column) => column.width || '1fr'), "$columnsMinWidths": columns.map((column) => column.minWidth || 'auto'), to: getEntityDetailsLink(), style: { color: 'var(--catalog-page-wrapper-text-color)' } }, columns.map((column) => (react_1.default.createElement(TableCell, { key: column.key, className: column.key === 'entity' ? '' : 'tooltip-cell-container' }, column.render(entity))))));
73
71
  };
74
72
  exports.CatalogTableViewRow = CatalogTableViewRow;
75
- const TableRow = styled_components_1.default.div `
73
+ const TableRow = (0, styled_components_1.default)(Link_1.Link) `
76
74
  display: grid;
77
- grid-template-columns: ${({ columnsWidths, columnsMinWidths }) => columnsWidths
78
- .map((width, index) => columnsMinWidths[index] !== 'auto' ? `minmax(${columnsMinWidths[index]}, ${width})` : width)
75
+ grid-template-columns: ${({ $columnsWidths, $columnsMinWidths }) => $columnsWidths
76
+ .map((width, index) => $columnsMinWidths[index] !== 'auto'
77
+ ? `minmax(${$columnsMinWidths[index]}, ${width})`
78
+ : width)
79
79
  .join(' ')};
80
80
  border-bottom: 1px solid var(--catalog-table-border-color);
81
81
  cursor: pointer;
@@ -15,6 +15,7 @@ function CatalogTagsCell({ entity }) {
15
15
  },
16
16
  borderless: true,
17
17
  color: 'grey',
18
+ textTransform: 'none',
18
19
  } })));
19
20
  }
20
21
  //# sourceMappingURL=CatalogTagsCell.js.map
@@ -26,7 +26,7 @@ function CatalogTagsWithTooltip({ items, itemsToShow = 1, showPlaceholder = true
26
26
  const remainingCount = items.length - itemsToShow;
27
27
  return (react_1.default.createElement(Tooltip_1.TooltipComponent, { tip: items.join(', '), placement: "bottom", className: "catalog", width: "400px" },
28
28
  react_1.default.createElement(CatalogTagsWrapper, { "data-component-name": "Catalog/CatalogTagsWithTooltip" },
29
- displayedItems.map((item, index) => (react_1.default.createElement(Tag_1.Tag, Object.assign({ key: `${item}-${index}` }, tagProps, { maxLength: constants_1.CATALOG_TAG_MAX_LENGTH }),
29
+ displayedItems.map((item, index) => (react_1.default.createElement(Tag_1.Tag, Object.assign({ key: `${item}-${index}` }, tagProps, { textTransform: "none", maxLength: constants_1.CATALOG_TAG_MAX_LENGTH }),
30
30
  react_1.default.createElement(CatalogHighlight_1.CatalogHighlight, null, item)))),
31
31
  react_1.default.createElement(MoreTagsButton, null,
32
32
  "+",
@@ -193,9 +193,9 @@ exports.catalog = (0, styled_components_1.css) `
193
193
  /**
194
194
  * @tokens Catalog card
195
195
  */
196
- --catalog-card-min-height: 194px;
197
- --catalog-card-min-width: 490px;
198
- --catalog-card-padding-vertical: var(--spacing-base);
196
+ --catalog-card-height: 241px;
197
+ --catalog-card-min-width: 400px;
198
+ --catalog-card-padding-vertical: var(--spacing-md);
199
199
  --catalog-card-padding-horizontal: var(--spacing-md);
200
200
  --catalog-card-gap: var(--spacing-sm);
201
201
  --catalog-card-text-color: var(--text-color-secondary);
@@ -251,6 +251,11 @@ exports.catalog = (0, styled_components_1.css) `
251
251
  --catalog-card-title-line-height: var(--line-height-lg);
252
252
  --catalog-card-title-line-clamp: 2;
253
253
 
254
+ /**
255
+ * @tokens Catalog card footer
256
+ */
257
+ --catalog-card-footer-height: 72px;
258
+
254
259
  /**
255
260
  * @tokens Catalog card description
256
261
  */
@@ -88,6 +88,7 @@ function CodeBlock(_a) {
88
88
  }
89
89
  const ContainerWrapper = styled_components_1.default.div `
90
90
  display: grid; // prevents content to overstretch
91
+ position: relative;
91
92
  `;
92
93
  const CodeBlockWrapper = styled_components_1.default.div `
93
94
  border: 1px solid var(--border-color-secondary);
@@ -30,6 +30,7 @@ function CodeBlockControls({ children, className, title, controls, tabs, }) {
30
30
  deselect: null,
31
31
  report: null,
32
32
  };
33
+ const isEmptyTitle = !title && !tabs;
33
34
  const defaultControls = controls ? (react_1.default.createElement(react_1.default.Fragment, null,
34
35
  title && react_1.default.createElement(Title, null, title),
35
36
  tabs && react_1.default.createElement(CodeBlockTabs_1.CodeBlockTabs, { tabs: tabs }),
@@ -41,7 +42,7 @@ function CodeBlockControls({ children, className, title, controls, tabs, }) {
41
42
  select ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "select-all", icon: controlsType === 'icon' ? react_1.default.createElement(SelectIcon_1.SelectIcon, null) : undefined, onClick: select === null || select === void 0 ? void 0 : select.onClick }, controlsType !== 'icon' && (select === null || select === void 0 ? void 0 : select.label) ? select.label : 'Select all')) : null,
42
43
  deselect ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "clear-all", icon: controlsType === 'icon' ? react_1.default.createElement(DeselectIcon_1.DeselectIcon, null) : undefined, onClick: deselect === null || deselect === void 0 ? void 0 : deselect.onClick }, controlsType !== 'icon' && (deselect === null || deselect === void 0 ? void 0 : deselect.label) ? deselect.label : 'Clear all')) : null,
43
44
  copy && !((_e = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.copy) === null || _e === void 0 ? void 0 : _e.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tooltipTranslationKey: "codeSnippet.copy.tooltipText", placement: "top" },
44
- react_1.default.createElement(CopyButton_1.CopyButton, { data: copy.data, "data-source": copy.dataSource, "data-hash": copy.dataHash, type: controlsType, toasterPlacement: copy.toasterPlacement, toasterDuration: copy.toasterDuration, buttonText: copy.label, onCopyClick: () => {
45
+ react_1.default.createElement(StyledCopyButton, { data: copy.data, "data-source": copy.dataSource, "data-hash": copy.dataHash, type: controlsType, toasterPlacement: copy.toasterPlacement, toasterDuration: copy.toasterDuration, buttonText: copy.label, onCopyClick: () => {
45
46
  var _a;
46
47
  // If there already is a click handler, events should be handled there, cause they pass additional data
47
48
  if (copy === null || copy === void 0 ? void 0 : copy.onClick) {
@@ -50,15 +51,16 @@ function CodeBlockControls({ children, className, title, controls, tabs, }) {
50
51
  else {
51
52
  telemetry.send({
52
53
  type: 'openapi_docs.copy_code_snippet.clicked',
53
- payload: { snippet_type: 'copy' },
54
+ payload: { snippetType: 'copy' },
54
55
  });
55
56
  }
56
57
  } }))) : null))) : null;
57
- return children || controls ? (react_1.default.createElement(ContainerWrapper, { "data-component-name": "CodeBlock/CodeBlockControls", className: className }, children ? children : defaultControls)) : null;
58
+ return children || controls ? (react_1.default.createElement(ContainerWrapper, { "data-component-name": "CodeBlock/CodeBlockControls", className: className, "$isEmptyTitle": isEmptyTitle }, children ? children : defaultControls)) : null;
58
59
  }
59
60
  const ContainerWrapper = styled_components_1.default.div `
60
61
  display: grid;
61
62
  justify-content: end;
63
+ gap: var(--spacing-sm);
62
64
  font-size: var(--code-block-controls-font-size);
63
65
  font-family: var(--code-block-controls-font-family);
64
66
  background-color: var(--code-block-controls-bg-color);
@@ -67,6 +69,17 @@ const ContainerWrapper = styled_components_1.default.div `
67
69
  line-height: var(--line-height-lg);
68
70
  min-height: var(--control-height-base);
69
71
  grid-template-columns: 1fr auto;
72
+ ${({ $isEmptyTitle }) => $isEmptyTitle &&
73
+ `
74
+ grid-template-columns: 1fr;
75
+ padding-left: var(--spacing-xxs);
76
+ position: absolute;
77
+ right: 0;
78
+ width: auto;
79
+ border: none;
80
+ background-color: transparent;
81
+ margin: 0;
82
+ `}
70
83
  `;
71
84
  const Title = styled_components_1.default.span `
72
85
  display: flex;
@@ -81,11 +94,19 @@ const ControlsWrapper = styled_components_1.default.div `
81
94
  align-items: center;
82
95
  gap: var(--spacing-xxs);
83
96
  justify-content: end;
84
- margin-left: var(--spacing-sm);
85
97
  `;
86
98
  const ControlButton = (0, styled_components_1.default)(Button_1.Button) `
99
+ --button-icon-size: 16px; /* increase icon size for code blocks */
100
+ --button-icon-padding: 3px;
101
+ --button-backdrop-filter: blur(8px); /* backdrop filter when there is text under the button */
102
+
87
103
  & + & {
88
104
  margin-left: 0;
89
105
  }
90
106
  `;
107
+ const StyledCopyButton = (0, styled_components_1.default)(CopyButton_1.CopyButton) `
108
+ --button-icon-size: 16px; /* increase icon size for code blocks */
109
+ --button-icon-padding: 3px;
110
+ --button-backdrop-filter: blur(8px);
111
+ `;
91
112
  //# sourceMappingURL=CodeBlockControls.js.map
@@ -64,7 +64,7 @@ function Feedback(props) {
64
64
  return (React.createElement(FeedbackWrapper, { "data-component-name": "Feedback/Feedback" },
65
65
  React.createElement(FeedbackComponent, { settings: settings, onSubmit: (values) => {
66
66
  submitFeedback({ type, values, path });
67
- telemetry.send({ type: 'feedback.sent', payload: { feedback_type: type } });
67
+ telemetry.send({ type: 'feedback.sent', payload: { feedbackType: type } });
68
68
  } })));
69
69
  };
70
70
  return React.createElement(React.Fragment, { key: pathname }, renderFeedbackComponent());
@@ -20,13 +20,14 @@ function FilterCheckboxes({ filter, filterValuesCasing, showCounter = true, }) {
20
20
  const telemetry = useTelemetry();
21
21
  return (react_1.default.createElement(FilterCheckboxesWrapper, { "data-component-name": "Filter/FilterCheckboxes" },
22
22
  react_1.default.createElement(FilterTitle_1.FilterTitle, { "data-translation-key": filter.titleTranslationKey }, translate(filter.titleTranslationKey, filter.title)),
23
- react_1.default.createElement(FilterOptions_1.FilterOptions, null, filter.options.map(({ value, count }) => {
23
+ react_1.default.createElement(FilterOptions_1.FilterOptions, null, (filter.filteredOptions || filter.options).map(({ value, count }) => {
24
24
  const id = 'filter--' + filter.property + '--' + value;
25
25
  return (react_1.default.createElement(FilterCheckboxOption, { key: id, role: "link", onClick: () => {
26
26
  filter.toggleOption(value);
27
27
  telemetry.send({ type: 'filter_checkbox.toggled', payload: { id } });
28
28
  } },
29
- react_1.default.createElement(CheckboxIcon_1.CheckboxIcon, { checked: filter.selectedOptions.has(value === null || value === void 0 ? void 0 : value.toLowerCase()) }),
29
+ react_1.default.createElement(CheckboxIcon_1.CheckboxIcon, { checked: filter.selectedOptions.has(value) ||
30
+ filter.selectedOptions.has(value === null || value === void 0 ? void 0 : value.toLowerCase()) }),
30
31
  react_1.default.createElement(FilterOptionLabel_1.FilterOptionLabel, { "data-translation-key": value }, (0, utils_1.changeTextCasing)(translate(value), filterValuesCasing)),
31
32
  showCounter && react_1.default.createElement(CounterTag_1.CounterTag, { borderless: true }, count)));
32
33
  }))));
@@ -30,6 +30,7 @@ exports.Image = Image;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
32
  const utils_1 = require("../../core/utils");
33
+ const hooks_1 = require("../../core/hooks");
33
34
  function Image(props) {
34
35
  const { src, srcSet, alt, className, width, height, border, style, withLightbox, lightboxStyle } = props;
35
36
  const lightboxContainerRef = (0, react_1.useRef)(null);
@@ -52,6 +53,7 @@ function Image(props) {
52
53
  const handleCloseLightbox = (0, react_1.useCallback)(() => {
53
54
  setLightboxImage(undefined);
54
55
  }, []);
56
+ (0, hooks_1.useModalScrollLock)(!!lightboxImage);
55
57
  (0, react_1.useEffect)(() => {
56
58
  var _a;
57
59
  if (lightboxImage) {
@@ -115,9 +115,9 @@ function SearchDialog({ onClose, className }) {
115
115
  payload: {
116
116
  query,
117
117
  url: item.document.url,
118
- total_results: results.length.toString(),
118
+ totalResults: results.length.toString(),
119
119
  index: index.toString(),
120
- search_engine: mode,
120
+ searchEngine: mode,
121
121
  },
122
122
  });
123
123
  onClose();
@@ -52,6 +52,10 @@ export type ResolvedFilter = Omit<CatalogFilterConfig, 'options'> & {
52
52
  from?: string;
53
53
  to?: string;
54
54
  };
55
+ filteredOptions?: {
56
+ value: string;
57
+ count: number;
58
+ }[];
55
59
  };
56
60
  export type CatalogItem = {
57
61
  title: string;
@@ -1,30 +1,15 @@
1
1
  import { AsyncApiRealm } from '@redocly/realm-asyncapi-sdk';
2
2
  type ExtractEventType<T> = T extends {
3
- span?: {
4
- attributes?: {
5
- 'cloudevents.event_type': infer EventType;
6
- };
7
- };
3
+ type: infer EventType;
8
4
  } ? EventType : never;
9
5
  export type EventType = ExtractEventType<AsyncApiRealm.Messages>;
10
6
  type GetMessageForEventType<TEventType extends EventType> = Extract<AsyncApiRealm.Messages, {
11
- span?: {
12
- attributes?: {
13
- 'cloudevents.event_type': TEventType;
14
- };
15
- };
7
+ type: TEventType;
16
8
  }>;
17
9
  type ExtractEventDataForType<TEventType extends EventType> = GetMessageForEventType<TEventType> extends {
18
- span?: {
19
- attributes?: infer Attrs;
20
- };
21
- } ? {
22
- [K in keyof Attrs as K extends `cloudevents.event_data.${string}` ? K : never]: Attrs[K];
23
- } : never;
24
- export type ConvertEventDataToPayload<T> = {
25
- [K in keyof T as K extends `cloudevents.event_data.${infer FieldName}` ? FieldName : never]: T[K];
26
- };
27
- export type EventPayload<TEventType extends EventType> = ConvertEventDataToPayload<ExtractEventDataForType<TEventType>>;
10
+ data: infer Data;
11
+ } ? Data : never;
12
+ export type EventPayload<TEventType extends EventType> = ExtractEventDataForType<TEventType>;
28
13
  export interface SendEventParams<TEventType extends EventType> {
29
14
  type: TEventType;
30
15
  payload?: EventPayload<TEventType>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.56.0-next.6",
3
+ "version": "0.56.0-next.8",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -36,7 +36,7 @@ export function Breadcrumbs(props: {
36
36
  payload: {
37
37
  link: breadcrumb.link,
38
38
  position: idx + 1,
39
- total_breadcrumbs: breadcrumbs.length,
39
+ totalBreadcrumbs: breadcrumbs.length,
40
40
  },
41
41
  });
42
42
  }}
@@ -96,6 +96,7 @@ const StyledButton = styled.button.attrs((props: ButtonProps) => ({
96
96
  background-color: var(--button-bg-color);
97
97
  border: var(--button-border-width) var(--button-border-style) var(--button-border-color);
98
98
  box-shadow: var(--button-box-shadow);
99
+ backdrop-filter: var(--button-backdrop-filter, none);
99
100
 
100
101
  font-weight: var(--button-font-weight);
101
102
  font-size: var(--button-font-size);
@@ -60,6 +60,7 @@ export function CatalogCard({ entity, catalogConfig }: CatalogCardProps): JSX.El
60
60
  backgroundColor: 'var(--catalog-card-icon-bg-color)',
61
61
  },
62
62
  icon: <GraphIcon color="var(--color-green-8)" />,
63
+ textTransform: 'none',
63
64
  }}
64
65
  />
65
66
  </MetadataColumn>
@@ -74,6 +75,7 @@ export function CatalogCard({ entity, catalogConfig }: CatalogCardProps): JSX.El
74
75
  backgroundColor: 'var(--catalog-card-icon-bg-color)',
75
76
  borderRadius: 'var(--border-radius-xl)',
76
77
  },
78
+ textTransform: 'none',
77
79
  }}
78
80
  />
79
81
  </MetadataColumn>
@@ -92,6 +94,7 @@ export function CatalogCard({ entity, catalogConfig }: CatalogCardProps): JSX.El
92
94
  },
93
95
  borderless: true,
94
96
  color: 'grey',
97
+ textTransform: 'none',
95
98
  }}
96
99
  itemsToShow={3}
97
100
  />
@@ -166,6 +169,7 @@ const CardContent = styled.div`
166
169
  `;
167
170
 
168
171
  const CardFooter = styled.div`
172
+ height: var(--catalog-card-footer-height);
169
173
  display: flex;
170
174
  align-items: center;
171
175
  justify-content: space-between;
@@ -179,8 +183,7 @@ const Divider = styled.div`
179
183
  `;
180
184
 
181
185
  const CatalogCardWrapper = styled.div`
182
- min-height: var(--catalog-card-min-height);
183
- height: 100%;
186
+ height: var(--catalog-card-height);
184
187
  color: var(--catalog-card-text-color);
185
188
  font-size: var(--catalog-card-font-size);
186
189
  font-weight: var(--catalog-card-font-weight);
@@ -6,6 +6,7 @@ export type CatalogEntityInfoBarProps = {
6
6
  rightContent?: ReactNode;
7
7
  withSeparator?: boolean;
8
8
  hoverEffect?: boolean;
9
+ isCodeBlock?: boolean;
9
10
  };
10
11
 
11
12
  export function CatalogEntityInfoBar({
@@ -13,6 +14,7 @@ export function CatalogEntityInfoBar({
13
14
  rightContent,
14
15
  withSeparator = true,
15
16
  hoverEffect = true,
17
+ isCodeBlock = false,
16
18
  }: CatalogEntityInfoBarProps): JSX.Element {
17
19
  return (
18
20
  <InfoBarWrapper
@@ -20,7 +22,7 @@ export function CatalogEntityInfoBar({
20
22
  hoverEffect={hoverEffect}
21
23
  >
22
24
  <LeftColumn withSeparator={withSeparator}>{leftContent}</LeftColumn>
23
- {rightContent && <RightColumn>{rightContent}</RightColumn>}
25
+ {rightContent && <RightColumn isCodeBlock={isCodeBlock}>{rightContent}</RightColumn>}
24
26
  </InfoBarWrapper>
25
27
  );
26
28
  }
@@ -59,12 +61,16 @@ const LeftColumn = styled.div<{ withSeparator?: boolean }>`
59
61
  text-align: left;
60
62
  border-right: ${({ withSeparator }) =>
61
63
  withSeparator ? '1px solid var(--border-color-primary)' : 'none'};
64
+ height: 100%;
65
+ display: flex;
66
+ align-items: center;
62
67
  `;
63
68
 
64
- const RightColumn = styled.div`
69
+ const RightColumn = styled.div<{ isCodeBlock?: boolean }>`
65
70
  color: var(--catalog-metadata-value-color);
66
71
  font-weight: var(--font-weight-medium);
67
72
  grid-area: right;
68
73
  justify-self: end;
69
74
  text-align: right;
75
+ width: ${({ isCodeBlock }) => (isCodeBlock ? '100%' : 'auto')};
70
76
  `;
@@ -3,7 +3,8 @@ import styled from 'styled-components';
3
3
 
4
4
  import { BffCatalogEntity } from '@redocly/theme/core/types';
5
5
  import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
6
- import { capitalize } from '@redocly/theme/core/utils';
6
+ import { JsonViewer } from '@redocly/theme/components/JsonViewer/JsonViewer';
7
+ import { capitalize, isPlainObject } from '@redocly/theme/core/utils';
7
8
  import { useThemeHooks } from '@redocly/theme/core/hooks';
8
9
  import { CatalogEntityInfoBar } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityInfoBar';
9
10
 
@@ -13,6 +14,30 @@ export type CatalogEntityMetadataProps = {
13
14
  entity: BffCatalogEntity;
14
15
  };
15
16
 
17
+ function renderMetadataValue(value: any): React.JSX.Element {
18
+ if (isPlainObject(value)) {
19
+ return <JsonViewerWrapper data={value} expandLevel={3} hideHeader={true} />;
20
+ }
21
+
22
+ if (Array.isArray(value)) {
23
+ return (
24
+ <ArrayWrapper>
25
+ {value.map((item, index) => (
26
+ <div key={index}>
27
+ {isPlainObject(item) ? (
28
+ <JsonViewerWrapper data={item} expandLevel={3} hideHeader={true} />
29
+ ) : (
30
+ <span>{String(item)}</span>
31
+ )}
32
+ </div>
33
+ ))}
34
+ </ArrayWrapper>
35
+ );
36
+ }
37
+
38
+ return <span>{String(value)}</span>;
39
+ }
40
+
16
41
  export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
17
42
  const { useTranslate } = useThemeHooks();
18
43
  const { translate } = useTranslate();
@@ -25,6 +50,7 @@ export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
25
50
  if (!metadata.length) {
26
51
  return null;
27
52
  }
53
+
28
54
  return (
29
55
  <MetadataWrapper data-component-name="Catalog/CatalogEntity/CatalogEntityMetadata">
30
56
  <Heading>{translate('catalog.entity.metadata.title')}</Heading>
@@ -32,8 +58,9 @@ export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
32
58
  <CatalogEntityInfoBar
33
59
  key={key}
34
60
  leftContent={<Label>{capitalize(key)}:</Label>}
35
- rightContent={<Value>{value}</Value>}
61
+ rightContent={<Value>{renderMetadataValue(value)}</Value>}
36
62
  hoverEffect={false}
63
+ isCodeBlock={isPlainObject(value) || Array.isArray(value)}
37
64
  />
38
65
  ))}
39
66
  {hasMoreItems && (
@@ -45,6 +72,10 @@ export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
45
72
  );
46
73
  }
47
74
 
75
+ const JsonViewerWrapper = styled(JsonViewer)`
76
+ text-align: left;
77
+ `;
78
+
48
79
  const MetadataWrapper = styled.div`
49
80
  display: flex;
50
81
  flex-direction: column;
@@ -65,6 +96,11 @@ const Value = styled.span`
65
96
  font-weight: var(--font-weight-medium);
66
97
  `;
67
98
 
99
+ const ArrayWrapper = styled.div`
100
+ display: flex;
101
+ flex-direction: column;
102
+ `;
103
+
68
104
  const Heading = styled.h2`
69
105
  margin-bottom: var(--spacing-base);
70
106
  margin-top: 0;
@@ -24,7 +24,11 @@ export function ContactProperty({ entity }: ContactPropertyProps): JSX.Element {
24
24
  content={
25
25
  <>
26
26
  {channels?.map((channel) => (
27
- <Tag key={channel.name} style={{ backgroundColor: 'var(--bg-color)' }}>
27
+ <Tag
28
+ key={channel.name}
29
+ textTransform="none"
30
+ style={{ backgroundColor: 'var(--bg-color)' }}
31
+ >
28
32
  {channel.name}
29
33
  </Tag>
30
34
  ))}
@@ -28,7 +28,7 @@ export function GitProperty({ entity }: GitPropertyProps): JSX.Element {
28
28
  const url = new URL(repo);
29
29
  const repoName = removeLeadingSlash(url.pathname);
30
30
  return (
31
- <Tag key={repo} style={{ backgroundColor: 'var(--bg-color)' }}>
31
+ <Tag key={repo} textTransform="none" style={{ backgroundColor: 'var(--bg-color)' }}>
32
32
  {repoName}
33
33
  </Tag>
34
34
  );
@@ -30,6 +30,7 @@ export function TagsProperty({ entity }: TagsPropertyProps): JSX.Element {
30
30
  },
31
31
  borderless: true,
32
32
  color: 'grey',
33
+ textTransform: 'none',
33
34
  }}
34
35
  />
35
36
  }
@@ -3,6 +3,7 @@ import styled from 'styled-components';
3
3
 
4
4
  import { EntityType } from '@redocly/theme/core/types';
5
5
  import { Tag } from '@redocly/theme/components/Tag/Tag';
6
+ import { CatalogHighlight } from '@redocly/theme/components/Catalog/CatalogHighlight';
6
7
 
7
8
  export type CatalogEntityTypeTagProps = {
8
9
  entityType: string;
@@ -30,7 +31,9 @@ export const getEntityTagColor = (type: EntityType): string => {
30
31
 
31
32
  export function CatalogEntityTypeTag({ entityType }: CatalogEntityTypeTagProps): JSX.Element {
32
33
  return (
33
- <EntityTypeTagWrapper entityType={entityType as EntityType}>{entityType}</EntityTypeTagWrapper>
34
+ <EntityTypeTagWrapper entityType={entityType as EntityType}>
35
+ <CatalogHighlight>{entityType}</CatalogHighlight>
36
+ </EntityTypeTagWrapper>
34
37
  );
35
38
  }
36
39
 
@@ -19,6 +19,7 @@ export function CatalogDomainsCell({ domains }: CatalogDomainsCellProps) {
19
19
  backgroundColor: 'transparent',
20
20
  borderRadius: 'var(--border-radius-xl)',
21
21
  },
22
+ textTransform: 'none',
22
23
  }}
23
24
  />
24
25
  </div>
@@ -19,6 +19,7 @@ export function CatalogOwnersCell({ owners }: CatalogOwnersCellProps) {
19
19
  backgroundColor: 'transparent',
20
20
  borderRadius: 'var(--border-radius-xl)',
21
21
  },
22
+ textTransform: 'none',
22
23
  }}
23
24
  />
24
25
  </div>
@@ -39,7 +39,7 @@ export const CatalogTableHeaderCell = <T extends BaseEntity>({
39
39
  $sortable={Boolean(column.sortable && sortKey)}
40
40
  >
41
41
  <HeaderContent>
42
- <HeaderTitle>{column.title}</HeaderTitle>
42
+ <span>{column.title}</span>
43
43
  {column.sortable && sortKey && (
44
44
  <SortIndicator>
45
45
  <SortArrow $isActive={isUpActive}>
@@ -83,14 +83,9 @@ const TableHeaderCellWrapper = styled.div<{ $sortable: boolean }>`
83
83
  const HeaderContent = styled.div`
84
84
  display: flex;
85
85
  align-items: center;
86
- justify-content: space-between;
87
86
  width: 100%;
88
87
  `;
89
88
 
90
- const HeaderTitle = styled.span`
91
- flex: 1;
92
- `;
93
-
94
89
  const SortIndicator = styled.div`
95
90
  display: flex;
96
91
  flex-direction: column;
@@ -10,6 +10,8 @@ import { CatalogTagsCell } from '@redocly/theme/components/Catalog/CatalogTableV
10
10
  import { useCatalogTableViewRow } from '@redocly/theme/core/hooks/catalog/useCatalogTableViewRow';
11
11
  import { CatalogEntityTypeTag } from '@redocly/theme/components/Catalog/CatalogEntityTypeTag';
12
12
 
13
+ import { Link } from '../../Link/Link';
14
+
13
15
  export type BaseEntity = {
14
16
  id: string;
15
17
  key: string;
@@ -94,16 +96,13 @@ export const CatalogTableViewRow = <T extends BaseEntity>({
94
96
  entitiesCatalogConfig,
95
97
  });
96
98
 
97
- const handleRowClick = (): void => {
98
- window.location.assign(getEntityDetailsLink());
99
- };
100
-
101
99
  return (
102
100
  <TableRow
103
101
  key={entity.id}
104
- columnsWidths={columns.map((column) => column.width || '1fr')}
105
- columnsMinWidths={columns.map((column) => column.minWidth || 'auto')}
106
- onClick={() => handleRowClick()}
102
+ $columnsWidths={columns.map((column) => column.width || '1fr')}
103
+ $columnsMinWidths={columns.map((column) => column.minWidth || 'auto')}
104
+ to={getEntityDetailsLink()}
105
+ style={{ color: 'var(--catalog-page-wrapper-text-color)' }}
107
106
  >
108
107
  {columns.map((column) => (
109
108
  <TableCell
@@ -117,12 +116,14 @@ export const CatalogTableViewRow = <T extends BaseEntity>({
117
116
  );
118
117
  };
119
118
 
120
- const TableRow = styled.div<{ columnsWidths: string[]; columnsMinWidths: string[] }>`
119
+ const TableRow = styled(Link)<{ $columnsWidths: string[]; $columnsMinWidths: string[] }>`
121
120
  display: grid;
122
- grid-template-columns: ${({ columnsWidths, columnsMinWidths }) =>
123
- columnsWidths
121
+ grid-template-columns: ${({ $columnsWidths, $columnsMinWidths }) =>
122
+ $columnsWidths
124
123
  .map((width, index) =>
125
- columnsMinWidths[index] !== 'auto' ? `minmax(${columnsMinWidths[index]}, ${width})` : width,
124
+ $columnsMinWidths[index] !== 'auto'
125
+ ? `minmax(${$columnsMinWidths[index]}, ${width})`
126
+ : width,
126
127
  )
127
128
  .join(' ')};
128
129
  border-bottom: 1px solid var(--catalog-table-border-color);
@@ -21,6 +21,7 @@ export function CatalogTagsCell({ entity }: CatalogTagsCellProps) {
21
21
  },
22
22
  borderless: true,
23
23
  color: 'grey',
24
+ textTransform: 'none',
24
25
  }}
25
26
  />
26
27
  </div>
@@ -51,7 +51,12 @@ export function CatalogTagsWithTooltip({
51
51
  <TooltipComponent tip={items.join(', ')} placement="bottom" className="catalog" width="400px">
52
52
  <CatalogTagsWrapper data-component-name="Catalog/CatalogTagsWithTooltip">
53
53
  {displayedItems.map((item, index) => (
54
- <Tag key={`${item}-${index}`} {...tagProps} maxLength={CATALOG_TAG_MAX_LENGTH}>
54
+ <Tag
55
+ key={`${item}-${index}`}
56
+ {...tagProps}
57
+ textTransform="none"
58
+ maxLength={CATALOG_TAG_MAX_LENGTH}
59
+ >
55
60
  <CatalogHighlight>{item}</CatalogHighlight>
56
61
  </Tag>
57
62
  ))}
@@ -191,9 +191,9 @@ export const catalog = css`
191
191
  /**
192
192
  * @tokens Catalog card
193
193
  */
194
- --catalog-card-min-height: 194px;
195
- --catalog-card-min-width: 490px;
196
- --catalog-card-padding-vertical: var(--spacing-base);
194
+ --catalog-card-height: 241px;
195
+ --catalog-card-min-width: 400px;
196
+ --catalog-card-padding-vertical: var(--spacing-md);
197
197
  --catalog-card-padding-horizontal: var(--spacing-md);
198
198
  --catalog-card-gap: var(--spacing-sm);
199
199
  --catalog-card-text-color: var(--text-color-secondary);
@@ -249,6 +249,11 @@ export const catalog = css`
249
249
  --catalog-card-title-line-height: var(--line-height-lg);
250
250
  --catalog-card-title-line-clamp: 2;
251
251
 
252
+ /**
253
+ * @tokens Catalog card footer
254
+ */
255
+ --catalog-card-footer-height: 72px;
256
+
252
257
  /**
253
258
  * @tokens Catalog card description
254
259
  */
@@ -148,6 +148,7 @@ export function CodeBlock({
148
148
 
149
149
  const ContainerWrapper = styled.div`
150
150
  display: grid; // prevents content to overstretch
151
+ position: relative;
151
152
  `;
152
153
 
153
154
  const CodeBlockWrapper = styled.div`
@@ -72,6 +72,8 @@ export function CodeBlockControls({
72
72
  report: null,
73
73
  };
74
74
 
75
+ const isEmptyTitle = !title && !tabs;
76
+
75
77
  const defaultControls = controls ? (
76
78
  <>
77
79
  {title && <Title>{title}</Title>}
@@ -141,7 +143,7 @@ export function CodeBlockControls({
141
143
 
142
144
  {copy && !codeSnippet?.copy?.hide ? (
143
145
  <TooltipWrapper tooltipTranslationKey="codeSnippet.copy.tooltipText" placement="top">
144
- <CopyButton
146
+ <StyledCopyButton
145
147
  data={copy.data}
146
148
  data-source={copy.dataSource}
147
149
  data-hash={copy.dataHash}
@@ -156,7 +158,7 @@ export function CodeBlockControls({
156
158
  } else {
157
159
  telemetry.send({
158
160
  type: 'openapi_docs.copy_code_snippet.clicked',
159
- payload: { snippet_type: 'copy' },
161
+ payload: { snippetType: 'copy' },
160
162
  });
161
163
  }
162
164
  }}
@@ -168,15 +170,20 @@ export function CodeBlockControls({
168
170
  ) : null;
169
171
 
170
172
  return children || controls ? (
171
- <ContainerWrapper data-component-name="CodeBlock/CodeBlockControls" className={className}>
173
+ <ContainerWrapper
174
+ data-component-name="CodeBlock/CodeBlockControls"
175
+ className={className}
176
+ $isEmptyTitle={isEmptyTitle}
177
+ >
172
178
  {children ? children : defaultControls}
173
179
  </ContainerWrapper>
174
180
  ) : null;
175
181
  }
176
182
 
177
- const ContainerWrapper = styled.div`
183
+ const ContainerWrapper = styled.div<{ $isEmptyTitle: boolean }>`
178
184
  display: grid;
179
185
  justify-content: end;
186
+ gap: var(--spacing-sm);
180
187
  font-size: var(--code-block-controls-font-size);
181
188
  font-family: var(--code-block-controls-font-family);
182
189
  background-color: var(--code-block-controls-bg-color);
@@ -185,6 +192,18 @@ const ContainerWrapper = styled.div`
185
192
  line-height: var(--line-height-lg);
186
193
  min-height: var(--control-height-base);
187
194
  grid-template-columns: 1fr auto;
195
+ ${({ $isEmptyTitle }) =>
196
+ $isEmptyTitle &&
197
+ `
198
+ grid-template-columns: 1fr;
199
+ padding-left: var(--spacing-xxs);
200
+ position: absolute;
201
+ right: 0;
202
+ width: auto;
203
+ border: none;
204
+ background-color: transparent;
205
+ margin: 0;
206
+ `}
188
207
  `;
189
208
 
190
209
  const Title = styled.span`
@@ -201,11 +220,20 @@ const ControlsWrapper = styled.div`
201
220
  align-items: center;
202
221
  gap: var(--spacing-xxs);
203
222
  justify-content: end;
204
- margin-left: var(--spacing-sm);
205
223
  `;
206
224
 
207
225
  const ControlButton = styled(Button)`
226
+ --button-icon-size: 16px; /* increase icon size for code blocks */
227
+ --button-icon-padding: 3px;
228
+ --button-backdrop-filter: blur(8px); /* backdrop filter when there is text under the button */
229
+
208
230
  & + & {
209
231
  margin-left: 0;
210
232
  }
211
233
  `;
234
+
235
+ const StyledCopyButton = styled(CopyButton)`
236
+ --button-icon-size: 16px; /* increase icon size for code blocks */
237
+ --button-icon-padding: 3px;
238
+ --button-backdrop-filter: blur(8px);
239
+ `;
@@ -58,7 +58,7 @@ export function Feedback(props: FeedbackProps & { path?: string }) {
58
58
  settings={settings}
59
59
  onSubmit={(values) => {
60
60
  submitFeedback({ type, values, path });
61
- telemetry.send({ type: 'feedback.sent', payload: { feedback_type: type } });
61
+ telemetry.send({ type: 'feedback.sent', payload: { feedbackType: type } });
62
62
  }}
63
63
  />
64
64
  </FeedbackWrapper>
@@ -28,7 +28,7 @@ export function FilterCheckboxes({
28
28
  {translate(filter.titleTranslationKey, filter.title)}
29
29
  </FilterTitle>
30
30
  <FilterOptions>
31
- {filter.options.map(({ value, count }) => {
31
+ {(filter.filteredOptions || filter.options).map(({ value, count }) => {
32
32
  const id = 'filter--' + filter.property + '--' + value;
33
33
  return (
34
34
  <FilterCheckboxOption
@@ -39,7 +39,12 @@ export function FilterCheckboxes({
39
39
  telemetry.send({ type: 'filter_checkbox.toggled', payload: { id } });
40
40
  }}
41
41
  >
42
- <CheckboxIcon checked={filter.selectedOptions.has(value?.toLowerCase())} />
42
+ <CheckboxIcon
43
+ checked={
44
+ filter.selectedOptions.has(value) ||
45
+ filter.selectedOptions.has(value?.toLowerCase())
46
+ }
47
+ />
43
48
  <FilterOptionLabel data-translation-key={value}>
44
49
  {changeTextCasing(translate(value), filterValuesCasing)}
45
50
  </FilterOptionLabel>
@@ -4,6 +4,7 @@ import styled from 'styled-components';
4
4
  import type { KeyboardEvent, JSX } from 'react';
5
5
 
6
6
  import { parseSrcSet, parseStyleString } from '@redocly/theme/core/utils';
7
+ import { useModalScrollLock } from '@redocly/theme/core/hooks';
7
8
 
8
9
  export type ImageProps = {
9
10
  src?: string;
@@ -49,6 +50,7 @@ export function Image(props: ImageProps): JSX.Element {
49
50
  setLightboxImage(undefined);
50
51
  }, []);
51
52
 
53
+ useModalScrollLock(!!lightboxImage);
52
54
  useEffect(() => {
53
55
  if (lightboxImage) {
54
56
  lightboxContainerRef.current?.focus();
@@ -144,9 +144,9 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
144
144
  payload: {
145
145
  query,
146
146
  url: item.document.url,
147
- total_results: results.length.toString(),
147
+ totalResults: results.length.toString(),
148
148
  index: index.toString(),
149
- search_engine: mode,
149
+ searchEngine: mode,
150
150
  },
151
151
  });
152
152
  onClose();
@@ -54,6 +54,10 @@ export type ResolvedFilter = Omit<CatalogFilterConfig, 'options'> & {
54
54
  selectOption: (option: string) => void;
55
55
  parentUsed: boolean;
56
56
  selectedOptions: Set<string> | { from?: string; to?: string };
57
+ filteredOptions?: {
58
+ value: string;
59
+ count: number;
60
+ }[];
57
61
  };
58
62
 
59
63
  export type CatalogItem = {
@@ -1,7 +1,7 @@
1
1
  import { AsyncApiRealm } from '@redocly/realm-asyncapi-sdk';
2
2
 
3
3
  type ExtractEventType<T> = T extends {
4
- span?: { attributes?: { 'cloudevents.event_type': infer EventType } };
4
+ type: infer EventType;
5
5
  }
6
6
  ? EventType
7
7
  : never;
@@ -10,25 +10,17 @@ export type EventType = ExtractEventType<AsyncApiRealm.Messages>;
10
10
 
11
11
  type GetMessageForEventType<TEventType extends EventType> = Extract<
12
12
  AsyncApiRealm.Messages,
13
- { span?: { attributes?: { 'cloudevents.event_type': TEventType } } }
13
+ { type: TEventType }
14
14
  >;
15
15
 
16
16
  type ExtractEventDataForType<TEventType extends EventType> =
17
17
  GetMessageForEventType<TEventType> extends {
18
- span?: { attributes?: infer Attrs };
18
+ data: infer Data;
19
19
  }
20
- ? {
21
- [K in keyof Attrs as K extends `cloudevents.event_data.${string}` ? K : never]: Attrs[K];
22
- }
20
+ ? Data
23
21
  : never;
24
22
 
25
- export type ConvertEventDataToPayload<T> = {
26
- [K in keyof T as K extends `cloudevents.event_data.${infer FieldName}` ? FieldName : never]: T[K];
27
- };
28
-
29
- export type EventPayload<TEventType extends EventType> = ConvertEventDataToPayload<
30
- ExtractEventDataForType<TEventType>
31
- >;
23
+ export type EventPayload<TEventType extends EventType> = ExtractEventDataForType<TEventType>;
32
24
 
33
25
  export interface SendEventParams<TEventType extends EventType> {
34
26
  type: TEventType;