@jpmorganchase/elemental 6.0.1 → 7.0.1
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/components/API/APIWithResponsiveSidebarLayout.d.ts +19 -0
- package/components/API/APIWithSidebarLayout.d.ts +11 -1
- package/components/API/APIWithStackedLayout.d.ts +11 -0
- package/components/API/utils.d.ts +7 -6
- package/containers/API.d.ts +4 -1
- package/containers/API.stories.d.ts +2 -0
- package/containers/story-helper.d.ts +2 -0
- package/index.d.ts +2 -0
- package/index.esm.js +222 -115
- package/index.js +222 -114
- package/index.mjs +222 -115
- package/package.json +7 -7
- package/styles.min.css +1 -1
- package/utils/oas/types.d.ts +5 -2
- package/web-components.min.js +1 -1
@@ -0,0 +1,19 @@
|
|
1
|
+
import { ExportButtonProps } from '@jpmorganchase/elemental-core';
|
2
|
+
import { ExtensionAddonRenderer } from '@jpmorganchase/elemental-core/components/Docs';
|
3
|
+
import * as React from 'react';
|
4
|
+
import { ServiceNode } from '../../utils/oas/types';
|
5
|
+
declare type SidebarLayoutProps = {
|
6
|
+
serviceNode: ServiceNode;
|
7
|
+
logo?: string;
|
8
|
+
hideTryIt?: boolean;
|
9
|
+
hideSchemas?: boolean;
|
10
|
+
hideInternal?: boolean;
|
11
|
+
hideExport?: boolean;
|
12
|
+
exportProps?: ExportButtonProps;
|
13
|
+
tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
|
14
|
+
tryItCorsProxy?: string;
|
15
|
+
compact?: number | boolean;
|
16
|
+
renderExtensionAddon?: ExtensionAddonRenderer;
|
17
|
+
};
|
18
|
+
export declare const APIWithResponsiveSidebarLayout: React.FC<SidebarLayoutProps>;
|
19
|
+
export {};
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import { ExportButtonProps } from '@jpmorganchase/elemental-core';
|
1
|
+
import { ExportButtonProps, TableOfContentsItem } from '@jpmorganchase/elemental-core';
|
2
|
+
import { ExtensionAddonRenderer } from '@jpmorganchase/elemental-core/components/Docs';
|
2
3
|
import * as React from 'react';
|
3
4
|
import { ServiceNode } from '../../utils/oas/types';
|
4
5
|
declare type SidebarLayoutProps = {
|
@@ -12,9 +13,18 @@ declare type SidebarLayoutProps = {
|
|
12
13
|
exportProps?: ExportButtonProps;
|
13
14
|
tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
|
14
15
|
tryItCorsProxy?: string;
|
16
|
+
renderExtensionAddon?: ExtensionAddonRenderer;
|
15
17
|
tryItOutDefaultServer?: string;
|
16
18
|
useCustomNav?: boolean;
|
17
19
|
layout?: 'sidebar' | 'drawer';
|
18
20
|
};
|
19
21
|
export declare const APIWithSidebarLayout: React.FC<SidebarLayoutProps>;
|
22
|
+
declare type SidebarProps = {
|
23
|
+
serviceNode: ServiceNode;
|
24
|
+
logo?: string;
|
25
|
+
container: React.RefObject<HTMLElement>;
|
26
|
+
pathname: string;
|
27
|
+
tree: TableOfContentsItem[];
|
28
|
+
};
|
29
|
+
export declare const Sidebar: React.FC<SidebarProps>;
|
20
30
|
export {};
|
@@ -1,7 +1,15 @@
|
|
1
1
|
import { ExportButtonProps } from '@jpmorganchase/elemental-core';
|
2
|
+
import { ExtensionAddonRenderer } from '@jpmorganchase/elemental-core/components/Docs';
|
2
3
|
import * as React from 'react';
|
3
4
|
import { ServiceNode } from '../../utils/oas/types';
|
4
5
|
declare type TryItCredentialsPolicy = 'omit' | 'include' | 'same-origin';
|
6
|
+
interface Location {
|
7
|
+
pathname: string;
|
8
|
+
search: string;
|
9
|
+
hash: string;
|
10
|
+
state: unknown;
|
11
|
+
key: string;
|
12
|
+
}
|
5
13
|
declare type StackedLayoutProps = {
|
6
14
|
serviceNode: ServiceNode;
|
7
15
|
hideTryIt?: boolean;
|
@@ -10,6 +18,9 @@ declare type StackedLayoutProps = {
|
|
10
18
|
exportProps?: ExportButtonProps;
|
11
19
|
tryItCredentialsPolicy?: TryItCredentialsPolicy;
|
12
20
|
tryItCorsProxy?: string;
|
21
|
+
showPoweredByLink?: boolean;
|
22
|
+
location: Location;
|
23
|
+
renderExtensionAddon?: ExtensionAddonRenderer;
|
13
24
|
tryItOutDefaultServer?: string;
|
14
25
|
};
|
15
26
|
export declare const APIWithStackedLayout: React.FC<StackedLayoutProps>;
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import { TableOfContentsItem } from '@jpmorganchase/elemental-core';
|
2
|
-
import { OperationNode, ServiceChildNode, ServiceNode } from '../../utils/oas/types';
|
3
|
-
|
2
|
+
import { OperationNode, SchemaNode, ServiceChildNode, ServiceNode, WebhookNode } from '../../utils/oas/types';
|
3
|
+
declare type GroupableNode = OperationNode | WebhookNode | SchemaNode;
|
4
|
+
export declare type TagGroup<T extends GroupableNode> = {
|
4
5
|
title: string;
|
5
|
-
items:
|
6
|
+
items: T[];
|
6
7
|
};
|
7
|
-
export declare
|
8
|
-
groups: TagGroup[];
|
9
|
-
ungrouped:
|
8
|
+
export declare function computeTagGroups<T extends GroupableNode>(serviceNode: ServiceNode, nodeType: T['type']): {
|
9
|
+
groups: TagGroup<T>[];
|
10
|
+
ungrouped: T[];
|
10
11
|
};
|
11
12
|
interface ComputeAPITreeConfig {
|
12
13
|
hideSchemas?: boolean;
|
package/containers/API.d.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { RoutingProps } from '@jpmorganchase/elemental-core';
|
2
|
+
import { ExtensionAddonRenderer } from '@jpmorganchase/elemental-core/components/Docs';
|
2
3
|
import * as React from 'react';
|
3
4
|
export declare type APIProps = APIPropsWithDocument | APIPropsWithUrl;
|
4
5
|
export declare type APIPropsWithUrl = {
|
@@ -9,7 +10,7 @@ export declare type APIPropsWithDocument = {
|
|
9
10
|
apiDescriptionUrl?: string;
|
10
11
|
} & CommonAPIProps;
|
11
12
|
export interface CommonAPIProps extends RoutingProps {
|
12
|
-
layout?: 'sidebar' | 'stacked' | 'drawer';
|
13
|
+
layout?: 'sidebar' | 'stacked' | 'responsive' | 'drawer';
|
13
14
|
logo?: string;
|
14
15
|
hideTryIt?: boolean;
|
15
16
|
hideSchemas?: boolean;
|
@@ -18,6 +19,8 @@ export interface CommonAPIProps extends RoutingProps {
|
|
18
19
|
hideInlineExamples?: boolean;
|
19
20
|
tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
|
20
21
|
tryItCorsProxy?: string;
|
22
|
+
maxRefDepth?: number;
|
23
|
+
renderExtensionAddon?: ExtensionAddonRenderer;
|
21
24
|
tryItOutDefaultServer?: string;
|
22
25
|
useCustomNav?: boolean;
|
23
26
|
}
|
@@ -50,7 +50,9 @@ export declare const APIWithInternalOperations: import("@storybook/types").Annot
|
|
50
50
|
export declare const OpenApi3Schema: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
51
51
|
export declare const BadgesForSchema: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
52
52
|
export declare const StackedLayout: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
53
|
+
export declare const ResponsiveLayout: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
53
54
|
export declare const Box: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
54
55
|
export declare const DigitalOcean: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
55
56
|
export declare const Github: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
56
57
|
export declare const Instagram: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
58
|
+
export declare const WithExtensionRenderer: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
|
package/index.d.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
export { APIWithStackedLayout } from './components/API/APIWithStackedLayout';
|
1
2
|
export type { APIProps } from './containers/API';
|
2
3
|
export { API } from './containers/API';
|
3
4
|
export { useGetOasNavTree } from './hooks/oas-nav-tree/useGetOasNavTree';
|
4
5
|
export { useExportDocumentProps } from './hooks/useExportDocumentProps';
|
5
6
|
export { transformOasToServiceNode } from './utils/oas';
|
7
|
+
export type { ServiceNode } from './utils/oas/types';
|
package/index.esm.js
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
import { isHttpOperation, isHttpService,
|
2
|
-
import {
|
3
|
-
import
|
1
|
+
import { isHttpOperation, isHttpWebhookOperation, isHttpService, HttpMethodColors, DeprecatedBadge, ParsedDocs, TryItWithRequestSamples, Docs, ResponsiveSidebarLayout, ElementsOptionsProvider, SidebarLayout, Logo, TableOfContents, PoweredByLink, slugify, withRouter, withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider, useResponsiveLayout, useParsedValue, useBundleRefsIntoDocument, NonIdealState, InlineRefResolverProvider } from '@jpmorganchase/elemental-core';
|
2
|
+
import { Box, Flex, Icon, Tabs, TabList, Tab, TabPanels, TabPanel, Heading } from '@stoplight/mosaic';
|
3
|
+
import { NodeType } from '@stoplight/types';
|
4
|
+
import cn from 'classnames';
|
4
5
|
import * as React from 'react';
|
6
|
+
import defaults from 'lodash/defaults.js';
|
7
|
+
import flow from 'lodash/flow.js';
|
5
8
|
import { useQuery } from 'react-query';
|
6
|
-
import { NodeType } from '@stoplight/types';
|
7
9
|
import { useLocation, Redirect, Link } from 'react-router-dom';
|
8
|
-
import defaults from 'lodash/defaults.js';
|
9
|
-
import cn from 'classnames';
|
10
10
|
import { safeStringify } from '@stoplight/yaml';
|
11
11
|
import saver from 'file-saver';
|
12
|
+
import { OPERATION_CONFIG, WEBHOOK_CONFIG } from '@stoplight/http-spec/oas';
|
12
13
|
import { transformOas2Service, transformOas2Operation } from '@stoplight/http-spec/oas2';
|
13
14
|
import { transformOas3Service, transformOas3Operation } from '@stoplight/http-spec/oas3';
|
14
15
|
import { encodePointerFragment, pointerToPath } from '@stoplight/json';
|
@@ -16,13 +17,12 @@ import get from 'lodash/get.js';
|
|
16
17
|
import isObject from 'lodash/isObject.js';
|
17
18
|
import last from 'lodash/last.js';
|
18
19
|
|
19
|
-
|
20
|
+
function computeTagGroups(serviceNode, nodeType) {
|
20
21
|
const groupsByTagId = {};
|
21
22
|
const ungrouped = [];
|
22
23
|
const lowerCaseServiceTags = serviceNode.tags.map(tn => tn.toLowerCase());
|
23
|
-
|
24
|
-
|
25
|
-
continue;
|
24
|
+
const groupableNodes = serviceNode.children.filter(n => n.type === nodeType);
|
25
|
+
for (const node of groupableNodes) {
|
26
26
|
const tagName = node.tags[0];
|
27
27
|
if (tagName) {
|
28
28
|
const tagId = tagName.toLowerCase();
|
@@ -58,7 +58,7 @@ const computeTagGroups = (serviceNode) => {
|
|
58
58
|
})
|
59
59
|
.map(([, tagGroup]) => tagGroup);
|
60
60
|
return { groups: orderedTagGroups, ungrouped };
|
61
|
-
}
|
61
|
+
}
|
62
62
|
const defaultComputerAPITreeConfig = {
|
63
63
|
hideSchemas: false,
|
64
64
|
hideInternal: false,
|
@@ -73,62 +73,32 @@ const computeAPITree = (serviceNode, config = {}) => {
|
|
73
73
|
type: 'overview',
|
74
74
|
meta: '',
|
75
75
|
});
|
76
|
-
const
|
77
|
-
if (
|
76
|
+
const hasOperationNodes = serviceNode.children.some(node => node.type === NodeType.HttpOperation);
|
77
|
+
if (hasOperationNodes) {
|
78
78
|
tree.push({
|
79
79
|
title: 'Endpoints',
|
80
80
|
});
|
81
|
-
const { groups, ungrouped } = computeTagGroups(serviceNode);
|
82
|
-
ungrouped.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
slug: operationNode.uri,
|
89
|
-
title: operationNode.name,
|
90
|
-
type: operationNode.type,
|
91
|
-
meta: operationNode.data.method,
|
92
|
-
});
|
93
|
-
});
|
94
|
-
groups.forEach(group => {
|
95
|
-
const items = group.items.flatMap(operationNode => {
|
96
|
-
if (mergedConfig.hideInternal && operationNode.data.internal) {
|
97
|
-
return [];
|
98
|
-
}
|
99
|
-
return {
|
100
|
-
id: operationNode.uri,
|
101
|
-
slug: operationNode.uri,
|
102
|
-
title: operationNode.name,
|
103
|
-
type: operationNode.type,
|
104
|
-
meta: operationNode.data.method,
|
105
|
-
};
|
106
|
-
});
|
107
|
-
if (items.length > 0) {
|
108
|
-
tree.push({
|
109
|
-
title: group.title,
|
110
|
-
items,
|
111
|
-
});
|
112
|
-
}
|
81
|
+
const { groups, ungrouped } = computeTagGroups(serviceNode, NodeType.HttpOperation);
|
82
|
+
addTagGroupsToTree(groups, ungrouped, tree, NodeType.HttpOperation, mergedConfig.hideInternal);
|
83
|
+
}
|
84
|
+
const hasWebhookNodes = serviceNode.children.some(node => node.type === NodeType.HttpWebhook);
|
85
|
+
if (hasWebhookNodes) {
|
86
|
+
tree.push({
|
87
|
+
title: 'Webhooks',
|
113
88
|
});
|
89
|
+
const { groups, ungrouped } = computeTagGroups(serviceNode, NodeType.HttpWebhook);
|
90
|
+
addTagGroupsToTree(groups, ungrouped, tree, NodeType.HttpWebhook, mergedConfig.hideInternal);
|
114
91
|
}
|
115
92
|
let schemaNodes = serviceNode.children.filter(node => node.type === NodeType.Model);
|
116
93
|
if (mergedConfig.hideInternal) {
|
117
|
-
schemaNodes = schemaNodes.filter(
|
94
|
+
schemaNodes = schemaNodes.filter(n => !isInternal(n));
|
118
95
|
}
|
119
96
|
if (!mergedConfig.hideSchemas && schemaNodes.length) {
|
120
97
|
tree.push({
|
121
98
|
title: 'Schemas',
|
122
99
|
});
|
123
|
-
|
124
|
-
|
125
|
-
id: node.uri,
|
126
|
-
slug: node.uri,
|
127
|
-
title: node.name,
|
128
|
-
type: node.type,
|
129
|
-
meta: '',
|
130
|
-
});
|
131
|
-
});
|
100
|
+
const { groups, ungrouped } = computeTagGroups(serviceNode, NodeType.Model);
|
101
|
+
addTagGroupsToTree(groups, ungrouped, tree, NodeType.Model, mergedConfig.hideInternal);
|
132
102
|
}
|
133
103
|
return tree;
|
134
104
|
};
|
@@ -148,52 +118,48 @@ const findFirstNodeSlug = (tree) => {
|
|
148
118
|
};
|
149
119
|
const isInternal = (node) => {
|
150
120
|
const data = node.data;
|
151
|
-
if (isHttpOperation(data)) {
|
121
|
+
if (isHttpOperation(data) || isHttpWebhookOperation(data)) {
|
152
122
|
return !!data.internal;
|
153
123
|
}
|
154
124
|
if (isHttpService(data)) {
|
155
125
|
return false;
|
156
126
|
}
|
157
127
|
return !!data['x-internal'];
|
158
|
-
};
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
if (!useCustomNav)
|
164
|
-
return computeAPITree(serviceNode, { hideSchemas, hideInternal });
|
165
|
-
else
|
166
|
-
return [];
|
167
|
-
}, [serviceNode, hideSchemas, hideInternal, useCustomNav]);
|
168
|
-
const location = useLocation();
|
169
|
-
const { pathname } = location;
|
170
|
-
const isRootPath = !pathname || pathname === '/';
|
171
|
-
const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
|
172
|
-
React.useEffect(() => {
|
173
|
-
}, [pathname]);
|
174
|
-
const layoutOptions = React.useMemo(() => ({ hideTryIt: hideTryIt, hideInlineExamples, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== NodeType.HttpService }), [hideTryIt, hideExport, node, hideInlineExamples]);
|
175
|
-
if (!node) {
|
176
|
-
const firstSlug = findFirstNodeSlug(tree);
|
177
|
-
if (firstSlug) {
|
178
|
-
return React.createElement(Redirect, { to: firstSlug });
|
128
|
+
};
|
129
|
+
const addTagGroupsToTree = (groups, ungrouped, tree, itemsType, hideInternal) => {
|
130
|
+
ungrouped.forEach(node => {
|
131
|
+
if (hideInternal && isInternal(node)) {
|
132
|
+
return;
|
179
133
|
}
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
134
|
+
tree.push({
|
135
|
+
id: node.uri,
|
136
|
+
slug: node.uri,
|
137
|
+
title: node.name,
|
138
|
+
type: node.type,
|
139
|
+
meta: isHttpOperation(node.data) || isHttpWebhookOperation(node.data) ? node.data.method : '',
|
140
|
+
});
|
141
|
+
});
|
142
|
+
groups.forEach(group => {
|
143
|
+
const items = group.items.flatMap(node => {
|
144
|
+
if (hideInternal && isInternal(node)) {
|
145
|
+
return [];
|
146
|
+
}
|
147
|
+
return {
|
148
|
+
id: node.uri,
|
149
|
+
slug: node.uri,
|
150
|
+
title: node.name,
|
151
|
+
type: node.type,
|
152
|
+
meta: isHttpOperation(node.data) || isHttpWebhookOperation(node.data) ? node.data.method : '',
|
153
|
+
};
|
154
|
+
});
|
155
|
+
if (items.length > 0) {
|
156
|
+
tree.push({
|
157
|
+
title: group.title,
|
158
|
+
items,
|
159
|
+
itemsType,
|
160
|
+
});
|
187
161
|
}
|
188
|
-
};
|
189
|
-
const sidebar = (React.createElement(React.Fragment, null,
|
190
|
-
React.createElement(Flex, { ml: 4, mb: 5, alignItems: "center" },
|
191
|
-
logo ? (React.createElement(Logo, { logo: { url: logo, altText: 'logo' } })) : (serviceNode.data.logo && React.createElement(Logo, { logo: serviceNode.data.logo })),
|
192
|
-
React.createElement(Heading, { size: 4 }, serviceNode.name)),
|
193
|
-
React.createElement(Flex, { flexGrow: true, flexShrink: true, overflowY: "auto", direction: "col" },
|
194
|
-
React.createElement(TableOfContents, { tree: tree, activeId: pathname, Link: Link, onLinkClick: handleTocClick })),
|
195
|
-
React.createElement(PoweredByLink, { source: serviceNode.name, pathname: pathname, packageType: "elements" })));
|
196
|
-
return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar, renderSideBar: !useCustomNav, layout: layout }, node && (React.createElement(ParsedDocs, { key: pathname, uri: pathname, node: node, nodeTitle: node.name, layoutOptions: layoutOptions, location: location, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
|
162
|
+
});
|
197
163
|
};
|
198
164
|
|
199
165
|
const itemUriMatchesPathname = (itemUri, pathname) => itemUri === pathname;
|
@@ -202,24 +168,39 @@ const TryItContext = React.createContext({
|
|
202
168
|
tryItCredentialsPolicy: 'omit',
|
203
169
|
});
|
204
170
|
TryItContext.displayName = 'TryItContext';
|
205
|
-
const
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
171
|
+
const LocationContext = React.createContext({
|
172
|
+
location: {
|
173
|
+
hash: '',
|
174
|
+
key: '',
|
175
|
+
pathname: '',
|
176
|
+
search: '',
|
177
|
+
state: '',
|
178
|
+
},
|
179
|
+
});
|
180
|
+
LocationContext.displayName = 'LocationContext';
|
181
|
+
const APIWithStackedLayout = ({ serviceNode, hideTryIt, hideExport, hideInlineExamples, exportProps, tryItCredentialsPolicy, tryItCorsProxy, renderExtensionAddon, showPoweredByLink = true, location, tryItOutDefaultServer, }) => {
|
182
|
+
const { groups: operationGroups } = computeTagGroups(serviceNode, NodeType.HttpOperation);
|
183
|
+
const { groups: webhookGroups } = computeTagGroups(serviceNode, NodeType.HttpWebhook);
|
184
|
+
return (React.createElement(LocationContext.Provider, { value: { location } },
|
185
|
+
React.createElement(TryItContext.Provider, { value: {
|
186
|
+
hideTryIt,
|
187
|
+
tryItCredentialsPolicy,
|
188
|
+
corsProxy: tryItCorsProxy,
|
189
|
+
hideInlineExamples,
|
190
|
+
tryItOutDefaultServer,
|
191
|
+
} },
|
192
|
+
React.createElement(Flex, { w: "full", flexDirection: "col", m: "auto", className: "sl-max-w-4xl" },
|
193
|
+
React.createElement(Box, { w: "full", borderB: true },
|
194
|
+
React.createElement(Docs, { className: "sl-mx-auto", nodeData: serviceNode.data, nodeTitle: serviceNode.name, nodeType: NodeType.HttpService, location: location, layoutOptions: { showPoweredByLink, hideExport }, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, renderExtensionAddon: renderExtensionAddon, tryItOutDefaultServer: tryItOutDefaultServer })),
|
195
|
+
operationGroups.length > 0 && webhookGroups.length > 0 ? React.createElement(Heading, { size: 2 }, "Endpoints") : null,
|
196
|
+
operationGroups.map(group => (React.createElement(Group, { key: group.title, group: group }))),
|
197
|
+
webhookGroups.length > 0 ? React.createElement(Heading, { size: 2 }, "Webhooks") : null,
|
198
|
+
webhookGroups.map(group => (React.createElement(Group, { key: group.title, group: group })))))));
|
219
199
|
};
|
200
|
+
APIWithStackedLayout.displayName = 'APIWithStackedLayout';
|
220
201
|
const Group = React.memo(({ group }) => {
|
221
202
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
222
|
-
const { pathname } =
|
203
|
+
const { location: { pathname }, } = React.useContext(LocationContext);
|
223
204
|
const onClick = React.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
|
224
205
|
const shouldExpand = React.useMemo(() => {
|
225
206
|
return group.items.some(item => itemUriMatchesPathname(item.uri, pathname));
|
@@ -237,8 +218,9 @@ const Group = React.memo(({ group }) => {
|
|
237
218
|
return React.createElement(Item, { key: item.uri, item: item });
|
238
219
|
}))));
|
239
220
|
});
|
221
|
+
Group.displayName = 'Group';
|
240
222
|
const Item = React.memo(({ item }) => {
|
241
|
-
const location =
|
223
|
+
const { location } = React.useContext(LocationContext);
|
242
224
|
const { pathname } = location;
|
243
225
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
244
226
|
const scrollRef = React.useRef(null);
|
@@ -262,7 +244,7 @@ const Item = React.memo(({ item }) => {
|
|
262
244
|
return (React.createElement(Box, { ref: scrollRef, w: "full", my: 2, border: true, borderColor: { default: isExpanded ? 'light' : 'transparent', hover: 'light' }, bg: { default: isExpanded ? 'code' : 'transparent', hover: 'code' } },
|
263
245
|
React.createElement(Flex, { mx: "auto", alignItems: "center", cursor: "pointer", fontSize: "lg", p: 2, onClick: onClick, color: "current" },
|
264
246
|
React.createElement(Box, { w: 24, textTransform: "uppercase", textAlign: "center", fontWeight: "semibold", border: true, rounded: true, px: 2, bg: "canvas", className: cn(`sl-mr-5 sl-text-base`, `sl-text-${color}`, `sl-border-${color}`) }, item.data.method || 'UNKNOWN'),
|
265
|
-
React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.data.path),
|
247
|
+
React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.type === NodeType.HttpOperation ? item.data.path : item.name),
|
266
248
|
isDeprecated && React.createElement(DeprecatedBadge, null)),
|
267
249
|
React.createElement(Collapse, { isOpen: isExpanded },
|
268
250
|
React.createElement(Box, { flex: 1, p: 2, fontWeight: "medium", mx: "auto", fontSize: "xl" }, item.name),
|
@@ -276,17 +258,91 @@ const Item = React.memo(({ item }) => {
|
|
276
258
|
React.createElement(TabPanel, null,
|
277
259
|
React.createElement(TryItWithRequestSamples, { httpOperation: item.data, hideInlineExamples: hideInlineExamples, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
|
278
260
|
});
|
261
|
+
Item.displayName = 'Item';
|
279
262
|
const Collapse = ({ isOpen, children }) => {
|
280
263
|
if (!isOpen)
|
281
264
|
return null;
|
282
265
|
return React.createElement(Box, null, children);
|
266
|
+
};
|
267
|
+
Collapse.displayName = 'Collapse';
|
268
|
+
|
269
|
+
const APIWithResponsiveSidebarLayout = ({ serviceNode, logo, hideTryIt, compact, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, renderExtensionAddon, }) => {
|
270
|
+
const container = React.useRef(null);
|
271
|
+
const tree = React.useMemo(() => computeAPITree(serviceNode, { hideSchemas, hideInternal }), [serviceNode, hideSchemas, hideInternal]);
|
272
|
+
const location = useLocation();
|
273
|
+
const { pathname } = location;
|
274
|
+
const isRootPath = !pathname || pathname === '/';
|
275
|
+
const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
|
276
|
+
const layoutOptions = React.useMemo(() => ({ hideTryIt: hideTryIt, compact: compact, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== NodeType.HttpService }), [hideTryIt, hideExport, node, compact]);
|
277
|
+
if (!node) {
|
278
|
+
const firstSlug = findFirstNodeSlug(tree);
|
279
|
+
if (firstSlug) {
|
280
|
+
return React.createElement(Redirect, { to: firstSlug });
|
281
|
+
}
|
282
|
+
}
|
283
|
+
if (hideInternal && node && isInternal(node)) {
|
284
|
+
return React.createElement(Redirect, { to: "/" });
|
285
|
+
}
|
286
|
+
const handleTocClick = () => {
|
287
|
+
if (container.current) {
|
288
|
+
container.current.scrollIntoView();
|
289
|
+
}
|
290
|
+
};
|
291
|
+
return (React.createElement(ResponsiveSidebarLayout, { onTocClick: handleTocClick, tree: tree, logo: logo !== null && logo !== void 0 ? logo : serviceNode.data.logo, ref: container, name: serviceNode.name }, node && (React.createElement(ElementsOptionsProvider, { renderExtensionAddon: renderExtensionAddon },
|
292
|
+
React.createElement(ParsedDocs, { key: pathname, uri: pathname, node: node, nodeTitle: node.name, layoutOptions: layoutOptions, location: location, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, renderExtensionAddon: renderExtensionAddon })))));
|
283
293
|
};
|
284
294
|
|
295
|
+
const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, hideInlineExamples = false, exportProps, tryItCredentialsPolicy, tryItCorsProxy, renderExtensionAddon, tryItOutDefaultServer, useCustomNav, layout, }) => {
|
296
|
+
const container = React.useRef(null);
|
297
|
+
const tree = React.useMemo(() => {
|
298
|
+
if (!useCustomNav)
|
299
|
+
return computeAPITree(serviceNode, { hideSchemas, hideInternal });
|
300
|
+
else
|
301
|
+
return [];
|
302
|
+
}, [serviceNode, hideSchemas, hideInternal, useCustomNav]);
|
303
|
+
const location = useLocation();
|
304
|
+
const { pathname } = location;
|
305
|
+
const isRootPath = !pathname || pathname === '/';
|
306
|
+
const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
|
307
|
+
React.useEffect(() => {
|
308
|
+
}, [pathname]);
|
309
|
+
const layoutOptions = React.useMemo(() => ({ hideTryIt: hideTryIt, hideInlineExamples, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== NodeType.HttpService }), [hideTryIt, hideExport, node, hideInlineExamples]);
|
310
|
+
if (!node) {
|
311
|
+
const firstSlug = findFirstNodeSlug(tree);
|
312
|
+
if (firstSlug) {
|
313
|
+
return React.createElement(Redirect, { to: firstSlug });
|
314
|
+
}
|
315
|
+
}
|
316
|
+
if (hideInternal && node && isInternal(node)) {
|
317
|
+
return React.createElement(Redirect, { to: "/" });
|
318
|
+
}
|
319
|
+
const sidebar = (React.createElement(Sidebar, { serviceNode: serviceNode, logo: logo, container: container, pathname: pathname, tree: tree }));
|
320
|
+
return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar, renderSideBar: !useCustomNav, layout: layout }, node && (React.createElement(ElementsOptionsProvider, { renderExtensionAddon: renderExtensionAddon },
|
321
|
+
React.createElement(ParsedDocs, { key: pathname, uri: pathname, node: node, nodeTitle: node.name, layoutOptions: layoutOptions, location: location, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, renderExtensionAddon: renderExtensionAddon, tryItOutDefaultServer: tryItOutDefaultServer })))));
|
322
|
+
};
|
323
|
+
const Sidebar = ({ serviceNode, logo, container, pathname, tree }) => {
|
324
|
+
const handleTocClick = () => {
|
325
|
+
if (container.current) {
|
326
|
+
container.current.scrollIntoView();
|
327
|
+
}
|
328
|
+
};
|
329
|
+
return (React.createElement(React.Fragment, null,
|
330
|
+
React.createElement(Flex, { ml: 4, mb: 5, alignItems: "center" },
|
331
|
+
logo ? (React.createElement(Logo, { logo: { url: logo, altText: 'logo' } })) : (serviceNode.data.logo && React.createElement(Logo, { logo: serviceNode.data.logo })),
|
332
|
+
React.createElement(Heading, { size: 4 }, serviceNode.name)),
|
333
|
+
React.createElement(Flex, { flexGrow: true, flexShrink: true, overflowY: "auto", direction: "col" },
|
334
|
+
React.createElement(TableOfContents, { tree: tree, activeId: pathname, Link: Link, onLinkClick: handleTocClick })),
|
335
|
+
React.createElement(PoweredByLink, { source: serviceNode.name, pathname: pathname, packageType: "elements" })));
|
336
|
+
};
|
337
|
+
Sidebar.displayName = 'Sidebar';
|
338
|
+
|
285
339
|
var NodeTypes;
|
286
340
|
(function (NodeTypes) {
|
287
341
|
NodeTypes["Paths"] = "paths";
|
288
342
|
NodeTypes["Path"] = "path";
|
289
343
|
NodeTypes["Operation"] = "operation";
|
344
|
+
NodeTypes["Webhooks"] = "webhooks";
|
345
|
+
NodeTypes["Webhook"] = "webhook";
|
290
346
|
NodeTypes["Components"] = "components";
|
291
347
|
NodeTypes["Models"] = "models";
|
292
348
|
NodeTypes["Model"] = "model";
|
@@ -338,6 +394,22 @@ const oas3SourceMap = [
|
|
338
394
|
},
|
339
395
|
],
|
340
396
|
},
|
397
|
+
{
|
398
|
+
match: 'webhooks',
|
399
|
+
type: NodeTypes.Webhooks,
|
400
|
+
children: [
|
401
|
+
{
|
402
|
+
notMatch: '^x-',
|
403
|
+
type: NodeTypes.Webhook,
|
404
|
+
children: [
|
405
|
+
{
|
406
|
+
match: 'get|post|put|delete|options|head|patch|trace',
|
407
|
+
type: NodeTypes.Webhook,
|
408
|
+
},
|
409
|
+
],
|
410
|
+
},
|
411
|
+
],
|
412
|
+
},
|
341
413
|
{
|
342
414
|
match: 'components',
|
343
415
|
type: NodeTypes.Components,
|
@@ -392,7 +464,7 @@ function computeServiceNode(document, map, transformService, transformOperation)
|
|
392
464
|
return serviceNode;
|
393
465
|
}
|
394
466
|
function computeChildNodes(document, data, map, transformer, parentUri = '') {
|
395
|
-
var _a;
|
467
|
+
var _a, _b;
|
396
468
|
const nodes = [];
|
397
469
|
if (!isObject(data))
|
398
470
|
return nodes;
|
@@ -405,7 +477,12 @@ function computeChildNodes(document, data, map, transformer, parentUri = '') {
|
|
405
477
|
if (match.type === NodeTypes.Operation && jsonPath.length === 3) {
|
406
478
|
const path = String(jsonPath[1]);
|
407
479
|
const method = String(jsonPath[2]);
|
408
|
-
const operationDocument = transformer({
|
480
|
+
const operationDocument = transformer({
|
481
|
+
document,
|
482
|
+
name: path,
|
483
|
+
method,
|
484
|
+
config: OPERATION_CONFIG,
|
485
|
+
});
|
409
486
|
let parsedUri;
|
410
487
|
const encodedPath = String(encodePointerFragment(path));
|
411
488
|
if (operationDocument.iid) {
|
@@ -422,6 +499,31 @@ function computeChildNodes(document, data, map, transformer, parentUri = '') {
|
|
422
499
|
tags: ((_a = operationDocument.tags) === null || _a === void 0 ? void 0 : _a.map(tag => tag.name)) || [],
|
423
500
|
});
|
424
501
|
}
|
502
|
+
else if (match.type === NodeTypes.Webhook && jsonPath.length === 3) {
|
503
|
+
const name = String(jsonPath[1]);
|
504
|
+
const method = String(jsonPath[2]);
|
505
|
+
const webhookDocument = transformer({
|
506
|
+
document,
|
507
|
+
name,
|
508
|
+
method,
|
509
|
+
config: WEBHOOK_CONFIG,
|
510
|
+
});
|
511
|
+
let parsedUri;
|
512
|
+
const encodedPath = String(encodePointerFragment(name));
|
513
|
+
if (webhookDocument.iid) {
|
514
|
+
parsedUri = `/webhooks/${webhookDocument.iid}`;
|
515
|
+
}
|
516
|
+
else {
|
517
|
+
parsedUri = uri.replace(encodedPath, slugify(name));
|
518
|
+
}
|
519
|
+
nodes.push({
|
520
|
+
type: NodeType.HttpWebhook,
|
521
|
+
uri: parsedUri,
|
522
|
+
data: webhookDocument,
|
523
|
+
name: webhookDocument.summary || webhookDocument.name,
|
524
|
+
tags: ((_b = webhookDocument.tags) === null || _b === void 0 ? void 0 : _b.map(tag => tag.name)) || [],
|
525
|
+
});
|
526
|
+
}
|
425
527
|
else if (match.type === NodeTypes.Model) {
|
426
528
|
const schemaDocument = get(document, jsonPath);
|
427
529
|
const parsedUri = uri.replace(OAS_MODEL_REGEXP, 'schemas/');
|
@@ -494,8 +596,10 @@ const propsAreWithDocument = (props) => {
|
|
494
596
|
return props.hasOwnProperty('apiDescriptionDocument');
|
495
597
|
};
|
496
598
|
const APIImpl = props => {
|
497
|
-
const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, hideInlineExamples, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, } = props;
|
599
|
+
const { layout = 'sidebar', apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, hideInlineExamples, tryItCredentialsPolicy, tryItCorsProxy, maxRefDepth, renderExtensionAddon, tryItOutDefaultServer, useCustomNav, } = props;
|
600
|
+
const location = useLocation();
|
498
601
|
const apiDescriptionDocument = propsAreWithDocument(props) ? props.apiDescriptionDocument : undefined;
|
602
|
+
const { isResponsiveLayoutEnabled } = useResponsiveLayout();
|
499
603
|
const { data: fetchedDocument, error } = useQuery([apiDescriptionUrl], () => fetch(apiDescriptionUrl).then(res => {
|
500
604
|
if (res.ok) {
|
501
605
|
return res.text();
|
@@ -521,7 +625,10 @@ const APIImpl = props => {
|
|
521
625
|
return (React.createElement(Flex, { justify: "center", alignItems: "center", w: "full", minH: "screen" },
|
522
626
|
React.createElement(NonIdealState, { title: "Failed to parse OpenAPI file", description: "Please make sure your OpenAPI file is valid and try again" })));
|
523
627
|
}
|
524
|
-
return (React.createElement(InlineRefResolverProvider, { document: parsedDocument
|
628
|
+
return (React.createElement(InlineRefResolverProvider, { document: parsedDocument, maxRefDepth: maxRefDepth },
|
629
|
+
layout === 'stacked' && (React.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, hideInlineExamples: hideInlineExamples, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, renderExtensionAddon: renderExtensionAddon, location: location, tryItOutDefaultServer: tryItOutDefaultServer })),
|
630
|
+
layout === 'sidebar' && (React.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, hideInlineExamples: hideInlineExamples, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, renderExtensionAddon: renderExtensionAddon, tryItOutDefaultServer: tryItOutDefaultServer, useCustomNav: useCustomNav, layout: layout })),
|
631
|
+
layout === 'responsive' && (React.createElement(APIWithResponsiveSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, renderExtensionAddon: renderExtensionAddon, compact: isResponsiveLayoutEnabled }))));
|
525
632
|
};
|
526
633
|
const API = flow(withRouter, withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider)(APIImpl);
|
527
634
|
|
@@ -554,4 +661,4 @@ const useGetOasNavTree = (apiDescriptionDocument) => {
|
|
554
661
|
return groupSchemas(apiTree);
|
555
662
|
};
|
556
663
|
|
557
|
-
export { API, transformOasToServiceNode, useExportDocumentProps, useGetOasNavTree };
|
664
|
+
export { API, APIWithStackedLayout, transformOasToServiceNode, useExportDocumentProps, useGetOasNavTree };
|