@redocly/theme 0.61.0-next.2 → 0.61.0-next.3

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 (71) hide show
  1. package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +5 -0
  2. package/lib/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.js +9 -0
  3. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.d.ts +6 -0
  4. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.js +144 -0
  5. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.d.ts +8 -0
  6. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js +161 -0
  7. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.d.ts +8 -0
  8. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.js +67 -0
  9. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.d.ts +9 -0
  10. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.js +212 -0
  11. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +2 -25
  12. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +12 -1
  13. package/lib/components/Catalog/CatalogEntity/ShowMoreButton.d.ts +8 -0
  14. package/lib/components/Catalog/CatalogEntity/ShowMoreButton.js +35 -0
  15. package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.d.ts +2 -0
  16. package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.js +4 -1
  17. package/lib/components/Catalog/variables.js +112 -0
  18. package/lib/components/Menu/variables.js +1 -0
  19. package/lib/components/Tooltip/Tooltip.js +2 -0
  20. package/lib/core/constants/catalog.d.ts +1 -0
  21. package/lib/core/constants/catalog.js +2 -1
  22. package/lib/core/hooks/catalog/use-catalog-entity-details.d.ts +3 -1
  23. package/lib/core/hooks/catalog/use-catalog-entity-details.js +12 -5
  24. package/lib/core/hooks/use-color-switcher.js +7 -8
  25. package/lib/core/hooks/use-page-actions.js +37 -6
  26. package/lib/core/hooks/use-telemetry-fallback.d.ts +2 -0
  27. package/lib/core/hooks/use-telemetry-fallback.js +2 -0
  28. package/lib/core/types/catalog.d.ts +33 -4
  29. package/lib/core/types/hooks.d.ts +14 -3
  30. package/lib/core/types/l10n.d.ts +1 -1
  31. package/lib/core/utils/build-revision-url.d.ts +1 -0
  32. package/lib/core/utils/build-revision-url.js +15 -0
  33. package/lib/core/utils/date.d.ts +14 -0
  34. package/lib/core/utils/date.js +39 -0
  35. package/lib/core/utils/index.d.ts +2 -0
  36. package/lib/core/utils/index.js +2 -0
  37. package/lib/core/utils/transform-revisions-to-version-history.d.ts +8 -0
  38. package/lib/core/utils/transform-revisions-to-version-history.js +110 -0
  39. package/lib/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.d.ts +9 -0
  40. package/lib/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.js +26 -0
  41. package/lib/index.d.ts +2 -0
  42. package/lib/index.js +2 -0
  43. package/package.json +4 -4
  44. package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +7 -1
  45. package/src/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.tsx +12 -0
  46. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.tsx +147 -0
  47. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx +180 -0
  48. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.tsx +93 -0
  49. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.tsx +284 -0
  50. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +3 -25
  51. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +15 -2
  52. package/src/components/Catalog/CatalogEntity/ShowMoreButton.tsx +47 -0
  53. package/src/components/Catalog/CatalogTableView/CatalogTableViewRow.tsx +6 -1
  54. package/src/components/Catalog/variables.ts +112 -0
  55. package/src/components/Menu/variables.ts +1 -0
  56. package/src/components/Tooltip/Tooltip.tsx +2 -0
  57. package/src/core/constants/catalog.ts +2 -0
  58. package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -0
  59. package/src/core/hooks/catalog/use-catalog-entity-details.ts +22 -6
  60. package/src/core/hooks/use-color-switcher.ts +13 -10
  61. package/src/core/hooks/use-page-actions.ts +63 -6
  62. package/src/core/hooks/use-telemetry-fallback.ts +2 -0
  63. package/src/core/types/catalog.ts +38 -10
  64. package/src/core/types/hooks.ts +23 -4
  65. package/src/core/types/l10n.ts +10 -0
  66. package/src/core/utils/build-revision-url.ts +16 -0
  67. package/src/core/utils/date.ts +33 -0
  68. package/src/core/utils/index.ts +2 -0
  69. package/src/core/utils/transform-revisions-to-version-history.ts +163 -0
  70. package/src/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.tsx +43 -0
  71. package/src/index.ts +2 -0
@@ -0,0 +1,180 @@
1
+ import React, { useState, useEffect, useCallback, useMemo } from 'react';
2
+ import styled from 'styled-components';
3
+ import { useLocation } from 'react-router-dom';
4
+
5
+ import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
6
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
7
+ import { MenuContainer } from '@redocly/theme/components/Menu/MenuContainer';
8
+ import { transformRevisionsToVersionHistory } from '@redocly/theme/core/utils';
9
+
10
+ import { CatalogEntityVersionItem } from './CatalogEntityVersionItem';
11
+
12
+ export type CatalogHistorySidebarProps = {
13
+ entityKey: string;
14
+ revision?: string;
15
+ version?: string | null;
16
+ className?: string;
17
+ };
18
+
19
+ export function CatalogEntityHistorySidebar({
20
+ entityKey,
21
+ revision,
22
+ version,
23
+ className,
24
+ }: CatalogHistorySidebarProps): React.ReactElement | null {
25
+ const [isOpen, setIsOpen] = useState(false);
26
+ const location = useLocation();
27
+ const basePath = location.pathname;
28
+ const { useTranslate, useFetchCatalogEntityRevisions, useL10nConfig } = useThemeHooks();
29
+ const { translate } = useTranslate();
30
+ const { currentLocale } = useL10nConfig();
31
+
32
+ const { items: revisions } = useFetchCatalogEntityRevisions({ entityKey });
33
+
34
+ const versionHistoryItems = useMemo(
35
+ () =>
36
+ transformRevisionsToVersionHistory({
37
+ revisions,
38
+ currentRevisionDate: revision,
39
+ currentVersion: version,
40
+ locale: currentLocale,
41
+ }),
42
+ [revisions, revision, version, currentLocale],
43
+ );
44
+ const activeRevisionLabel = useMemo(() => {
45
+ const itemWithActiveRevision = versionHistoryItems.find((item) =>
46
+ item.revisions?.some((revision) => revision.isActive),
47
+ );
48
+ const activeRevision = itemWithActiveRevision?.revisions?.find((revision) => revision.isActive);
49
+ return activeRevision?.name;
50
+ }, [versionHistoryItems]);
51
+
52
+ const [expandedVersions, setExpandedVersions] = useState<Set<string>>(new Set());
53
+
54
+ useEffect(() => {
55
+ setExpandedVersions(
56
+ new Set(versionHistoryItems.filter((item) => item.isExpanded).map((item) => item.version)),
57
+ );
58
+ }, [versionHistoryItems]);
59
+
60
+ const handleOpenSidebar = useCallback(() => {
61
+ setIsOpen(true);
62
+ }, []);
63
+
64
+ useEffect(() => {
65
+ window.addEventListener('portal:sidebar:open-version-history', handleOpenSidebar);
66
+
67
+ return () => {
68
+ window.removeEventListener('portal:sidebar:open-version-history', handleOpenSidebar);
69
+ };
70
+ }, [handleOpenSidebar]);
71
+
72
+ const handleClose = (): void => {
73
+ window.dispatchEvent(
74
+ new CustomEvent('portal:sidebar:close-version-history', {
75
+ detail: { version, revision: activeRevisionLabel },
76
+ }),
77
+ );
78
+ setIsOpen(false);
79
+ };
80
+
81
+ const toggleVersion = (version: string): void => {
82
+ setExpandedVersions((prev) => {
83
+ const newSet = new Set(prev);
84
+ if (newSet.has(version)) {
85
+ newSet.delete(version);
86
+ } else {
87
+ newSet.add(version);
88
+ }
89
+ return newSet;
90
+ });
91
+ };
92
+
93
+ if (!isOpen) {
94
+ return null;
95
+ }
96
+
97
+ return (
98
+ <SidebarOverlay className={className} data-component-name="Catalog/CatalogHistorySidebar">
99
+ <SidebarHeader>
100
+ <HeaderTitle>{translate('catalog.history.sidebar.title', 'Version history')}</HeaderTitle>
101
+ <CloseButton
102
+ onClick={handleClose}
103
+ aria-label={translate('catalog.history.sidebar.close', 'Close version history')}
104
+ >
105
+ <CloseIcon size="20px" color="--catalog-history-sidebar-close-icon-color" />
106
+ </CloseButton>
107
+ </SidebarHeader>
108
+
109
+ <MenuContainer growContent>
110
+ <VersionList>
111
+ {versionHistoryItems.map((group) => (
112
+ <CatalogEntityVersionItem
113
+ key={group.version}
114
+ group={group}
115
+ basePath={basePath}
116
+ isExpanded={expandedVersions.has(group.version)}
117
+ onToggle={toggleVersion}
118
+ />
119
+ ))}
120
+ </VersionList>
121
+ </MenuContainer>
122
+ </SidebarOverlay>
123
+ );
124
+ }
125
+
126
+ const SidebarOverlay = styled.div`
127
+ position: fixed;
128
+ top: var(--navbar-height);
129
+ left: 0;
130
+ width: var(--sidebar-width);
131
+ height: calc(100vh - var(--navbar-height));
132
+ background-color: var(--catalog-history-sidebar-bg-color);
133
+ border-right: 1px solid var(--catalog-history-sidebar-border-color);
134
+ display: flex;
135
+ flex-direction: column;
136
+ z-index: calc(var(--z-index-raised) - 1);
137
+ overflow: hidden;
138
+ `;
139
+
140
+ const SidebarHeader = styled.div`
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: space-between;
144
+ padding: var(--catalog-history-sidebar-header-padding);
145
+ border-bottom: 1px solid var(--catalog-history-sidebar-border-color);
146
+ flex-shrink: 0;
147
+ `;
148
+
149
+ const HeaderTitle = styled.h2`
150
+ margin: 0;
151
+ font-family: var(--catalog-history-sidebar-header-font-family);
152
+ font-size: var(--catalog-history-sidebar-header-font-size);
153
+ font-weight: var(--catalog-history-sidebar-header-font-weight);
154
+ line-height: var(--catalog-history-sidebar-header-line-height);
155
+ letter-spacing: var(--catalog-history-sidebar-header-letter-spacing);
156
+ color: var(--catalog-history-sidebar-header-color);
157
+ `;
158
+
159
+ const CloseButton = styled.button`
160
+ all: unset;
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ width: var(--catalog-history-sidebar-close-button-size);
165
+ height: var(--catalog-history-sidebar-close-button-size);
166
+ cursor: pointer;
167
+ border-radius: var(--catalog-history-sidebar-close-button-border-radius);
168
+ transition: background-color 0.2s ease;
169
+
170
+ &:hover {
171
+ background-color: var(--catalog-history-sidebar-close-button-bg-color-hover);
172
+ }
173
+ `;
174
+
175
+ const VersionList = styled.ul`
176
+ list-style: none;
177
+ margin: 0;
178
+ padding: var(--catalog-history-sidebar-content-padding);
179
+ margin-top: var(--catalog-history-sidebar-content-margin-top);
180
+ `;
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { CatalogEntityRevision } from '@redocly/theme/core/types';
5
+
6
+ import { Link } from '@redocly/theme/components/Link/Link';
7
+ import { Tag } from '@redocly/theme/components/Tag/Tag';
8
+ import { buildRevisionUrl } from '@redocly/theme/core/utils';
9
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
10
+
11
+ export type CatalogEntityRevisionItemProps = {
12
+ revisionItem: CatalogEntityRevision;
13
+ basePath: string;
14
+ version?: string | null;
15
+ };
16
+
17
+ export function CatalogEntityRevisionItem({
18
+ revisionItem,
19
+ basePath,
20
+ version,
21
+ }: CatalogEntityRevisionItemProps): React.ReactElement {
22
+ const { useTranslate } = useThemeHooks();
23
+ const { translate } = useTranslate();
24
+ const revisionFilter = buildRevisionUrl(basePath, revisionItem.revisionDate, version) ?? basePath;
25
+ const isActive = revisionItem.isActive ?? false;
26
+
27
+ return (
28
+ <RevisionItemWrapper to={revisionFilter} $isActive={isActive}>
29
+ <RevisionNameRow>
30
+ <RevisionName>{revisionItem.name}</RevisionName>
31
+ {revisionItem.isCurrent && (
32
+ <Tag
33
+ color="grey"
34
+ borderless
35
+ textTransform="none"
36
+ style={{
37
+ fontSize: 'var(--font-size-xs)',
38
+ borderRadius: 'var(--catalog-history-sidebar-revision-tag-border-radius)',
39
+ }}
40
+ >
41
+ {translate('catalog.history.revision.current', 'current')}
42
+ </Tag>
43
+ )}
44
+ </RevisionNameRow>
45
+ <RevisionDate>{revisionItem.date}</RevisionDate>
46
+ </RevisionItemWrapper>
47
+ );
48
+ }
49
+
50
+ const RevisionItemWrapper = styled(Link)<{ $isActive?: boolean }>`
51
+ display: flex;
52
+ justify-content: space-between;
53
+ align-items: center;
54
+ padding: var(--catalog-history-sidebar-revision-item-padding);
55
+ margin-left: calc(-1 * var(--catalog-history-sidebar-revisions-padding-left));
56
+ padding-left: var(--catalog-history-sidebar-revisions-padding-left);
57
+ border-radius: var(--catalog-history-sidebar-revision-item-border-radius);
58
+ transition: 0.2s ease;
59
+ text-decoration: none;
60
+ color: inherit;
61
+ cursor: pointer;
62
+ background-color: ${({ $isActive }) =>
63
+ $isActive ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)' : 'transparent'};
64
+
65
+ &:hover {
66
+ background-color: ${({ $isActive }) =>
67
+ $isActive
68
+ ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)'
69
+ : 'var(--catalog-history-sidebar-revision-item-bg-color-hover)'};
70
+ }
71
+ `;
72
+
73
+ const RevisionNameRow = styled.div`
74
+ display: flex;
75
+ align-items: center;
76
+ gap: var(--spacing-xs, 8px);
77
+ `;
78
+
79
+ const RevisionName = styled.span`
80
+ font-family: var(--catalog-history-sidebar-revision-name-font-family);
81
+ font-size: var(--catalog-history-sidebar-revision-name-font-size);
82
+ font-weight: var(--catalog-history-sidebar-revision-name-font-weight);
83
+ line-height: var(--catalog-history-sidebar-revision-name-line-height);
84
+ color: var(--catalog-history-sidebar-revision-name-color);
85
+ `;
86
+
87
+ const RevisionDate = styled.span`
88
+ font-family: var(--catalog-history-sidebar-revision-date-font-family);
89
+ font-size: var(--catalog-history-sidebar-revision-date-font-size);
90
+ font-weight: var(--catalog-history-sidebar-revision-date-font-weight);
91
+ line-height: var(--catalog-history-sidebar-revision-date-line-height);
92
+ color: var(--catalog-history-sidebar-revision-date-color);
93
+ `;
@@ -0,0 +1,284 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { CatalogEntityVersionHistoryGroup } from '@redocly/theme/core/types';
5
+
6
+ import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
7
+ import { ChevronRightIcon } from '@redocly/theme/icons/ChevronRightIcon/ChevronRightIcon';
8
+ import { CheckmarkOutlineIcon } from '@redocly/theme/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon';
9
+ import { NavaidMilitaryIcon } from '@redocly/theme/icons/NavaidMilitaryIcon/NavaidMilitaryIcon';
10
+ import { Link } from '@redocly/theme/components/Link/Link';
11
+ import { Tag } from '@redocly/theme/components/Tag/Tag';
12
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
13
+ import { ShowMoreButton } from '@redocly/theme/components/Catalog/CatalogEntity/ShowMoreButton';
14
+ import { CatalogEntityRevisionItem } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem';
15
+ import { buildRevisionUrl } from '@redocly/theme/core/utils';
16
+ import { VERSION_NOT_SPECIFIED } from '@redocly/theme/core/constants';
17
+
18
+ const MAX_INITIAL_REVISIONS = 5;
19
+ const MAX_REVISIONS = 20;
20
+
21
+ export type CatalogEntityVersionItemProps = {
22
+ group: CatalogEntityVersionHistoryGroup;
23
+ basePath: string;
24
+ isExpanded: boolean;
25
+ onToggle: (version: string) => void;
26
+ };
27
+
28
+ export function CatalogEntityVersionItem({
29
+ group,
30
+ basePath,
31
+ isExpanded,
32
+ onToggle,
33
+ }: CatalogEntityVersionItemProps): React.ReactElement {
34
+ const { useTranslate } = useThemeHooks();
35
+ const { translate } = useTranslate();
36
+ const [showAllRevisions, setShowAllRevisions] = useState(false);
37
+
38
+ const revisions = group.revisions || [];
39
+ const hasRevisions = revisions.length > 0;
40
+ const hasMoreThanMax = revisions.length > MAX_INITIAL_REVISIONS;
41
+ const hasMoreThanLimit = revisions.length > MAX_REVISIONS;
42
+ const displayedRevisions = showAllRevisions
43
+ ? revisions.slice(0, MAX_REVISIONS)
44
+ : revisions.slice(0, MAX_INITIAL_REVISIONS);
45
+
46
+ useEffect(() => {
47
+ if (!isExpanded) {
48
+ setShowAllRevisions(false);
49
+ }
50
+ }, [isExpanded]);
51
+
52
+ const isNotSpecifiedVersion = group.version === VERSION_NOT_SPECIFIED;
53
+
54
+ const singleRevisionLink = buildRevisionUrl(basePath, group.singleRevisionDate, group.version);
55
+
56
+ const isClickable = hasRevisions || Boolean(singleRevisionLink);
57
+ const isSingleRevisionActive = Boolean(singleRevisionLink && group.isCurrent);
58
+
59
+ const versionTitle = isNotSpecifiedVersion
60
+ ? `${translate('catalog.history.version.label', 'Version')}: ${translate('catalog.history.version.notSpecified', 'not specified')}`
61
+ : `${translate('catalog.history.version.label', 'Version')}: ${group.version}`;
62
+
63
+ const versionButton = (
64
+ <VersionButton
65
+ type="button"
66
+ onClick={() => hasRevisions && onToggle(group.version)}
67
+ $isClickable={isClickable}
68
+ $isCurrent={group.isCurrent}
69
+ $isActive={isSingleRevisionActive}
70
+ >
71
+ <VersionIcon $isCurrent={group.isCurrent}>
72
+ {group.isCurrent ? (
73
+ <CheckmarkOutlineIcon
74
+ size="16px"
75
+ color="--catalog-history-sidebar-version-icon-color-current"
76
+ />
77
+ ) : (
78
+ <NavaidMilitaryIcon size="16px" color="--catalog-history-sidebar-version-icon-color" />
79
+ )}
80
+ </VersionIcon>
81
+ <VersionInfo>
82
+ <VersionTitleRow>
83
+ <VersionTitle>{versionTitle}</VersionTitle>
84
+ {group.isDefaultVersion && (
85
+ <Tag
86
+ color="grey"
87
+ borderless
88
+ textTransform="none"
89
+ style={{
90
+ fontSize: 'var(--font-size-xs)',
91
+ borderRadius: 'var(--catalog-history-sidebar-version-tag-border-radius)',
92
+ flexShrink: 0,
93
+ }}
94
+ >
95
+ {translate('catalog.history.version.default', 'default')}
96
+ </Tag>
97
+ )}
98
+ </VersionTitleRow>
99
+ {!isNotSpecifiedVersion && <VersionDate>{group.date}</VersionDate>}
100
+ </VersionInfo>
101
+ {hasRevisions && (
102
+ <ChevronIcon>
103
+ {isExpanded ? (
104
+ <ChevronDownIcon size="16px" color="--catalog-history-sidebar-chevron-icon-color" />
105
+ ) : (
106
+ <ChevronRightIcon size="16px" color="--catalog-history-sidebar-chevron-icon-color" />
107
+ )}
108
+ </ChevronIcon>
109
+ )}
110
+ </VersionButton>
111
+ );
112
+
113
+ return (
114
+ <li>
115
+ {singleRevisionLink ? <Link to={singleRevisionLink}>{versionButton}</Link> : versionButton}
116
+
117
+ {hasRevisions && isExpanded && (
118
+ <RevisionsList>
119
+ {displayedRevisions.map((revisionItem) => (
120
+ <CatalogEntityRevisionItem
121
+ key={revisionItem.name}
122
+ revisionItem={revisionItem}
123
+ basePath={basePath}
124
+ version={group.version}
125
+ />
126
+ ))}
127
+ {hasMoreThanLimit && showAllRevisions && (
128
+ <RevisionsLimitMessage>
129
+ {translate(
130
+ 'catalog.history.revisions.limitMessage',
131
+ 'Older revisions are not stored.',
132
+ )}
133
+ </RevisionsLimitMessage>
134
+ )}
135
+ {hasMoreThanMax && (
136
+ <ShowMoreButton
137
+ onClick={() => setShowAllRevisions(!showAllRevisions)}
138
+ isExpanded={showAllRevisions}
139
+ >
140
+ {showAllRevisions
141
+ ? translate('catalog.history.revisions.showLess', 'Show less')
142
+ : translate('catalog.history.revisions.showMore', {
143
+ defaultValue: 'Show more',
144
+ count: Math.min(
145
+ revisions.length - MAX_INITIAL_REVISIONS,
146
+ MAX_REVISIONS - MAX_INITIAL_REVISIONS,
147
+ ),
148
+ })}
149
+ </ShowMoreButton>
150
+ )}
151
+ </RevisionsList>
152
+ )}
153
+ </li>
154
+ );
155
+ }
156
+
157
+ const VersionButton = styled.button<{
158
+ $isClickable?: boolean;
159
+ $isCurrent?: boolean;
160
+ $isActive?: boolean;
161
+ }>`
162
+ all: unset;
163
+ display: flex;
164
+ align-items: center;
165
+ width: calc(100% - var(--catalog-history-sidebar-version-icon-margin-right));
166
+ padding: var(--catalog-history-sidebar-version-header-padding);
167
+ cursor: ${({ $isClickable }) => ($isClickable ? 'pointer' : 'default')};
168
+ border-radius: var(--catalog-history-sidebar-version-header-border-radius);
169
+ transition: 0.2s ease;
170
+ text-decoration: none;
171
+ color: inherit;
172
+ background-color: ${({ $isActive }) =>
173
+ $isActive ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)' : 'transparent'};
174
+
175
+ ${({ $isClickable, $isActive }) =>
176
+ $isClickable &&
177
+ `
178
+ &:hover {
179
+ background-color: ${
180
+ $isActive
181
+ ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)'
182
+ : 'var(--catalog-history-sidebar-version-header-bg-color-hover)'
183
+ };
184
+ }
185
+ `}
186
+
187
+ ${({ $isCurrent }) =>
188
+ !$isCurrent &&
189
+ `
190
+ &:hover ${VersionIcon} {
191
+ background-color: var(--color-static-white);
192
+ }
193
+ `}
194
+ `;
195
+
196
+ const VersionIcon = styled.div<{ $isCurrent?: boolean }>`
197
+ display: flex;
198
+ align-items: center;
199
+ justify-content: center;
200
+ width: var(--catalog-history-sidebar-version-icon-size);
201
+ height: var(--catalog-history-sidebar-version-icon-size);
202
+ flex-shrink: 0;
203
+ border-radius: 50%;
204
+ background-color: ${({ $isCurrent }) =>
205
+ $isCurrent ? 'var(--color-primary-base)' : 'var(--catalog-avatar-bg-color)'};
206
+ transition: background-color 0.2s ease;
207
+ margin-right: var(--catalog-history-sidebar-version-icon-margin-right);
208
+
209
+ svg path {
210
+ transition: fill 0.2s ease;
211
+ }
212
+ `;
213
+
214
+ const VersionInfo = styled.div`
215
+ display: flex;
216
+ flex-direction: column;
217
+ align-items: flex-start;
218
+ gap: var(--catalog-history-sidebar-version-info-gap);
219
+ `;
220
+
221
+ const VersionTitleRow = styled.div`
222
+ display: flex;
223
+ align-items: center;
224
+ gap: var(--spacing-xs, 8px);
225
+ `;
226
+
227
+ const VersionTitle = styled.span`
228
+ font-family: var(--catalog-history-sidebar-version-title-font-family);
229
+ font-size: var(--catalog-history-sidebar-version-title-font-size);
230
+ font-weight: var(--catalog-history-sidebar-version-title-font-weight);
231
+ line-height: var(--catalog-history-sidebar-version-title-line-height);
232
+ color: var(--catalog-history-sidebar-version-title-color);
233
+ flex-shrink: 1;
234
+ min-width: 0;
235
+ `;
236
+
237
+ const VersionDate = styled.span`
238
+ font-family: var(--catalog-history-sidebar-version-date-font-family);
239
+ font-size: var(--catalog-history-sidebar-version-date-font-size);
240
+ font-weight: var(--catalog-history-sidebar-version-date-font-weight);
241
+ line-height: var(--catalog-history-sidebar-version-date-line-height);
242
+ color: var(--catalog-history-sidebar-version-date-color);
243
+ `;
244
+
245
+ const ChevronIcon = styled.div`
246
+ display: flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+ flex-shrink: 0;
250
+ margin-left: auto;
251
+ `;
252
+
253
+ const RevisionsList = styled.ul`
254
+ list-style: none;
255
+ margin: 0;
256
+ padding: 0;
257
+ padding-left: var(--catalog-history-sidebar-revisions-padding-left);
258
+ position: relative;
259
+
260
+ &::before {
261
+ content: '';
262
+ position: absolute;
263
+ left: 22px;
264
+ top: 0;
265
+ bottom: 0;
266
+ width: 1px;
267
+ background-color: var(
268
+ --catalog-history-sidebar-revision-line-color,
269
+ var(--border-color-secondary)
270
+ );
271
+ }
272
+ `;
273
+
274
+ const RevisionsLimitMessage = styled.div`
275
+ padding: var(--catalog-history-sidebar-revision-item-padding);
276
+ margin-left: calc(-1 * var(--catalog-history-sidebar-revisions-padding-left));
277
+ padding-left: var(--catalog-history-sidebar-revisions-padding-left);
278
+ font-family: var(--catalog-history-sidebar-revision-name-font-family);
279
+ font-size: var(--font-size-sm);
280
+ font-weight: var(--catalog-history-sidebar-revision-name-font-weight);
281
+ line-height: var(--catalog-history-sidebar-revision-name-line-height);
282
+ color: var(--catalog-history-sidebar-revisions-limit-message-color);
283
+ text-align: center;
284
+ `;
@@ -2,11 +2,11 @@ import React, { useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
4
  import { BffCatalogEntity } from '@redocly/theme/core/types';
5
- import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
6
5
  import { JsonViewer } from '@redocly/theme/components/JsonViewer/JsonViewer';
7
6
  import { capitalize, isPlainObject } from '@redocly/theme/core/utils';
8
7
  import { useThemeHooks } from '@redocly/theme/core/hooks';
9
8
  import { CatalogEntityInfoBar } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityInfoBar';
9
+ import { ShowMoreButton } from '@redocly/theme/components/Catalog/CatalogEntity/ShowMoreButton';
10
10
 
11
11
  const MAX_INITIAL_ITEMS = 4;
12
12
 
@@ -67,8 +67,8 @@ export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
67
67
  />
68
68
  ))}
69
69
  {hasMoreItems && (
70
- <ShowMoreButton onClick={() => setIsOn(!isOn)}>
71
- {isOn ? 'Show less' : 'Show more'} <ChevronIcon $isExpanded={isOn} />
70
+ <ShowMoreButton onClick={() => setIsOn(!isOn)} isExpanded={isOn}>
71
+ {isOn ? 'Show less' : 'Show more'}
72
72
  </ShowMoreButton>
73
73
  )}
74
74
  </MetadataWrapper>
@@ -108,25 +108,3 @@ const Heading = styled.h2`
108
108
  margin-top: 0;
109
109
  font-size: var(--catalog-metadata-heading-size);
110
110
  `;
111
-
112
- const ChevronIcon = styled(ChevronDownIcon)<{ $isExpanded: boolean }>`
113
- transform: ${({ $isExpanded }) => ($isExpanded ? 'rotate(180deg)' : 'rotate(0)')};
114
- transition: transform 0.2s ease;
115
- `;
116
-
117
- const ShowMoreButton = styled.button`
118
- background: none;
119
- border: none;
120
- display: flex;
121
- align-items: center;
122
- gap: var(--catalog-metadata-button-gap, 0.5rem);
123
- cursor: pointer;
124
- color: var(--catalog-metadata-button-color);
125
- padding: 0;
126
- font-weight: var(--font-weight-medium);
127
- margin-top: var(--spacing-unit);
128
-
129
- &:hover {
130
- color: var(--catalog-metadata-button-color-hover);
131
- }
132
- `;
@@ -1,4 +1,4 @@
1
- import React, { JSX, useState, useEffect } from 'react';
1
+ import React, { JSX, useState, useEffect, useMemo } from 'react';
2
2
 
3
3
  import type { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
4
4
  import type { BffCatalogEntity, BffCatalogRelatedEntityList } from '@redocly/theme/core/types';
@@ -40,12 +40,25 @@ export function CatalogEntityRelations({
40
40
  setFilter(ENTITY_DEFAULT_FILTERS[entity.key]);
41
41
  }, [entity.key]);
42
42
 
43
+ const combinedFilter = useMemo(() => {
44
+ const baseFilter = filter ?? ENTITY_DEFAULT_FILTERS[entity.type];
45
+ if (entity.version && entity.revision) {
46
+ const versionFilter = `version:"${entity.version}"`;
47
+ const revisionFilter = `revision:"${entity.revision}"`;
48
+ return baseFilter
49
+ ? `${baseFilter} AND ${versionFilter} AND ${revisionFilter}`
50
+ : `${versionFilter} AND ${revisionFilter}`;
51
+ }
52
+
53
+ return baseFilter;
54
+ }, [filter, entity.version, entity.type, entity.revision]);
55
+
43
56
  const { items: relations, query } = useFetchCatalogEntitiesRelations(
44
57
  {
45
58
  entityKey: entity.key,
46
59
  search: searchQuery,
47
60
  sort: sortOption ?? undefined,
48
- filter: filter ?? ENTITY_DEFAULT_FILTERS[entity.type],
61
+ filter: combinedFilter,
49
62
  limit: 10,
50
63
  },
51
64
  initialRelations,
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import { ChevronDownIcon } from '@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon';
5
+
6
+ export type ShowMoreButtonProps = {
7
+ onClick: () => void;
8
+ children: React.ReactNode;
9
+ className?: string;
10
+ isExpanded?: boolean;
11
+ };
12
+
13
+ export function ShowMoreButton({
14
+ onClick,
15
+ children,
16
+ className,
17
+ isExpanded = false,
18
+ }: ShowMoreButtonProps): React.ReactElement {
19
+ return (
20
+ <BaseShowMoreButton type="button" onClick={onClick} className={className}>
21
+ {children}
22
+ <ChevronIcon $isExpanded={isExpanded} />
23
+ </BaseShowMoreButton>
24
+ );
25
+ }
26
+
27
+ const BaseShowMoreButton = styled.button`
28
+ all: unset;
29
+ display: flex;
30
+ align-items: center;
31
+ cursor: pointer;
32
+ background: none;
33
+ border: none;
34
+ gap: var(--catalog-show-more-button-gap);
35
+ color: var(--catalog-show-more-button-color);
36
+ padding: 0;
37
+ margin-top: var(--spacing-unit);
38
+
39
+ &:hover {
40
+ color: var(--catalog-show-more-button-color-hover);
41
+ }
42
+ `;
43
+
44
+ const ChevronIcon = styled(ChevronDownIcon)<{ $isExpanded: boolean }>`
45
+ transform: ${({ $isExpanded }) => ($isExpanded ? 'rotate(180deg)' : 'rotate(0)')};
46
+ transition: transform 0.2s ease;
47
+ `;