@redocly/theme 0.58.0-next.9 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/lib/components/Catalog/CatalogEntity/CatalogEntity.d.ts +5 -1
  2. package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +4 -4
  3. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +3 -3
  4. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.d.ts +5 -1
  5. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +9 -7
  6. package/lib/components/CodeBlock/CodeBlock.d.ts +5 -12
  7. package/lib/components/CodeBlock/CodeBlockControls.d.ts +3 -3
  8. package/lib/components/CodeBlock/CodeBlockControls.js +1 -1
  9. package/lib/components/CodeBlock/CodeBlockDropdown.d.ts +2 -2
  10. package/lib/components/CodeBlock/CodeBlockDropdown.js +4 -13
  11. package/lib/components/CodeBlock/CodeBlockTabs.d.ts +2 -2
  12. package/lib/components/CodeBlock/CodeBlockTabs.js +4 -3
  13. package/lib/components/JsonViewer/JsonViewer.d.ts +1 -1
  14. package/lib/components/JsonViewer/JsonViewer.js +9 -10
  15. package/lib/components/PageActions/PageActions.d.ts +4 -1
  16. package/lib/components/PageActions/PageActions.js +2 -2
  17. package/lib/core/constants/catalog.js +4 -0
  18. package/lib/core/contexts/CodeSnippetContext.d.ts +14 -6
  19. package/lib/core/contexts/CodeSnippetContext.js +57 -14
  20. package/lib/core/hooks/use-codeblock-tabs-controls.d.ts +2 -2
  21. package/lib/core/hooks/use-local-state.js +22 -18
  22. package/lib/core/hooks/use-page-actions.d.ts +2 -1
  23. package/lib/core/hooks/use-page-actions.js +48 -6
  24. package/lib/core/openapi/index.d.ts +1 -0
  25. package/lib/core/openapi/index.js +3 -1
  26. package/lib/core/types/l10n.d.ts +1 -1
  27. package/lib/core/types/open-api-server.d.ts +1 -0
  28. package/lib/icons/CursorIcon/CursorIcon.d.ts +9 -0
  29. package/lib/icons/CursorIcon/CursorIcon.js +22 -0
  30. package/lib/layouts/DocumentationLayout.js +1 -3
  31. package/lib/markdoc/components/CodeGroup/CodeGroup.js +49 -27
  32. package/lib/markdoc/components/Tabs/TabList.js +2 -0
  33. package/package.json +4 -4
  34. package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +15 -2
  35. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +3 -3
  36. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +27 -18
  37. package/src/components/CodeBlock/CodeBlock.tsx +5 -11
  38. package/src/components/CodeBlock/CodeBlockControls.tsx +4 -7
  39. package/src/components/CodeBlock/CodeBlockDropdown.tsx +11 -20
  40. package/src/components/CodeBlock/CodeBlockTabs.tsx +8 -8
  41. package/src/components/JsonViewer/JsonViewer.tsx +16 -9
  42. package/src/components/PageActions/PageActions.tsx +6 -4
  43. package/src/core/constants/catalog.ts +4 -0
  44. package/src/core/contexts/CodeSnippetContext.tsx +54 -18
  45. package/src/core/hooks/use-codeblock-tabs-controls.ts +2 -2
  46. package/src/core/hooks/use-local-state.ts +28 -19
  47. package/src/core/hooks/use-page-actions.ts +63 -6
  48. package/src/core/openapi/index.ts +1 -0
  49. package/src/core/types/l10n.ts +13 -0
  50. package/src/core/types/open-api-server.ts +1 -0
  51. package/src/icons/CursorIcon/CursorIcon.tsx +35 -0
  52. package/src/layouts/DocumentationLayout.tsx +3 -10
  53. package/src/markdoc/components/CodeGroup/CodeGroup.tsx +81 -52
  54. package/src/markdoc/components/Tabs/TabList.tsx +1 -0
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ThemeDataContext = exports.isObject = exports.isNotNull = exports.isString = exports.isUndefined = exports.SecurityVariablesEnvSuffix = exports.useDialogHotKeys = exports.useSearchDialog = exports.useModalScrollLock = exports.useActiveSectionId = exports.useOutsideClick = exports.useThemeHooks = exports.useFocusTrap = exports.getUserAgent = exports.ClipboardService = exports.isPrimitive = exports.breakpoints = exports.GlobalStyle = exports.useMount = exports.typedMemo = exports.withPathPrefix = exports.addTrailingSlash = exports.combineUrls = exports.getPathPrefix = exports.removeLeadingSlash = exports.addLeadingSlash = exports.IS_BROWSER = void 0;
3
+ exports.ThemeDataContext = exports.isObject = exports.isNotNull = exports.isString = exports.isUndefined = exports.SecurityVariablesEnvSuffix = exports.useDialogHotKeys = exports.useSearchDialog = exports.useModalScrollLock = exports.useActiveSectionId = exports.useOutsideClick = exports.useThemeHooks = exports.useFocusTrap = exports.getUserAgent = exports.ClipboardService = exports.isPrimitive = exports.breakpoints = exports.GlobalStyle = exports.useMount = exports.typedMemo = exports.capitalize = exports.withPathPrefix = exports.addTrailingSlash = exports.combineUrls = exports.getPathPrefix = exports.removeLeadingSlash = exports.addLeadingSlash = exports.IS_BROWSER = void 0;
4
4
  var dom_1 = require("../utils/dom");
5
5
  Object.defineProperty(exports, "IS_BROWSER", { enumerable: true, get: function () { return dom_1.IS_BROWSER; } });
6
6
  var urls_1 = require("../utils/urls");
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "getPathPrefix", { enumerable: true, get: functio
10
10
  Object.defineProperty(exports, "combineUrls", { enumerable: true, get: function () { return urls_1.combineUrls; } });
11
11
  Object.defineProperty(exports, "addTrailingSlash", { enumerable: true, get: function () { return urls_1.addTrailingSlash; } });
12
12
  Object.defineProperty(exports, "withPathPrefix", { enumerable: true, get: function () { return urls_1.withPathPrefix; } });
13
+ var string_1 = require("../utils/string");
14
+ Object.defineProperty(exports, "capitalize", { enumerable: true, get: function () { return string_1.capitalize; } });
13
15
  var typedMemo_1 = require("../hoc/typedMemo");
14
16
  Object.defineProperty(exports, "typedMemo", { enumerable: true, get: function () { return typedMemo_1.typedMemo; } });
15
17
  var use_mount_1 = require("../hooks/use-mount");
@@ -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.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.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | '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' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.notFound.title' | 'page.notFound.description' | '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' | '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.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' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | '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' | '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' | '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.servers.title' | 'openapi.operations' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | '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.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | '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' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | '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.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | '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';
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.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.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | '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' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.notFound.title' | 'page.notFound.description' | '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' | '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.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' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | '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' | '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' | '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.servers.title' | 'openapi.operations' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | '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.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | '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' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | '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.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | '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';
3
3
  export type Locale = {
4
4
  code: string;
5
5
  name: string;
@@ -1,6 +1,7 @@
1
1
  export type OpenAPIServer = {
2
2
  url: string;
3
3
  description?: string;
4
+ name?: string;
4
5
  variables?: Record<string, {
5
6
  default: string;
6
7
  enum?: string[];
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { IconProps } from '../../icons/types';
3
+ export declare const CursorIcon: import("styled-components").StyledComponent<(props: IconProps) => React.JSX.Element, any, {
4
+ 'data-component-name': string;
5
+ } & {
6
+ color?: string;
7
+ size?: string;
8
+ className?: string;
9
+ } & React.SVGProps<SVGSVGElement>, "data-component-name">;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CursorIcon = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const styled_components_1 = __importDefault(require("styled-components"));
9
+ const Icon = (props) => (react_1.default.createElement("svg", Object.assign({ width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, props),
10
+ react_1.default.createElement("path", { d: "M7.99956 15V8.0001L2 11.4999L7.99956 15Z", fill: "#939393" }),
11
+ react_1.default.createElement("path", { d: "M14 4.49979L7.99956 15V8.0001L14 4.49979Z", fill: "#E3E3E3" }),
12
+ react_1.default.createElement("path", { d: "M2 4.49979H14L7.99956 8.0001L2 4.49979Z", fill: "white" }),
13
+ react_1.default.createElement("path", { d: "M8.00025 1V4.49995L14 4.49979L8.00025 1Z", fill: "#444444" }),
14
+ react_1.default.createElement("path", { d: "M2 4.49979L8.00025 4.49995V1L2 4.49979ZM13.9999 11.4998L10.9999 9.74987L7.99956 15L13.9999 11.4998Z", fill: "#939393" }),
15
+ react_1.default.createElement("path", { d: "M14 4.49979L10.9999 9.74987L13.9999 11.4998L14 4.49979ZM7.99956 8.0001L2 11.4999V4.49979L7.99956 8.0001Z", fill: "#444444" })));
16
+ exports.CursorIcon = (0, styled_components_1.default)(Icon).attrs(() => ({
17
+ 'data-component-name': 'icons/CursorIcon/CursorIcon',
18
+ })) `
19
+ height: ${({ size }) => size || '16px'};
20
+ width: ${({ size }) => size || '16px'};
21
+ `;
22
+ //# sourceMappingURL=CursorIcon.js.map
@@ -12,13 +12,11 @@ const PageNavigation_1 = require("../components/PageNavigation/PageNavigation");
12
12
  const LastUpdated_1 = require("../components/LastUpdated/LastUpdated");
13
13
  const Breadcrumbs_1 = require("../components/Breadcrumbs/Breadcrumbs");
14
14
  const CodeSnippetContext_1 = require("../core/contexts/CodeSnippetContext");
15
- const use_local_state_1 = require("../core/hooks/use-local-state");
16
15
  function DocumentationLayout({ tableOfContent, feedback, config, editPage, lastModified, nextPage, prevPage, className, children, }) {
17
16
  var _a;
18
17
  const { editPage: themeEditPage } = config || {};
19
18
  const mergedConf = editPage ? Object.assign(Object.assign({}, themeEditPage), editPage) : undefined;
20
- const [activeSnippetName, setActiveSnippetName] = (0, use_local_state_1.useLocalState)(CodeSnippetContext_1.CODE_GROUP_SNIPPET_NAME_KEY, '');
21
- return (react_1.default.createElement(CodeSnippetContext_1.CodeSnippetContext.Provider, { value: { activeSnippetName, setActiveSnippetName } },
19
+ return (react_1.default.createElement(CodeSnippetContext_1.CodeSnippetProvider, null,
22
20
  react_1.default.createElement(LayoutWrapper, { "data-component-name": "Layout/DocumentationLayout", className: className },
23
21
  react_1.default.createElement(ContentWrapper, { withToc: !((_a = config === null || config === void 0 ? void 0 : config.toc) === null || _a === void 0 ? void 0 : _a.hide) },
24
22
  react_1.default.createElement(Breadcrumbs, null),
@@ -31,42 +31,64 @@ const contexts_1 = require("../../../core/contexts");
31
31
  function CodeGroup(props) {
32
32
  const mode = props.mode || 'tabs';
33
33
  const isTabsMode = mode === 'tabs';
34
- const rawSnippets = React.useMemo(() => React.Children.toArray(props.children).map((child, idx) => {
35
- const childProps = child;
36
- return {
37
- name: getTabName(childProps.props, idx),
38
- languageName: (0, utils_1.langToName)(childProps.props.lang || 'Default'),
39
- lang: childProps.props.lang || '',
40
- props: childProps.props,
41
- };
42
- }), [props.children]);
43
- const [activeSnippetName, setActiveSnippetName] = (0, contexts_1.useActiveCodeSnippetName)(mode);
44
- const snippets = React.useMemo(() => Object.fromEntries(rawSnippets.map((snippet) => {
45
- const getItemName = (snippet) => isTabsMode ? snippet === null || snippet === void 0 ? void 0 : snippet.name : (snippet === null || snippet === void 0 ? void 0 : snippet.languageName) || '';
46
- const name = getItemName(snippet);
47
- const items = rawSnippets.map((item) => ({
48
- name: getItemName(item),
49
- lang: item.lang,
50
- }));
34
+ const rawSnippets = React.useMemo(() => parseSnippetsFromChildren(props.children), [props.children]);
35
+ const groupId = React.useMemo(() => generateGroupId(rawSnippets, mode), [rawSnippets, mode]);
36
+ const [activeSnippetId, setActiveSnippetId] = (0, contexts_1.useActiveCodeSnippetId)(groupId, rawSnippets);
37
+ const snippets = React.useMemo(() => {
38
+ const items = createItemsFromSnippets(rawSnippets, isTabsMode);
51
39
  const itemsProps = {
52
40
  items,
53
- onChange: (name) => {
54
- setActiveSnippetName(name);
55
- },
56
- value: activeSnippetName || getItemName(rawSnippets[0]),
41
+ onChange: (id) => setActiveSnippetId(id),
42
+ value: activeSnippetId,
57
43
  };
58
- const snippetProps = Object.assign(Object.assign(Object.assign({}, snippet.props), { header: Object.assign(Object.assign({}, snippet.props.header), { title: isTabsMode ? undefined : snippet.name }) }), (isTabsMode ? { tabs: itemsProps } : { dropdown: itemsProps }));
59
- return [name, snippetProps];
60
- })), [rawSnippets, activeSnippetName, isTabsMode, setActiveSnippetName]);
61
- const firstName = Object.keys(snippets)[0];
62
- const activeSnippet = snippets[activeSnippetName] || snippets[firstName];
44
+ return Object.fromEntries(rawSnippets.map((snippet) => {
45
+ const snippetProps = Object.assign(Object.assign(Object.assign({}, snippet.props), { header: Object.assign(Object.assign({}, snippet.props.header), { title: isTabsMode ? undefined : snippet.name }) }), (isTabsMode ? { tabs: itemsProps } : { dropdown: itemsProps }));
46
+ return [snippet.id, snippetProps];
47
+ }));
48
+ }, [rawSnippets, activeSnippetId, isTabsMode, setActiveSnippetId]);
49
+ const activeSnippet = snippets[activeSnippetId];
63
50
  if (!activeSnippet) {
64
51
  return null;
65
52
  }
66
53
  return React.createElement(CodeBlock_1.CodeBlock, Object.assign({}, activeSnippet));
67
54
  }
55
+ function generateContentHash(content) {
56
+ let hash = 0;
57
+ for (let i = 0; i < content.length; i++) {
58
+ hash = content.charCodeAt(i) + ((hash << 5) - hash);
59
+ }
60
+ return Math.abs(hash);
61
+ }
62
+ // Generate unique group ID for CodeGroup instance
63
+ // Examples: "dropdown-8901234", "tabs-1234567"
64
+ function generateGroupId(rawSnippets, mode) {
65
+ const content = rawSnippets.map((s) => s.id + (s.props.source || '')).join('|') + `|${mode}`;
66
+ const hash = generateContentHash(content);
67
+ return `${mode}-${hash}`;
68
+ }
68
69
  function getTabName(props, idx) {
69
70
  var _a;
70
- return String(((_a = props.header) === null || _a === void 0 ? void 0 : _a.title) || props.file || (0, utils_1.langToName)(props.lang || '') || 'Tab ' + String(idx + 1));
71
+ const fallbackName = `Tab ${idx + 1}`;
72
+ return String(((_a = props.header) === null || _a === void 0 ? void 0 : _a.title) || props.file || (0, utils_1.langToName)(props.lang || '') || fallbackName);
73
+ }
74
+ function parseSnippetsFromChildren(children) {
75
+ return React.Children.toArray(children).map((child, idx) => {
76
+ const childProps = child;
77
+ const props = childProps.props;
78
+ return {
79
+ name: getTabName(props, idx),
80
+ languageName: String((0, utils_1.langToName)(props.lang || 'Default') || ''),
81
+ lang: props.lang || '',
82
+ props,
83
+ id: `${props.lang || ''}-${idx}`,
84
+ };
85
+ });
86
+ }
87
+ function createItemsFromSnippets(snippets, isTabsMode) {
88
+ return snippets.map((snippet) => ({
89
+ name: isTabsMode ? snippet.name : snippet.languageName || '',
90
+ lang: snippet.lang,
91
+ id: snippet.id,
92
+ }));
71
93
  }
72
94
  //# sourceMappingURL=CodeGroup.js.map
@@ -63,6 +63,8 @@ function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, on
63
63
  const { label } = childrenArray[index].props;
64
64
  const tabId = getTabId(label, index);
65
65
  return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
66
+ var _a, _b;
67
+ (_b = (_a = childrenArray[index].props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
66
68
  onTabClick(index);
67
69
  }, disabled: childrenArray[index].props.disable }, label));
68
70
  })))))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.58.0-next.9",
3
+ "version": "0.58.0",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -32,7 +32,7 @@
32
32
  "react": "^19.1.0",
33
33
  "react-dom": "^19.1.0",
34
34
  "react-router-dom": "^6.21.1",
35
- "styled-components": "^4.1.1 || ^5.3.11",
35
+ "styled-components": "^4.1.1 || ^5.3.11 || ^6.0.0",
36
36
  "styled-system": "^5.1.5"
37
37
  },
38
38
  "devDependencies": {
@@ -87,8 +87,8 @@
87
87
  "openapi-sampler": "1.6.1",
88
88
  "react-calendar": "5.1.0",
89
89
  "react-date-picker": "11.0.0",
90
- "@redocly/config": "0.35.0",
91
- "@redocly/realm-asyncapi-sdk": "0.4.0-next.4"
90
+ "@redocly/realm-asyncapi-sdk": "0.4.0",
91
+ "@redocly/config": "0.35.1"
92
92
  },
93
93
  "scripts": {
94
94
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -24,6 +24,7 @@ import { CatalogEntityRelationsGraph } from '@redocly/theme/components/Catalog/C
24
24
  export type CatalogEntityProps = {
25
25
  RedocSchema: React.ComponentType<any>;
26
26
  StoreProvider: React.ComponentType<any>;
27
+ GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>;
27
28
  };
28
29
 
29
30
  type CatalogEntityPageProps = {
@@ -50,6 +51,7 @@ const renderDataSchemaSection = (
50
51
  relatedEntity: BffCatalogRelatedEntity | null,
51
52
  RedocSchema: React.ComponentType<any>,
52
53
  StoreProvider: React.ComponentType<any>,
54
+ GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>,
53
55
  ): React.ReactElement | null => {
54
56
  if (entity.type !== 'data-schema') {
55
57
  return null;
@@ -61,11 +63,16 @@ const renderDataSchemaSection = (
61
63
  relatedEntity={relatedEntity}
62
64
  RedocSchema={RedocSchema}
63
65
  StoreProvider={StoreProvider}
66
+ GraphqlTypeRenderer={GraphqlTypeRenderer}
64
67
  />
65
68
  );
66
69
  };
67
70
 
68
- export function CatalogEntity({ RedocSchema, StoreProvider }: CatalogEntityProps) {
71
+ export function CatalogEntity({
72
+ RedocSchema,
73
+ StoreProvider,
74
+ GraphqlTypeRenderer,
75
+ }: CatalogEntityProps) {
69
76
  const { useTranslate, useCatalog, usePageProps } = useThemeHooks();
70
77
  const { translate } = useTranslate();
71
78
  const { entity, relations, catalogConfig, entitiesCatalogConfig, relatedEntity } =
@@ -98,7 +105,13 @@ export function CatalogEntity({ RedocSchema, StoreProvider }: CatalogEntityProps
98
105
  tag={entity.key}
99
106
  />
100
107
  <CatalogEntityProperties entity={entity} />
101
- {renderDataSchemaSection(entity, relatedEntity, RedocSchema, StoreProvider)}
108
+ {renderDataSchemaSection(
109
+ entity,
110
+ relatedEntity,
111
+ RedocSchema,
112
+ StoreProvider,
113
+ GraphqlTypeRenderer,
114
+ )}
102
115
  <CatalogTwoColumnsSection>
103
116
  {renderFirstColumnEntitySection(entity)}
104
117
  <CatalogEntityLinks entity={entity} />
@@ -16,7 +16,7 @@ export type CatalogEntityMetadataProps = {
16
16
 
17
17
  function renderMetadataValue(value: any): React.JSX.Element {
18
18
  if (isPlainObject(value)) {
19
- return <JsonViewerWrapper data={value} expandLevel={3} hideHeader={true} />;
19
+ return <JsonViewerWrapper data={value} expandLevel={3} controls={false} />;
20
20
  }
21
21
 
22
22
  if (Array.isArray(value)) {
@@ -25,7 +25,7 @@ function renderMetadataValue(value: any): React.JSX.Element {
25
25
  {value.map((item, index) => (
26
26
  <div key={index}>
27
27
  {isPlainObject(item) ? (
28
- <JsonViewerWrapper data={item} expandLevel={3} hideHeader={true} />
28
+ <JsonViewerWrapper data={item} expandLevel={3} controls={false} />
29
29
  ) : (
30
30
  <span>{String(item)}</span>
31
31
  )}
@@ -41,7 +41,7 @@ function renderMetadataValue(value: any): React.JSX.Element {
41
41
  export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
42
42
  const { useTranslate } = useThemeHooks();
43
43
  const { translate } = useTranslate();
44
- const { schema, ...metadata } = entity.metadata || {};
44
+ const { schema, sdl, ...metadata } = entity.metadata || {};
45
45
  const metadataToShow = Object.entries(metadata).filter(
46
46
  ([key]) => !(entity.type === 'api-description' && key === 'descriptionFile'),
47
47
  );
@@ -13,6 +13,7 @@ export type CatalogEntitySchemaProps = {
13
13
  relatedEntity: BffCatalogRelatedEntity | null;
14
14
  RedocSchema: React.ComponentType<any>;
15
15
  StoreProvider: React.ComponentType<any>;
16
+ GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>;
16
17
  };
17
18
 
18
19
  export function CatalogEntitySchema({
@@ -20,37 +21,45 @@ export function CatalogEntitySchema({
20
21
  relatedEntity,
21
22
  RedocSchema,
22
23
  StoreProvider,
24
+ GraphqlTypeRenderer,
23
25
  }: CatalogEntitySchemaProps) {
24
26
  const { useTranslate } = useThemeHooks();
25
27
  const { translate } = useTranslate();
26
28
  const { definition, parsedSchema, rawSchema } = useCatalogEntitySchema({ entity, relatedEntity });
29
+ const isGraphql = entity.metadata?.specType === 'graphql';
30
+ const graphqlSDL = entity?.metadata?.sdl;
27
31
 
28
32
  return (
29
33
  <MetadataWrapper data-component-name="Catalog/CatalogEntity/CatalogEntityMetadata">
30
34
  <HeaderWrapper>
31
35
  <Heading>{translate('catalog.entity.schema.title')}</Heading>
32
- <CopyButton
33
- data={rawSchema}
34
- buttonText="Copy Schema"
35
- type="compound"
36
- variant="secondary"
37
- iconPosition="right"
38
- size="medium"
39
- ></CopyButton>
36
+ {!isGraphql && (
37
+ <CopyButton
38
+ data={rawSchema}
39
+ buttonText="Copy Schema"
40
+ type="compound"
41
+ variant="secondary"
42
+ iconPosition="right"
43
+ size="medium"
44
+ ></CopyButton>
45
+ )}
40
46
  </HeaderWrapper>
41
47
  <SplitViewWrapper>
42
48
  <SchemaContentWrapper>
43
- <StoreProvider definition={definition}>
44
- <RedocSchema schema={parsedSchema} />
45
- </StoreProvider>
49
+ {isGraphql && graphqlSDL && GraphqlTypeRenderer ? (
50
+ <GraphqlTypeRenderer sdl={graphqlSDL} typeName={entity.title} />
51
+ ) : (
52
+ <StoreProvider definition={definition}>
53
+ <RedocSchema schema={parsedSchema} />
54
+ </StoreProvider>
55
+ )}
46
56
  </SchemaContentWrapper>
47
- <SchemaSampleWrapper>
48
- <JsonViewer
49
- data={Sampler.sample({ ...parsedSchema })}
50
- expandLevel={3}
51
- hideHeader={false}
52
- />
53
- </SchemaSampleWrapper>
57
+
58
+ {!isGraphql && (
59
+ <SchemaSampleWrapper>
60
+ <JsonViewer data={Sampler.sample({ ...parsedSchema })} expandLevel={3} />
61
+ </SchemaSampleWrapper>
62
+ )}
54
63
  </SplitViewWrapper>
55
64
  </MetadataWrapper>
56
65
  );
@@ -18,8 +18,8 @@ export type CodeBlockProps = {
18
18
  header?: CodeBlockControlsProps;
19
19
  dataTestId?: string;
20
20
  className?: string;
21
- tabs?: CodeBlockTabItems;
22
- dropdown?: CodeBlockDropdownItems;
21
+ tabs?: CodeBlockItems;
22
+ dropdown?: CodeBlockItems;
23
23
  withLineNumbers?: boolean;
24
24
  startLineNumber?: number;
25
25
  highlightedHtml?: string;
@@ -37,15 +37,9 @@ type UnstableExternalCodeSample = {
37
37
  get: (source: ExternalSource) => string;
38
38
  };
39
39
 
40
- export type CodeBlockTabItems = {
41
- items: { name: string; lang?: string }[];
42
- onChange: (name: string) => void;
43
- value: string;
44
- };
45
-
46
- export type CodeBlockDropdownItems = {
47
- items: { name: string; lang?: string }[];
48
- onChange: (name: string | string[]) => void;
40
+ export type CodeBlockItems = {
41
+ items: { name: string; lang?: string; id: string }[];
42
+ onChange: (id: string) => void;
49
43
  value: string;
50
44
  };
51
45
 
@@ -2,10 +2,7 @@ import React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
- import type {
6
- CodeBlockDropdownItems,
7
- CodeBlockTabItems,
8
- } from '@redocly/theme/components/CodeBlock/CodeBlock';
5
+ import type { CodeBlockItems } from '@redocly/theme/components/CodeBlock/CodeBlock';
9
6
 
10
7
  import { CodeBlockTabs } from '@redocly/theme/components/CodeBlock/CodeBlockTabs';
11
8
  import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
@@ -24,8 +21,8 @@ export type CodeBlockControlsProps = {
24
21
  className?: string;
25
22
  title?: React.ReactNode | string;
26
23
  controls?: ControlItems | false;
27
- tabs?: CodeBlockTabItems;
28
- dropdown?: CodeBlockDropdownItems;
24
+ tabs?: CodeBlockItems;
25
+ dropdown?: CodeBlockItems;
29
26
  };
30
27
 
31
28
  type ControlItems = {
@@ -87,7 +84,7 @@ export function CodeBlockControls({
87
84
  {tabs && <CodeBlockTabs tabs={tabs} />}
88
85
  <ControlsWrapper>
89
86
  {dropdown && <CodeBlockDropdown {...dropdown} />}
90
- {report && !report?.props?.hide ? (
87
+ {report && !report.hidden && !report?.props?.hide ? (
91
88
  <TooltipWrapper
92
89
  tip={translate('codeSnippet.report.tooltipText', 'Report a problem')}
93
90
  placement="top"
@@ -1,24 +1,23 @@
1
1
  import React, { type JSX } from 'react';
2
- import styled from 'styled-components';
3
2
 
4
- import type { CodeBlockDropdownItems } from '@redocly/theme/components/CodeBlock/CodeBlock';
3
+ import type { CodeBlockItems } from '@redocly/theme/components/CodeBlock/CodeBlock';
5
4
 
6
5
  import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
7
6
  import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
8
7
  import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
9
8
  import { Button } from '@redocly/theme/components/Button/Button';
10
- import { ChevronSortIcon } from '@redocly/theme/icons/ChevronSortIcon/ChevronSortIcon';
11
9
  import { NoneIcon } from '@redocly/theme/icons/NoneIcon/NoneIcon';
12
10
  import { getFileIconByLanguage } from '@redocly/theme/core/utils';
13
11
 
14
- export function CodeBlockDropdown({ items, onChange, value }: CodeBlockDropdownItems): JSX.Element {
15
- const activeItem = items.find((item) => item.name === value) || items[0];
12
+ export function CodeBlockDropdown({ items, onChange, value }: CodeBlockItems): JSX.Element {
13
+ const activeItem = items.find((item) => item.id === value) || items[0];
16
14
  const icon = activeItem?.lang ? getFileIconByLanguage(activeItem?.lang) : null;
17
15
  return (
18
- <StyledDropdown
16
+ <Dropdown
17
+ withArrow
19
18
  alignment="end"
20
19
  trigger={
21
- <Button icon={<ChevronSortIcon />} iconPosition="right" variant="text" size="small">
20
+ <Button iconPosition="right" variant="ghost" size="small">
22
21
  {icon}
23
22
  {activeItem.name}
24
23
  </Button>
@@ -27,11 +26,12 @@ export function CodeBlockDropdown({ items, onChange, value }: CodeBlockDropdownI
27
26
  <DropdownMenu>
28
27
  {items.map((item) => {
29
28
  const icon = getFileIconByLanguage(item.lang || '');
29
+ const isActive = item.id === value;
30
30
  return (
31
31
  <DropdownMenuItem
32
- key={item.lang}
33
- onAction={() => onChange(item.name)}
34
- active={item.name === activeItem.name}
32
+ key={item.id}
33
+ onAction={() => onChange(item.id)}
34
+ active={isActive}
35
35
  prefix={item.lang ? icon : <NoneIcon size="var(--icon-size)" />}
36
36
  >
37
37
  {item.name}
@@ -39,15 +39,6 @@ export function CodeBlockDropdown({ items, onChange, value }: CodeBlockDropdownI
39
39
  );
40
40
  })}
41
41
  </DropdownMenu>
42
- </StyledDropdown>
42
+ </Dropdown>
43
43
  );
44
44
  }
45
-
46
- const StyledDropdown = styled(Dropdown)`
47
- margin-left: auto;
48
- --icon-size: 18px;
49
- --button-color: var(--text-color-secondary);
50
- button.button-size-small {
51
- --button-icon-size: 18px;
52
- }
53
- `;
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
- import type { CodeBlockTabItems } from '@redocly/theme/components/CodeBlock/CodeBlock';
5
+ import type { CodeBlockItems } from '@redocly/theme/components/CodeBlock/CodeBlock';
6
6
 
7
7
  import { useCodeBlockTabsControls } from '@redocly/theme/core/hooks';
8
8
  import { Button } from '@redocly/theme/components/Button/Button';
@@ -11,7 +11,7 @@ import { ChevronRightIcon } from '@redocly/theme/icons/ChevronRightIcon/ChevronR
11
11
  import { getFileIconByExt, getFileIconByLanguage } from '@redocly/theme/core/utils/get-file-icon';
12
12
 
13
13
  export type CodeBlockTabsProps = {
14
- tabs: CodeBlockTabItems;
14
+ tabs: CodeBlockItems;
15
15
  };
16
16
 
17
17
  export function CodeBlockTabs({ tabs }: CodeBlockTabsProps): JSX.Element {
@@ -24,7 +24,7 @@ export function CodeBlockTabs({ tabs }: CodeBlockTabsProps): JSX.Element {
24
24
  });
25
25
 
26
26
  useEffect(() => {
27
- const activeTab = tabRefs.current.find((tab) => tab?.dataset.name === tabs.value);
27
+ const activeTab = tabRefs.current.find((tab) => tab?.dataset.id === tabs.value);
28
28
 
29
29
  if (activeTab) {
30
30
  activeTab.scrollIntoView({ block: 'nearest', inline: 'center' });
@@ -35,23 +35,23 @@ export function CodeBlockTabs({ tabs }: CodeBlockTabsProps): JSX.Element {
35
35
  <CodeBlockTabsWrapper ref={containerRef} data-component-name="CodeBlock/CodeBlockTabs">
36
36
  <ShadowWrapper>
37
37
  <Tabs>
38
- {tabs.items.map(({ name, lang }, i) => {
38
+ {tabs.items.map((item, i) => {
39
+ const { name, lang, id } = item;
39
40
  const ext = name.match(/\.([^.]+)$/)?.[1];
40
41
  const fileIcon = lang
41
42
  ? getFileIconByLanguage(lang)
42
43
  : ext
43
44
  ? getFileIconByExt(ext)
44
45
  : null;
45
-
46
46
  return (
47
47
  <Tab
48
48
  ref={(el: HTMLButtonElement | null) => {
49
49
  tabRefs.current[i] = el as HTMLButtonElement;
50
50
  }}
51
51
  data-name={name}
52
- active={name === tabs.value}
53
- key={name + i}
54
- onClick={() => tabs.onChange(name)}
52
+ active={id === tabs.value}
53
+ key={id}
54
+ onClick={() => tabs.onChange(id)}
55
55
  >
56
56
  {fileIcon}
57
57
  {name}