@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.
- package/lib/components/Catalog/CatalogEntity/CatalogEntity.d.ts +5 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +4 -4
- package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +3 -3
- package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.d.ts +5 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +9 -7
- package/lib/components/CodeBlock/CodeBlock.d.ts +5 -12
- package/lib/components/CodeBlock/CodeBlockControls.d.ts +3 -3
- package/lib/components/CodeBlock/CodeBlockControls.js +1 -1
- package/lib/components/CodeBlock/CodeBlockDropdown.d.ts +2 -2
- package/lib/components/CodeBlock/CodeBlockDropdown.js +4 -13
- package/lib/components/CodeBlock/CodeBlockTabs.d.ts +2 -2
- package/lib/components/CodeBlock/CodeBlockTabs.js +4 -3
- package/lib/components/JsonViewer/JsonViewer.d.ts +1 -1
- package/lib/components/JsonViewer/JsonViewer.js +9 -10
- package/lib/components/PageActions/PageActions.d.ts +4 -1
- package/lib/components/PageActions/PageActions.js +2 -2
- package/lib/core/constants/catalog.js +4 -0
- package/lib/core/contexts/CodeSnippetContext.d.ts +14 -6
- package/lib/core/contexts/CodeSnippetContext.js +57 -14
- package/lib/core/hooks/use-codeblock-tabs-controls.d.ts +2 -2
- package/lib/core/hooks/use-local-state.js +22 -18
- package/lib/core/hooks/use-page-actions.d.ts +2 -1
- package/lib/core/hooks/use-page-actions.js +48 -6
- package/lib/core/openapi/index.d.ts +1 -0
- package/lib/core/openapi/index.js +3 -1
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/types/open-api-server.d.ts +1 -0
- package/lib/icons/CursorIcon/CursorIcon.d.ts +9 -0
- package/lib/icons/CursorIcon/CursorIcon.js +22 -0
- package/lib/layouts/DocumentationLayout.js +1 -3
- package/lib/markdoc/components/CodeGroup/CodeGroup.js +49 -27
- package/lib/markdoc/components/Tabs/TabList.js +2 -0
- package/package.json +4 -4
- package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +15 -2
- package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +3 -3
- package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +27 -18
- package/src/components/CodeBlock/CodeBlock.tsx +5 -11
- package/src/components/CodeBlock/CodeBlockControls.tsx +4 -7
- package/src/components/CodeBlock/CodeBlockDropdown.tsx +11 -20
- package/src/components/CodeBlock/CodeBlockTabs.tsx +8 -8
- package/src/components/JsonViewer/JsonViewer.tsx +16 -9
- package/src/components/PageActions/PageActions.tsx +6 -4
- package/src/core/constants/catalog.ts +4 -0
- package/src/core/contexts/CodeSnippetContext.tsx +54 -18
- package/src/core/hooks/use-codeblock-tabs-controls.ts +2 -2
- package/src/core/hooks/use-local-state.ts +28 -19
- package/src/core/hooks/use-page-actions.ts +63 -6
- package/src/core/openapi/index.ts +1 -0
- package/src/core/types/l10n.ts +13 -0
- package/src/core/types/open-api-server.ts +1 -0
- package/src/icons/CursorIcon/CursorIcon.tsx +35 -0
- package/src/layouts/DocumentationLayout.tsx +3 -10
- package/src/markdoc/components/CodeGroup/CodeGroup.tsx +81 -52
- package/src/markdoc/components/Tabs/TabList.tsx +1 -0
|
@@ -2,5 +2,9 @@ import React from 'react';
|
|
|
2
2
|
export type CatalogEntityProps = {
|
|
3
3
|
RedocSchema: React.ComponentType<any>;
|
|
4
4
|
StoreProvider: React.ComponentType<any>;
|
|
5
|
+
GraphqlTypeRenderer?: React.ComponentType<{
|
|
6
|
+
sdl: string;
|
|
7
|
+
typeName: string;
|
|
8
|
+
}>;
|
|
5
9
|
};
|
|
6
|
-
export declare function CatalogEntity({ RedocSchema, StoreProvider }: CatalogEntityProps): React.JSX.Element;
|
|
10
|
+
export declare function CatalogEntity({ RedocSchema, StoreProvider, GraphqlTypeRenderer, }: CatalogEntityProps): React.JSX.Element;
|
|
@@ -26,13 +26,13 @@ const renderFirstColumnEntitySection = (entity) => {
|
|
|
26
26
|
return react_1.default.createElement(CatalogEntityMetadata_1.CatalogEntityMetadata, { entity: entity });
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
|
-
const renderDataSchemaSection = (entity, relatedEntity, RedocSchema, StoreProvider) => {
|
|
29
|
+
const renderDataSchemaSection = (entity, relatedEntity, RedocSchema, StoreProvider, GraphqlTypeRenderer) => {
|
|
30
30
|
if (entity.type !== 'data-schema') {
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
return (react_1.default.createElement(CatalogEntitySchema_1.CatalogEntitySchema, { entity: entity, relatedEntity: relatedEntity, RedocSchema: RedocSchema, StoreProvider: StoreProvider }));
|
|
33
|
+
return (react_1.default.createElement(CatalogEntitySchema_1.CatalogEntitySchema, { entity: entity, relatedEntity: relatedEntity, RedocSchema: RedocSchema, StoreProvider: StoreProvider, GraphqlTypeRenderer: GraphqlTypeRenderer }));
|
|
34
34
|
};
|
|
35
|
-
function CatalogEntity({ RedocSchema, StoreProvider }) {
|
|
35
|
+
function CatalogEntity({ RedocSchema, StoreProvider, GraphqlTypeRenderer, }) {
|
|
36
36
|
var _a;
|
|
37
37
|
const { useTranslate, useCatalog, usePageProps } = (0, hooks_1.useThemeHooks)();
|
|
38
38
|
const { translate } = useTranslate();
|
|
@@ -52,7 +52,7 @@ function CatalogEntity({ RedocSchema, StoreProvider }) {
|
|
|
52
52
|
react_1.default.createElement(react_router_dom_1.Route, { index: true, element: react_1.default.createElement(react_1.default.Fragment, null,
|
|
53
53
|
react_1.default.createElement(CatalogPageDescription_1.CatalogPageDescription, { title: entity.title, description: (_a = entity.summary) !== null && _a !== void 0 ? _a : '', tag: entity.key }),
|
|
54
54
|
react_1.default.createElement(CatalogEntityProperties_1.CatalogEntityProperties, { entity: entity }),
|
|
55
|
-
renderDataSchemaSection(entity, relatedEntity, RedocSchema, StoreProvider),
|
|
55
|
+
renderDataSchemaSection(entity, relatedEntity, RedocSchema, StoreProvider, GraphqlTypeRenderer),
|
|
56
56
|
react_1.default.createElement(CatalogTwoColumnsSection, null,
|
|
57
57
|
renderFirstColumnEntitySection(entity),
|
|
58
58
|
react_1.default.createElement(CatalogEntityLinks_1.CatalogEntityLinks, { entity: entity })),
|
|
@@ -48,17 +48,17 @@ const CatalogEntityInfoBar_1 = require("../../../components/Catalog/CatalogEntit
|
|
|
48
48
|
const MAX_INITIAL_ITEMS = 4;
|
|
49
49
|
function renderMetadataValue(value) {
|
|
50
50
|
if ((0, utils_1.isPlainObject)(value)) {
|
|
51
|
-
return react_1.default.createElement(JsonViewerWrapper, { data: value, expandLevel: 3,
|
|
51
|
+
return react_1.default.createElement(JsonViewerWrapper, { data: value, expandLevel: 3, controls: false });
|
|
52
52
|
}
|
|
53
53
|
if (Array.isArray(value)) {
|
|
54
|
-
return (react_1.default.createElement(ArrayWrapper, null, value.map((item, index) => (react_1.default.createElement("div", { key: index }, (0, utils_1.isPlainObject)(item) ? (react_1.default.createElement(JsonViewerWrapper, { data: item, expandLevel: 3,
|
|
54
|
+
return (react_1.default.createElement(ArrayWrapper, null, value.map((item, index) => (react_1.default.createElement("div", { key: index }, (0, utils_1.isPlainObject)(item) ? (react_1.default.createElement(JsonViewerWrapper, { data: item, expandLevel: 3, controls: false })) : (react_1.default.createElement("span", null, String(item))))))));
|
|
55
55
|
}
|
|
56
56
|
return react_1.default.createElement("span", null, String(value));
|
|
57
57
|
}
|
|
58
58
|
function CatalogEntityMetadata({ entity }) {
|
|
59
59
|
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
60
60
|
const { translate } = useTranslate();
|
|
61
|
-
const _a = entity.metadata || {}, { schema } = _a, metadata = __rest(_a, ["schema"]);
|
|
61
|
+
const _a = entity.metadata || {}, { schema, sdl } = _a, metadata = __rest(_a, ["schema", "sdl"]);
|
|
62
62
|
const metadataToShow = Object.entries(metadata).filter(([key]) => !(entity.type === 'api-description' && key === 'descriptionFile'));
|
|
63
63
|
const [isOn, setIsOn] = (0, react_1.useState)(false);
|
|
64
64
|
const hasMoreItems = metadataToShow.length > MAX_INITIAL_ITEMS;
|
|
@@ -5,5 +5,9 @@ export type CatalogEntitySchemaProps = {
|
|
|
5
5
|
relatedEntity: BffCatalogRelatedEntity | null;
|
|
6
6
|
RedocSchema: React.ComponentType<any>;
|
|
7
7
|
StoreProvider: React.ComponentType<any>;
|
|
8
|
+
GraphqlTypeRenderer?: React.ComponentType<{
|
|
9
|
+
sdl: string;
|
|
10
|
+
typeName: string;
|
|
11
|
+
}>;
|
|
8
12
|
};
|
|
9
|
-
export declare function CatalogEntitySchema({ entity, relatedEntity, RedocSchema, StoreProvider, }: CatalogEntitySchemaProps): React.JSX.Element;
|
|
13
|
+
export declare function CatalogEntitySchema({ entity, relatedEntity, RedocSchema, StoreProvider, GraphqlTypeRenderer, }: CatalogEntitySchemaProps): React.JSX.Element;
|
|
@@ -34,20 +34,22 @@ const hooks_1 = require("../../../core/hooks");
|
|
|
34
34
|
const useCatalogEntitySchema_1 = require("../../../core/hooks/catalog/useCatalogEntitySchema");
|
|
35
35
|
const JsonViewer_1 = require("../../../components/JsonViewer/JsonViewer");
|
|
36
36
|
const CopyButton_1 = require("../../../components/Buttons/CopyButton");
|
|
37
|
-
function CatalogEntitySchema({ entity, relatedEntity, RedocSchema, StoreProvider, }) {
|
|
37
|
+
function CatalogEntitySchema({ entity, relatedEntity, RedocSchema, StoreProvider, GraphqlTypeRenderer, }) {
|
|
38
|
+
var _a, _b;
|
|
38
39
|
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
39
40
|
const { translate } = useTranslate();
|
|
40
41
|
const { definition, parsedSchema, rawSchema } = (0, useCatalogEntitySchema_1.useCatalogEntitySchema)({ entity, relatedEntity });
|
|
42
|
+
const isGraphql = ((_a = entity.metadata) === null || _a === void 0 ? void 0 : _a.specType) === 'graphql';
|
|
43
|
+
const graphqlSDL = (_b = entity === null || entity === void 0 ? void 0 : entity.metadata) === null || _b === void 0 ? void 0 : _b.sdl;
|
|
41
44
|
return (react_1.default.createElement(MetadataWrapper, { "data-component-name": "Catalog/CatalogEntity/CatalogEntityMetadata" },
|
|
42
45
|
react_1.default.createElement(HeaderWrapper, null,
|
|
43
46
|
react_1.default.createElement(Heading, null, translate('catalog.entity.schema.title')),
|
|
44
|
-
react_1.default.createElement(CopyButton_1.CopyButton, { data: rawSchema, buttonText: "Copy Schema", type: "compound", variant: "secondary", iconPosition: "right", size: "medium" })),
|
|
47
|
+
!isGraphql && (react_1.default.createElement(CopyButton_1.CopyButton, { data: rawSchema, buttonText: "Copy Schema", type: "compound", variant: "secondary", iconPosition: "right", size: "medium" }))),
|
|
45
48
|
react_1.default.createElement(SplitViewWrapper, null,
|
|
46
|
-
react_1.default.createElement(SchemaContentWrapper, null,
|
|
47
|
-
react_1.default.createElement(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
react_1.default.createElement(JsonViewer_1.JsonViewer, { data: Sampler.sample(Object.assign({}, parsedSchema)), expandLevel: 3, hideHeader: false })))));
|
|
49
|
+
react_1.default.createElement(SchemaContentWrapper, null, isGraphql && graphqlSDL && GraphqlTypeRenderer ? (react_1.default.createElement(GraphqlTypeRenderer, { sdl: graphqlSDL, typeName: entity.title })) : (react_1.default.createElement(StoreProvider, { definition: definition },
|
|
50
|
+
react_1.default.createElement(RedocSchema, { schema: parsedSchema })))),
|
|
51
|
+
!isGraphql && (react_1.default.createElement(SchemaSampleWrapper, null,
|
|
52
|
+
react_1.default.createElement(JsonViewer_1.JsonViewer, { data: Sampler.sample(Object.assign({}, parsedSchema)), expandLevel: 3 }))))));
|
|
51
53
|
}
|
|
52
54
|
const MetadataWrapper = styled_components_1.default.div `
|
|
53
55
|
display: flex;
|
|
@@ -8,8 +8,8 @@ export type CodeBlockProps = {
|
|
|
8
8
|
header?: CodeBlockControlsProps;
|
|
9
9
|
dataTestId?: string;
|
|
10
10
|
className?: string;
|
|
11
|
-
tabs?:
|
|
12
|
-
dropdown?:
|
|
11
|
+
tabs?: CodeBlockItems;
|
|
12
|
+
dropdown?: CodeBlockItems;
|
|
13
13
|
withLineNumbers?: boolean;
|
|
14
14
|
startLineNumber?: number;
|
|
15
15
|
highlightedHtml?: string;
|
|
@@ -25,20 +25,13 @@ type UnstableExternalCodeSample = {
|
|
|
25
25
|
label?: string;
|
|
26
26
|
get: (source: ExternalSource) => string;
|
|
27
27
|
};
|
|
28
|
-
export type
|
|
28
|
+
export type CodeBlockItems = {
|
|
29
29
|
items: {
|
|
30
30
|
name: string;
|
|
31
31
|
lang?: string;
|
|
32
|
+
id: string;
|
|
32
33
|
}[];
|
|
33
|
-
onChange: (
|
|
34
|
-
value: string;
|
|
35
|
-
};
|
|
36
|
-
export type CodeBlockDropdownItems = {
|
|
37
|
-
items: {
|
|
38
|
-
name: string;
|
|
39
|
-
lang?: string;
|
|
40
|
-
}[];
|
|
41
|
-
onChange: (name: string | string[]) => void;
|
|
34
|
+
onChange: (id: string) => void;
|
|
42
35
|
value: string;
|
|
43
36
|
};
|
|
44
37
|
type ExternalSource = {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { JSX } from 'react';
|
|
3
|
-
import type {
|
|
3
|
+
import type { CodeBlockItems } from '../../components/CodeBlock/CodeBlock';
|
|
4
4
|
export type CodeBlockControlsProps = {
|
|
5
5
|
children?: React.ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
title?: React.ReactNode | string;
|
|
8
8
|
controls?: ControlItems | false;
|
|
9
|
-
tabs?:
|
|
10
|
-
dropdown?:
|
|
9
|
+
tabs?: CodeBlockItems;
|
|
10
|
+
dropdown?: CodeBlockItems;
|
|
11
11
|
};
|
|
12
12
|
type ControlItems = {
|
|
13
13
|
copy?: CopyControlProps;
|
|
@@ -38,7 +38,7 @@ function CodeBlockControls({ children, className, title, controls, tabs, dropdow
|
|
|
38
38
|
tabs && react_1.default.createElement(CodeBlockTabs_1.CodeBlockTabs, { tabs: tabs }),
|
|
39
39
|
react_1.default.createElement(ControlsWrapper, null,
|
|
40
40
|
dropdown && react_1.default.createElement(CodeBlockDropdown_1.CodeBlockDropdown, Object.assign({}, dropdown)),
|
|
41
|
-
report && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.report.tooltipText', 'Report a problem'), placement: "top" },
|
|
41
|
+
report && !report.hidden && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.report.tooltipText', 'Report a problem'), placement: "top" },
|
|
42
42
|
react_1.default.createElement(ControlButton, Object.assign({ variant: "text", size: "small", "data-testid": "report-button", icon: controlsType === 'icon' ? react_1.default.createElement(WarningSquareIcon_1.WarningSquareIcon, { size: "18px" }) : undefined }, report.props), controlsType != 'icon' && (((_b = report.props) === null || _b === void 0 ? void 0 : _b.buttonText) || 'Report')))) : null,
|
|
43
43
|
expand && !((_c = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _c === void 0 ? void 0 : _c.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.expand.tooltipText', 'Expand all'), placement: "top" },
|
|
44
44
|
react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "expand-all", icon: controlsType === 'icon' ? react_1.default.createElement(MaximizeIcon_1.MaximizeIcon, null) : undefined, onClick: expand === null || expand === void 0 ? void 0 : expand.onClick }, controlsType !== 'icon' && ((expand === null || expand === void 0 ? void 0 : expand.label) || 'Expand all')))) : null,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type JSX } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function CodeBlockDropdown({ items, onChange, value }:
|
|
2
|
+
import type { CodeBlockItems } from '../../components/CodeBlock/CodeBlock';
|
|
3
|
+
export declare function CodeBlockDropdown({ items, onChange, value }: CodeBlockItems): JSX.Element;
|
|
@@ -5,31 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.CodeBlockDropdown = CodeBlockDropdown;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
8
|
const Dropdown_1 = require("../../components/Dropdown/Dropdown");
|
|
10
9
|
const DropdownMenu_1 = require("../../components/Dropdown/DropdownMenu");
|
|
11
10
|
const DropdownMenuItem_1 = require("../../components/Dropdown/DropdownMenuItem");
|
|
12
11
|
const Button_1 = require("../../components/Button/Button");
|
|
13
|
-
const ChevronSortIcon_1 = require("../../icons/ChevronSortIcon/ChevronSortIcon");
|
|
14
12
|
const NoneIcon_1 = require("../../icons/NoneIcon/NoneIcon");
|
|
15
13
|
const utils_1 = require("../../core/utils");
|
|
16
14
|
function CodeBlockDropdown({ items, onChange, value }) {
|
|
17
|
-
const activeItem = items.find((item) => item.
|
|
15
|
+
const activeItem = items.find((item) => item.id === value) || items[0];
|
|
18
16
|
const icon = (activeItem === null || activeItem === void 0 ? void 0 : activeItem.lang) ? (0, utils_1.getFileIconByLanguage)(activeItem === null || activeItem === void 0 ? void 0 : activeItem.lang) : null;
|
|
19
|
-
return (react_1.default.createElement(
|
|
17
|
+
return (react_1.default.createElement(Dropdown_1.Dropdown, { withArrow: true, alignment: "end", trigger: react_1.default.createElement(Button_1.Button, { iconPosition: "right", variant: "ghost", size: "small" },
|
|
20
18
|
icon,
|
|
21
19
|
activeItem.name) },
|
|
22
20
|
react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, items.map((item) => {
|
|
23
21
|
const icon = (0, utils_1.getFileIconByLanguage)(item.lang || '');
|
|
24
|
-
|
|
22
|
+
const isActive = item.id === value;
|
|
23
|
+
return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: item.id, onAction: () => onChange(item.id), active: isActive, prefix: item.lang ? icon : react_1.default.createElement(NoneIcon_1.NoneIcon, { size: "var(--icon-size)" }) }, item.name));
|
|
25
24
|
}))));
|
|
26
25
|
}
|
|
27
|
-
const StyledDropdown = (0, styled_components_1.default)(Dropdown_1.Dropdown) `
|
|
28
|
-
margin-left: auto;
|
|
29
|
-
--icon-size: 18px;
|
|
30
|
-
--button-color: var(--text-color-secondary);
|
|
31
|
-
button.button-size-small {
|
|
32
|
-
--button-icon-size: 18px;
|
|
33
|
-
}
|
|
34
|
-
`;
|
|
35
26
|
//# sourceMappingURL=CodeBlockDropdown.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CodeBlockItems } from '../../components/CodeBlock/CodeBlock';
|
|
3
3
|
export type CodeBlockTabsProps = {
|
|
4
|
-
tabs:
|
|
4
|
+
tabs: CodeBlockItems;
|
|
5
5
|
};
|
|
6
6
|
export declare function CodeBlockTabs({ tabs }: CodeBlockTabsProps): JSX.Element;
|
|
@@ -40,15 +40,16 @@ function CodeBlockTabs({ tabs }) {
|
|
|
40
40
|
tabRefs,
|
|
41
41
|
});
|
|
42
42
|
(0, react_1.useEffect)(() => {
|
|
43
|
-
const activeTab = tabRefs.current.find((tab) => (tab === null || tab === void 0 ? void 0 : tab.dataset.
|
|
43
|
+
const activeTab = tabRefs.current.find((tab) => (tab === null || tab === void 0 ? void 0 : tab.dataset.id) === tabs.value);
|
|
44
44
|
if (activeTab) {
|
|
45
45
|
activeTab.scrollIntoView({ block: 'nearest', inline: 'center' });
|
|
46
46
|
}
|
|
47
47
|
}, [tabs.value]);
|
|
48
48
|
return (react_1.default.createElement(CodeBlockTabsWrapper, { ref: containerRef, "data-component-name": "CodeBlock/CodeBlockTabs" },
|
|
49
49
|
react_1.default.createElement(ShadowWrapper, null,
|
|
50
|
-
react_1.default.createElement(Tabs, null, tabs.items.map((
|
|
50
|
+
react_1.default.createElement(Tabs, null, tabs.items.map((item, i) => {
|
|
51
51
|
var _a;
|
|
52
|
+
const { name, lang, id } = item;
|
|
52
53
|
const ext = (_a = name.match(/\.([^.]+)$/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
53
54
|
const fileIcon = lang
|
|
54
55
|
? (0, get_file_icon_1.getFileIconByLanguage)(lang)
|
|
@@ -57,7 +58,7 @@ function CodeBlockTabs({ tabs }) {
|
|
|
57
58
|
: null;
|
|
58
59
|
return (react_1.default.createElement(Tab, { ref: (el) => {
|
|
59
60
|
tabRefs.current[i] = el;
|
|
60
|
-
}, "data-name": name, active:
|
|
61
|
+
}, "data-name": name, active: id === tabs.value, key: id, onClick: () => tabs.onChange(id) },
|
|
61
62
|
fileIcon,
|
|
62
63
|
name));
|
|
63
64
|
}))),
|
|
@@ -3,11 +3,11 @@ import type { CodeBlockControlsProps } from '../../components/CodeBlock/CodeBloc
|
|
|
3
3
|
export type PanelType = 'request' | 'responses' | 'request-samples' | 'response-samples';
|
|
4
4
|
export type JsonProps = {
|
|
5
5
|
title?: CodeBlockControlsProps['title'];
|
|
6
|
+
controls?: CodeBlockControlsProps['controls'];
|
|
6
7
|
data: any;
|
|
7
8
|
className?: string;
|
|
8
9
|
expandLevel: number;
|
|
9
10
|
startLineNumber?: number;
|
|
10
|
-
hideHeader?: boolean;
|
|
11
11
|
onCopyClick?: () => void;
|
|
12
12
|
onPanelToggle?: (isExpanded: boolean, panelType?: PanelType) => void;
|
|
13
13
|
};
|
|
@@ -31,7 +31,7 @@ const react_1 = __importStar(require("react"));
|
|
|
31
31
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
32
|
const CodeBlock_1 = require("../../components/CodeBlock/CodeBlock");
|
|
33
33
|
const helpers_1 = require("./helpers");
|
|
34
|
-
function JsonComponent({ data, expandLevel = 1, className, onCopyClick, onPanelToggle, title,
|
|
34
|
+
function JsonComponent({ data, expandLevel = 1, className, onCopyClick, onPanelToggle, title, controls = {}, }) {
|
|
35
35
|
const showFoldingButtons = data && Object.values(data).some((value) => typeof value === 'object' && value !== null);
|
|
36
36
|
const [expandAllSignal, setExpandAllSignal] = react_1.default.useState(undefined);
|
|
37
37
|
const expandAll = () => {
|
|
@@ -49,18 +49,17 @@ function JsonComponent({ data, expandLevel = 1, className, onCopyClick, onPanelT
|
|
|
49
49
|
});
|
|
50
50
|
};
|
|
51
51
|
const source = JSON.stringify(data, null, 2);
|
|
52
|
+
const hasHeader = title || controls;
|
|
52
53
|
return (react_1.default.createElement(exports.JsonViewerWrap, { "data-testid": "json-viewer", "data-component-name": "JsonViewer/JsonViewer", className: className },
|
|
53
|
-
react_1.default.createElement(CodeBlock_1.CodeBlock, { header:
|
|
54
|
-
?
|
|
55
|
-
: {
|
|
54
|
+
react_1.default.createElement(CodeBlock_1.CodeBlock, { header: hasHeader
|
|
55
|
+
? {
|
|
56
56
|
title,
|
|
57
57
|
className: 'code-block-header',
|
|
58
|
-
controls: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}, source: source },
|
|
58
|
+
controls: controls && Object.assign(Object.assign({}, controls), { copy: Object.assign(Object.assign({}, controls.copy), { data, onClick: onCopyClick, handleOutside: true }), expand: showFoldingButtons
|
|
59
|
+
? Object.assign(Object.assign({}, controls.expand), { onClick: expandAll }) : undefined, collapse: showFoldingButtons
|
|
60
|
+
? Object.assign(Object.assign({}, controls.collapse), { onClick: collapseAll }) : undefined }),
|
|
61
|
+
}
|
|
62
|
+
: undefined, source: source },
|
|
64
63
|
react_1.default.createElement(FoldingWrap, null,
|
|
65
64
|
react_1.default.createElement(helpers_1.JsonValue, { value: data, level: 0, standalone: true, expandAllSignal: expandAllSignal, defaultExpandLevel: Math.max(1, expandLevel) })))));
|
|
66
65
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
|
+
import { PageActionType } from '../../core/hooks';
|
|
2
3
|
type PageActionProps = {
|
|
3
|
-
pageSlug
|
|
4
|
+
pageSlug?: string;
|
|
5
|
+
mcpUrl?: string;
|
|
6
|
+
actions?: PageActionType[];
|
|
4
7
|
};
|
|
5
8
|
export declare function PageActions(props: PageActionProps): JSX.Element | null;
|
|
6
9
|
export {};
|
|
@@ -49,8 +49,8 @@ const CheckmarkFilledIcon_1 = require("../../icons/CheckmarkFilledIcon/Checkmark
|
|
|
49
49
|
const hooks_1 = require("../../core/hooks");
|
|
50
50
|
const ACTION_DONE_DISPLAY_DURATION = 1000;
|
|
51
51
|
function PageActions(props) {
|
|
52
|
-
const { pageSlug } = props;
|
|
53
|
-
const actions = (0, hooks_1.usePageActions)(pageSlug || '/');
|
|
52
|
+
const { pageSlug, mcpUrl } = props;
|
|
53
|
+
const actions = (0, hooks_1.usePageActions)(pageSlug || '/', mcpUrl, props.actions);
|
|
54
54
|
const [actionState, setActionState] = (0, react_1.useState)('idle');
|
|
55
55
|
if (!actions.length) {
|
|
56
56
|
return null;
|
|
@@ -37,6 +37,8 @@ exports.reverseRelationMap = {
|
|
|
37
37
|
memberOf: 'hasMember',
|
|
38
38
|
triggers: 'triggeredBy',
|
|
39
39
|
triggeredBy: 'triggers',
|
|
40
|
+
returns: 'returnedBy',
|
|
41
|
+
returnedBy: 'returns',
|
|
40
42
|
};
|
|
41
43
|
exports.relationTypeMap = {
|
|
42
44
|
partOf: 'Part of',
|
|
@@ -64,6 +66,8 @@ exports.relationTypeMap = {
|
|
|
64
66
|
memberOf: 'Member of',
|
|
65
67
|
triggers: 'Triggers',
|
|
66
68
|
triggeredBy: 'Triggered by',
|
|
69
|
+
returns: 'Returns',
|
|
70
|
+
returnedBy: 'Returned by',
|
|
67
71
|
};
|
|
68
72
|
var GraphHandleType;
|
|
69
73
|
(function (GraphHandleType) {
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
activeSnippetName: string;
|
|
3
|
-
setActiveSnippetName: (name: string) => void;
|
|
4
|
-
};
|
|
1
|
+
import React from 'react';
|
|
5
2
|
export declare const CODE_GROUP_SNIPPET_NAME_KEY = "redocly:codeGroupSnippetName";
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
type CodeSnippetContextType = {
|
|
4
|
+
activeSnippets: Record<string, string>;
|
|
5
|
+
setActiveSnippet: (groupId: string, snippetId: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const CodeSnippetContext: React.Context<CodeSnippetContextType | null>;
|
|
8
|
+
export declare function CodeSnippetProvider({ children }: {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
export declare const useCodeSnippetContext: () => CodeSnippetContextType;
|
|
12
|
+
export declare const useActiveCodeSnippetId: (groupId?: string, availableSnippets?: {
|
|
13
|
+
id: string;
|
|
14
|
+
}[]) => [string, (id: string) => void];
|
|
15
|
+
export {};
|
|
@@ -1,23 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CodeSnippetContext = exports.CODE_GROUP_SNIPPET_NAME_KEY = void 0;
|
|
4
|
-
exports.
|
|
5
|
-
const react_1 = require("react");
|
|
26
|
+
exports.useActiveCodeSnippetId = exports.useCodeSnippetContext = exports.CodeSnippetContext = exports.CODE_GROUP_SNIPPET_NAME_KEY = void 0;
|
|
27
|
+
exports.CodeSnippetProvider = CodeSnippetProvider;
|
|
28
|
+
const react_1 = __importStar(require("react"));
|
|
29
|
+
const use_local_state_1 = require("../hooks/use-local-state");
|
|
6
30
|
exports.CODE_GROUP_SNIPPET_NAME_KEY = 'redocly:codeGroupSnippetName';
|
|
7
31
|
exports.CodeSnippetContext = (0, react_1.createContext)(null);
|
|
8
|
-
function
|
|
32
|
+
function CodeSnippetProvider({ children }) {
|
|
33
|
+
const [activeSnippets, setActiveSnippets] = (0, use_local_state_1.useLocalState)(exports.CODE_GROUP_SNIPPET_NAME_KEY, {});
|
|
34
|
+
const setActiveSnippet = (0, react_1.useCallback)((groupId, snippetId) => {
|
|
35
|
+
setActiveSnippets(Object.assign(Object.assign({}, activeSnippets), { [groupId]: snippetId }));
|
|
36
|
+
}, [activeSnippets, setActiveSnippets]);
|
|
37
|
+
const contextValue = { activeSnippets, setActiveSnippet };
|
|
38
|
+
return react_1.default.createElement(exports.CodeSnippetContext.Provider, { value: contextValue }, children);
|
|
39
|
+
}
|
|
40
|
+
const useCodeSnippetContext = () => {
|
|
9
41
|
const context = (0, react_1.useContext)(exports.CodeSnippetContext);
|
|
10
42
|
if (!context) {
|
|
11
43
|
throw new Error('useCodeSnippetContext must be used within a CodeSnippetContext');
|
|
12
44
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
45
|
+
return context;
|
|
46
|
+
};
|
|
47
|
+
exports.useCodeSnippetContext = useCodeSnippetContext;
|
|
48
|
+
const useActiveCodeSnippetId = (groupId, availableSnippets) => {
|
|
49
|
+
const { activeSnippets, setActiveSnippet } = (0, exports.useCodeSnippetContext)();
|
|
50
|
+
const storedSnippetId = groupId ? activeSnippets[groupId] || '' : '';
|
|
51
|
+
const activeId = (0, react_1.useMemo)(() => {
|
|
52
|
+
var _a;
|
|
53
|
+
if (!(availableSnippets === null || availableSnippets === void 0 ? void 0 : availableSnippets.length))
|
|
54
|
+
return storedSnippetId;
|
|
55
|
+
const found = storedSnippetId && availableSnippets.find((s) => s.id === storedSnippetId);
|
|
56
|
+
return found ? storedSnippetId : ((_a = availableSnippets[0]) === null || _a === void 0 ? void 0 : _a.id) || '';
|
|
57
|
+
}, [storedSnippetId, availableSnippets]);
|
|
58
|
+
const setActiveSnippetId = (0, react_1.useCallback)((id) => {
|
|
59
|
+
if (groupId) {
|
|
60
|
+
setActiveSnippet(groupId, id);
|
|
61
|
+
}
|
|
62
|
+
}, [groupId, setActiveSnippet]);
|
|
63
|
+
return [activeId, setActiveSnippetId];
|
|
64
|
+
};
|
|
65
|
+
exports.useActiveCodeSnippetId = useActiveCodeSnippetId;
|
|
23
66
|
//# sourceMappingURL=CodeSnippetContext.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CodeBlockItems } from '../../components/CodeBlock/CodeBlock';
|
|
2
2
|
type CodeBlockTabsProps = {
|
|
3
|
-
tabs:
|
|
3
|
+
tabs: CodeBlockItems;
|
|
4
4
|
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
5
5
|
tabRefs: React.RefObject<HTMLButtonElement[]>;
|
|
6
6
|
};
|
|
@@ -2,31 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useLocalState = useLocalState;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const js_utils_1 = require("../utils/js-utils");
|
|
6
|
+
function getStoredValue(key, fallback) {
|
|
7
|
+
if (!(0, js_utils_1.isBrowser)())
|
|
8
|
+
return fallback;
|
|
9
9
|
try {
|
|
10
10
|
const savedValue = localStorage.getItem(key);
|
|
11
|
-
|
|
12
|
-
return JSON.parse(savedValue);
|
|
13
|
-
}
|
|
11
|
+
return savedValue ? JSON.parse(savedValue) : fallback;
|
|
14
12
|
}
|
|
15
|
-
catch (
|
|
16
|
-
|
|
13
|
+
catch (_a) {
|
|
14
|
+
return fallback;
|
|
17
15
|
}
|
|
18
|
-
return initialValue;
|
|
19
16
|
}
|
|
20
17
|
function useLocalState(key, initialValue) {
|
|
21
|
-
const [value, setValue] = (0, react_1.useState)(
|
|
18
|
+
const [value, setValue] = (0, react_1.useState)(initialValue);
|
|
19
|
+
// Load stored value from localStorage after component mounts
|
|
20
|
+
// This ensures SSR compatibility: server and client both start with initialValue,
|
|
21
|
+
// then client loads the actual stored value without hydration mismatch
|
|
22
22
|
(0, react_1.useEffect)(() => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
if (!(0, js_utils_1.isBrowser)())
|
|
24
|
+
return;
|
|
25
|
+
setValue(getStoredValue(key, initialValue));
|
|
26
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
+
}, [key]);
|
|
28
|
+
const handleSetValue = (0, react_1.useCallback)((newValue) => {
|
|
29
|
+
setValue(newValue);
|
|
30
|
+
if ((0, js_utils_1.isBrowser)()) {
|
|
31
|
+
localStorage.setItem(key, JSON.stringify(newValue));
|
|
28
32
|
}
|
|
29
|
-
}, [key
|
|
30
|
-
return [value,
|
|
33
|
+
}, [key]);
|
|
34
|
+
return [value, handleSetValue];
|
|
31
35
|
}
|
|
32
36
|
//# sourceMappingURL=use-local-state.js.map
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { PageAction } from '../types';
|
|
2
|
-
export
|
|
2
|
+
export type PageActionType = 'copy' | 'view' | 'chatgpt' | 'claude' | 'mcp-cursor';
|
|
3
|
+
export declare function usePageActions(pageSlug: string, mcpUrl?: string, actions?: PageActionType[]): PageAction[];
|
|
@@ -19,9 +19,11 @@ const use_theme_hooks_1 = require("./use-theme-hooks");
|
|
|
19
19
|
const use_theme_config_1 = require("./use-theme-config");
|
|
20
20
|
const clipboard_service_1 = require("../utils/clipboard-service");
|
|
21
21
|
const dom_1 = require("../utils/dom");
|
|
22
|
+
const CursorIcon_1 = require("../../icons/CursorIcon/CursorIcon");
|
|
22
23
|
const DEFAULT_ENABLED_ACTIONS = ['copy', 'view', 'chatgpt', 'claude'];
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const CURSOR_URL = 'cursor://anysphere.cursor-deeplink/mcp/install?name=$NAME&config=$BASE64_ENCODED_CONFIG';
|
|
25
|
+
function usePageActions(pageSlug, mcpUrl, actions) {
|
|
26
|
+
var _a, _b, _c;
|
|
25
27
|
const { useTranslate, usePageData, usePageProps, usePageSharedData } = (0, use_theme_hooks_1.useThemeHooks)();
|
|
26
28
|
const { translate } = useTranslate();
|
|
27
29
|
const themeConfig = (0, use_theme_config_1.useThemeConfig)();
|
|
@@ -29,7 +31,7 @@ function usePageActions(pageSlug) {
|
|
|
29
31
|
const openApiSharedData = usePageSharedData('openAPIDocsStore');
|
|
30
32
|
const shouldHideAllActions = shouldHidePageActions(pageProps, themeConfig, (_a = openApiSharedData === null || openApiSharedData === void 0 ? void 0 : openApiSharedData.options) === null || _a === void 0 ? void 0 : _a.excludeFromSearch);
|
|
31
33
|
const { isPublic } = usePageData() || {};
|
|
32
|
-
const
|
|
34
|
+
const result = (0, react_1.useMemo)(() => {
|
|
33
35
|
var _a, _b;
|
|
34
36
|
if (shouldHideAllActions) {
|
|
35
37
|
return [];
|
|
@@ -43,9 +45,41 @@ function usePageActions(pageSlug) {
|
|
|
43
45
|
url.searchParams.set('q', externalAiPrompt);
|
|
44
46
|
return url.toString();
|
|
45
47
|
}
|
|
46
|
-
return (((_b = (_a = themeConfig.navigation) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.items) || DEFAULT_ENABLED_ACTIONS)
|
|
48
|
+
return (((_b = (_a = themeConfig.navigation) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.items) || actions || DEFAULT_ENABLED_ACTIONS)
|
|
47
49
|
.map((action) => {
|
|
50
|
+
function generateMCPConfig(isCursor) {
|
|
51
|
+
const jsonConfig = {
|
|
52
|
+
'mcp-server': {
|
|
53
|
+
url: mcpUrl,
|
|
54
|
+
description: 'MCP Server',
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
if (isCursor) {
|
|
58
|
+
const url = CURSOR_URL.replace('$NAME', 'mcp-server').replace('$BASE64_ENCODED_CONFIG', btoa(JSON.stringify(jsonConfig['mcp-server'])));
|
|
59
|
+
return url;
|
|
60
|
+
}
|
|
61
|
+
return JSON.stringify(jsonConfig, null, 2);
|
|
62
|
+
}
|
|
48
63
|
switch (action) {
|
|
64
|
+
case 'mcp-cursor':
|
|
65
|
+
if (!mcpUrl) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
buttonText: translate('page.actions.cursorMcpButtonText', 'Connect to Cursor'),
|
|
70
|
+
title: translate('page.actions.cursorMcpTitle', 'Connect to Cursor'),
|
|
71
|
+
description: translate('page.actions.cursorMcpDescription', 'Install MCP server on Cursor'),
|
|
72
|
+
iconComponent: CursorIcon_1.CursorIcon,
|
|
73
|
+
onClick: () => {
|
|
74
|
+
try {
|
|
75
|
+
const url = generateMCPConfig(true);
|
|
76
|
+
window.open(url, '_blank');
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error(error);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
49
83
|
case 'copy':
|
|
50
84
|
return {
|
|
51
85
|
buttonText: translate('page.actions.copyButtonText', 'Copy'),
|
|
@@ -99,8 +133,16 @@ function usePageActions(pageSlug) {
|
|
|
99
133
|
}
|
|
100
134
|
})
|
|
101
135
|
.filter((action) => action !== null);
|
|
102
|
-
}, [
|
|
103
|
-
|
|
136
|
+
}, [
|
|
137
|
+
shouldHideAllActions,
|
|
138
|
+
pageSlug,
|
|
139
|
+
(_c = (_b = themeConfig.navigation) === null || _b === void 0 ? void 0 : _b.actions) === null || _c === void 0 ? void 0 : _c.items,
|
|
140
|
+
actions,
|
|
141
|
+
mcpUrl,
|
|
142
|
+
translate,
|
|
143
|
+
isPublic,
|
|
144
|
+
]);
|
|
145
|
+
return result;
|
|
104
146
|
}
|
|
105
147
|
function shouldHidePageActions(pageProps, themeConfig, openapiExcludeFromSearch) {
|
|
106
148
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -4,6 +4,7 @@ export type { TFunction, TOptions } from '../types/l10n';
|
|
|
4
4
|
export type { SelectOption, SelectProps } from '../types/select';
|
|
5
5
|
export { IS_BROWSER } from '../utils/dom';
|
|
6
6
|
export { addLeadingSlash, removeLeadingSlash, getPathPrefix, combineUrls, addTrailingSlash, withPathPrefix, } from '../utils/urls';
|
|
7
|
+
export { capitalize } from '../utils/string';
|
|
7
8
|
export { typedMemo } from '../hoc/typedMemo';
|
|
8
9
|
export { useMount } from '../hooks/use-mount';
|
|
9
10
|
export { GlobalStyle } from '../styles/global';
|