@redocly/theme 0.70.0-next.6 → 0.70.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 (87) hide show
  1. package/lib/components/Buttons/ConnectMCPButton.js +11 -1
  2. package/lib/components/Buttons/variables.d.ts +1 -0
  3. package/lib/components/Buttons/variables.js +4 -1
  4. package/lib/components/Catalog/Catalog.js +2 -2
  5. package/lib/components/JsonViewer/Helpers.js +3 -3
  6. package/lib/components/MCP/McpConnectionTabs.js +9 -2
  7. package/lib/components/Portal/Portal.js +37 -5
  8. package/lib/components/Search/SearchAiActionButtons.js +8 -3
  9. package/lib/components/Search/SearchDialog.js +10 -0
  10. package/lib/components/Search/SearchItem.js +1 -1
  11. package/lib/components/Search/SearchTrigger.js +33 -8
  12. package/lib/components/Search/variables.js +2 -0
  13. package/lib/core/constants/mcp.d.ts +2 -2
  14. package/lib/core/constants/mcp.js +1 -1
  15. package/lib/core/contexts/PortalContainerContext.d.ts +2 -0
  16. package/lib/core/contexts/PortalContainerContext.js +7 -0
  17. package/lib/core/hooks/code-walkthrough/use-code-panel.d.ts +1 -1
  18. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.d.ts +1 -1
  19. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +1 -1
  20. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.d.ts +1 -1
  21. package/lib/core/hooks/code-walkthrough/use-code-walkthrough.d.ts +1 -2
  22. package/lib/core/hooks/code-walkthrough/use-renderable-files.d.ts +1 -1
  23. package/lib/core/hooks/index.d.ts +1 -0
  24. package/lib/core/hooks/index.js +1 -0
  25. package/lib/core/hooks/search/use-persisted-quick-filter.d.ts +21 -0
  26. package/lib/core/hooks/search/use-persisted-quick-filter.js +92 -0
  27. package/lib/core/hooks/use-connect-mcp-button.js +1 -0
  28. package/lib/core/hooks/use-page-actions.d.ts +1 -1
  29. package/lib/core/hooks/use-page-actions.js +6 -0
  30. package/lib/core/styles/global.js +1 -0
  31. package/lib/core/types/code-walkthrough.d.ts +84 -0
  32. package/lib/core/types/hooks.d.ts +1 -1
  33. package/lib/core/types/l10n.d.ts +1 -1
  34. package/lib/core/types/mcp.d.ts +1 -1
  35. package/lib/core/utils/download-code-walkthrough.d.ts +1 -1
  36. package/lib/core/utils/get-code-walkthrough-file-text.d.ts +1 -1
  37. package/lib/core/utils/match-code-walkthrough-conditions.d.ts +1 -1
  38. package/lib/core/utils/mcp.js +7 -2
  39. package/lib/markdoc/components/CodeWalkthrough/CodeFilters.d.ts +1 -1
  40. package/lib/markdoc/components/CodeWalkthrough/CodePanel.d.ts +1 -1
  41. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.d.ts +1 -1
  42. package/lib/markdoc/components/CodeWalkthrough/CodePanelToolbar.d.ts +1 -1
  43. package/lib/markdoc/components/CodeWalkthrough/CodeStep.d.ts +1 -1
  44. package/lib/markdoc/components/CodeWalkthrough/CodeWalkthrough.d.ts +1 -1
  45. package/lib/markdoc/components/Tabs/TabList.js +8 -6
  46. package/lib/markdoc/tags/code-walkthrough.d.ts +1 -1
  47. package/package.json +4 -3
  48. package/src/components/Buttons/ConnectMCPButton.tsx +13 -2
  49. package/src/components/Buttons/variables.ts +4 -0
  50. package/src/components/Catalog/Catalog.tsx +5 -3
  51. package/src/components/JsonViewer/Helpers.tsx +5 -3
  52. package/src/components/MCP/McpConnectionTabs.tsx +22 -5
  53. package/src/components/Portal/Portal.tsx +4 -2
  54. package/src/components/Search/SearchAiActionButtons.tsx +31 -19
  55. package/src/components/Search/SearchDialog.tsx +11 -0
  56. package/src/components/Search/SearchItem.tsx +3 -1
  57. package/src/components/Search/SearchTrigger.tsx +42 -7
  58. package/src/components/Search/variables.ts +2 -0
  59. package/src/core/constants/mcp.ts +1 -1
  60. package/src/core/contexts/PortalContainerContext.tsx +4 -0
  61. package/src/core/hooks/__mocks__/index.ts +1 -0
  62. package/src/core/hooks/code-walkthrough/use-code-panel.ts +1 -1
  63. package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +2 -2
  64. package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +1 -1
  65. package/src/core/hooks/code-walkthrough/use-code-walkthrough.ts +3 -3
  66. package/src/core/hooks/code-walkthrough/use-renderable-files.ts +1 -1
  67. package/src/core/hooks/index.ts +1 -0
  68. package/src/core/hooks/search/use-persisted-quick-filter.ts +125 -0
  69. package/src/core/hooks/use-connect-mcp-button.ts +7 -1
  70. package/src/core/hooks/use-page-actions.ts +17 -0
  71. package/src/core/styles/global.ts +2 -1
  72. package/src/core/types/code-walkthrough.ts +103 -0
  73. package/src/core/types/hooks.ts +1 -0
  74. package/src/core/types/l10n.ts +6 -0
  75. package/src/core/types/mcp.ts +1 -1
  76. package/src/core/utils/download-code-walkthrough.ts +1 -1
  77. package/src/core/utils/get-code-walkthrough-file-text.ts +1 -1
  78. package/src/core/utils/match-code-walkthrough-conditions.ts +1 -1
  79. package/src/core/utils/mcp.ts +8 -2
  80. package/src/markdoc/components/CodeWalkthrough/CodeFilters.tsx +1 -1
  81. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -1
  82. package/src/markdoc/components/CodeWalkthrough/CodePanelHeader.tsx +1 -1
  83. package/src/markdoc/components/CodeWalkthrough/CodePanelToolbar.tsx +1 -1
  84. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +1 -1
  85. package/src/markdoc/components/CodeWalkthrough/CodeWalkthrough.tsx +1 -1
  86. package/src/markdoc/components/Tabs/TabList.tsx +9 -12
  87. package/src/markdoc/tags/code-walkthrough.ts +1 -1
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { MarkerArea } from './marker';
2
3
  export type ActiveStep = string | null;
3
4
  export type WalkthroughStepsState = {
@@ -11,3 +12,86 @@ export type WalkthroughStepsState = {
11
12
  lockObserver?: React.RefObject<boolean>;
12
13
  filtersElementRef?: React.RefObject<HTMLDivElement | null>;
13
14
  };
15
+ export type CodeWalkthroughStepAttr = {
16
+ id: string;
17
+ title?: string;
18
+ };
19
+ export type FilesetsMarkdocAttr = WithConditions<{
20
+ files?: string[];
21
+ downloadAssociatedFiles?: string[];
22
+ }>[];
23
+ export type InputsMarkdocAttr = {
24
+ [id: string]: WithConditions<{
25
+ value: string;
26
+ }>;
27
+ };
28
+ export type TogglesMarkdocAttr = {
29
+ [id: string]: CodeWalkthroughConditionsObject;
30
+ };
31
+ export type CodeWalkthroughConditions = {
32
+ [key: string]: string | string[] | undefined | boolean;
33
+ };
34
+ export type CodeWalkthroughFileset = WithConditions<{
35
+ files?: CodeWalkthroughFile[];
36
+ downloadAssociatedFiles?: CodeWalkthroughFile[];
37
+ }>;
38
+ export type CodeWalkthroughFile = {
39
+ path: string;
40
+ content: CodeWalkthroughNode[];
41
+ basename: string;
42
+ metadata: CodeWalkthroughFileMetadata;
43
+ language: string;
44
+ };
45
+ export type CodeWalkthroughChunk = {
46
+ start: number;
47
+ children: CodeWalkthroughNode[];
48
+ condition: CodeWalkthroughChunkCondition;
49
+ };
50
+ export type CodeWalkthroughChunkCondition = WithConditions<{
51
+ steps: string[];
52
+ }>;
53
+ export type CodeWalkthroughNode = CodeWalkthroughChunk | string;
54
+ export type CodeWalkthroughFileMetadata = {
55
+ steps: string[];
56
+ };
57
+ export type CodeWalkthroughFilter = WithConditions<{
58
+ id: string;
59
+ label?: string;
60
+ items: CodeWalkthroughFilterItem[];
61
+ }>;
62
+ export type CodeWalkthroughFilterItem = WithConditions<{
63
+ value: string;
64
+ }>;
65
+ export type CodeWalkthroughConditionsObject = {
66
+ when?: CodeWalkthroughConditions;
67
+ unless?: CodeWalkthroughConditions;
68
+ };
69
+ export type WithConditions<T> = T & CodeWalkthroughConditionsObject;
70
+ export type CodeWalkthroughControls = {
71
+ toggle: boolean;
72
+ input: string;
73
+ filter: string;
74
+ };
75
+ export type CodeWalkthroughControlState = WithConditions<{
76
+ value: string;
77
+ render: boolean;
78
+ type: 'input';
79
+ } | {
80
+ value: string;
81
+ render: boolean;
82
+ type: 'filter';
83
+ } | {
84
+ value: boolean;
85
+ render: boolean;
86
+ type: 'toggle';
87
+ }>;
88
+ export type CodeWalkthroughControlsState = Record<string, CodeWalkthroughControlState>;
89
+ export type CodeWalkthroughAttr = {
90
+ steps: CodeWalkthroughStepAttr[];
91
+ filters: Record<string, CodeWalkthroughFilter>;
92
+ filesets: CodeWalkthroughFileset[];
93
+ preview: ReactNode[];
94
+ inputs: InputsMarkdocAttr;
95
+ toggles: TogglesMarkdocAttr;
96
+ __idx: number;
97
+ };
@@ -152,7 +152,7 @@ export type ThemeHooks = {
152
152
  items: BffCatalogEntityRevision[];
153
153
  };
154
154
  useCatalogClassic: (config: CatalogConfig) => FilteredCatalog;
155
- useTelemetry: () => Omit<AsyncApiRealmUI.Telemetry, 'init' | 'updateCloudEventData' | 'forceFlush' | 'startSpan' | 'constructCloudEvent' | 'sendToOtelService'> & {
155
+ useTelemetry: () => Omit<AsyncApiRealmUI.Telemetry, 'init' | 'updateCloudEventData' | 'forceFlush' | 'startSpan' | 'constructCloudEvent' | 'sendToOtelService' | 'withTracer'> & {
156
156
  send<TEventType extends AsyncApiRealmUI.EventType>(event: TEventType, data?: AsyncApiRealmUI.EventPayload<TEventType>): void;
157
157
  /**
158
158
  * @deprecated This method is deprecated. Use send(event, data) instead.
@@ -1,5 +1,5 @@
1
1
  import type { TOptions } from 'i18next';
2
- export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.create.app.dialog.callbackUrls' | 'dev.create.app.dialog.callbackUrls.placeholder' | 'dev.create.app.dialog.callbackUrls.hint' | 'dev.app.callbackUrls.title' | 'dev.edit.callbackUrls.dialog.title' | 'dev.edit.callbackUrls.dialog.placeholder' | 'dev.edit.callbackUrls.dialog.hint' | 'dev.edit.callbackUrls.dialog.save' | 'dev.edit.callbackUrls.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.error.title' | 'search.error.button' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.back' | 'search.ai.assistant' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.send' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | 'search.ai.feedback.title' | 'search.ai.feedback.detailsPlaceholder' | 'search.ai.feedback.thanks' | 'search.ai.toolCall.executed' | 'search.ai.toolCall.executing' | 'search.ai.toolCall.usedTools' | 'search.ai.button' | 'search.ai.label' | 'search.ai.disclaimer' | 'search.ai.error.description' | 'search.ai.error.description.forbidden' | 'search.ai.error.description.unauthorized' | 'search.ai.error.header' | 'search.ai.error.header.forbidden' | 'search.ai.error.header.unauthorized' | 'search.ai.feedback.more' | 'search.searchItem.deprecated' | 'search.searchItem.enum' | 'search.searchItem.example' | 'search.groups.all' | 'search.filter.field.footer' | 'aiAssistant.trigger' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.forbidden.description' | 'page.notFound.title' | 'page.notFound.description' | 'page.apiNotFound.title' | 'page.apiNotFound.description' | 'page.apiNotFound.hint' | 'page.apiNotFound.backButton' | 'page.mcpNotAllowed.title' | 'page.mcpNotAllowed.description' | 'page.mcpNotAllowed.publicNote' | 'page.mcpNotAllowed.publicEndpointHint' | 'page.mcpNotAllowed.mainEndpointHint' | 'page.mcpNotAllowed.snippets.terminal.hint' | 'page.mcpNotAllowed.snippets.claudeCode.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.instruction' | 'page.mcpNotAllowed.snippets.chatgptApp.headline' | 'page.mcpNotAllowed.snippets.chatgptApp.instruction' | 'page.mcpNotAllowed.snippets.codexCli.headline' | 'page.mcpNotAllowed.snippets.prompt.headline' | 'page.mcpNotAllowed.snippets.prompt.hint' | 'page.mcpNotAllowed.snippets.json.hint' | 'page.mcpNotAllowed.tabs.claude' | 'page.mcpNotAllowed.tabs.chatgpt' | 'page.mcpNotAllowed.tabs.json' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.add' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'catalog.catalogs.all.title' | 'catalog.catalogs.all.description' | 'catalog.catalogs.all.switcherLabel' | 'catalog.catalogs.service.title' | 'catalog.catalogs.service.description' | 'catalog.catalogs.service.switcherLabel' | 'catalog.catalogs.user.title' | 'catalog.catalogs.user.description' | 'catalog.catalogs.user.switcherLabel' | 'catalog.catalogs.team.title' | 'catalog.catalogs.team.description' | 'catalog.catalogs.team.switcherLabel' | 'catalog.catalogs.domain.title' | 'catalog.catalogs.domain.description' | 'catalog.catalogs.domain.switcherLabel' | 'catalog.catalogs.apiDescription.title' | 'catalog.catalogs.apiDescription.description' | 'catalog.catalogs.apiDescription.switcherLabel' | 'catalog.catalogs.dataSchema.title' | 'catalog.catalogs.dataSchema.description' | 'catalog.catalogs.dataSchema.switcherLabel' | 'catalog.catalogs.apiOperation.title' | 'catalog.catalogs.apiOperation.description' | 'catalog.catalogs.apiOperation.switcherLabel' | 'catalog.entity.metadata.title' | 'catalog.entity.schema.title' | 'catalog.entity.properties.apiDescription.title' | 'catalog.backToAllLabel' | 'catalog.notConnected' | 'catalog.tags.label' | 'catalog.sort' | 'catalog.catalogs.label' | 'catalog.owners.label' | 'catalog.repositories.label' | 'catalog.email.label' | 'catalog.format.label' | 'catalog.entityType.label' | 'catalog.domains.label' | 'catalog.contact.label' | 'catalog.methodAndPath.label' | 'catalog.links.label' | 'catalog.metadata.domains' | 'catalog.metadata.owners' | 'catalog.history.button.label' | 'catalog.history.sidebar.title' | 'catalog.history.sidebar.close' | 'catalog.history.version.label' | 'catalog.filters.close' | 'catalog.history.version.notSpecified' | 'catalog.history.version.default' | 'catalog.history.revisions.limitMessage' | 'catalog.history.revision.current' | 'catalog.history.revisions.showLess' | 'catalog.history.revisions.showMore' | 'navigationTabs.label' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeToSingleColumn' | 'sidebar.actions.changeToTwoColumns' | 'sidebar.actions.singleColumn' | 'sidebar.actions.twoColumns' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.maxLength' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.submit' | 'feedback.cancel' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.optionalEmail.placeholder' | 'feedback.settings.optionalEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'codeSnippet.expand.tooltipText' | 'codeSnippet.collapse.tooltipText' | 'jsonViewer.showMore' | 'jsonViewer.showLess' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | 'navbar.label' | 'navbar.products' | 'page.nextButton' | 'page.previousButton' | 'page.actions.copyButtonText' | 'page.actions.copyTitle' | 'page.actions.copyDescription' | 'page.actions.viewAsMdTitle' | 'page.actions.viewAsMdButtonText' | 'page.actions.viewAsMdDescription' | 'page.actions.chatGptTitle' | 'page.actions.chatGptButtonText' | 'page.actions.chatGptDescription' | 'page.actions.claudeTitle' | 'page.actions.claudeButtonText' | 'page.actions.claudeDescription' | 'page.actions.cursorMcpButtonText' | 'page.actions.cursorMcpTitle' | 'page.actions.cursorMcpDescription' | 'page.actions.connectMcp' | 'page.actions.connectMcp.cursor' | 'page.actions.connectMcp.cursorDescription' | 'page.actions.connectMcp.vscode' | 'page.actions.connectMcp.vscodeDescription' | 'page.actions.connectMcp.claudeCode' | 'page.actions.connectMcp.claudeCodeDescription' | 'page.actions.connectMcp.codex' | 'page.actions.connectMcp.codexDescription' | 'page.actions.connectMcp.copyConfig' | 'page.actions.connectMcp.copyConfigDescription' | 'page.actions.connectMcp.moreOptions' | 'page.actions.moreActions' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'graphql.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.languages.moreButton.tooltipText' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.schemas' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.querystring' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.property' | 'openapi.properties' | 'openapi.details' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.deepLink.tooltip' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.discriminator.defaultMapping' | 'openapi.discriminator.defaultMappingTooltip' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.noRequestData' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.showOptionalScopes' | 'openapi.hideOptionalScopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'openapi.schemaCatalogLink.title' | 'openapi.schemaCatalogLink.copyButtonTooltip' | 'openapi.schemaCatalogLink.copiedTooltip' | 'openapi.mcp.title' | 'openapi.mcp.endpoint' | 'openapi.mcp.tools' | 'openapi.mcp.protocolVersion' | 'openapi.mcp.capabilities' | 'openapi.mcp.experimentalCapabilities' | 'openapi.mcp.inputSchema' | 'openapi.mcp.inputExample' | 'openapi.mcp.outputSchema' | 'openapi.mcp.outputExample' | 'openapi.mcp.exampleTitle' | 'openapi.mcp.argumentsExample' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'asyncapi.info.contact.url' | 'asyncapi.info.contact.name' | 'asyncapi.info.license' | 'asyncapi.info.termsOfService' | 'asyncapi.key' | 'asyncapi.value' | 'asyncapi.variables' | 'asyncapi.required' | 'asyncapi.requiredScopes' | 'asyncapi.viewSecurityDetails' | 'graphql.download.description.title' | 'graphql.info.title' | 'graphql.info.contact.url' | 'graphql.info.contact.name' | 'graphql.info.license' | 'graphql.info.termsOfService' | 'graphql.overview' | 'graphql.metadata' | 'graphql.key' | 'graphql.value' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.actions.show' | 'graphql.actions.hide' | 'graphql.actions.more' | 'graphql.fields' | 'graphql.inputFields' | 'graphql.values' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.requiredScopes' | 'graphql.viewSecurityDetails' | 'graphql.objectScopes' | 'graphql.fieldScopes' | 'graphql.implementedInterfaces' | 'graphql.implementedBy' | 'graphql.nonNull' | 'graphql.required' | 'asyncapi.badges.deprecated' | 'graphql.badges.deprecated' | 'asyncapi.actions.show' | 'asyncapi.actions.hide' | 'asyncapi.actions.more' | 'asyncapi.payload' | 'asyncapi.parameters' | 'asyncapi.messages' | 'asyncapi.contentType' | 'asyncapi.moreDetails' | 'asyncapi.property' | 'asyncapi.properties' | 'asyncapi.details' | 'asyncapi.reply' | 'asyncapi.servers.title' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | 'button.download.tooltipText' | 'button.externalLink.tooltipText' | 'button.email.tooltipText' | 'codeWalkthrough.download' | 'codeWalkthrough.preview' | 'time.justNow' | 'time.past.second' | 'time.past.seconds' | 'time.past.minute' | 'time.past.minutes' | 'time.past.hour' | 'time.past.hours' | 'time.past.day' | 'time.past.days' | 'time.past.week' | 'time.past.weeks' | 'time.past.month' | 'time.past.months' | 'time.past.year' | 'time.past.years' | 'page.internalServerError.title' | 'page.internalServerError.description' | 'page.skipToContent.label' | 'select.noResults' | 'loaders.loading' | 'filter.dateRange.from' | 'filter.dateRange.to' | 'diagram.openFullscreen' | 'diagram.zoomIn' | 'diagram.zoomOut' | 'diagram.reset' | 'diagram.close' | 'diagram.viewer' | 'consent.title' | 'consent.message' | 'consent.privacyPolicy' | 'consent.customize' | 'consent.rejectAll' | 'consent.acceptAll' | 'consent.acceptAllCookies' | 'consent.savePreferences' | 'consent.dialog.title' | 'consent.dialog.description' | 'consent.dialog.close' | 'consent.alwaysOn' | 'consent.alwaysOff' | 'consent.gpcNotice' | 'consent.category.necessary.title' | 'consent.category.necessary.description' | 'consent.category.analytics.title' | 'consent.category.analytics.description' | 'consent.category.marketing.title' | 'consent.category.marketing.description' | 'consent.settingsLink';
2
+ export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.create.app.dialog.callbackUrls' | 'dev.create.app.dialog.callbackUrls.placeholder' | 'dev.create.app.dialog.callbackUrls.hint' | 'dev.app.callbackUrls.title' | 'dev.edit.callbackUrls.dialog.title' | 'dev.edit.callbackUrls.dialog.placeholder' | 'dev.edit.callbackUrls.dialog.hint' | 'dev.edit.callbackUrls.dialog.save' | 'dev.edit.callbackUrls.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.error.title' | 'search.error.button' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.back' | 'search.ai.assistant' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.send' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | 'search.ai.feedback.title' | 'search.ai.feedback.detailsPlaceholder' | 'search.ai.feedback.thanks' | 'search.ai.toolCall.executed' | 'search.ai.toolCall.executing' | 'search.ai.toolCall.usedTools' | 'search.ai.button' | 'search.ai.label' | 'search.ai.disclaimer' | 'search.ai.error.description' | 'search.ai.error.description.forbidden' | 'search.ai.error.description.unauthorized' | 'search.ai.error.header' | 'search.ai.error.header.forbidden' | 'search.ai.error.header.unauthorized' | 'search.ai.feedback.more' | 'search.ai.actions.copy' | 'search.ai.actions.like' | 'search.ai.actions.dislike' | 'search.searchItem.deprecated' | 'search.searchItem.enum' | 'search.searchItem.example' | 'search.groups.all' | 'search.filter.field.footer' | 'aiAssistant.trigger' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.forbidden.description' | 'page.notFound.title' | 'page.notFound.description' | 'page.apiNotFound.title' | 'page.apiNotFound.description' | 'page.apiNotFound.hint' | 'page.apiNotFound.backButton' | 'page.mcpNotAllowed.title' | 'page.mcpNotAllowed.description' | 'page.mcpNotAllowed.publicNote' | 'page.mcpNotAllowed.publicEndpointHint' | 'page.mcpNotAllowed.mainEndpointHint' | 'page.mcpNotAllowed.snippets.terminal.hint' | 'page.mcpNotAllowed.snippets.claudeCode.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.accountHint' | 'page.mcpNotAllowed.snippets.claudeDesktop.instruction' | 'page.mcpNotAllowed.snippets.chatgptApp.headline' | 'page.mcpNotAllowed.snippets.chatgptApp.instruction' | 'page.mcpNotAllowed.snippets.codexCli.headline' | 'page.mcpNotAllowed.snippets.prompt.headline' | 'page.mcpNotAllowed.snippets.prompt.hint' | 'page.mcpNotAllowed.snippets.json.hint' | 'page.mcpNotAllowed.tabs.claude' | 'page.mcpNotAllowed.tabs.chatgpt' | 'page.mcpNotAllowed.tabs.json' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.add' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'catalog.catalogs.all.title' | 'catalog.catalogs.all.description' | 'catalog.catalogs.all.switcherLabel' | 'catalog.catalogs.service.title' | 'catalog.catalogs.service.description' | 'catalog.catalogs.service.switcherLabel' | 'catalog.catalogs.user.title' | 'catalog.catalogs.user.description' | 'catalog.catalogs.user.switcherLabel' | 'catalog.catalogs.team.title' | 'catalog.catalogs.team.description' | 'catalog.catalogs.team.switcherLabel' | 'catalog.catalogs.domain.title' | 'catalog.catalogs.domain.description' | 'catalog.catalogs.domain.switcherLabel' | 'catalog.catalogs.apiDescription.title' | 'catalog.catalogs.apiDescription.description' | 'catalog.catalogs.apiDescription.switcherLabel' | 'catalog.catalogs.dataSchema.title' | 'catalog.catalogs.dataSchema.description' | 'catalog.catalogs.dataSchema.switcherLabel' | 'catalog.catalogs.apiOperation.title' | 'catalog.catalogs.apiOperation.description' | 'catalog.catalogs.apiOperation.switcherLabel' | 'catalog.entity.metadata.title' | 'catalog.entity.schema.title' | 'catalog.entity.properties.apiDescription.title' | 'catalog.backToAllLabel' | 'catalog.notConnected' | 'catalog.tags.label' | 'catalog.sort' | 'catalog.catalogs.label' | 'catalog.owners.label' | 'catalog.repositories.label' | 'catalog.email.label' | 'catalog.format.label' | 'catalog.entityType.label' | 'catalog.domains.label' | 'catalog.contact.label' | 'catalog.methodAndPath.label' | 'catalog.links.label' | 'catalog.metadata.domains' | 'catalog.metadata.owners' | 'catalog.history.button.label' | 'catalog.history.sidebar.title' | 'catalog.history.sidebar.close' | 'catalog.history.version.label' | 'catalog.filters.close' | 'catalog.history.version.notSpecified' | 'catalog.history.version.default' | 'catalog.history.revisions.limitMessage' | 'catalog.history.revision.current' | 'catalog.history.revisions.showLess' | 'catalog.history.revisions.showMore' | 'navigationTabs.label' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeToSingleColumn' | 'sidebar.actions.changeToTwoColumns' | 'sidebar.actions.singleColumn' | 'sidebar.actions.twoColumns' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.maxLength' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.submit' | 'feedback.cancel' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.optionalEmail.placeholder' | 'feedback.settings.optionalEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'codeSnippet.expand.tooltipText' | 'codeSnippet.collapse.tooltipText' | 'jsonViewer.showMore' | 'jsonViewer.showLess' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | 'navbar.label' | 'navbar.products' | 'page.nextButton' | 'page.previousButton' | 'page.actions.copyButtonText' | 'page.actions.copyTitle' | 'page.actions.copyDescription' | 'page.actions.viewAsMdTitle' | 'page.actions.viewAsMdButtonText' | 'page.actions.viewAsMdDescription' | 'page.actions.chatGptTitle' | 'page.actions.chatGptButtonText' | 'page.actions.chatGptDescription' | 'page.actions.claudeTitle' | 'page.actions.claudeButtonText' | 'page.actions.claudeDescription' | 'page.actions.cursorMcpButtonText' | 'page.actions.cursorMcpTitle' | 'page.actions.cursorMcpDescription' | 'page.actions.connectMcp' | 'page.actions.connectMcp.cursor' | 'page.actions.connectMcp.cursorDescription' | 'page.actions.connectMcp.vscode' | 'page.actions.connectMcp.vscodeDescription' | 'page.actions.connectMcp.claude' | 'page.actions.connectMcp.claudeDescription' | 'page.actions.connectMcp.claudeCode' | 'page.actions.connectMcp.claudeCodeDescription' | 'page.actions.connectMcp.codex' | 'page.actions.connectMcp.codexDescription' | 'page.actions.connectMcp.copyConfig' | 'page.actions.connectMcp.copyConfigDescription' | 'page.actions.connectMcp.moreOptions' | 'page.actions.moreActions' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'graphql.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.languages.moreButton.tooltipText' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.schemas' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.querystring' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.property' | 'openapi.properties' | 'openapi.details' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.deepLink.tooltip' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.discriminator.defaultMapping' | 'openapi.discriminator.defaultMappingTooltip' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.noRequestData' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.showOptionalScopes' | 'openapi.hideOptionalScopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'openapi.schemaCatalogLink.title' | 'openapi.schemaCatalogLink.copyButtonTooltip' | 'openapi.schemaCatalogLink.copiedTooltip' | 'openapi.mcp.title' | 'openapi.mcp.endpoint' | 'openapi.mcp.tools' | 'openapi.mcp.protocolVersion' | 'openapi.mcp.capabilities' | 'openapi.mcp.experimentalCapabilities' | 'openapi.mcp.inputSchema' | 'openapi.mcp.inputExample' | 'openapi.mcp.outputSchema' | 'openapi.mcp.outputExample' | 'openapi.mcp.exampleTitle' | 'openapi.mcp.argumentsExample' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'asyncapi.info.contact.url' | 'asyncapi.info.contact.name' | 'asyncapi.info.license' | 'asyncapi.info.termsOfService' | 'asyncapi.key' | 'asyncapi.value' | 'asyncapi.variables' | 'asyncapi.required' | 'asyncapi.requiredScopes' | 'asyncapi.viewSecurityDetails' | 'graphql.download.description.title' | 'graphql.info.title' | 'graphql.info.contact.url' | 'graphql.info.contact.name' | 'graphql.info.license' | 'graphql.info.termsOfService' | 'graphql.overview' | 'graphql.metadata' | 'graphql.key' | 'graphql.value' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.actions.show' | 'graphql.actions.hide' | 'graphql.actions.more' | 'graphql.fields' | 'graphql.inputFields' | 'graphql.values' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.requiredScopes' | 'graphql.viewSecurityDetails' | 'graphql.objectScopes' | 'graphql.fieldScopes' | 'graphql.implementedInterfaces' | 'graphql.implementedBy' | 'graphql.nonNull' | 'graphql.required' | 'asyncapi.badges.deprecated' | 'graphql.badges.deprecated' | 'asyncapi.actions.show' | 'asyncapi.actions.hide' | 'asyncapi.actions.more' | 'asyncapi.payload' | 'asyncapi.parameters' | 'asyncapi.messages' | 'asyncapi.contentType' | 'asyncapi.moreDetails' | 'asyncapi.property' | 'asyncapi.properties' | 'asyncapi.details' | 'asyncapi.reply' | 'asyncapi.servers.title' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | 'button.download.tooltipText' | 'button.externalLink.tooltipText' | 'button.email.tooltipText' | 'codeWalkthrough.download' | 'codeWalkthrough.preview' | 'time.justNow' | 'time.past.second' | 'time.past.seconds' | 'time.past.minute' | 'time.past.minutes' | 'time.past.hour' | 'time.past.hours' | 'time.past.day' | 'time.past.days' | 'time.past.week' | 'time.past.weeks' | 'time.past.month' | 'time.past.months' | 'time.past.year' | 'time.past.years' | 'page.internalServerError.title' | 'page.internalServerError.description' | 'page.skipToContent.label' | 'select.noResults' | 'loaders.loading' | 'filter.dateRange.from' | 'filter.dateRange.to' | 'diagram.openFullscreen' | 'diagram.zoomIn' | 'diagram.zoomOut' | 'diagram.reset' | 'diagram.close' | 'diagram.viewer' | 'consent.title' | 'consent.message' | 'consent.privacyPolicy' | 'consent.customize' | 'consent.rejectAll' | 'consent.acceptAll' | 'consent.acceptAllCookies' | 'consent.savePreferences' | 'consent.dialog.title' | 'consent.dialog.description' | 'consent.dialog.close' | 'consent.alwaysOn' | 'consent.alwaysOff' | 'consent.gpcNotice' | 'consent.category.necessary.title' | 'consent.category.necessary.description' | 'consent.category.analytics.title' | 'consent.category.analytics.description' | 'consent.category.marketing.title' | 'consent.category.marketing.description' | 'consent.settingsLink';
3
3
  export type Locale = {
4
4
  code: string;
5
5
  name: string;
@@ -1,5 +1,5 @@
1
1
  import type { MCP_OPTIONS } from '../constants/mcp';
2
- export type MCPClientType = 'cursor' | 'vscode';
2
+ export type MCPClientType = 'cursor' | 'vscode' | 'claude';
3
3
  export type MCPOption = (typeof MCP_OPTIONS)[number];
4
4
  export type McpConnectionParams = {
5
5
  serverName: string;
@@ -1,4 +1,4 @@
1
- import type { CodeWalkthroughFile } from '@redocly/config';
1
+ import type { CodeWalkthroughFile } from '../../core/types';
2
2
  export declare function downloadCodeWalkthrough(files: CodeWalkthroughFile[], state: Record<string, {
3
3
  value: string | boolean;
4
4
  }>, inputsState: Record<string, {
@@ -1,4 +1,4 @@
1
- import type { CodeWalkthroughFile } from '@redocly/config';
1
+ import type { CodeWalkthroughFile } from '../../core/types';
2
2
  export declare function getCodeWalkthroughFileText(file: CodeWalkthroughFile, state: Record<string, {
3
3
  value: string | boolean;
4
4
  }>, inputsState: Record<string, {
@@ -1,4 +1,4 @@
1
- import type { CodeWalkthroughConditionsObject } from '@redocly/config';
1
+ import type { CodeWalkthroughConditionsObject } from '../../core/types';
2
2
  export declare function matchCodeWalkthroughConditions(conditions: CodeWalkthroughConditionsObject | undefined, state: Record<string, {
3
3
  value: string | boolean;
4
4
  }>): boolean;
@@ -27,14 +27,19 @@ function generateVSCodeMCPDeepLink(config) {
27
27
  const encodedConfig = encodeURIComponent(JSON.stringify(vscodeConfig));
28
28
  return `vscode:mcp/install?${encodedConfig}`;
29
29
  }
30
+ function generateClaudeConnectorLink(config) {
31
+ const connectorName = encodeURIComponent(config.serverName);
32
+ const connectorUrl = encodeURIComponent(config.url);
33
+ return `https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=${connectorName}&connectorUrl=${connectorUrl}`;
34
+ }
30
35
  function generateMCPDeepLink(clientType, config) {
31
36
  switch (clientType) {
32
37
  case 'cursor':
33
38
  return generateCursorMCPDeepLink(config);
34
39
  case 'vscode':
35
40
  return generateVSCodeMCPDeepLink(config);
36
- default:
37
- return generateCursorMCPDeepLink(config);
41
+ case 'claude':
42
+ return generateClaudeConnectorLink(config);
38
43
  }
39
44
  }
40
45
  // Server names can contain spaces (e.g. "Docs MCP server") which break bare CLI
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { CodeWalkthroughFilter } from '@redocly/config';
2
+ import type { CodeWalkthroughFilter } from '../../../core/types';
3
3
  export type GetFilterState = (groupId: string) => {
4
4
  value: string;
5
5
  render: boolean;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { JSX } from 'react';
3
- import type { CodeWalkthroughFile } from '@redocly/config';
3
+ import type { CodeWalkthroughFile } from '../../../core/types';
4
4
  export type CodePanelProps = {
5
5
  files: CodeWalkthroughFile[];
6
6
  downloadAssociatedFiles: CodeWalkthroughFile[];
@@ -1,5 +1,5 @@
1
1
  import type { JSX } from 'react';
2
- import type { CodeWalkthroughFile } from '@redocly/config';
2
+ import type { CodeWalkthroughFile } from '../../../core/types';
3
3
  export type CodePanelHeaderProps = {
4
4
  files: CodeWalkthroughFile[];
5
5
  handleTabSwitch: (name: string) => void;
@@ -1,5 +1,5 @@
1
1
  import type { JSX } from 'react';
2
- import type { CodeWalkthroughFile } from '@redocly/config';
2
+ import type { CodeWalkthroughFile } from '../../../core/types';
3
3
  export type CodeToolbarProps = {
4
4
  file: CodeWalkthroughFile;
5
5
  };
@@ -1,5 +1,5 @@
1
1
  import React, { type PropsWithChildren } from 'react';
2
- import type { WithConditions } from '@redocly/config';
2
+ import type { WithConditions } from '../../../core/types';
3
3
  export type CodeStepProps = WithConditions<{
4
4
  id: string;
5
5
  heading?: string;
@@ -1,4 +1,4 @@
1
1
  import React, { type PropsWithChildren } from 'react';
2
- import type { CodeWalkthroughAttr } from '@redocly/config';
2
+ import type { CodeWalkthroughAttr } from '../../../core/types';
3
3
  export type CodeWalkthroughProps = PropsWithChildren<CodeWalkthroughAttr>;
4
4
  export declare function CodeWalkthrough({ children, steps, preview, ...attributes }: CodeWalkthroughProps): React.JSX.Element;
@@ -152,7 +152,7 @@ function TabList({ childrenArray, size, activeTab, onTabChange, containerRef, on
152
152
  overflowTabs.some((i) => childrenArray[i] && activeTab === childrenArray[i].props.label);
153
153
  // Show as selector when no visible tabs (all tabs in dropdown)
154
154
  const showAsSelector = visibleTabs.length === 0 && hasOverflow;
155
- const { dropdownPosition, setIsDropdownOpen, setDropdownPosition } = useDropdownPosition(hasOverflow, dropdownRef);
155
+ const { dropdownPosition, isDropdownOpen, setIsDropdownOpen, setDropdownPosition } = useDropdownPosition(hasOverflow, dropdownRef);
156
156
  return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: containerRef },
157
157
  react_1.default.createElement(HighlightBar, { $size: size, style: highlightStyle },
158
158
  react_1.default.createElement("div", null)),
@@ -163,11 +163,9 @@ function TabList({ childrenArray, size, activeTab, onTabChange, containerRef, on
163
163
  return null;
164
164
  return renderTab(child, index, size, setTabRef, handleKeyboard, onTabClick);
165
165
  }),
166
- hasOverflow && (react_1.default.createElement(exports.TabItem, { size: size, active: isMoreActive || showAsSelector, tabIndex: 0, className: "dropdown-tab" },
167
- react_1.default.createElement(DropdownWrapper, { $top: dropdownPosition.top, $left: dropdownPosition.left, onClickCapture: () => {
168
- setIsDropdownOpen(true);
169
- } },
170
- react_1.default.createElement(FixedPositionDropdown, { ref: dropdownRef, trigger: react_1.default.createElement(exports.TabButtonLink, { size: size, className: isMoreActive || showAsSelector ? 'active' : undefined }, showAsSelector ? react_1.default.createElement(TabButtonText, null, activeTab) : 'More'), alignment: "start", withArrow: true, onClose: () => {
166
+ hasOverflow && (react_1.default.createElement(exports.TabItem, { size: size, active: isMoreActive || showAsSelector, tabIndex: 0, className: isDropdownOpen ? 'dropdown-tab dropdown-tab-open' : 'dropdown-tab' },
167
+ react_1.default.createElement(DropdownWrapper, { $top: dropdownPosition.top, $left: dropdownPosition.left },
168
+ react_1.default.createElement(FixedPositionDropdown, { ref: dropdownRef, trigger: react_1.default.createElement(exports.TabButtonLink, { size: size, className: isMoreActive || showAsSelector ? 'active' : undefined }, showAsSelector ? react_1.default.createElement(TabButtonText, null, activeTab) : 'More'), alignment: "start", withArrow: true, onOpen: () => setIsDropdownOpen(true), onClose: () => {
171
169
  setIsDropdownOpen(false);
172
170
  setDropdownPosition({});
173
171
  } },
@@ -259,6 +257,10 @@ exports.TabListContainer = styled_components_1.default.ul `
259
257
  min-width: 0;
260
258
  max-width: 100%;
261
259
  }
260
+
261
+ &.dropdown-tab-open {
262
+ z-index: var(--dropdown-menu-z-index);
263
+ }
262
264
  }
263
265
  }
264
266
  `;
@@ -1,6 +1,6 @@
1
1
  import type { Node, RenderableTreeNode } from '@markdoc/markdoc';
2
2
  import type { MarkdocSchemaWrapper } from '../../markdoc/tags/types';
3
- import type { CodeWalkthroughConditions, CodeWalkthroughFilter, TogglesMarkdocAttr, InputsMarkdocAttr } from '@redocly/config';
3
+ import type { CodeWalkthroughConditions, CodeWalkthroughFilter, TogglesMarkdocAttr, InputsMarkdocAttr } from '../../core/types';
4
4
  export declare const codeWalkthrough: MarkdocSchemaWrapper;
5
5
  export declare function collectStepsFromChildren(children: RenderableTreeNode[], idx?: number): RenderableTreeNode[];
6
6
  export declare function collectTogglesFromChildren(children: Node[], toggles?: TogglesMarkdocAttr): TogglesMarkdocAttr;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.70.0-next.6",
3
+ "version": "0.70.0-next.8",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -42,7 +42,8 @@
42
42
  "devDependencies": {
43
43
  "@babel/core": "7.29.7",
44
44
  "@markdoc/markdoc": "0.5.2",
45
- "@redocly/realm-asyncapi-sdk": "0.16.0-next.2",
45
+ "@redocly/realm-asyncapi-sdk": "0.16.0-next.4",
46
+ "@redocly/tooling-test-utils": "0.0.0",
46
47
  "@shikijs/types": "3.21.0",
47
48
  "@testing-library/react": "16.3.0",
48
49
  "@testing-library/user-event": "14.6.1",
@@ -71,7 +72,7 @@
71
72
  "webpack": "5.105.2"
72
73
  },
73
74
  "dependencies": {
74
- "@redocly/config": "0.62.0",
75
+ "@redocly/config": "0.65.0",
75
76
  "@tanstack/react-query": "5.62.3",
76
77
  "@tanstack/react-virtual": "3.13.0",
77
78
  "@xyflow/react": "12.8.3",
@@ -41,6 +41,13 @@ const MENU_OPTIONS: Record<MCPOption, MenuOption> = {
41
41
  descriptionTranslationKey: 'page.actions.connectMcp.vscodeDescription',
42
42
  descriptionDefault: 'Install MCP server on VS Code',
43
43
  },
44
+ claude: {
45
+ icon: ClaudeIcon,
46
+ titleTranslationKey: 'page.actions.connectMcp.claude',
47
+ titleDefault: 'Connect to Claude',
48
+ descriptionTranslationKey: 'page.actions.connectMcp.claudeDescription',
49
+ descriptionDefault: 'Add MCP server to your Claude account',
50
+ },
44
51
  'claude-code': {
45
52
  icon: ClaudeIcon,
46
53
  titleTranslationKey: 'page.actions.connectMcp.claudeCode',
@@ -118,7 +125,7 @@ export function ConnectMCPButton({
118
125
  >
119
126
  {dropdownOptions.length > 0
120
127
  ? ({ close }: { close: () => void }) => (
121
- <DropdownMenu>
128
+ <StyledDropdownMenu>
122
129
  {dropdownOptions.map((option) => {
123
130
  const Icon = option.icon;
124
131
  const showCheckmark = copiedOption === option.key;
@@ -150,7 +157,7 @@ export function ConnectMCPButton({
150
157
  </DropdownMenuItem>
151
158
  );
152
159
  })}
153
- </DropdownMenu>
160
+ </StyledDropdownMenu>
154
161
  )
155
162
  : null}
156
163
  </SplitButton>
@@ -158,6 +165,10 @@ export function ConnectMCPButton({
158
165
  );
159
166
  }
160
167
 
168
+ const StyledDropdownMenu = styled(DropdownMenu)`
169
+ --dropdown-menu-max-height: var(--connect-mcp-button-dropdown-max-height);
170
+ `;
171
+
161
172
  const ConnectMCPButtonWrapper = styled.div`
162
173
  display: inline-block;
163
174
  position: relative;
@@ -50,3 +50,7 @@ export const aiAssistantButton = css`
50
50
  // @tokens End
51
51
  `;
52
52
  /* eslint-enable theme/no-raw-colors-in-styles */
53
+
54
+ export const connectMcpButton = css`
55
+ --connect-mcp-button-dropdown-max-height: fit-content;
56
+ `;
@@ -162,9 +162,11 @@ export function Catalog(props: CatalogProps): JSX.Element {
162
162
  <CatalogPageContentWrapper>
163
163
  <CatalogTitleWrapper>
164
164
  <CatalogTitle data-translation-key={catalogConfig?.titleTranslationKey}>
165
- {catalogConfig?.titleTranslationKey
166
- ? translate(catalogConfig?.titleTranslationKey)
167
- : catalogConfig?.slug}{' '}
165
+ <span>
166
+ {catalogConfig?.titleTranslationKey
167
+ ? translate(catalogConfig?.titleTranslationKey)
168
+ : catalogConfig?.slug}
169
+ </span>{' '}
168
170
  </CatalogTitle>
169
171
  <CounterTag borderless>{entitiesCounter}</CounterTag>
170
172
  </CatalogTitleWrapper>
@@ -79,7 +79,7 @@ export function JsonValue(props: {
79
79
  fold={fold}
80
80
  maxStringLength={maxStringLength}
81
81
  />
82
- {index < value.length - 1 ? ',\n' : null}
82
+ {index < value.length - 1 ? <span>{',\n'}</span> : null}
83
83
  </React.Fragment>
84
84
  ))
85
85
  : keys.map((key, index) => (
@@ -92,7 +92,7 @@ export function JsonValue(props: {
92
92
  fold={fold}
93
93
  maxStringLength={maxStringLength}
94
94
  />
95
- {index < keys.length - 1 ? ',\n' : null}
95
+ {index < keys.length - 1 ? <span>{',\n'}</span> : null}
96
96
  </React.Fragment>
97
97
  ));
98
98
 
@@ -177,7 +177,9 @@ function JsonKeyValue(props: {
177
177
  {isFoldable(value) ? (
178
178
  <ExpandIcon onClick={() => fold.setExpanded(path, !isExpanded)} isExpanded={isExpanded} />
179
179
  ) : null}
180
- <span className="property token string">{`"${name}"`}</span>: {valueElement}
180
+ <span className="property token string">{`"${name}"`}</span>
181
+ <span>{': '}</span>
182
+ {valueElement}
181
183
  </>
182
184
  );
183
185
  }
@@ -10,9 +10,11 @@ import { useMCPConfig, useThemeHooks } from '@redocly/theme/core/hooks';
10
10
  import {
11
11
  generateClaudeCodeCommand,
12
12
  generateCodexCommand,
13
+ generateMCPDeepLink,
13
14
  generateMcpInstallPrompt,
14
15
  getBaseDataAttributes,
15
16
  } from '@redocly/theme/core/utils';
17
+ import { Button } from '@redocly/theme/components/Button/Button';
16
18
  import { CodeBlock } from '@redocly/theme/components/CodeBlock/CodeBlock';
17
19
  import { ClaudeIcon } from '@redocly/theme/icons/ClaudeIcon/ClaudeIcon';
18
20
  import { ChatGptIcon } from '@redocly/theme/icons/ChatGptIcon/ChatGptIcon';
@@ -167,16 +169,26 @@ function renderTabContent(
167
169
  ),
168
170
  },
169
171
  {
170
- headline: translate(
171
- 'page.mcpNotAllowed.snippets.claudeDesktop.headline',
172
- 'Claude Desktop',
173
- ),
172
+ headline: translate('page.mcpNotAllowed.snippets.claudeDesktop.headline', 'Claude app'),
174
173
  content: (
175
174
  <>
175
+ <TabHint>
176
+ {translate(
177
+ 'page.mcpNotAllowed.snippets.claudeDesktop.accountHint',
178
+ 'Claude adds the connector to your account and syncs it between Claude on the web and Claude Desktop.',
179
+ )}
180
+ </TabHint>
181
+ <ConnectButton
182
+ variant="secondary"
183
+ icon={<ClaudeIcon />}
184
+ onClick={() => window.open(generateMCPDeepLink('claude', connection), '_blank')}
185
+ >
186
+ {translate('page.actions.connectMcp.claude', 'Connect to Claude')}
187
+ </ConnectButton>
176
188
  <TabHint>
177
189
  {translate(
178
190
  'page.mcpNotAllowed.snippets.claudeDesktop.instruction',
179
- 'Open Customize → Connectors → Add custom connector and paste this server URL:',
191
+ 'Or open Customize → Connectors → Add custom connector and paste this server URL:',
180
192
  )}
181
193
  </TabHint>
182
194
  <CodeBlock
@@ -278,6 +290,11 @@ const McpConnectionTabsWrapper = styled.div`
278
290
  }
279
291
  `;
280
292
 
293
+ const ConnectButton = styled(Button)`
294
+ align-self: flex-start;
295
+ margin-bottom: var(--spacing-sm);
296
+ `;
297
+
281
298
  const TabHint = styled.p`
282
299
  margin: 0 0 var(--spacing-xs);
283
300
  color: var(--page-mcp-405-snippets-hint-text-color);
@@ -1,9 +1,10 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
 
4
4
  import type { PropsWithChildren, JSX } from 'react';
5
5
 
6
6
  import { IS_BROWSER } from '@redocly/theme/core/utils';
7
+ import { PortalContainerContext } from '@redocly/theme/core/contexts/PortalContainerContext';
7
8
 
8
9
  export type PortalProps = {
9
10
  mountId?: string;
@@ -13,7 +14,8 @@ export function Portal({
13
14
  children,
14
15
  mountId = 'root',
15
16
  }: PropsWithChildren<PortalProps>): React.ReactPortal | JSX.Element {
16
- const mount = IS_BROWSER ? document.getElementById(mountId) || document.body : null;
17
+ const container = useContext(PortalContainerContext);
18
+ const mount = IS_BROWSER ? container || document.getElementById(mountId) || document.body : null;
17
19
 
18
20
  if (!mount) {
19
21
  return <>{children}</>;
@@ -10,6 +10,8 @@ import { ThumbUpFilledIcon } from '@redocly/theme/icons/ThumbUpFilledIcon/ThumbU
10
10
  import { ThumbDownIcon } from '@redocly/theme/icons/ThumbDownIcon/ThumbDownIcon';
11
11
  import { ThumbDownFilledIcon } from '@redocly/theme/icons/ThumbDownFilledIcon/ThumbDownFilledIcon';
12
12
  import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
13
+ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
14
+ import { useThemeHooks } from '@redocly/theme/core/hooks';
13
15
 
14
16
  export type SearchAiActionButtonsProps = {
15
17
  content: string;
@@ -26,28 +28,38 @@ export function SearchAiActionButtons({
26
28
  onFeedback,
27
29
  disabled,
28
30
  }: SearchAiActionButtonsProps): JSX.Element {
31
+ const { useTranslate } = useThemeHooks();
32
+ const { translate } = useTranslate();
33
+
29
34
  return (
30
35
  <ActionButtonsWrapper className={className} data-component-name="Search/SearchAiActionButtons">
31
- <CopyButton data={content} />
32
- <FeedbackButton
33
- variant="text"
34
- size="small"
35
- icon={feedback === FeedbackType.Like ? <ThumbUpFilledIcon /> : <ThumbUpIcon />}
36
- onClick={() => !disabled && onFeedback(FeedbackType.Like)}
37
- extraClass={feedback === FeedbackType.Like ? 'active' : ''}
38
- aria-label="Like this response"
39
- disabled={disabled}
40
- />
36
+ <Tooltip tip={translate('search.ai.actions.copy', 'Copy the response')} placement="top">
37
+ <CopyButton data={content} />
38
+ </Tooltip>
39
+
40
+ <Tooltip tip={translate('search.ai.actions.like', 'Like the response')} placement="top">
41
+ <FeedbackButton
42
+ variant="text"
43
+ size="small"
44
+ icon={feedback === FeedbackType.Like ? <ThumbUpFilledIcon /> : <ThumbUpIcon />}
45
+ onClick={() => !disabled && onFeedback(FeedbackType.Like)}
46
+ extraClass={feedback === FeedbackType.Like ? 'active' : ''}
47
+ aria-label="Like this response"
48
+ disabled={disabled}
49
+ />
50
+ </Tooltip>
41
51
 
42
- <FeedbackButton
43
- variant="text"
44
- size="small"
45
- icon={feedback === FeedbackType.Dislike ? <ThumbDownFilledIcon /> : <ThumbDownIcon />}
46
- onClick={() => !disabled && onFeedback(FeedbackType.Dislike)}
47
- extraClass={feedback === FeedbackType.Dislike ? 'active' : ''}
48
- aria-label="Dislike this response"
49
- disabled={disabled}
50
- />
52
+ <Tooltip tip={translate('search.ai.actions.dislike', 'Dislike the response')} placement="top">
53
+ <FeedbackButton
54
+ variant="text"
55
+ size="small"
56
+ icon={feedback === FeedbackType.Dislike ? <ThumbDownFilledIcon /> : <ThumbDownIcon />}
57
+ onClick={() => !disabled && onFeedback(FeedbackType.Dislike)}
58
+ extraClass={feedback === FeedbackType.Dislike ? 'active' : ''}
59
+ aria-label="Dislike this response"
60
+ disabled={disabled}
61
+ />
62
+ </Tooltip>
51
63
  </ActionButtonsWrapper>
52
64
  );
53
65
  }