@redocly/theme 0.51.0-next.0 → 0.51.0-next.2

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.
@@ -1,8 +1,9 @@
1
+ import { AiSearchError } from '../../core/constants';
1
2
  export type SearchAiResponseProps = {
2
3
  question: string;
3
4
  isGeneratingResponse: boolean;
4
5
  response?: string;
5
- error: string | null;
6
+ error: AiSearchError | null;
6
7
  resources: {
7
8
  url: string;
8
9
  title: string;
@@ -15,6 +15,7 @@ const hooks_1 = require("../../core/hooks");
15
15
  const Markdown_1 = require("../../components/Markdown/Markdown");
16
16
  const Admonition_1 = require("../../components/Admonition/Admonition");
17
17
  const ErrorFilledIcon_1 = require("../../icons/ErrorFilledIcon/ErrorFilledIcon");
18
+ const constants_1 = require("../../core/constants");
18
19
  function SearchAiResponse(props) {
19
20
  const { useMarkdownText } = (0, hooks_1.useThemeHooks)();
20
21
  const { question, response, isGeneratingResponse, resources, error } = props;
@@ -43,7 +44,7 @@ function SearchAiResponse(props) {
43
44
  react_1.default.createElement(ResponseBody, null,
44
45
  response && react_1.default.createElement(ResponseText, Object.assign({ children: markdownResponse, as: "div" }, props)),
45
46
  !response && isGeneratingResponse && (react_1.default.createElement(ThinkingResponseText, { "data-translation-key": "search.ai.thinkingText" }, translate('search.ai.thinkingText', 'Thinking...'))),
46
- error && (react_1.default.createElement(Admonition_1.Admonition, { type: "danger", name: translate('search.ai.error.header', 'Oops! Something went wrong.') }, translate('search.ai.error.description', 'We encountered an issue while processing your search. Please try again later or refine your query. If the problem persists, feel free to contact support.'))),
47
+ error && (react_1.default.createElement(Admonition_1.Admonition, { type: "danger", name: translate(constants_1.AI_SEARCH_ERROR_CONFIG[error].headerKey, constants_1.AI_SEARCH_ERROR_CONFIG[error].headerDefault) }, translate(constants_1.AI_SEARCH_ERROR_CONFIG[error].messageKey, constants_1.AI_SEARCH_ERROR_CONFIG[error].messageDefault))),
47
48
  resources.length && !isGeneratingResponse ? (react_1.default.createElement(Resources, null,
48
49
  react_1.default.createElement(ResourcesTitle, { "data-translation-key": "search.ai.resourcesFound" },
49
50
  resources.length,
@@ -125,7 +126,10 @@ const ResourceTags = styled_components_1.default.div `
125
126
  flex-wrap: wrap;
126
127
  gap: var(--search-ai-resource-tags-gap);
127
128
  `;
128
- const ResourceTag = (0, styled_components_1.default)(Tag_1.Tag) `
129
+ const ResourceTag = (0, styled_components_1.default)(Tag_1.Tag).attrs({
130
+ className: 'tag-resource',
131
+ 'data-component-name': 'Tags/SearchAiResourceTag',
132
+ }) `
129
133
  .tag-default {
130
134
  --tag-color: --search-ai-resource-tag-text-color;
131
135
  }
@@ -1,3 +1,4 @@
1
1
  export * from '../../core/constants/common';
2
2
  export * from '../../core/constants/environments';
3
3
  export * from '../../core/constants/code-walkthrough';
4
+ export * from '../../core/constants/search';
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("../../core/constants/common"), exports);
18
18
  __exportStar(require("../../core/constants/environments"), exports);
19
19
  __exportStar(require("../../core/constants/code-walkthrough"), exports);
20
+ __exportStar(require("../../core/constants/search"), exports);
20
21
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ import type { AiSearchErrorConfig } from '../../core/types';
2
+ export declare enum AiSearchError {
3
+ Unauthorized = "ai_search_unauthorized",
4
+ Forbidden = "ai_search_forbidden",
5
+ HttpRequestFailed = "http_request_in_failed_status",
6
+ EmptyResponse = "empty_response",
7
+ ErrorProcessingResponse = "error_processing_response"
8
+ }
9
+ export declare const AI_SEARCH_ERROR_CONFIG: Record<AiSearchError, AiSearchErrorConfig>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AI_SEARCH_ERROR_CONFIG = exports.AiSearchError = void 0;
4
+ var AiSearchError;
5
+ (function (AiSearchError) {
6
+ AiSearchError["Unauthorized"] = "ai_search_unauthorized";
7
+ AiSearchError["Forbidden"] = "ai_search_forbidden";
8
+ AiSearchError["HttpRequestFailed"] = "http_request_in_failed_status";
9
+ AiSearchError["EmptyResponse"] = "empty_response";
10
+ AiSearchError["ErrorProcessingResponse"] = "error_processing_response";
11
+ })(AiSearchError || (exports.AiSearchError = AiSearchError = {}));
12
+ const defaultErrorConfig = {
13
+ headerKey: 'search.ai.error.header',
14
+ headerDefault: 'Oops! Something went wrong.',
15
+ messageKey: 'search.ai.error.description',
16
+ messageDefault: 'We encountered an issue while processing your search. Try again later or refine your query. If the problem persists, please contact Redocly support.',
17
+ };
18
+ exports.AI_SEARCH_ERROR_CONFIG = {
19
+ [AiSearchError.Forbidden]: {
20
+ headerKey: 'search.ai.error.header.forbidden',
21
+ headerDefault: 'Feature Unavailable',
22
+ messageKey: 'search.ai.error.description.forbidden',
23
+ messageDefault: 'AI Search is currently unavailable.',
24
+ },
25
+ [AiSearchError.Unauthorized]: {
26
+ headerKey: 'search.ai.error.header.unauthorized',
27
+ headerDefault: 'Authentication Required',
28
+ messageKey: 'search.ai.error.description.unauthorized',
29
+ messageDefault: 'You are not authorized to use AI Search.',
30
+ },
31
+ [AiSearchError.HttpRequestFailed]: defaultErrorConfig,
32
+ [AiSearchError.EmptyResponse]: defaultErrorConfig,
33
+ [AiSearchError.ErrorProcessingResponse]: defaultErrorConfig,
34
+ };
35
+ //# sourceMappingURL=search.js.map
@@ -4,6 +4,7 @@ import type { Callback, TFunction as TFunc } from 'i18next';
4
4
  import type { To, Location, NavigateFunction } from 'react-router-dom';
5
5
  import type { CatalogConfig, ProductUiConfig } from '../../config';
6
6
  import type { UserMenuData, FilteredCatalog, ItemState, SearchItemData, SubmitFeedbackParams, TFunction, BreadcrumbItem, DrilldownMenuItemDetails, SearchFacet, SearchFilterItem, SearchFacetQuery } from '../../core/types';
7
+ import { AiSearchError } from '../../core/constants';
7
8
  export type ThemeHooks = {
8
9
  useTranslate: () => {
9
10
  translate: TFunction;
@@ -73,7 +74,7 @@ export type ThemeHooks = {
73
74
  title: string;
74
75
  url: string;
75
76
  }[];
76
- error: null | string;
77
+ error: null | AiSearchError;
77
78
  clearAiSearchState: () => void;
78
79
  };
79
80
  useMarkdownText: (text: string) => React.ReactNode;
@@ -10,4 +10,3 @@ export * from '../../core/types/select';
10
10
  export * from '../../core/types/sidebar';
11
11
  export * from '../../core/types/filter';
12
12
  export * from '../../core/types/user-menu';
13
- export * from '../../core/types/api-functions';
@@ -26,5 +26,4 @@ __exportStar(require("../../core/types/select"), exports);
26
26
  __exportStar(require("../../core/types/sidebar"), exports);
27
27
  __exportStar(require("../../core/types/filter"), exports);
28
28
  __exportStar(require("../../core/types/user-menu"), exports);
29
- __exportStar(require("../../core/types/api-functions"), exports);
30
29
  //# sourceMappingURL=index.js.map
@@ -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.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.button' | 'search.ai.label' | 'search.ai.disclaimer' | 'search.ai.error.description' | 'search.ai.error.header' | '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.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeLayout' | '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.settings.reasons.send' | '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' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'page.nextButton' | 'page.previousButton' | '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.deprecated' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.noResponseExample' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.scopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | '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.implementedInterfaces' | 'graphql.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'codeWalkthrough.download' | 'codeWalkthrough.preview';
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.thinkingText' | 'search.ai.resourcesFound' | '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.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeLayout' | '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.settings.reasons.send' | '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' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'page.nextButton' | 'page.previousButton' | '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.deprecated' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.collapseAll' | 'openapi.noResponseExample' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.scopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | '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.implementedInterfaces' | 'graphql.nonNull' | 'graphql.required' | 'graphql.deprecated' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'codeWalkthrough.download' | 'codeWalkthrough.preview';
3
3
  export type Locale = {
4
4
  code: string;
5
5
  name: string;
@@ -70,3 +70,9 @@ export type SearchFilterItem = {
70
70
  values: string[];
71
71
  isQuickFilter?: boolean;
72
72
  };
73
+ export type AiSearchErrorConfig = {
74
+ headerKey: string;
75
+ headerDefault: string;
76
+ messageKey: string;
77
+ messageDefault: string;
78
+ };
@@ -61,7 +61,7 @@ function CodePanelHeader({ files, handleTabSwitch, activeTabName, onDownloadCode
61
61
  if (!tab)
62
62
  continue;
63
63
  const { left: tabLeft, right: tabRight } = tab.getBoundingClientRect();
64
- const visible = tabLeft > wrapperLeft && tabRight < wrapperRight;
64
+ const visible = tabLeft >= wrapperLeft && tabRight <= wrapperRight;
65
65
  if (!visible) {
66
66
  hidden.push(renderableFiles[i]);
67
67
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.51.0-next.0",
3
+ "version": "0.51.0-next.2",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -59,8 +59,6 @@
59
59
  "jest-styled-components": "7.2.0",
60
60
  "jest-when": "3.6.0",
61
61
  "json-schema-to-ts": "2.7.2",
62
- "lodash.debounce": "4.0.8",
63
- "lodash.throttle": "4.1.1",
64
62
  "npm-run-all2": "5.0.2",
65
63
  "react-refresh": "0.14.2",
66
64
  "react-router-dom": "6.21.1",
@@ -82,12 +80,14 @@
82
80
  "highlight-words-core": "1.2.2",
83
81
  "hotkeys-js": "3.10.1",
84
82
  "jszip": "3.10.1",
83
+ "lodash.debounce": "4.0.8",
84
+ "lodash.throttle": "4.1.1",
85
85
  "react-calendar": "4.2.1",
86
86
  "react-date-picker": "10.0.3",
87
87
  "timeago.js": "4.0.2",
88
88
  "i18next": "22.4.15",
89
89
  "nprogress": "0.2.0",
90
- "@redocly/config": "0.20.3"
90
+ "@redocly/config": "0.21.0"
91
91
  },
92
92
  "scripts": {
93
93
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -10,18 +10,21 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
10
10
  import { Markdown } from '@redocly/theme/components/Markdown/Markdown';
11
11
  import { Admonition } from '@redocly/theme/components/Admonition/Admonition';
12
12
  import { ErrorFilledIcon } from '@redocly/theme/icons/ErrorFilledIcon/ErrorFilledIcon';
13
+ import {
14
+ AiSearchError,
15
+ AI_SEARCH_ERROR_CONFIG as ERROR_CONFIG,
16
+ } from '@redocly/theme/core/constants';
13
17
 
14
18
  export type SearchAiResponseProps = {
15
19
  question: string;
16
20
  isGeneratingResponse: boolean;
17
21
  response?: string;
18
- error: string | null;
22
+ error: AiSearchError | null;
19
23
  resources: {
20
24
  url: string;
21
25
  title: string;
22
26
  }[];
23
27
  };
24
-
25
28
  export function SearchAiResponse(props: SearchAiResponseProps): JSX.Element {
26
29
  const { useMarkdownText } = useThemeHooks();
27
30
  const { question, response, isGeneratingResponse, resources, error } = props;
@@ -62,12 +65,9 @@ export function SearchAiResponse(props: SearchAiResponseProps): JSX.Element {
62
65
  {error && (
63
66
  <Admonition
64
67
  type="danger"
65
- name={translate('search.ai.error.header', 'Oops! Something went wrong.')}
68
+ name={translate(ERROR_CONFIG[error].headerKey, ERROR_CONFIG[error].headerDefault)}
66
69
  >
67
- {translate(
68
- 'search.ai.error.description',
69
- 'We encountered an issue while processing your search. Please try again later or refine your query. If the problem persists, feel free to contact support.',
70
- )}
70
+ {translate(ERROR_CONFIG[error].messageKey, ERROR_CONFIG[error].messageDefault)}
71
71
  </Admonition>
72
72
  )}
73
73
  {resources.length && !isGeneratingResponse ? (
@@ -180,8 +180,10 @@ const ResourceTags = styled.div`
180
180
  flex-wrap: wrap;
181
181
  gap: var(--search-ai-resource-tags-gap);
182
182
  `;
183
-
184
- const ResourceTag = styled(Tag)`
183
+ const ResourceTag = styled(Tag).attrs({
184
+ className: 'tag-resource',
185
+ 'data-component-name': 'Tags/SearchAiResourceTag',
186
+ })`
185
187
  .tag-default {
186
188
  --tag-color: --search-ai-resource-tag-text-color;
187
189
  }
@@ -1,3 +1,4 @@
1
1
  export * from '@redocly/theme/core/constants/common';
2
2
  export * from '@redocly/theme/core/constants/environments';
3
3
  export * from '@redocly/theme/core/constants/code-walkthrough';
4
+ export * from '@redocly/theme/core/constants/search';
@@ -0,0 +1,35 @@
1
+ import type { AiSearchErrorConfig } from '@redocly/theme/core/types';
2
+
3
+ export enum AiSearchError {
4
+ Unauthorized = 'ai_search_unauthorized',
5
+ Forbidden = 'ai_search_forbidden',
6
+ HttpRequestFailed = 'http_request_in_failed_status',
7
+ EmptyResponse = 'empty_response',
8
+ ErrorProcessingResponse = 'error_processing_response',
9
+ }
10
+
11
+ const defaultErrorConfig: AiSearchErrorConfig = {
12
+ headerKey: 'search.ai.error.header',
13
+ headerDefault: 'Oops! Something went wrong.',
14
+ messageKey: 'search.ai.error.description',
15
+ messageDefault:
16
+ 'We encountered an issue while processing your search. Try again later or refine your query. If the problem persists, please contact Redocly support.',
17
+ };
18
+
19
+ export const AI_SEARCH_ERROR_CONFIG: Record<AiSearchError, AiSearchErrorConfig> = {
20
+ [AiSearchError.Forbidden]: {
21
+ headerKey: 'search.ai.error.header.forbidden',
22
+ headerDefault: 'Feature Unavailable',
23
+ messageKey: 'search.ai.error.description.forbidden',
24
+ messageDefault: 'AI Search is currently unavailable.',
25
+ },
26
+ [AiSearchError.Unauthorized]: {
27
+ headerKey: 'search.ai.error.header.unauthorized',
28
+ headerDefault: 'Authentication Required',
29
+ messageKey: 'search.ai.error.description.unauthorized',
30
+ messageDefault: 'You are not authorized to use AI Search.',
31
+ },
32
+ [AiSearchError.HttpRequestFailed]: defaultErrorConfig,
33
+ [AiSearchError.EmptyResponse]: defaultErrorConfig,
34
+ [AiSearchError.ErrorProcessingResponse]: defaultErrorConfig,
35
+ } as const;
@@ -17,6 +17,8 @@ import type {
17
17
  SearchFacetQuery,
18
18
  } from '@redocly/theme/core/types';
19
19
 
20
+ import { AiSearchError } from '@redocly/theme/core/constants';
21
+
20
22
  export type ThemeHooks = {
21
23
  useTranslate: () => { translate: TFunction };
22
24
  /**
@@ -88,7 +90,7 @@ export type ThemeHooks = {
88
90
  title: string;
89
91
  url: string;
90
92
  }[];
91
- error: null | string;
93
+ error: null | AiSearchError;
92
94
  clearAiSearchState: () => void;
93
95
  };
94
96
  useMarkdownText: (text: string) => React.ReactNode;
@@ -10,4 +10,3 @@ export * from '@redocly/theme/core/types/select';
10
10
  export * from '@redocly/theme/core/types/sidebar';
11
11
  export * from '@redocly/theme/core/types/filter';
12
12
  export * from '@redocly/theme/core/types/user-menu';
13
- export * from '@redocly/theme/core/types/api-functions';
@@ -89,7 +89,11 @@ export type TranslationKey =
89
89
  | 'search.ai.label'
90
90
  | 'search.ai.disclaimer'
91
91
  | 'search.ai.error.description'
92
+ | 'search.ai.error.description.forbidden'
93
+ | 'search.ai.error.description.unauthorized'
92
94
  | 'search.ai.error.header'
95
+ | 'search.ai.error.header.forbidden'
96
+ | 'search.ai.error.header.unauthorized'
93
97
  | 'toc.header'
94
98
  | 'footer.copyrightText'
95
99
  | 'page.homeButton'
@@ -78,3 +78,10 @@ export type SearchFilterItem = {
78
78
  values: string[];
79
79
  isQuickFilter?: boolean;
80
80
  };
81
+
82
+ export type AiSearchErrorConfig = {
83
+ headerKey: string;
84
+ headerDefault: string;
85
+ messageKey: string;
86
+ messageDefault: string;
87
+ };
@@ -57,7 +57,7 @@ export function CodePanelHeader({
57
57
  if (!tab) continue;
58
58
 
59
59
  const { left: tabLeft, right: tabRight } = tab.getBoundingClientRect();
60
- const visible = tabLeft > wrapperLeft && tabRight < wrapperRight;
60
+ const visible = tabLeft >= wrapperLeft && tabRight <= wrapperRight;
61
61
 
62
62
  if (!visible) {
63
63
  hidden.push(renderableFiles[i]);
@@ -1,5 +0,0 @@
1
- export type { ApiFunctionsRequest as Request } from '@redocly/config';
2
- export type { ApiFunctionsResponse as Response } from '@redocly/config';
3
- export type { ApiFunctionsContext as Context } from '@redocly/config';
4
- export type { PropsContext } from '@redocly/config';
5
- export type { PageStaticData as PropsData } from '@redocly/config';
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=api-functions.js.map
@@ -1,5 +0,0 @@
1
- export type { ApiFunctionsRequest as Request } from '@redocly/config';
2
- export type { ApiFunctionsResponse as Response } from '@redocly/config';
3
- export type { ApiFunctionsContext as Context } from '@redocly/config';
4
- export type { PropsContext } from '@redocly/config';
5
- export type { PageStaticData as PropsData } from '@redocly/config';