@redocly/theme 0.61.0-next.2 → 0.61.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.
- package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +5 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.js +9 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.d.ts +6 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.js +144 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.d.ts +8 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js +161 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.d.ts +8 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.js +67 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.d.ts +9 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.js +212 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +2 -25
- package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +12 -1
- package/lib/components/Catalog/CatalogEntity/ShowMoreButton.d.ts +8 -0
- package/lib/components/Catalog/CatalogEntity/ShowMoreButton.js +35 -0
- package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.d.ts +2 -0
- package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.js +4 -1
- package/lib/components/Catalog/variables.js +112 -0
- package/lib/components/Menu/variables.js +1 -0
- package/lib/components/Tooltip/Tooltip.js +2 -0
- package/lib/core/constants/catalog.d.ts +1 -0
- package/lib/core/constants/catalog.js +2 -1
- package/lib/core/hooks/catalog/use-catalog-entity-details.d.ts +3 -1
- package/lib/core/hooks/catalog/use-catalog-entity-details.js +12 -5
- package/lib/core/hooks/use-color-switcher.js +7 -8
- package/lib/core/hooks/use-page-actions.js +37 -6
- package/lib/core/hooks/use-telemetry-fallback.d.ts +2 -0
- package/lib/core/hooks/use-telemetry-fallback.js +2 -0
- package/lib/core/types/catalog.d.ts +33 -4
- package/lib/core/types/hooks.d.ts +14 -3
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/utils/build-revision-url.d.ts +1 -0
- package/lib/core/utils/build-revision-url.js +15 -0
- package/lib/core/utils/date.d.ts +14 -0
- package/lib/core/utils/date.js +39 -0
- package/lib/core/utils/index.d.ts +2 -0
- package/lib/core/utils/index.js +2 -0
- package/lib/core/utils/transform-revisions-to-version-history.d.ts +8 -0
- package/lib/core/utils/transform-revisions-to-version-history.js +110 -0
- package/lib/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.d.ts +9 -0
- package/lib/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.js +26 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/package.json +6 -6
- package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +7 -1
- package/src/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.tsx +12 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistoryButton.tsx +147 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx +180 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityRevisionItem.tsx +93 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.tsx +284 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +3 -25
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +15 -2
- package/src/components/Catalog/CatalogEntity/ShowMoreButton.tsx +47 -0
- package/src/components/Catalog/CatalogTableView/CatalogTableViewRow.tsx +6 -1
- package/src/components/Catalog/variables.ts +112 -0
- package/src/components/Menu/variables.ts +1 -0
- package/src/components/Tooltip/Tooltip.tsx +2 -0
- package/src/core/constants/catalog.ts +2 -0
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -0
- package/src/core/hooks/catalog/use-catalog-entity-details.ts +22 -6
- package/src/core/hooks/use-color-switcher.ts +13 -10
- package/src/core/hooks/use-page-actions.ts +63 -6
- package/src/core/hooks/use-telemetry-fallback.ts +2 -0
- package/src/core/types/catalog.ts +38 -10
- package/src/core/types/hooks.ts +23 -4
- package/src/core/types/l10n.ts +10 -0
- package/src/core/utils/build-revision-url.ts +16 -0
- package/src/core/utils/date.ts +33 -0
- package/src/core/utils/index.ts +2 -0
- package/src/core/utils/transform-revisions-to-version-history.ts +163 -0
- package/src/icons/NavaidMilitaryIcon/NavaidMilitaryIcon.tsx +43 -0
- package/src/index.ts +2 -0
|
@@ -19,6 +19,8 @@ export type BaseEntity = {
|
|
|
19
19
|
type: string;
|
|
20
20
|
title: string;
|
|
21
21
|
summary?: string | null;
|
|
22
|
+
revision?: string | null;
|
|
23
|
+
version?: string | null;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export type CatalogTableViewRowProps<T extends BaseEntity> = {
|
|
@@ -95,14 +97,17 @@ export const CatalogTableViewRow = <T extends BaseEntity>({
|
|
|
95
97
|
const { getEntityDetailsLink } = useCatalogEntityDetails({
|
|
96
98
|
catalogConfig,
|
|
97
99
|
entitiesCatalogConfig,
|
|
100
|
+
revision: entity.revision,
|
|
101
|
+
version: entity.version,
|
|
98
102
|
});
|
|
103
|
+
const link = getEntityDetailsLink({ key: entity.key, type: entity.type });
|
|
99
104
|
|
|
100
105
|
return (
|
|
101
106
|
<TableRow
|
|
102
107
|
key={entity.id}
|
|
103
108
|
$columnsWidths={columns.map((column) => column.width || '1fr')}
|
|
104
109
|
$columnsMinWidths={columns.map((column) => column.minWidth || 'auto')}
|
|
105
|
-
to={
|
|
110
|
+
to={link}
|
|
106
111
|
onClick={() => onRowClick(entity)}
|
|
107
112
|
style={{ color: 'var(--catalog-page-wrapper-text-color)' }}
|
|
108
113
|
data-component-name="Catalog/CatalogTableView/CatalogTableViewRow"
|
|
@@ -235,6 +235,13 @@ export const catalog = css`
|
|
|
235
235
|
--catalog-metadata-column-half-gap: var(--spacing-sm);
|
|
236
236
|
--catalog-metadata-heading-size: var(--font-size-md);
|
|
237
237
|
|
|
238
|
+
/**
|
|
239
|
+
* @tokens Catalog show more button
|
|
240
|
+
*/
|
|
241
|
+
--catalog-show-more-button-gap: 0.5rem;
|
|
242
|
+
--catalog-show-more-button-color: var(--text-color-primary);
|
|
243
|
+
--catalog-show-more-button-color-hover: var(--text-color-secondary);
|
|
244
|
+
|
|
238
245
|
/**
|
|
239
246
|
* @tokens Catalog arrow circle
|
|
240
247
|
*/
|
|
@@ -427,5 +434,110 @@ export const catalog = css`
|
|
|
427
434
|
--catalog-entity-relations-edge-label-font-size: 12px;
|
|
428
435
|
--catalog-entity-relations-edge-label-line-height: 1.2;
|
|
429
436
|
// @tokens End
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* @tokens Catalog history button
|
|
440
|
+
*/
|
|
441
|
+
--catalog-history-separator-border-color: var(--border-color-secondary);
|
|
442
|
+
--catalog-history-separator-margin-bottom: var(--spacing-sm);
|
|
443
|
+
--catalog-history-item-padding: var(--spacing-xxs);
|
|
444
|
+
--catalog-history-item-margin-bottom: calc(var(--spacing-xxs) * -1);
|
|
445
|
+
--catalog-history-item-gap: var(--spacing-xxs);
|
|
446
|
+
--catalog-history-item-border-radius: var(--menu-item-label-border-radius);
|
|
447
|
+
--catalog-history-item-bg-color-hover: var(--menu-item-bg-color-hover);
|
|
448
|
+
--catalog-history-icon-size: 16px;
|
|
449
|
+
--catalog-history-text-font-family: var(--font-family-base);
|
|
450
|
+
--catalog-history-text-font-size: var(--font-size-base);
|
|
451
|
+
--catalog-history-text-font-weight: var(--font-weight-regular);
|
|
452
|
+
--catalog-history-text-line-height: var(--line-height-base);
|
|
453
|
+
--catalog-history-text-color: var(--text-color-primary);
|
|
454
|
+
--catalog-history-pill-gap: var(--spacing-xxs);
|
|
455
|
+
--catalog-history-pill-padding-vertical: 1px;
|
|
456
|
+
--catalog-history-pill-padding-horizontal: var(--spacing-xs);
|
|
457
|
+
--catalog-history-pill-border-color: var(--border-color-primary);
|
|
458
|
+
--catalog-history-pill-border-radius: 12px;
|
|
459
|
+
--catalog-history-pill-icon-size: 14px;
|
|
460
|
+
--catalog-history-pill-icon-color: var(--color-green-8);
|
|
461
|
+
--catalog-history-pill-font-family: var(--font-family-base);
|
|
462
|
+
--catalog-history-pill-font-size: var(--font-size-base);
|
|
463
|
+
--catalog-history-pill-line-height: var(--line-height-base);
|
|
464
|
+
--catalog-history-pill-text-color: var(--text-color-primary);
|
|
465
|
+
// @tokens End
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @tokens Catalog history sidebar
|
|
469
|
+
*/
|
|
470
|
+
--catalog-history-sidebar-width: 320px;
|
|
471
|
+
--catalog-history-sidebar-bg-color: var(--sidebar-bg-color);
|
|
472
|
+
--catalog-history-sidebar-border-color: var(--border-color-secondary);
|
|
473
|
+
|
|
474
|
+
--catalog-history-sidebar-header-padding: var(--spacing-base) var(--spacing-sm) var(--spacing-base);
|
|
475
|
+
--catalog-history-sidebar-header-font-family: var(--font-family-base);
|
|
476
|
+
--catalog-history-sidebar-header-font-size: var(--font-size-base);
|
|
477
|
+
--catalog-history-sidebar-header-font-weight: var(--font-weight-semibold);
|
|
478
|
+
--catalog-history-sidebar-header-line-height: var(--line-height-base);
|
|
479
|
+
--catalog-history-sidebar-header-letter-spacing: 0;
|
|
480
|
+
--catalog-history-sidebar-header-color: var(--text-color-primary);
|
|
481
|
+
|
|
482
|
+
--catalog-history-sidebar-close-button-size: 32px;
|
|
483
|
+
--catalog-history-sidebar-close-button-border-radius: var(--border-radius-md);
|
|
484
|
+
--catalog-history-sidebar-close-button-bg-color-hover: var(--color-hover-base);
|
|
485
|
+
--catalog-history-sidebar-close-icon-color: var(--text-color-primary);
|
|
486
|
+
|
|
487
|
+
--catalog-history-sidebar-content-padding: 0 var(--spacing-sm);
|
|
488
|
+
--catalog-history-sidebar-content-margin-top: calc(var(--spacing-xxs) * -1);
|
|
489
|
+
|
|
490
|
+
--catalog-history-sidebar-version-header-padding: var(--spacing-xs) var(--spacing-xxs);
|
|
491
|
+
--catalog-history-sidebar-version-header-border-radius: var(--border-radius-md);
|
|
492
|
+
--catalog-history-sidebar-version-header-bg-color-hover: var(--color-hover-base);
|
|
493
|
+
|
|
494
|
+
--catalog-history-sidebar-version-icon-size: 32px;
|
|
495
|
+
--catalog-history-sidebar-version-icon-color: var(--text-color-secondary);
|
|
496
|
+
--catalog-history-sidebar-version-icon-color-current: var(--color-static-white);
|
|
497
|
+
--catalog-history-sidebar-version-icon-margin-right: var(--spacing-xs);
|
|
498
|
+
--catalog-history-sidebar-chevron-icon-color: var(--text-color-secondary);
|
|
499
|
+
--catalog-history-sidebar-version-info-gap: 2px;
|
|
500
|
+
|
|
501
|
+
--catalog-history-sidebar-version-title-font-family: var(--font-family-base);
|
|
502
|
+
--catalog-history-sidebar-version-title-font-size: var(--font-size-base);
|
|
503
|
+
--catalog-history-sidebar-version-title-font-weight: var(--font-weight-medium);
|
|
504
|
+
--catalog-history-sidebar-version-title-line-height: var(--line-height-base);
|
|
505
|
+
--catalog-history-sidebar-version-title-color: var(--color-warm-grey-7);
|
|
506
|
+
|
|
507
|
+
--catalog-history-sidebar-version-date-font-family: var(--font-family-base);
|
|
508
|
+
--catalog-history-sidebar-version-date-font-size: var(--font-size-sm);
|
|
509
|
+
--catalog-history-sidebar-version-date-font-weight: var(--font-weight-regular);
|
|
510
|
+
--catalog-history-sidebar-version-date-line-height: var(--line-height-sm);
|
|
511
|
+
--catalog-history-sidebar-version-date-color: var(--color-warm-grey-7);
|
|
512
|
+
|
|
513
|
+
--catalog-history-sidebar-revisions-padding-left: 40px;
|
|
514
|
+
|
|
515
|
+
--catalog-history-sidebar-revision-item-padding: var(--spacing-xs) var(--spacing-sm);
|
|
516
|
+
--catalog-history-sidebar-revision-item-border-radius: var(--border-radius-md);
|
|
517
|
+
--catalog-history-sidebar-revision-item-bg-color-hover: var(--bg-color-hover);
|
|
518
|
+
|
|
519
|
+
--catalog-history-sidebar-revision-name-font-family: var(--font-family-base);
|
|
520
|
+
--catalog-history-sidebar-revision-name-font-size: var(--font-size-base);
|
|
521
|
+
--catalog-history-sidebar-revision-name-font-weight: var(--font-weight-regular);
|
|
522
|
+
--catalog-history-sidebar-revision-name-line-height: var(--line-height-base);
|
|
523
|
+
--catalog-history-sidebar-revision-name-color: var(--text-color-primary);
|
|
524
|
+
|
|
525
|
+
--catalog-history-sidebar-revision-date-font-family: var(--font-family-base);
|
|
526
|
+
--catalog-history-sidebar-revision-date-font-size: var(--font-size-sm);
|
|
527
|
+
--catalog-history-sidebar-revision-date-font-weight: var(--font-weight-regular);
|
|
528
|
+
--catalog-history-sidebar-revision-date-line-height: var(--line-height-sm);
|
|
529
|
+
--catalog-history-sidebar-revision-date-color: var(--color-warm-grey-7);
|
|
530
|
+
|
|
531
|
+
--catalog-history-sidebar-revision-line-color: var(--border-color-secondary);
|
|
532
|
+
--catalog-history-sidebar-revision-item-bg-color-active: var(--bg-color-active);
|
|
533
|
+
|
|
534
|
+
--catalog-history-sidebar-revisions-limit-message-color: var(--color-warm-grey-6);
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* @tokens Catalog history tag border radius
|
|
538
|
+
*/
|
|
539
|
+
--catalog-history-sidebar-version-tag-border-radius: var(--border-radius-xl);
|
|
540
|
+
--catalog-history-sidebar-revision-tag-border-radius: var(--border-radius-xl);
|
|
541
|
+
// @tokens End
|
|
430
542
|
`;
|
|
431
543
|
/* eslint-enable theme/no-raw-colors-in-styles */
|
|
@@ -40,6 +40,7 @@ export const menu = css`
|
|
|
40
40
|
--menu-item-padding-vertical: var(--spacing-unit); // @presenter Spacing
|
|
41
41
|
--menu-item-padding-horizontal: var(--spacing-xxs); // @presenter Spacing
|
|
42
42
|
--menu-item-nested-offset: var(--spacing-sm); // @presenter Spacing
|
|
43
|
+
--menu-header-container-gap: var(--spacing-sm); // @presenter Spacing
|
|
43
44
|
|
|
44
45
|
/**
|
|
45
46
|
* @tokens Menu item label
|
|
@@ -15,6 +15,7 @@ export const useThemeHooks = vi.fn(() => ({
|
|
|
15
15
|
useTelemetry: vi.fn(() => ({
|
|
16
16
|
send: vi.fn(),
|
|
17
17
|
sendCodeSnippetReportedMessage: vi.fn(),
|
|
18
|
+
sendPageActionsButtonClickedMessage: vi.fn(),
|
|
18
19
|
})),
|
|
19
20
|
useBreadcrumbs: vi.fn().mockReturnValue({ breadcrumbs: [], siblings: undefined }),
|
|
20
21
|
useBanner: vi.fn(() => ({
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import type { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
|
|
2
2
|
import type { BffCatalogEntity } from '@redocly/theme/core/types';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { withPathPrefix } from '../../utils/urls';
|
|
5
5
|
|
|
6
6
|
type Props = {
|
|
7
7
|
catalogConfig: CatalogEntityConfig;
|
|
8
8
|
entitiesCatalogConfig?: EntitiesCatalogConfig;
|
|
9
|
+
revision?: string | null;
|
|
10
|
+
version?: string | null;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
type BaseEntity = Pick<BffCatalogEntity, 'key' | 'type'>;
|
|
12
14
|
|
|
13
|
-
export function useCatalogEntityDetails({
|
|
15
|
+
export function useCatalogEntityDetails({
|
|
16
|
+
catalogConfig,
|
|
17
|
+
entitiesCatalogConfig,
|
|
18
|
+
revision,
|
|
19
|
+
version,
|
|
20
|
+
}: Props) {
|
|
14
21
|
const getCatalogSpecificConfigByEntityTypeIncluded = (entity: BaseEntity) => {
|
|
15
22
|
if (!entitiesCatalogConfig) {
|
|
16
23
|
return;
|
|
@@ -22,14 +29,23 @@ export function useCatalogEntityDetails({ catalogConfig, entitiesCatalogConfig }
|
|
|
22
29
|
};
|
|
23
30
|
|
|
24
31
|
const getEntityDetailsLink = (entity: BaseEntity) => {
|
|
25
|
-
const pathPrefix = getPathPrefix();
|
|
26
32
|
const catalogSpecificConfig = getCatalogSpecificConfigByEntityTypeIncluded(entity);
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
const basePath =
|
|
35
|
+
!catalogSpecificConfig || !entitiesCatalogConfig
|
|
36
|
+
? withPathPrefix(`/catalogs/${catalogConfig.slug}/entities/${entity.key}`)
|
|
37
|
+
: withPathPrefix(`/catalogs/${catalogSpecificConfig.slug}/entities/${entity.key}`);
|
|
38
|
+
|
|
39
|
+
const params = new URLSearchParams();
|
|
40
|
+
if (revision) {
|
|
41
|
+
params.set('revision', revision);
|
|
42
|
+
}
|
|
43
|
+
if (version !== undefined) {
|
|
44
|
+
params.set('version', version ?? '');
|
|
30
45
|
}
|
|
46
|
+
params.set('search', '');
|
|
31
47
|
|
|
32
|
-
return `${
|
|
48
|
+
return `${basePath}?${params.toString()}`;
|
|
33
49
|
};
|
|
34
50
|
|
|
35
51
|
return { getEntityDetailsLink };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useMount } from '@redocly/theme/core/hooks';
|
|
4
|
+
|
|
3
5
|
import { useThemeConfig } from './use-theme-config';
|
|
4
6
|
import { useThemeHooks } from './use-theme-hooks';
|
|
5
7
|
import { createStore, useStore } from './use-store';
|
|
6
8
|
import { DEFAULT_COLOR_MODES } from '../constants';
|
|
7
|
-
import { isBrowser } from '../utils/js-utils';
|
|
8
9
|
|
|
9
10
|
const COLOR_MODE_KEY = 'colorSchema';
|
|
10
11
|
const colorModeStore = createStore<string>({
|
|
@@ -21,15 +22,17 @@ export const useColorSwitcher = () => {
|
|
|
21
22
|
() => themeColorMode?.modes || [DEFAULT_COLOR_MODES.LIGHT, DEFAULT_COLOR_MODES.DARK],
|
|
22
23
|
[themeColorMode],
|
|
23
24
|
);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
|
|
26
|
+
const defaultMode = modes[0] || DEFAULT_COLOR_MODES.LIGHT;
|
|
27
|
+
|
|
28
|
+
const [activeColorMode, setActiveColorMode] = useStore<string>(colorModeStore, defaultMode);
|
|
29
|
+
|
|
30
|
+
useMount(() => {
|
|
31
|
+
const activeMode = Array.from(document.documentElement.classList).find((c) =>
|
|
32
|
+
modes.includes(c),
|
|
33
|
+
);
|
|
34
|
+
setActiveColorMode(activeMode || defaultMode);
|
|
35
|
+
});
|
|
33
36
|
|
|
34
37
|
const switchColorMode = (mode?: string): void => {
|
|
35
38
|
if (mode && !modes.includes(mode)) {
|
|
@@ -17,6 +17,14 @@ import { ClipboardService } from '../utils/clipboard-service';
|
|
|
17
17
|
import { IS_BROWSER } from '../utils/dom';
|
|
18
18
|
import { generateMCPDeepLink } from '../utils/mcp';
|
|
19
19
|
|
|
20
|
+
function createPageActionResource(pageSlug: string, pageUrl: string) {
|
|
21
|
+
return {
|
|
22
|
+
id: pageSlug,
|
|
23
|
+
object: 'page' as const,
|
|
24
|
+
uri: pageUrl,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
const DEFAULT_ENABLED_ACTIONS = [
|
|
21
29
|
'copy',
|
|
22
30
|
'view',
|
|
@@ -41,10 +49,12 @@ export function usePageActions(
|
|
|
41
49
|
mcpUrl?: string,
|
|
42
50
|
actions?: PageActionType[],
|
|
43
51
|
): PageAction[] {
|
|
44
|
-
const { useTranslate, usePageData, usePageProps, usePageSharedData } =
|
|
52
|
+
const { useTranslate, usePageData, usePageProps, usePageSharedData, useTelemetry } =
|
|
53
|
+
useThemeHooks();
|
|
45
54
|
const { translate } = useTranslate();
|
|
46
55
|
const themeConfig = useThemeConfig();
|
|
47
56
|
const pageProps = usePageProps();
|
|
57
|
+
const telemetry = useTelemetry();
|
|
48
58
|
const openApiSharedData = usePageSharedData<
|
|
49
59
|
{ options: { excludeFromSearch: boolean } } | undefined
|
|
50
60
|
>('openAPIDocsStore');
|
|
@@ -67,9 +77,25 @@ export function usePageActions(
|
|
|
67
77
|
? { serverName: mcpConfig.serverName, url: mcpUrl || '' }
|
|
68
78
|
: { serverName: mcpConfig.serverName, url: mcpConfig.serverUrl || '' };
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
const isDocsMcp = !requiresMcpUrl;
|
|
81
|
+
|
|
82
|
+
const origin = IS_BROWSER ? window.location.origin : '';
|
|
83
|
+
const pageUrl = `${origin}${pageSlug}`;
|
|
84
|
+
|
|
85
|
+
return createMCPAction({
|
|
86
|
+
clientType,
|
|
87
|
+
mcpConfig: config,
|
|
88
|
+
translate,
|
|
89
|
+
onClickCallback: isDocsMcp
|
|
90
|
+
? () =>
|
|
91
|
+
telemetry.sendPageActionsButtonClickedMessage({
|
|
92
|
+
...createPageActionResource(pageSlug, pageUrl),
|
|
93
|
+
action_type: `docs-mcp-${clientType}` as const,
|
|
94
|
+
})
|
|
95
|
+
: undefined,
|
|
96
|
+
});
|
|
71
97
|
},
|
|
72
|
-
[mcpUrl, mcpConfig, translate],
|
|
98
|
+
[mcpUrl, mcpConfig, translate, telemetry, pageSlug],
|
|
73
99
|
);
|
|
74
100
|
|
|
75
101
|
const result: PageAction[] = useMemo(() => {
|
|
@@ -81,13 +107,14 @@ export function usePageActions(
|
|
|
81
107
|
? window.location.origin
|
|
82
108
|
: ((globalThis as { SSR_HOSTNAME?: string })['SSR_HOSTNAME'] ?? '');
|
|
83
109
|
const normalizedSlug = pageSlug.startsWith('/') ? pageSlug : '/' + pageSlug;
|
|
110
|
+
const pageUrl = `${origin}${normalizedSlug}`;
|
|
84
111
|
const mdPageUrl = new URL(
|
|
85
112
|
origin + normalizedSlug + (normalizedSlug === '/' ? 'index.html.md' : '.md'),
|
|
86
113
|
).toString();
|
|
87
114
|
|
|
88
115
|
const actionHandlers: Record<PageActionType, () => PageAction | null> = {
|
|
89
|
-
'docs-mcp-cursor': createMCPHandler('cursor'),
|
|
90
|
-
'docs-mcp-vscode': createMCPHandler('vscode'),
|
|
116
|
+
'docs-mcp-cursor': createMCPHandler('cursor', false),
|
|
117
|
+
'docs-mcp-vscode': createMCPHandler('vscode', false),
|
|
91
118
|
'mcp-cursor': createMCPHandler('cursor', true),
|
|
92
119
|
'mcp-vscode': createMCPHandler('vscode', true),
|
|
93
120
|
|
|
@@ -104,6 +131,10 @@ export function usePageActions(
|
|
|
104
131
|
}
|
|
105
132
|
const text = await result.text();
|
|
106
133
|
ClipboardService.copyCustom(text);
|
|
134
|
+
telemetry.sendPageActionsButtonClickedMessage({
|
|
135
|
+
...createPageActionResource(pageSlug, pageUrl),
|
|
136
|
+
action_type: 'copy',
|
|
137
|
+
});
|
|
107
138
|
} catch (error) {
|
|
108
139
|
console.error(error);
|
|
109
140
|
}
|
|
@@ -116,6 +147,12 @@ export function usePageActions(
|
|
|
116
147
|
description: translate('page.actions.viewAsMdDescription', 'Open this page as Markdown'),
|
|
117
148
|
iconComponent: MarkdownFullIcon,
|
|
118
149
|
link: mdPageUrl,
|
|
150
|
+
onClick: () => {
|
|
151
|
+
telemetry.sendPageActionsButtonClickedMessage({
|
|
152
|
+
...createPageActionResource(pageSlug, pageUrl),
|
|
153
|
+
action_type: 'view',
|
|
154
|
+
});
|
|
155
|
+
},
|
|
119
156
|
}),
|
|
120
157
|
|
|
121
158
|
chatgpt: () => {
|
|
@@ -128,6 +165,12 @@ export function usePageActions(
|
|
|
128
165
|
description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
|
|
129
166
|
iconComponent: ChatGptIcon,
|
|
130
167
|
link: getExternalAiPromptLink('https://chat.openai.com', mdPageUrl),
|
|
168
|
+
onClick: () => {
|
|
169
|
+
telemetry.sendPageActionsButtonClickedMessage({
|
|
170
|
+
...createPageActionResource(pageSlug, pageUrl),
|
|
171
|
+
action_type: 'chatgpt',
|
|
172
|
+
});
|
|
173
|
+
},
|
|
131
174
|
};
|
|
132
175
|
},
|
|
133
176
|
|
|
@@ -141,6 +184,12 @@ export function usePageActions(
|
|
|
141
184
|
description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
|
|
142
185
|
iconComponent: ClaudeIcon,
|
|
143
186
|
link: getExternalAiPromptLink('https://claude.ai/new', mdPageUrl),
|
|
187
|
+
onClick: () => {
|
|
188
|
+
telemetry.sendPageActionsButtonClickedMessage({
|
|
189
|
+
...createPageActionResource(pageSlug, pageUrl),
|
|
190
|
+
action_type: 'claude',
|
|
191
|
+
});
|
|
192
|
+
},
|
|
144
193
|
};
|
|
145
194
|
},
|
|
146
195
|
};
|
|
@@ -156,6 +205,7 @@ export function usePageActions(
|
|
|
156
205
|
translate,
|
|
157
206
|
isPublic,
|
|
158
207
|
createMCPHandler,
|
|
208
|
+
telemetry,
|
|
159
209
|
]);
|
|
160
210
|
|
|
161
211
|
return result;
|
|
@@ -172,12 +222,19 @@ type CreateMCPActionParams = {
|
|
|
172
222
|
clientType: MCPClientType;
|
|
173
223
|
mcpConfig: McpConnectionParams;
|
|
174
224
|
translate: (key: string, defaultValue: string) => string;
|
|
225
|
+
onClickCallback?: () => void;
|
|
175
226
|
};
|
|
176
227
|
|
|
177
|
-
function createMCPAction({
|
|
228
|
+
function createMCPAction({
|
|
229
|
+
clientType,
|
|
230
|
+
mcpConfig,
|
|
231
|
+
translate,
|
|
232
|
+
onClickCallback,
|
|
233
|
+
}: CreateMCPActionParams): PageAction {
|
|
178
234
|
const url = generateMCPDeepLink(clientType, mcpConfig);
|
|
179
235
|
const sharedProps = {
|
|
180
236
|
onClick: () => {
|
|
237
|
+
onClickCallback?.();
|
|
181
238
|
window.open(url, '_blank');
|
|
182
239
|
},
|
|
183
240
|
};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
export const useTelemetryFallback = () => ({
|
|
4
4
|
send: () => {},
|
|
5
5
|
sendPageViewedMessage: () => {},
|
|
6
|
+
sendPageActionsButtonClickedMessage: () => {},
|
|
6
7
|
sendErrorMessage: () => {},
|
|
7
8
|
sendClientErrorMessage: () => {},
|
|
8
9
|
sendBreadcrumbClickedMessage: () => {},
|
|
@@ -63,6 +64,7 @@ export const useTelemetryFallback = () => ({
|
|
|
63
64
|
sendAsyncapiDocsMessageClickedMessage: () => {},
|
|
64
65
|
sendAsyncapiDocsServerModalOpenedMessage: () => {},
|
|
65
66
|
sendAsyncapiDocsDownloadDefinitionClickedMessage: () => {},
|
|
67
|
+
sendAsyncapiDocsReferencedInClickedMessage: () => {},
|
|
66
68
|
sendGraphqlDocsViewedMessage: () => {},
|
|
67
69
|
sendGraphqlDocsPerformanceMetricsMessage: () => {},
|
|
68
70
|
sendGraphqlDocsReferencedInLinkClickedMessage: () => {},
|
|
@@ -40,16 +40,6 @@ export type UseCatalogResponse = {
|
|
|
40
40
|
collapsedSidebar: boolean;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export type UseCatalogFetchCatalogEntities = (
|
|
44
|
-
params: CatalogApiParams,
|
|
45
|
-
initialData?: BffCatalogEntityList,
|
|
46
|
-
) => CatalogApiResults<BffCatalogEntity>;
|
|
47
|
-
|
|
48
|
-
export type UseCatalogFetchCatalogEntitiesRelations = (
|
|
49
|
-
params: CatalogApiParams & { entityKey: string },
|
|
50
|
-
initialData?: BffCatalogRelatedEntityList,
|
|
51
|
-
) => CatalogApiResults<BffCatalogRelatedEntity>;
|
|
52
|
-
|
|
53
43
|
export type UseCatalogSortResponse = {
|
|
54
44
|
sortOption: SortOption | null;
|
|
55
45
|
setSortOption: (option: SortOption | null) => void;
|
|
@@ -128,6 +118,7 @@ export type CatalogApiParams = {
|
|
|
128
118
|
filter?: string;
|
|
129
119
|
sort?: string;
|
|
130
120
|
search?: string;
|
|
121
|
+
entityVersion?: string | null;
|
|
131
122
|
};
|
|
132
123
|
|
|
133
124
|
export type UseCatalogEntitiesProps = {
|
|
@@ -170,6 +161,7 @@ export type BffCatalogRelatedEntity = {
|
|
|
170
161
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
171
162
|
metadata?: Record<string, any>;
|
|
172
163
|
version?: string | null;
|
|
164
|
+
revision?: string | null;
|
|
173
165
|
readonly createdAt: string | null;
|
|
174
166
|
readonly updatedAt: string | null;
|
|
175
167
|
};
|
|
@@ -207,6 +199,7 @@ export type BffCatalogEntity = {
|
|
|
207
199
|
readonly revision: string;
|
|
208
200
|
readonly isCurrent?: boolean | null;
|
|
209
201
|
readonly isDefaultVersion?: boolean | null;
|
|
202
|
+
readonly isDeleted?: boolean | null;
|
|
210
203
|
readonly createdAt: string;
|
|
211
204
|
readonly updatedAt: string;
|
|
212
205
|
};
|
|
@@ -229,6 +222,41 @@ export type Page = {
|
|
|
229
222
|
total: number;
|
|
230
223
|
};
|
|
231
224
|
|
|
225
|
+
export type BffCatalogEntityRevision = {
|
|
226
|
+
readonly version: string | null;
|
|
227
|
+
readonly revision: string | null;
|
|
228
|
+
readonly isCurrent: boolean | null;
|
|
229
|
+
readonly isDefaultVersion: boolean | null;
|
|
230
|
+
readonly createdAt: string | null;
|
|
231
|
+
readonly updatedAt: string | null;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export type BffCatalogEntityRevisionList = BffCatalogList<BffCatalogEntityRevision>;
|
|
235
|
+
|
|
232
236
|
export type EntityRelationType = (typeof ENTITY_RELATION_TYPES)[number];
|
|
233
237
|
|
|
234
238
|
export type ListType = 'default' | 'team' | 'api-operation' | 'data-schema';
|
|
239
|
+
|
|
240
|
+
export type CatalogEntityRevision = {
|
|
241
|
+
name: string;
|
|
242
|
+
date: string;
|
|
243
|
+
revisionDate: string | null;
|
|
244
|
+
isActive?: boolean;
|
|
245
|
+
isCurrent?: boolean;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export type CatalogEntityVersionHistoryGroup = {
|
|
249
|
+
version: string;
|
|
250
|
+
date: string;
|
|
251
|
+
isCurrent?: boolean;
|
|
252
|
+
isExpanded?: boolean;
|
|
253
|
+
revisions?: CatalogEntityRevision[];
|
|
254
|
+
singleRevisionDate?: string | null;
|
|
255
|
+
hasCurrentRevisionFromBackend?: boolean;
|
|
256
|
+
isDefaultVersion?: boolean;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export type SidebarConnectedEntity = {
|
|
260
|
+
key: string;
|
|
261
|
+
version?: string;
|
|
262
|
+
};
|
package/src/core/types/hooks.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
import type { ShikiTransformer } from '@shikijs/types';
|
|
10
10
|
import type { Callback, TFunction as TFunc } from 'i18next';
|
|
11
11
|
import type { To, Location, NavigateFunction } from 'react-router-dom';
|
|
12
|
+
import type { UseQueryResult } from '@tanstack/react-query';
|
|
12
13
|
import type { CatalogConfig, ProductUiConfig } from '@redocly/theme/config';
|
|
13
14
|
import type {
|
|
14
15
|
UseCatalogResponse,
|
|
@@ -16,8 +17,8 @@ import type {
|
|
|
16
17
|
UseCatalogSortResponse,
|
|
17
18
|
UseCatalogSearchResponse,
|
|
18
19
|
UseCatalogProps,
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
CatalogApiParams,
|
|
21
|
+
CatalogApiResults,
|
|
21
22
|
} from './catalog';
|
|
22
23
|
import type { UserMenuData } from './user-menu';
|
|
23
24
|
import type { ItemState } from './sidebar';
|
|
@@ -33,6 +34,14 @@ import type { TFunction } from './l10n';
|
|
|
33
34
|
import type { BreadcrumbItem } from './breadcrumb';
|
|
34
35
|
import type { DrilldownMenuItemDetails } from './sidebar';
|
|
35
36
|
|
|
37
|
+
import {
|
|
38
|
+
BffCatalogEntity,
|
|
39
|
+
BffCatalogEntityList,
|
|
40
|
+
BffCatalogRelatedEntity,
|
|
41
|
+
BffCatalogRelatedEntityList,
|
|
42
|
+
BffCatalogEntityRevision,
|
|
43
|
+
BffCatalogEntityRevisionList,
|
|
44
|
+
} from './catalog';
|
|
36
45
|
import { AiSearchError } from '../constants/search';
|
|
37
46
|
|
|
38
47
|
export type ThemeHooks = {
|
|
@@ -147,8 +156,18 @@ export type ThemeHooks = {
|
|
|
147
156
|
useCatalog: (props?: UseCatalogProps) => UseCatalogResponse;
|
|
148
157
|
useCatalogSort: () => UseCatalogSortResponse;
|
|
149
158
|
useCatalogSearch: () => UseCatalogSearchResponse;
|
|
150
|
-
useFetchCatalogEntities:
|
|
151
|
-
|
|
159
|
+
useFetchCatalogEntities: (
|
|
160
|
+
params: CatalogApiParams,
|
|
161
|
+
initialData?: BffCatalogEntityList,
|
|
162
|
+
) => CatalogApiResults<BffCatalogEntity>;
|
|
163
|
+
useFetchCatalogEntitiesRelations: (
|
|
164
|
+
params: CatalogApiParams & { entityKey: string },
|
|
165
|
+
initialData?: BffCatalogRelatedEntityList,
|
|
166
|
+
) => CatalogApiResults<BffCatalogRelatedEntity>;
|
|
167
|
+
useFetchCatalogEntityRevisions: (params: { entityKey: string; version?: string | null }) => {
|
|
168
|
+
query: UseQueryResult<BffCatalogEntityRevisionList, Error>;
|
|
169
|
+
items: BffCatalogEntityRevision[];
|
|
170
|
+
};
|
|
152
171
|
useCatalogClassic: (config: CatalogConfig) => FilteredCatalog;
|
|
153
172
|
useTelemetry: () => Omit<
|
|
154
173
|
AsyncApiRealmUI.Telemetry,
|
package/src/core/types/l10n.ts
CHANGED
|
@@ -170,6 +170,16 @@ export type TranslationKey =
|
|
|
170
170
|
| 'catalog.links.label'
|
|
171
171
|
| 'catalog.metadata.domains'
|
|
172
172
|
| 'catalog.metadata.owners'
|
|
173
|
+
| 'catalog.history.button.label'
|
|
174
|
+
| 'catalog.history.sidebar.title'
|
|
175
|
+
| 'catalog.history.sidebar.close'
|
|
176
|
+
| 'catalog.history.version.label'
|
|
177
|
+
| 'catalog.history.version.notSpecified'
|
|
178
|
+
| 'catalog.history.version.default'
|
|
179
|
+
| 'catalog.history.revisions.limitMessage'
|
|
180
|
+
| 'catalog.history.revision.current'
|
|
181
|
+
| 'catalog.history.revisions.showLess'
|
|
182
|
+
| 'catalog.history.revisions.showMore'
|
|
173
183
|
| 'sidebar.menu.backLabel'
|
|
174
184
|
| 'sidebar.menu.backToLabel'
|
|
175
185
|
| 'sidebar.actions.show'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function buildRevisionUrl(
|
|
2
|
+
basePath: string,
|
|
3
|
+
revisionDate: string | null | undefined,
|
|
4
|
+
version?: string | null,
|
|
5
|
+
): string | undefined {
|
|
6
|
+
if (!revisionDate) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const params = new URLSearchParams();
|
|
11
|
+
params.set('revision', revisionDate);
|
|
12
|
+
if (version) {
|
|
13
|
+
params.set('version', version);
|
|
14
|
+
}
|
|
15
|
+
return `${basePath}?${params.toString()}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a date string to localized short date format (e.g., "Dec 12, 2025")
|
|
3
|
+
* @param dateString - ISO date string or null
|
|
4
|
+
* @param locale - Locale string (e.g., "en-US")
|
|
5
|
+
* @returns Formatted date string or empty string if dateString is null
|
|
6
|
+
*/
|
|
7
|
+
export function toLocalizedShortDate(dateString: string | null, locale: string): string {
|
|
8
|
+
if (!dateString) return '';
|
|
9
|
+
const date = new Date(dateString);
|
|
10
|
+
return date.toLocaleDateString(locale, {
|
|
11
|
+
month: 'short',
|
|
12
|
+
day: 'numeric',
|
|
13
|
+
year: 'numeric',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Formats a date string to localized short date-time format (e.g., "Dec 12, 3:45 PM")
|
|
19
|
+
* @param dateString - ISO date string or null
|
|
20
|
+
* @param locale - Locale string (e.g., "en-US")
|
|
21
|
+
* @returns Formatted date-time string or empty string if dateString is null
|
|
22
|
+
*/
|
|
23
|
+
export function toLocalizedShortDateTime(dateString: string | null, locale: string): string {
|
|
24
|
+
if (!dateString) return '';
|
|
25
|
+
const date = new Date(dateString);
|
|
26
|
+
return date.toLocaleString(locale, {
|
|
27
|
+
month: 'short',
|
|
28
|
+
day: 'numeric',
|
|
29
|
+
hour: 'numeric',
|
|
30
|
+
minute: '2-digit',
|
|
31
|
+
hour12: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
package/src/core/utils/index.ts
CHANGED