@jpmorganchase/elemental 3.1.1 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,6 +12,7 @@ declare type SidebarLayoutProps = {
12
12
  tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
13
13
  tryItCorsProxy?: string;
14
14
  tryItOutDefaultServer?: string;
15
+ useCustomNav?: boolean;
15
16
  };
16
17
  export declare const APIWithSidebarLayout: React.FC<SidebarLayoutProps>;
17
18
  export {};
@@ -18,6 +18,7 @@ export interface CommonAPIProps extends RoutingProps {
18
18
  tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
19
19
  tryItCorsProxy?: string;
20
20
  tryItOutDefaultServer?: string;
21
+ useCustomNav?: boolean;
21
22
  }
22
23
  export declare const APIImpl: React.FC<APIProps>;
23
24
  export declare const API: React.FC<APIProps>;
@@ -1,4 +1,3 @@
1
- import { Story } from '@storybook/react';
2
1
  import * as React from 'react';
3
2
  import { APIProps } from './API';
4
3
  declare const _default: {
@@ -44,14 +43,14 @@ declare const _default: {
44
43
  };
45
44
  };
46
45
  export default _default;
47
- export declare const APIWithYamlProvidedDirectly: Story<APIProps>;
48
- export declare const APIWithJSONProvidedDirectly: Story<APIProps>;
49
- export declare const APIWithoutDescription: Story<APIProps>;
50
- export declare const APIWithInternalOperations: Story<APIProps>;
51
- export declare const OpenApi3Schema: Story<APIProps>;
52
- export declare const BadgesForSchema: Story<APIProps>;
53
- export declare const StackedLayout: Story<APIProps>;
54
- export declare const Box: Story<APIProps>;
55
- export declare const DigitalOcean: Story<APIProps>;
56
- export declare const Github: Story<APIProps>;
57
- export declare const Instagram: Story<APIProps>;
46
+ export declare const APIWithYamlProvidedDirectly: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
47
+ export declare const APIWithJSONProvidedDirectly: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
48
+ export declare const APIWithoutDescription: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
49
+ export declare const APIWithInternalOperations: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
50
+ export declare const OpenApi3Schema: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
51
+ export declare const BadgesForSchema: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
52
+ export declare const StackedLayout: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
53
+ export declare const Box: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
54
+ export declare const DigitalOcean: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
55
+ export declare const Github: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
56
+ export declare const Instagram: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, APIProps>;
@@ -0,0 +1 @@
1
+ export declare const useGetOasNavTree: (apiDescriptionDocument: string | object) => any[];
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
package/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export type { APIProps } from './containers/API';
2
2
  export { API } from './containers/API';
3
+ export { useGetOasNavTree } from './hooks/oas-nav-tree/useGetOasNavTree';
4
+ export { useExportDocumentProps } from './hooks/useExportDocumentProps';
5
+ export { transformOasToServiceNode } from './utils/oas';
package/index.esm.js CHANGED
@@ -157,13 +157,20 @@ const isInternal = (node) => {
157
157
  return !!data['x-internal'];
158
158
  };
159
159
 
160
- const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, }) => {
160
+ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, }) => {
161
161
  const container = React.useRef(null);
162
- const tree = React.useMemo(() => computeAPITree(serviceNode, { hideSchemas, hideInternal }), [serviceNode, hideSchemas, hideInternal]);
162
+ const tree = React.useMemo(() => {
163
+ if (!useCustomNav)
164
+ return computeAPITree(serviceNode, { hideSchemas, hideInternal });
165
+ else
166
+ return [];
167
+ }, [serviceNode, hideSchemas, hideInternal, useCustomNav]);
163
168
  const location = useLocation();
164
169
  const { pathname } = location;
165
170
  const isRootPath = !pathname || pathname === '/';
166
171
  const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
172
+ React.useEffect(() => {
173
+ }, [pathname]);
167
174
  const layoutOptions = React.useMemo(() => ({ hideTryIt: hideTryIt, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== NodeType.HttpService }), [hideTryIt, hideExport, node]);
168
175
  if (!node) {
169
176
  const firstSlug = findFirstNodeSlug(tree);
@@ -186,12 +193,10 @@ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideI
186
193
  React.createElement(Flex, { flexGrow: true, flexShrink: true, overflowY: "auto", direction: "col" },
187
194
  React.createElement(TableOfContents, { tree: tree, activeId: pathname, Link: Link, onLinkClick: handleTocClick })),
188
195
  React.createElement(PoweredByLink, { source: serviceNode.name, pathname: pathname, packageType: "elements" })));
189
- return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar }, 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 }))));
196
+ return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar, renderSideBar: !useCustomNav }, 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 }))));
190
197
  };
191
198
 
192
- const itemMatchesHash = (hash, item) => {
193
- return hash.substr(1) === `${item.name}-${item.data.method}`;
194
- };
199
+ const itemUriMatchesPathname = (itemUri, pathname) => itemUri === pathname;
195
200
  const TryItContext = React.createContext({
196
201
  hideTryIt: false,
197
202
  tryItCredentialsPolicy: 'omit',
@@ -208,24 +213,18 @@ const APIWithStackedLayout = ({ serviceNode, hideTryIt, hideExport, exportProps,
208
213
  };
209
214
  const Group = React.memo(({ group }) => {
210
215
  const [isExpanded, setIsExpanded] = React.useState(false);
211
- const { hash } = useLocation();
212
- const scrollRef = React.useRef(null);
213
- const urlHashMatches = hash.substr(1) === group.title;
216
+ const { pathname } = useLocation();
214
217
  const onClick = React.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
215
218
  const shouldExpand = React.useMemo(() => {
216
- return urlHashMatches || group.items.some(item => itemMatchesHash(hash, item));
217
- }, [group, hash, urlHashMatches]);
219
+ return group.items.some(item => itemUriMatchesPathname(item.uri, pathname));
220
+ }, [group, pathname]);
218
221
  React.useEffect(() => {
219
- var _a;
220
222
  if (shouldExpand) {
221
223
  setIsExpanded(true);
222
- if (urlHashMatches && ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop)) {
223
- window.scrollTo(0, scrollRef.current.offsetTop);
224
- }
225
224
  }
226
- }, [shouldExpand, urlHashMatches, group, hash]);
225
+ }, [shouldExpand]);
227
226
  return (React.createElement(Box, null,
228
- React.createElement(Flex, { ref: scrollRef, onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
227
+ React.createElement(Flex, { onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
229
228
  React.createElement(Box, { fontSize: "lg", fontWeight: "medium" }, group.title),
230
229
  React.createElement(Icon, { className: "sl-mr-2", icon: isExpanded ? 'chevron-down' : 'chevron-right', size: "sm" })),
231
230
  React.createElement(Collapse, { isOpen: isExpanded }, group.items.map(item => {
@@ -234,36 +233,42 @@ const Group = React.memo(({ group }) => {
234
233
  });
235
234
  const Item = React.memo(({ item }) => {
236
235
  const location = useLocation();
237
- const { hash } = location;
236
+ const { pathname } = location;
238
237
  const [isExpanded, setIsExpanded] = React.useState(false);
239
238
  const scrollRef = React.useRef(null);
240
239
  const color = HttpMethodColors[item.data.method] || 'gray';
241
240
  const isDeprecated = !!item.data.deprecated;
242
241
  const { hideTryIt, tryItCredentialsPolicy, corsProxy, tryItOutDefaultServer } = React.useContext(TryItContext);
243
- const onClick = React.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
242
+ const onClick = React.useCallback(() => {
243
+ setIsExpanded(!isExpanded);
244
+ if (window && window.location) {
245
+ window.history.pushState(null, '', `#${item.uri}`);
246
+ }
247
+ }, [isExpanded, item]);
244
248
  React.useEffect(() => {
245
- var _a;
246
- if (itemMatchesHash(hash, item)) {
249
+ if (itemUriMatchesPathname(item.uri, pathname)) {
247
250
  setIsExpanded(true);
248
- if ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop) {
249
- window.scrollTo(0, scrollRef.current.offsetTop);
251
+ if (scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) {
252
+ scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current.scrollIntoView();
250
253
  }
251
254
  }
252
- }, [hash, item]);
255
+ }, [pathname, item]);
253
256
  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' } },
254
257
  React.createElement(Flex, { mx: "auto", alignItems: "center", cursor: "pointer", fontSize: "lg", p: 2, onClick: onClick, color: "current" },
255
258
  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'),
256
- React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.name),
259
+ React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.data.path),
257
260
  isDeprecated && React.createElement(DeprecatedBadge, null)),
258
- React.createElement(Collapse, { isOpen: isExpanded }, hideTryIt ? (React.createElement(Box, { as: ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React.createElement(Tabs, { appearance: "line" },
259
- React.createElement(TabList, null,
260
- React.createElement(Tab, null, "Docs"),
261
- React.createElement(Tab, null, "TryIt")),
262
- React.createElement(TabPanels, null,
263
- React.createElement(TabPanel, null,
264
- React.createElement(ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
265
- React.createElement(TabPanel, null,
266
- React.createElement(TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
261
+ React.createElement(Collapse, { isOpen: isExpanded },
262
+ React.createElement(Box, { flex: 1, p: 2, fontWeight: "medium", mx: "auto", fontSize: "xl" }, item.name),
263
+ hideTryIt ? (React.createElement(Box, { as: ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React.createElement(Tabs, { appearance: "line" },
264
+ React.createElement(TabList, null,
265
+ React.createElement(Tab, null, "Docs"),
266
+ React.createElement(Tab, null, "TryIt")),
267
+ React.createElement(TabPanels, null,
268
+ React.createElement(TabPanel, null,
269
+ React.createElement(ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
270
+ React.createElement(TabPanel, null,
271
+ React.createElement(TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
267
272
  });
268
273
  const Collapse = ({ isOpen, children }) => {
269
274
  if (!isOpen)
@@ -483,7 +488,7 @@ const propsAreWithDocument = (props) => {
483
488
  return props.hasOwnProperty('apiDescriptionDocument');
484
489
  };
485
490
  const APIImpl = props => {
486
- const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, } = props;
491
+ const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, } = props;
487
492
  const apiDescriptionDocument = propsAreWithDocument(props) ? props.apiDescriptionDocument : undefined;
488
493
  const { data: fetchedDocument, error } = useQuery([apiDescriptionUrl], () => fetch(apiDescriptionUrl).then(res => {
489
494
  if (res.ok) {
@@ -510,8 +515,37 @@ const APIImpl = props => {
510
515
  return (React.createElement(Flex, { justify: "center", alignItems: "center", w: "full", minH: "screen" },
511
516
  React.createElement(NonIdealState, { title: "Failed to parse OpenAPI file", description: "Please make sure your OpenAPI file is valid and try again" })));
512
517
  }
513
- return (React.createElement(InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
518
+ return (React.createElement(InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer, useCustomNav: useCustomNav }))));
514
519
  };
515
520
  const API = flow(withRouter, withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider)(APIImpl);
516
521
 
517
- export { API };
522
+ const useGetOasNavTree = (apiDescriptionDocument) => {
523
+ const parsedDocument = useParsedValue(apiDescriptionDocument);
524
+ const bundledDocument = useBundleRefsIntoDocument(parsedDocument);
525
+ if (!bundledDocument)
526
+ return [];
527
+ const groupSchemas = (tree) => {
528
+ const targetTitle = 'Schemas';
529
+ const newTree = tree.reduce((accumulator, currentObject) => {
530
+ var _a;
531
+ if (currentObject.title === targetTitle) {
532
+ accumulator.matchedObject = currentObject;
533
+ }
534
+ else if ((_a = currentObject.id) === null || _a === void 0 ? void 0 : _a.includes(targetTitle.toLowerCase())) {
535
+ accumulator.matchedObject.items = accumulator.matchedObject.items || [];
536
+ accumulator.matchedObject.items.push(currentObject);
537
+ }
538
+ else {
539
+ accumulator.others = accumulator.others || [];
540
+ accumulator.others.push(currentObject);
541
+ }
542
+ return accumulator;
543
+ }, {});
544
+ const navTree = [...newTree.others, newTree.matchedObject];
545
+ return navTree;
546
+ };
547
+ const apiTree = computeAPITree(transformOasToServiceNode(bundledDocument));
548
+ return groupSchemas(apiTree);
549
+ };
550
+
551
+ export { API, transformOasToServiceNode, useExportDocumentProps, useGetOasNavTree };
package/index.js CHANGED
@@ -190,13 +190,20 @@ const isInternal = (node) => {
190
190
  return !!data['x-internal'];
191
191
  };
192
192
 
193
- const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, }) => {
193
+ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, }) => {
194
194
  const container = React__namespace.useRef(null);
195
- const tree = React__namespace.useMemo(() => computeAPITree(serviceNode, { hideSchemas, hideInternal }), [serviceNode, hideSchemas, hideInternal]);
195
+ const tree = React__namespace.useMemo(() => {
196
+ if (!useCustomNav)
197
+ return computeAPITree(serviceNode, { hideSchemas, hideInternal });
198
+ else
199
+ return [];
200
+ }, [serviceNode, hideSchemas, hideInternal, useCustomNav]);
196
201
  const location = reactRouterDom.useLocation();
197
202
  const { pathname } = location;
198
203
  const isRootPath = !pathname || pathname === '/';
199
204
  const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
205
+ React__namespace.useEffect(() => {
206
+ }, [pathname]);
200
207
  const layoutOptions = React__namespace.useMemo(() => ({ hideTryIt: hideTryIt, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== types.NodeType.HttpService }), [hideTryIt, hideExport, node]);
201
208
  if (!node) {
202
209
  const firstSlug = findFirstNodeSlug(tree);
@@ -219,12 +226,10 @@ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideI
219
226
  React__namespace.createElement(mosaic.Flex, { flexGrow: true, flexShrink: true, overflowY: "auto", direction: "col" },
220
227
  React__namespace.createElement(elementalCore.TableOfContents, { tree: tree, activeId: pathname, Link: reactRouterDom.Link, onLinkClick: handleTocClick })),
221
228
  React__namespace.createElement(elementalCore.PoweredByLink, { source: serviceNode.name, pathname: pathname, packageType: "elements" })));
222
- return (React__namespace.createElement(elementalCore.SidebarLayout, { ref: container, sidebar: sidebar }, node && (React__namespace.createElement(elementalCore.ParsedDocs, { key: pathname, uri: pathname, node: node, nodeTitle: node.name, layoutOptions: layoutOptions, location: location, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
229
+ return (React__namespace.createElement(elementalCore.SidebarLayout, { ref: container, sidebar: sidebar, renderSideBar: !useCustomNav }, node && (React__namespace.createElement(elementalCore.ParsedDocs, { key: pathname, uri: pathname, node: node, nodeTitle: node.name, layoutOptions: layoutOptions, location: location, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
223
230
  };
224
231
 
225
- const itemMatchesHash = (hash, item) => {
226
- return hash.substr(1) === `${item.name}-${item.data.method}`;
227
- };
232
+ const itemUriMatchesPathname = (itemUri, pathname) => itemUri === pathname;
228
233
  const TryItContext = React__namespace.createContext({
229
234
  hideTryIt: false,
230
235
  tryItCredentialsPolicy: 'omit',
@@ -241,24 +246,18 @@ const APIWithStackedLayout = ({ serviceNode, hideTryIt, hideExport, exportProps,
241
246
  };
242
247
  const Group = React__namespace.memo(({ group }) => {
243
248
  const [isExpanded, setIsExpanded] = React__namespace.useState(false);
244
- const { hash } = reactRouterDom.useLocation();
245
- const scrollRef = React__namespace.useRef(null);
246
- const urlHashMatches = hash.substr(1) === group.title;
249
+ const { pathname } = reactRouterDom.useLocation();
247
250
  const onClick = React__namespace.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
248
251
  const shouldExpand = React__namespace.useMemo(() => {
249
- return urlHashMatches || group.items.some(item => itemMatchesHash(hash, item));
250
- }, [group, hash, urlHashMatches]);
252
+ return group.items.some(item => itemUriMatchesPathname(item.uri, pathname));
253
+ }, [group, pathname]);
251
254
  React__namespace.useEffect(() => {
252
- var _a;
253
255
  if (shouldExpand) {
254
256
  setIsExpanded(true);
255
- if (urlHashMatches && ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop)) {
256
- window.scrollTo(0, scrollRef.current.offsetTop);
257
- }
258
257
  }
259
- }, [shouldExpand, urlHashMatches, group, hash]);
258
+ }, [shouldExpand]);
260
259
  return (React__namespace.createElement(mosaic.Box, null,
261
- React__namespace.createElement(mosaic.Flex, { ref: scrollRef, onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
260
+ React__namespace.createElement(mosaic.Flex, { onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
262
261
  React__namespace.createElement(mosaic.Box, { fontSize: "lg", fontWeight: "medium" }, group.title),
263
262
  React__namespace.createElement(mosaic.Icon, { className: "sl-mr-2", icon: isExpanded ? 'chevron-down' : 'chevron-right', size: "sm" })),
264
263
  React__namespace.createElement(Collapse, { isOpen: isExpanded }, group.items.map(item => {
@@ -267,36 +266,42 @@ const Group = React__namespace.memo(({ group }) => {
267
266
  });
268
267
  const Item = React__namespace.memo(({ item }) => {
269
268
  const location = reactRouterDom.useLocation();
270
- const { hash } = location;
269
+ const { pathname } = location;
271
270
  const [isExpanded, setIsExpanded] = React__namespace.useState(false);
272
271
  const scrollRef = React__namespace.useRef(null);
273
272
  const color = elementalCore.HttpMethodColors[item.data.method] || 'gray';
274
273
  const isDeprecated = !!item.data.deprecated;
275
274
  const { hideTryIt, tryItCredentialsPolicy, corsProxy, tryItOutDefaultServer } = React__namespace.useContext(TryItContext);
276
- const onClick = React__namespace.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
275
+ const onClick = React__namespace.useCallback(() => {
276
+ setIsExpanded(!isExpanded);
277
+ if (window && window.location) {
278
+ window.history.pushState(null, '', `#${item.uri}`);
279
+ }
280
+ }, [isExpanded, item]);
277
281
  React__namespace.useEffect(() => {
278
- var _a;
279
- if (itemMatchesHash(hash, item)) {
282
+ if (itemUriMatchesPathname(item.uri, pathname)) {
280
283
  setIsExpanded(true);
281
- if ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop) {
282
- window.scrollTo(0, scrollRef.current.offsetTop);
284
+ if (scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) {
285
+ scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current.scrollIntoView();
283
286
  }
284
287
  }
285
- }, [hash, item]);
288
+ }, [pathname, item]);
286
289
  return (React__namespace.createElement(mosaic.Box, { ref: scrollRef, w: "full", my: 2, border: true, borderColor: { default: isExpanded ? 'light' : 'transparent', hover: 'light' }, bg: { default: isExpanded ? 'code' : 'transparent', hover: 'code' } },
287
290
  React__namespace.createElement(mosaic.Flex, { mx: "auto", alignItems: "center", cursor: "pointer", fontSize: "lg", p: 2, onClick: onClick, color: "current" },
288
291
  React__namespace.createElement(mosaic.Box, { w: 24, textTransform: "uppercase", textAlign: "center", fontWeight: "semibold", border: true, rounded: true, px: 2, bg: "canvas", className: cn__default["default"](`sl-mr-5 sl-text-base`, `sl-text-${color}`, `sl-border-${color}`) }, item.data.method || 'UNKNOWN'),
289
- React__namespace.createElement(mosaic.Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.name),
292
+ React__namespace.createElement(mosaic.Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.data.path),
290
293
  isDeprecated && React__namespace.createElement(elementalCore.DeprecatedBadge, null)),
291
- React__namespace.createElement(Collapse, { isOpen: isExpanded }, hideTryIt ? (React__namespace.createElement(mosaic.Box, { as: elementalCore.ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React__namespace.createElement(mosaic.Tabs, { appearance: "line" },
292
- React__namespace.createElement(mosaic.TabList, null,
293
- React__namespace.createElement(mosaic.Tab, null, "Docs"),
294
- React__namespace.createElement(mosaic.Tab, null, "TryIt")),
295
- React__namespace.createElement(mosaic.TabPanels, null,
296
- React__namespace.createElement(mosaic.TabPanel, null,
297
- React__namespace.createElement(elementalCore.ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
298
- React__namespace.createElement(mosaic.TabPanel, null,
299
- React__namespace.createElement(elementalCore.TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
294
+ React__namespace.createElement(Collapse, { isOpen: isExpanded },
295
+ React__namespace.createElement(mosaic.Box, { flex: 1, p: 2, fontWeight: "medium", mx: "auto", fontSize: "xl" }, item.name),
296
+ hideTryIt ? (React__namespace.createElement(mosaic.Box, { as: elementalCore.ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React__namespace.createElement(mosaic.Tabs, { appearance: "line" },
297
+ React__namespace.createElement(mosaic.TabList, null,
298
+ React__namespace.createElement(mosaic.Tab, null, "Docs"),
299
+ React__namespace.createElement(mosaic.Tab, null, "TryIt")),
300
+ React__namespace.createElement(mosaic.TabPanels, null,
301
+ React__namespace.createElement(mosaic.TabPanel, null,
302
+ React__namespace.createElement(elementalCore.ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
303
+ React__namespace.createElement(mosaic.TabPanel, null,
304
+ React__namespace.createElement(elementalCore.TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
300
305
  });
301
306
  const Collapse = ({ isOpen, children }) => {
302
307
  if (!isOpen)
@@ -516,7 +521,7 @@ const propsAreWithDocument = (props) => {
516
521
  return props.hasOwnProperty('apiDescriptionDocument');
517
522
  };
518
523
  const APIImpl = props => {
519
- const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, } = props;
524
+ const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, } = props;
520
525
  const apiDescriptionDocument = propsAreWithDocument(props) ? props.apiDescriptionDocument : undefined;
521
526
  const { data: fetchedDocument, error } = reactQuery.useQuery([apiDescriptionUrl], () => fetch(apiDescriptionUrl).then(res => {
522
527
  if (res.ok) {
@@ -543,8 +548,40 @@ const APIImpl = props => {
543
548
  return (React__namespace.createElement(mosaic.Flex, { justify: "center", alignItems: "center", w: "full", minH: "screen" },
544
549
  React__namespace.createElement(elementalCore.NonIdealState, { title: "Failed to parse OpenAPI file", description: "Please make sure your OpenAPI file is valid and try again" })));
545
550
  }
546
- return (React__namespace.createElement(elementalCore.InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React__namespace.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React__namespace.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
551
+ return (React__namespace.createElement(elementalCore.InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React__namespace.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React__namespace.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer, useCustomNav: useCustomNav }))));
547
552
  };
548
553
  const API = flow__default["default"](elementalCore.withRouter, elementalCore.withStyles, elementalCore.withPersistenceBoundary, elementalCore.withMosaicProvider, elementalCore.withQueryClientProvider)(APIImpl);
549
554
 
555
+ const useGetOasNavTree = (apiDescriptionDocument) => {
556
+ const parsedDocument = elementalCore.useParsedValue(apiDescriptionDocument);
557
+ const bundledDocument = elementalCore.useBundleRefsIntoDocument(parsedDocument);
558
+ if (!bundledDocument)
559
+ return [];
560
+ const groupSchemas = (tree) => {
561
+ const targetTitle = 'Schemas';
562
+ const newTree = tree.reduce((accumulator, currentObject) => {
563
+ var _a;
564
+ if (currentObject.title === targetTitle) {
565
+ accumulator.matchedObject = currentObject;
566
+ }
567
+ else if ((_a = currentObject.id) === null || _a === void 0 ? void 0 : _a.includes(targetTitle.toLowerCase())) {
568
+ accumulator.matchedObject.items = accumulator.matchedObject.items || [];
569
+ accumulator.matchedObject.items.push(currentObject);
570
+ }
571
+ else {
572
+ accumulator.others = accumulator.others || [];
573
+ accumulator.others.push(currentObject);
574
+ }
575
+ return accumulator;
576
+ }, {});
577
+ const navTree = [...newTree.others, newTree.matchedObject];
578
+ return navTree;
579
+ };
580
+ const apiTree = computeAPITree(transformOasToServiceNode(bundledDocument));
581
+ return groupSchemas(apiTree);
582
+ };
583
+
550
584
  exports.API = API;
585
+ exports.transformOasToServiceNode = transformOasToServiceNode;
586
+ exports.useExportDocumentProps = useExportDocumentProps;
587
+ exports.useGetOasNavTree = useGetOasNavTree;
package/index.mjs CHANGED
@@ -157,13 +157,20 @@ const isInternal = (node) => {
157
157
  return !!data['x-internal'];
158
158
  };
159
159
 
160
- const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, }) => {
160
+ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideInternal, hideExport, exportProps, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, }) => {
161
161
  const container = React.useRef(null);
162
- const tree = React.useMemo(() => computeAPITree(serviceNode, { hideSchemas, hideInternal }), [serviceNode, hideSchemas, hideInternal]);
162
+ const tree = React.useMemo(() => {
163
+ if (!useCustomNav)
164
+ return computeAPITree(serviceNode, { hideSchemas, hideInternal });
165
+ else
166
+ return [];
167
+ }, [serviceNode, hideSchemas, hideInternal, useCustomNav]);
163
168
  const location = useLocation();
164
169
  const { pathname } = location;
165
170
  const isRootPath = !pathname || pathname === '/';
166
171
  const node = isRootPath ? serviceNode : serviceNode.children.find(child => child.uri === pathname);
172
+ React.useEffect(() => {
173
+ }, [pathname]);
167
174
  const layoutOptions = React.useMemo(() => ({ hideTryIt: hideTryIt, hideExport: hideExport || (node === null || node === void 0 ? void 0 : node.type) !== NodeType.HttpService }), [hideTryIt, hideExport, node]);
168
175
  if (!node) {
169
176
  const firstSlug = findFirstNodeSlug(tree);
@@ -186,12 +193,10 @@ const APIWithSidebarLayout = ({ serviceNode, logo, hideTryIt, hideSchemas, hideI
186
193
  React.createElement(Flex, { flexGrow: true, flexShrink: true, overflowY: "auto", direction: "col" },
187
194
  React.createElement(TableOfContents, { tree: tree, activeId: pathname, Link: Link, onLinkClick: handleTocClick })),
188
195
  React.createElement(PoweredByLink, { source: serviceNode.name, pathname: pathname, packageType: "elements" })));
189
- return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar }, 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 }))));
196
+ return (React.createElement(SidebarLayout, { ref: container, sidebar: sidebar, renderSideBar: !useCustomNav }, 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 }))));
190
197
  };
191
198
 
192
- const itemMatchesHash = (hash, item) => {
193
- return hash.substr(1) === `${item.name}-${item.data.method}`;
194
- };
199
+ const itemUriMatchesPathname = (itemUri, pathname) => itemUri === pathname;
195
200
  const TryItContext = React.createContext({
196
201
  hideTryIt: false,
197
202
  tryItCredentialsPolicy: 'omit',
@@ -208,24 +213,18 @@ const APIWithStackedLayout = ({ serviceNode, hideTryIt, hideExport, exportProps,
208
213
  };
209
214
  const Group = React.memo(({ group }) => {
210
215
  const [isExpanded, setIsExpanded] = React.useState(false);
211
- const { hash } = useLocation();
212
- const scrollRef = React.useRef(null);
213
- const urlHashMatches = hash.substr(1) === group.title;
216
+ const { pathname } = useLocation();
214
217
  const onClick = React.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
215
218
  const shouldExpand = React.useMemo(() => {
216
- return urlHashMatches || group.items.some(item => itemMatchesHash(hash, item));
217
- }, [group, hash, urlHashMatches]);
219
+ return group.items.some(item => itemUriMatchesPathname(item.uri, pathname));
220
+ }, [group, pathname]);
218
221
  React.useEffect(() => {
219
- var _a;
220
222
  if (shouldExpand) {
221
223
  setIsExpanded(true);
222
- if (urlHashMatches && ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop)) {
223
- window.scrollTo(0, scrollRef.current.offsetTop);
224
- }
225
224
  }
226
- }, [shouldExpand, urlHashMatches, group, hash]);
225
+ }, [shouldExpand]);
227
226
  return (React.createElement(Box, null,
228
- React.createElement(Flex, { ref: scrollRef, onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
227
+ React.createElement(Flex, { onClick: onClick, mx: "auto", justifyContent: "between", alignItems: "center", borderB: true, px: 2, py: 4, cursor: "pointer", color: { default: 'current', hover: 'muted' } },
229
228
  React.createElement(Box, { fontSize: "lg", fontWeight: "medium" }, group.title),
230
229
  React.createElement(Icon, { className: "sl-mr-2", icon: isExpanded ? 'chevron-down' : 'chevron-right', size: "sm" })),
231
230
  React.createElement(Collapse, { isOpen: isExpanded }, group.items.map(item => {
@@ -234,36 +233,42 @@ const Group = React.memo(({ group }) => {
234
233
  });
235
234
  const Item = React.memo(({ item }) => {
236
235
  const location = useLocation();
237
- const { hash } = location;
236
+ const { pathname } = location;
238
237
  const [isExpanded, setIsExpanded] = React.useState(false);
239
238
  const scrollRef = React.useRef(null);
240
239
  const color = HttpMethodColors[item.data.method] || 'gray';
241
240
  const isDeprecated = !!item.data.deprecated;
242
241
  const { hideTryIt, tryItCredentialsPolicy, corsProxy, tryItOutDefaultServer } = React.useContext(TryItContext);
243
- const onClick = React.useCallback(() => setIsExpanded(!isExpanded), [isExpanded]);
242
+ const onClick = React.useCallback(() => {
243
+ setIsExpanded(!isExpanded);
244
+ if (window && window.location) {
245
+ window.history.pushState(null, '', `#${item.uri}`);
246
+ }
247
+ }, [isExpanded, item]);
244
248
  React.useEffect(() => {
245
- var _a;
246
- if (itemMatchesHash(hash, item)) {
249
+ if (itemUriMatchesPathname(item.uri, pathname)) {
247
250
  setIsExpanded(true);
248
- if ((_a = scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop) {
249
- window.scrollTo(0, scrollRef.current.offsetTop);
251
+ if (scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) {
252
+ scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current.scrollIntoView();
250
253
  }
251
254
  }
252
- }, [hash, item]);
255
+ }, [pathname, item]);
253
256
  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' } },
254
257
  React.createElement(Flex, { mx: "auto", alignItems: "center", cursor: "pointer", fontSize: "lg", p: 2, onClick: onClick, color: "current" },
255
258
  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'),
256
- React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.name),
259
+ React.createElement(Box, { flex: 1, fontWeight: "medium", wordBreak: "all" }, item.data.path),
257
260
  isDeprecated && React.createElement(DeprecatedBadge, null)),
258
- React.createElement(Collapse, { isOpen: isExpanded }, hideTryIt ? (React.createElement(Box, { as: ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React.createElement(Tabs, { appearance: "line" },
259
- React.createElement(TabList, null,
260
- React.createElement(Tab, null, "Docs"),
261
- React.createElement(Tab, null, "TryIt")),
262
- React.createElement(TabPanels, null,
263
- React.createElement(TabPanel, null,
264
- React.createElement(ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
265
- React.createElement(TabPanel, null,
266
- React.createElement(TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
261
+ React.createElement(Collapse, { isOpen: isExpanded },
262
+ React.createElement(Box, { flex: 1, p: 2, fontWeight: "medium", mx: "auto", fontSize: "xl" }, item.name),
263
+ hideTryIt ? (React.createElement(Box, { as: ParsedDocs, layoutOptions: { noHeading: true, hideTryItPanel: true }, node: item, p: 4 })) : (React.createElement(Tabs, { appearance: "line" },
264
+ React.createElement(TabList, null,
265
+ React.createElement(Tab, null, "Docs"),
266
+ React.createElement(Tab, null, "TryIt")),
267
+ React.createElement(TabPanels, null,
268
+ React.createElement(TabPanel, null,
269
+ React.createElement(ParsedDocs, { className: "sl-px-4", node: item, location: location, layoutOptions: { noHeading: true, hideTryItPanel: true } })),
270
+ React.createElement(TabPanel, null,
271
+ React.createElement(TryItWithRequestSamples, { httpOperation: item.data, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItOutDefaultServer: tryItOutDefaultServer, corsProxy: corsProxy }))))))));
267
272
  });
268
273
  const Collapse = ({ isOpen, children }) => {
269
274
  if (!isOpen)
@@ -483,7 +488,7 @@ const propsAreWithDocument = (props) => {
483
488
  return props.hasOwnProperty('apiDescriptionDocument');
484
489
  };
485
490
  const APIImpl = props => {
486
- const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, } = props;
491
+ const { layout, apiDescriptionUrl = '', logo, hideTryIt, hideSchemas, hideInternal, hideExport, tryItCredentialsPolicy, tryItCorsProxy, tryItOutDefaultServer, useCustomNav, } = props;
487
492
  const apiDescriptionDocument = propsAreWithDocument(props) ? props.apiDescriptionDocument : undefined;
488
493
  const { data: fetchedDocument, error } = useQuery([apiDescriptionUrl], () => fetch(apiDescriptionUrl).then(res => {
489
494
  if (res.ok) {
@@ -510,8 +515,37 @@ const APIImpl = props => {
510
515
  return (React.createElement(Flex, { justify: "center", alignItems: "center", w: "full", minH: "screen" },
511
516
  React.createElement(NonIdealState, { title: "Failed to parse OpenAPI file", description: "Please make sure your OpenAPI file is valid and try again" })));
512
517
  }
513
- return (React.createElement(InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer }))));
518
+ return (React.createElement(InlineRefResolverProvider, { document: parsedDocument }, layout === 'stacked' ? (React.createElement(APIWithStackedLayout, { serviceNode: serviceNode, hideTryIt: hideTryIt, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer })) : (React.createElement(APIWithSidebarLayout, { logo: logo, serviceNode: serviceNode, hideTryIt: hideTryIt, hideSchemas: hideSchemas, hideInternal: hideInternal, hideExport: hideExport, exportProps: exportProps, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy, tryItOutDefaultServer: tryItOutDefaultServer, useCustomNav: useCustomNav }))));
514
519
  };
515
520
  const API = flow(withRouter, withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider)(APIImpl);
516
521
 
517
- export { API };
522
+ const useGetOasNavTree = (apiDescriptionDocument) => {
523
+ const parsedDocument = useParsedValue(apiDescriptionDocument);
524
+ const bundledDocument = useBundleRefsIntoDocument(parsedDocument);
525
+ if (!bundledDocument)
526
+ return [];
527
+ const groupSchemas = (tree) => {
528
+ const targetTitle = 'Schemas';
529
+ const newTree = tree.reduce((accumulator, currentObject) => {
530
+ var _a;
531
+ if (currentObject.title === targetTitle) {
532
+ accumulator.matchedObject = currentObject;
533
+ }
534
+ else if ((_a = currentObject.id) === null || _a === void 0 ? void 0 : _a.includes(targetTitle.toLowerCase())) {
535
+ accumulator.matchedObject.items = accumulator.matchedObject.items || [];
536
+ accumulator.matchedObject.items.push(currentObject);
537
+ }
538
+ else {
539
+ accumulator.others = accumulator.others || [];
540
+ accumulator.others.push(currentObject);
541
+ }
542
+ return accumulator;
543
+ }, {});
544
+ const navTree = [...newTree.others, newTree.matchedObject];
545
+ return navTree;
546
+ };
547
+ const apiTree = computeAPITree(transformOasToServiceNode(bundledDocument));
548
+ return groupSchemas(apiTree);
549
+ };
550
+
551
+ export { API, transformOasToServiceNode, useExportDocumentProps, useGetOasNavTree };