@stoplight/elements-core 7.3.10 → 7.5.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/index.esm.js CHANGED
@@ -2,32 +2,53 @@ import { __rest, __awaiter } from 'tslib';
2
2
  import * as React from 'react';
3
3
  import React__default, { useContext, useMemo } from 'react';
4
4
  import { resolveInlineRef, isPlainObject as isPlainObject$1, safeParse, safeStringify } from '@stoplight/json';
5
- import _, { isObject, isPlainObject, isArray, throttle, filter, capitalize, flatten, curry, map, omit, pickBy, isString, compact, uniq, uniqBy, orderBy, sortBy, get, omitBy, isEmpty, keys, entries, mapValues, isEqual } from 'lodash';
5
+ import isArray from 'lodash/isArray.js';
6
+ import isObject from 'lodash/isObject.js';
7
+ import isPlainObject from 'lodash/isPlainObject.js';
6
8
  import { parse } from '@stoplight/markdown';
7
9
  import { NodeType, HttpParamStyles } from '@stoplight/types';
8
10
  import { parse as parse$1 } from '@stoplight/yaml';
9
- import { isArray as isArray$1, Flex, Box, Popover, Button, Panel, CopyButton, Menu, Text, Input, Icon, Select, Image, Link, useThemeIsDark, Tooltip, VStack, InvertTheme, Badge, Tabs, TabList, Tab, TabPanels, TabPanel, Heading as Heading$1, HStack, useClipboard, Provider as Provider$1 } from '@stoplight/mosaic';
11
+ import { isArray as isArray$1, Box, Flex, Icon, Popover, Button, Panel, CopyButton, Menu, Text, Input, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading, Tabs, TabList, Tab, TabPanels, TabPanel, Heading as Heading$1, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
10
12
  import { withErrorBoundary } from '@stoplight/react-error-boundary';
11
13
  import { MarkdownViewer as MarkdownViewer$1, DefaultSMDComponents, MarkdownViewerProvider } from '@stoplight/markdown-viewer';
12
14
  export { DefaultSMDComponents } from '@stoplight/markdown-viewer';
13
- import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faExclamationTriangle, faEye, faLock, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
14
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
15
+ import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faServer, faExclamationTriangle, faEye, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
16
+ import throttle from 'lodash/throttle.js';
15
17
  import { selectAll } from 'unist-util-select';
16
18
  import cn from 'classnames';
19
+ import { atomWithStorage, useAtomValue } from 'jotai/utils';
17
20
  import { atom, useAtom, Provider } from 'jotai';
18
21
  import URI from 'urijs';
19
22
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
20
23
  import HTTPSnippet from 'httpsnippet';
24
+ import flatten from 'lodash/flatten.js';
25
+ import capitalize from 'lodash/capitalize.js';
26
+ import filter from 'lodash/filter.js';
21
27
  import { nanoid } from 'nanoid';
28
+ import curry from 'lodash/curry.js';
29
+ import omit from 'lodash/omit.js';
30
+ import keyBy from 'lodash/keyBy.js';
31
+ import map from 'lodash/map.js';
32
+ import mapValues from 'lodash/mapValues.js';
33
+ import isString from 'lodash/isString.js';
34
+ import pickBy from 'lodash/pickBy.js';
22
35
  import { CodeEditor } from '@stoplight/mosaic-code-editor';
23
36
  import * as Sampler from '@stoplight/json-schema-sampler';
37
+ import compact from 'lodash/compact.js';
38
+ import uniq from 'lodash/uniq.js';
39
+ import orderBy from 'lodash/orderBy.js';
40
+ import uniqBy from 'lodash/uniqBy.js';
24
41
  import formatXml from 'xml-formatter';
25
- import { Link as Link$1, useLocation, BrowserRouter, MemoryRouter, HashRouter, Route } from 'react-router-dom';
26
- import { JsonSchemaViewer, Validations } from '@stoplight/json-schema-viewer';
27
- import { QueryClient, QueryClientProvider } from 'react-query';
42
+ import entries from 'lodash/entries.js';
43
+ import keys from 'lodash/keys.js';
44
+ import { JsonSchemaViewer } from '@stoplight/json-schema-viewer';
45
+ import sortBy from 'lodash/sortBy.js';
46
+ import { useLocation, BrowserRouter, MemoryRouter, HashRouter, StaticRouter, Route } from 'react-router-dom';
28
47
  import { HashLink } from 'react-router-hash-link';
48
+ import { QueryClient, useQueryClient, QueryClientProvider } from 'react-query';
29
49
  import $RefParser from '@stoplight/json-schema-ref-parser';
30
50
  import * as PropTypes from 'prop-types';
51
+ import isEqual from 'lodash/isEqual.js';
31
52
  import * as ReactDOM from 'react-dom';
32
53
 
33
54
  const defaultResolver = (contextObject) => ({ pointer }, _, currentObject) => {
@@ -246,7 +267,7 @@ const findTitle = (parent) => {
246
267
  };
247
268
 
248
269
  function useLocationHash() {
249
- const isBrowser = typeof window !== undefined;
270
+ const isBrowser = typeof window !== 'undefined';
250
271
  const [locationHash, setLocationHash] = React.useState(isBrowser && window.location.hash);
251
272
  React.useEffect(() => {
252
273
  if (!isBrowser)
@@ -262,15 +283,15 @@ const ArticleHeadings = ({ tree, container }) => {
262
283
  const { width } = useComponentSize(container);
263
284
  const showHeadings = width >= 768;
264
285
  const headings = useComputeMarkdownHeadings(tree);
265
- return React.createElement(Headings, { className: "ArticleHeadings", headings: headings, minimal: !showHeadings });
286
+ return React.createElement(Headings, { className: "ArticleHeadings", headings: headings, minimal: !showHeadings, maxWidth: 300 });
266
287
  };
267
- const Headings = ({ headings, className, title = 'On This Page', minimal }) => {
288
+ const Headings = ({ headings, className, title = 'On This Page', minimal, maxWidth }) => {
268
289
  const locationHash = useLocationHash();
269
290
  if (!headings || !headings.length)
270
291
  return null;
271
- const component = (React.createElement("div", { style: { maxHeight: '85vh', overflow: 'auto' } },
292
+ const component = (React.createElement(Box, { overflowY: "auto", style: { maxHeight: '85vh', maxWidth } },
272
293
  title && (React.createElement(Flex, { py: 2, alignItems: "center", fontSize: "sm", fontWeight: "medium", color: "muted", style: { paddingLeft: 18 } },
273
- React.createElement(FontAwesomeIcon, { icon: faStream, className: "sl-mr-2" }),
294
+ React.createElement(Box, { as: Icon, icon: faStream, mr: 2 }),
274
295
  title)),
275
296
  headings.map((heading, i) => (React.createElement(Heading, { key: i, item: heading, isSelected: locationHash === `#${heading.id}` })))));
276
297
  if (minimal) {
@@ -290,59 +311,13 @@ const ArticleComponent = React.memo(({ data }) => {
290
311
  const tree = React.useMemo(() => (typeof data === 'object' ? data : parse(data)), [data]);
291
312
  if (tree === null)
292
313
  return null;
293
- return (React.createElement(Flex, { className: "sl-elements-article", w: "full", pos: "relative", ref: setContainer },
314
+ return (React.createElement(Flex, { className: "sl-elements-article", justifyContent: "evenly", w: "full", pos: "relative", ref: setContainer },
294
315
  React.createElement(Box, { className: "sl-elements-article-content", style: { width: 0 }, flex: 1 },
295
316
  React.createElement(MarkdownViewer, { markdown: tree })),
296
317
  React.createElement(ArticleHeadings, { tree: tree, container: container })));
297
318
  });
298
319
  const Article = withErrorBoundary(ArticleComponent, { recoverableProps: ['data'] });
299
320
 
300
- const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
301
- const MockingProvider = ({ mockUrl, hideMocking, children }) => {
302
- const info = {
303
- mockUrl,
304
- hideMocking: hideMocking || !mockUrl,
305
- };
306
- return React.createElement(MockingContext.Provider, { value: info }, children);
307
- };
308
- function createNamedContext(name, defaultValue) {
309
- const context = React.createContext(defaultValue);
310
- context.displayName = name;
311
- return context;
312
- }
313
-
314
- function getReadableSecurityName(securityScheme, includeKey = false) {
315
- let name = '';
316
- switch (securityScheme.type) {
317
- case 'apiKey':
318
- name = 'API Key';
319
- break;
320
- case 'http':
321
- name = `${capitalize(securityScheme.scheme)} Auth`;
322
- break;
323
- case 'oauth2':
324
- name = 'OAuth 2.0';
325
- break;
326
- case 'openIdConnect':
327
- name = 'OpenID Connect';
328
- break;
329
- case 'mutualTLS':
330
- name = 'Mutual TLS';
331
- break;
332
- }
333
- return includeKey ? `${name} (${securityScheme.key})` : name;
334
- }
335
- function getServiceUriFromOperation(uri) {
336
- const match = uri === null || uri === void 0 ? void 0 : uri.match(/(.*)\/(paths|operations)/);
337
- return match && match.length > 1 ? match[1] || '/' : undefined;
338
- }
339
- const isOAuth2ImplicitFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && !('tokenUrl' in maybeFlow);
340
- const isOauth2AuthorizationCodeFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && 'tokenUrl' in maybeFlow;
341
- const isOauth2ClientCredentialsOrPasswordFlow = (maybeFlow) => isObject(maybeFlow) && !('authorizationUrl' in maybeFlow) && 'tokenUrl' in maybeFlow;
342
- function shouldIncludeKey(schemes, type) {
343
- return filter(schemes, { type }).length > 1;
344
- }
345
-
346
321
  const NodeTypeColors = {
347
322
  http_operation: '#6a6acb',
348
323
  http_service: '#e056fd',
@@ -459,10 +434,36 @@ const HttpCodeDescriptions = {
459
434
  const badgeDefaultBackgroundColor = '#293742';
460
435
  const badgeDefaultColor = '#FFFFFF';
461
436
 
462
- const getServersToDisplay = (originalServers) => {
463
- return originalServers
464
- .map((server, i) => (Object.assign(Object.assign({}, server), { url: getServerUrlWithDefaultValues(server), description: server.description || `Server ${i + 1}` })))
437
+ const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
438
+ const MockingProvider = ({ mockUrl, hideMocking, children }) => {
439
+ const info = {
440
+ mockUrl,
441
+ hideMocking: hideMocking || !mockUrl,
442
+ };
443
+ return React.createElement(MockingContext.Provider, { value: info }, children);
444
+ };
445
+ function createNamedContext(name, defaultValue) {
446
+ const context = React.createContext(defaultValue);
447
+ context.displayName = name;
448
+ return context;
449
+ }
450
+
451
+ const chosenServerAtom = atom(undefined);
452
+
453
+ const getServersToDisplay = (originalServers, mockUrl) => {
454
+ const servers = originalServers
455
+ .map((server, i) => {
456
+ const fallbackDescription = originalServers.length === 1 ? 'Live Server' : `Server ${i + 1}`;
457
+ return Object.assign(Object.assign({}, server), { url: getServerUrlWithDefaultValues(server), description: server.description || fallbackDescription });
458
+ })
465
459
  .filter(server => isProperUrl(server.url));
460
+ if (mockUrl) {
461
+ servers.push({
462
+ description: 'Mock Server',
463
+ url: mockUrl,
464
+ });
465
+ }
466
+ return servers;
466
467
  };
467
468
  const getServerUrlWithDefaultValues = (server) => {
468
469
  var _a;
@@ -728,9 +729,42 @@ const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) =
728
729
  " ",
729
730
  selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
730
731
  React__default.createElement(Panel.Content, { p: 0 },
731
- React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText }))));
732
+ React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText, style: embeddedInMd
733
+ ? undefined
734
+ :
735
+ {
736
+ '--fs-code': 12,
737
+ } }))));
732
738
  });
733
739
 
740
+ function getReadableSecurityName(securityScheme, includeKey = false) {
741
+ let name = '';
742
+ switch (securityScheme.type) {
743
+ case 'apiKey':
744
+ name = 'API Key';
745
+ break;
746
+ case 'http':
747
+ name = `${capitalize(securityScheme.scheme)} Auth`;
748
+ break;
749
+ case 'oauth2':
750
+ name = 'OAuth 2.0';
751
+ break;
752
+ case 'openIdConnect':
753
+ name = 'OpenID Connect';
754
+ break;
755
+ case 'mutualTLS':
756
+ name = 'Mutual TLS';
757
+ break;
758
+ }
759
+ return includeKey ? `${name} (${securityScheme.key})` : name;
760
+ }
761
+ const isOAuth2ImplicitFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && !('tokenUrl' in maybeFlow);
762
+ const isOauth2AuthorizationCodeFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && 'tokenUrl' in maybeFlow;
763
+ const isOauth2ClientCredentialsOrPasswordFlow = (maybeFlow) => isObject(maybeFlow) && !('authorizationUrl' in maybeFlow) && 'tokenUrl' in maybeFlow;
764
+ function shouldIncludeKey(schemes, type) {
765
+ return filter(schemes, { type }).length > 1;
766
+ }
767
+
734
768
  const useUniqueId = (prefix = 'id_') => React.useRef(`${prefix}${nanoid(8)}`).current;
735
769
 
736
770
  const AuthTokenInput = ({ type, name, value, onChange }) => {
@@ -865,7 +899,14 @@ const SecuritySchemeComponent = (_a) => {
865
899
  };
866
900
  const securitySchemeKeys = ['apiKey', 'http', 'oauth2', 'openIdConnect'];
867
901
 
868
- const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
902
+ const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
903
+ function slugify(name) {
904
+ return name
905
+ .replace(/\/|{|}|\s/g, '-')
906
+ .replace(/-{2,}/, '-')
907
+ .replace(/^-/, '')
908
+ .replace(/-$/, '');
909
+ }
869
910
 
870
911
  const isApiKeySecurityScheme = (maybeIApiKey) => isObject(maybeIApiKey) && maybeIApiKey.type === 'apiKey';
871
912
  const isOAuth2SecurityScheme = (maybeIOAuth2) => isObject(maybeIOAuth2) && maybeIOAuth2.type === 'oauth2';
@@ -976,10 +1017,10 @@ function exampleValue(example) {
976
1017
  }
977
1018
  function getPlaceholderForParameter(parameter) {
978
1019
  var _a, _b;
979
- const parameterValue = getValueForParameter(parameter);
1020
+ const { value: parameterValue, isDefault } = getValueForParameter(parameter);
980
1021
  if (parameterValue)
981
- return `example: ${parameterValue}`;
982
- return parameterValue || String((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '');
1022
+ return `${isDefault ? 'defaults to' : 'example'}: ${parameterValue}`;
1023
+ return String((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '');
983
1024
  }
984
1025
  function retrieveDefaultFromSchema(parameter) {
985
1026
  var _a;
@@ -988,28 +1029,29 @@ function retrieveDefaultFromSchema(parameter) {
988
1029
  }
989
1030
  const getValueForParameter = (parameter) => {
990
1031
  var _a, _b, _c;
991
- const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
992
- if (examples.length > 0)
993
- return exampleValue(examples[0]);
994
1032
  const defaultValue = retrieveDefaultFromSchema(parameter);
995
- if (defaultValue)
996
- return String(defaultValue);
1033
+ if (typeof defaultValue !== 'undefined') {
1034
+ return { value: String(defaultValue), isDefault: true };
1035
+ }
1036
+ const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1037
+ if (examples.length > 0) {
1038
+ return { value: exampleValue(examples[0]) };
1039
+ }
997
1040
  const enums = (_c = (_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.enum) !== null && _c !== void 0 ? _c : [];
998
- if (enums.length > 0)
999
- return String(enums[0]);
1000
- return '';
1041
+ if (enums.length > 0) {
1042
+ return { value: String(enums[0]) };
1043
+ }
1044
+ return { value: '' };
1001
1045
  };
1002
1046
  const getInitialValueForParameter = (parameter) => {
1003
1047
  const isRequired = !!parameter.required;
1004
1048
  if (!isRequired)
1005
1049
  return '';
1006
- return getValueForParameter(parameter);
1050
+ return getValueForParameter(parameter).value;
1007
1051
  };
1008
1052
  const initialParameterValues = params => {
1009
- return _.chain(params)
1010
- .keyBy((param) => param.name)
1011
- .mapValues(param => getInitialValueForParameter(param))
1012
- .value();
1053
+ const paramsByName = keyBy(params, (param) => param.name);
1054
+ return mapValues(paramsByName, param => getInitialValueForParameter(param));
1013
1055
  };
1014
1056
  function mapSchemaPropertiesToParameters(properties, required) {
1015
1057
  return Object.entries(properties).map(([name, schema]) => (Object.assign({ name, schema: typeof schema !== 'boolean' ? schema : undefined, examples: typeof schema !== 'boolean' && schema.examples ? [{ key: 'example', value: schema.examples }] : undefined }, ((required === null || required === void 0 ? void 0 : required.includes(name)) && { required: true }))));
@@ -1150,7 +1192,9 @@ const RequestBody = ({ examples, requestBody, onChange }) => {
1150
1192
  return (React.createElement(Panel, { defaultIsOpen: true },
1151
1193
  React.createElement(Panel.Titlebar, { rightComponent: examples.length > 1 && React.createElement(ExampleMenu, { examples: examples, requestBody: requestBody, onChange: onChange }) }, "Body"),
1152
1194
  React.createElement(Panel.Content, { className: "TextRequestBody" },
1153
- React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0 }))));
1195
+ React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0, style: {
1196
+ fontSize: 12,
1197
+ } }))));
1154
1198
  };
1155
1199
  function ExampleMenu({ examples, requestBody, onChange }) {
1156
1200
  const handleClick = React.useCallback((example) => {
@@ -1235,7 +1279,6 @@ const generateExamplesFromJsonSchema = (schema) => {
1235
1279
  : [{ label: 'default', data: '' }];
1236
1280
  }
1237
1281
  catch (e) {
1238
- console.error(e);
1239
1282
  return [{ label: '', data: `Example cannot be created for this schema\n${e}` }];
1240
1283
  }
1241
1284
  };
@@ -1409,8 +1452,8 @@ const formatMultiValueHeader = (...keyValuePairs) => {
1409
1452
  .join(', ');
1410
1453
  };
1411
1454
 
1412
- function getMockData(url, httpOperation, { isEnabled, code, dynamic, example }) {
1413
- return isEnabled && url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1455
+ function getMockData(url, httpOperation, { code, dynamic, example }) {
1456
+ return url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1414
1457
  }
1415
1458
  function buildPreferHeader({ code, example, dynamic }, httpOperation) {
1416
1459
  if (!code) {
@@ -1443,23 +1486,14 @@ function supportsExample(httpOperation, code, exampleKey) {
1443
1486
  return exampleKeys.includes(exampleKey);
1444
1487
  }
1445
1488
 
1446
- const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic }, onOptionsChange, }) => {
1447
- const toggleEnabled = React.useCallback(() => {
1448
- onOptionsChange({ isEnabled: !isEnabled });
1449
- }, [isEnabled, onOptionsChange]);
1489
+ const MockingButton = ({ operation, options: { code, example, dynamic }, onOptionsChange, }) => {
1450
1490
  const operationResponses = operation.responses;
1451
1491
  const setMockingOptions = React.useCallback(({ code, example, dynamic }) => {
1452
- onOptionsChange({ isEnabled, code, example, dynamic });
1453
- }, [isEnabled, onOptionsChange]);
1492
+ onOptionsChange({ code, example, dynamic });
1493
+ }, [onOptionsChange]);
1454
1494
  const menuItems = React.useMemo(() => {
1455
1495
  var _a;
1456
- const items = [
1457
- { id: 'mocking-enabled', title: 'Enabled', isChecked: isEnabled, onPress: toggleEnabled },
1458
- {
1459
- type: 'group',
1460
- children: (_a = operationResponses === null || operationResponses === void 0 ? void 0 : operationResponses.filter(operationResponse => Number.isInteger(parseFloat(operationResponse.code)))) === null || _a === void 0 ? void 0 : _a.map(generateOperationResponseMenu),
1461
- },
1462
- ];
1496
+ const items = (_a = operationResponses === null || operationResponses === void 0 ? void 0 : operationResponses.filter(operationResponse => Number.isInteger(parseFloat(operationResponse.code)))) === null || _a === void 0 ? void 0 : _a.map(generateOperationResponseMenu);
1463
1497
  function generateOperationResponseMenu(operationResponse) {
1464
1498
  var _a;
1465
1499
  const menuId = `response-${operationResponse.code}`;
@@ -1493,7 +1527,6 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1493
1527
  ];
1494
1528
  const menuItem = {
1495
1529
  id: menuId,
1496
- isDisabled: !isEnabled,
1497
1530
  isChecked: isActive,
1498
1531
  title: operationResponse.code,
1499
1532
  onPress: () => {
@@ -1507,13 +1540,13 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1507
1540
  return menuItem;
1508
1541
  }
1509
1542
  return items;
1510
- }, [code, dynamic, example, isEnabled, operationResponses, setMockingOptions, toggleEnabled]);
1543
+ }, [code, dynamic, example, operationResponses, setMockingOptions]);
1511
1544
  return (React.createElement(Box, null,
1512
- React.createElement(Menu, { "aria-label": "Mocking", items: menuItems, renderTrigger: ({ isOpen }) => (React.createElement(Button, { iconRight: "chevron-down", icon: isEnabled ? 'check' : undefined, appearance: isEnabled ? 'primary' : 'minimal', ml: 2, active: isOpen, size: "sm" }, "Mocking")) })));
1545
+ React.createElement(Menu, { "aria-label": "Mock settings", items: menuItems, renderTrigger: ({ isOpen }) => (React.createElement(FieldButton, { active: isOpen, size: "sm" }, "Mock Settings")) })));
1513
1546
  };
1514
1547
 
1515
- const persistedMockingOptionsAtom = atom({ isEnabled: false });
1516
- const useMockingOptions = () => useAtom(persistedMockingOptionsAtom);
1548
+ const mockingOptionsAtom = atom({});
1549
+ const useMockingOptions = () => useAtom(mockingOptionsAtom);
1517
1550
 
1518
1551
  const OperationParameters = ({ parameters, values, onChangeValue, validate, }) => {
1519
1552
  return (React.createElement(Panel, { defaultIsOpen: true },
@@ -1611,7 +1644,7 @@ const TryItResponse = ({ response }) => {
1611
1644
  ? parseBody(response.bodyText, responseType)
1612
1645
  : response.bodyText })) : response.blob && responseType === 'image' ? (React.createElement(Flex, { justifyContent: "center" },
1613
1646
  React.createElement(Image, { src: URL.createObjectURL(response.blob), alt: "response image" }))) : (React.createElement("p", null,
1614
- React.createElement(FontAwesomeIcon, { icon: faExclamationCircle, className: "sl-mr-2" }),
1647
+ React.createElement(Box, { as: Icon, icon: faExclamationCircle, mr: 2 }),
1615
1648
  "No supported response body returned"))))));
1616
1649
  };
1617
1650
  const ResponseMenu = ({ types, type, onChange }) => {
@@ -1642,7 +1675,32 @@ class NetworkError extends Error {
1642
1675
  }
1643
1676
  const isNetworkError = (error) => error instanceof NetworkError;
1644
1677
 
1645
- const chosenServerAtom = atom(undefined);
1678
+ const ServersDropdown = ({ servers }) => {
1679
+ const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1680
+ const serverItems = [
1681
+ {
1682
+ type: 'option_group',
1683
+ title: 'Servers',
1684
+ value: (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || '',
1685
+ onChange: url => {
1686
+ const server = servers.find(server => server.url === url);
1687
+ setChosenServer(server);
1688
+ },
1689
+ children: [
1690
+ ...servers.map((server, i) => ({
1691
+ id: server.url,
1692
+ title: server.name || server.description,
1693
+ description: server.name ? server.description || server.url : server.description ? server.url : undefined,
1694
+ value: server.url,
1695
+ })),
1696
+ ],
1697
+ },
1698
+ ];
1699
+ return (React.createElement(Menu, { "aria-label": "Server", items: serverItems, closeOnPress: true, renderTrigger: ({ isOpen }) => (React.createElement(FieldButton, { icon: faServer, size: "sm", active: isOpen }, (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.name) || (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.description) || 'Server')) }));
1700
+ };
1701
+ ServersDropdown.displayName = 'ServersDropdown';
1702
+
1703
+ const defaultServers = [];
1646
1704
  const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embeddedInMd = false, tryItCredentialsPolicy, corsProxy, }) => {
1647
1705
  var _a, _b, _c, _d, _e, _f, _g;
1648
1706
  const isDark = useThemeIsDark();
@@ -1656,27 +1714,41 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1656
1714
  const [bodyParameterValues, setBodyParameterValues, formDataState] = useBodyParameterState(mediaTypeContent);
1657
1715
  const [textRequestBody, setTextRequestBody] = useTextRequestBodyState(mediaTypeContent);
1658
1716
  const [operationAuthValue, setOperationAuthValue] = usePersistedSecuritySchemeWithValues();
1659
- const servers = getServersToDisplay(httpOperation.servers || []);
1717
+ const servers = React.useMemo(() => {
1718
+ const toDisplay = getServersToDisplay(httpOperation.servers || defaultServers, mockUrl);
1719
+ return toDisplay;
1720
+ }, [httpOperation.servers, mockUrl]);
1721
+ const firstServer = servers[0] || null;
1660
1722
  const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1723
+ const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
1661
1724
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
1662
1725
  React.useEffect(() => {
1663
- if (!chosenServer) {
1664
- setChosenServer(servers[0]);
1726
+ const currentUrl = chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url;
1727
+ const exists = currentUrl && servers.find(s => s.url === currentUrl);
1728
+ if (!exists) {
1729
+ setChosenServer(firstServer);
1665
1730
  }
1666
- }, []);
1731
+ else if (exists !== chosenServer) {
1732
+ setChosenServer(exists);
1733
+ }
1734
+ }, [servers, firstServer, chosenServer, setChosenServer]);
1667
1735
  React.useEffect(() => {
1668
- let isActive = true;
1736
+ let isMounted = true;
1669
1737
  if (onRequestChange || embeddedInMd) {
1670
- buildHarRequest(Object.assign(Object.assign({ mediaTypeContent, parameterValues: parameterValuesWithDefaults, httpOperation, bodyInput: formDataState.isFormDataBody ? bodyParameterValues : textRequestBody, auth: operationAuthValue }, (mockingOptions.isEnabled && { mockData: getMockData(mockUrl, httpOperation, mockingOptions) })), { chosenServer,
1738
+ buildHarRequest(Object.assign(Object.assign({ mediaTypeContent, parameterValues: parameterValuesWithDefaults, httpOperation, bodyInput: formDataState.isFormDataBody ? bodyParameterValues : textRequestBody, auth: operationAuthValue }, (isMockingEnabled && { mockData: getMockData(mockUrl, httpOperation, mockingOptions) })), { chosenServer,
1671
1739
  corsProxy })).then(request => {
1672
- if (onRequestChange && isActive)
1673
- onRequestChange(request);
1674
- if (embeddedInMd)
1675
- setRequestData(request);
1740
+ if (isMounted) {
1741
+ if (onRequestChange) {
1742
+ onRequestChange(request);
1743
+ }
1744
+ if (embeddedInMd) {
1745
+ setRequestData(request);
1746
+ }
1747
+ }
1676
1748
  });
1677
1749
  }
1678
1750
  return () => {
1679
- isActive = false;
1751
+ isMounted = false;
1680
1752
  };
1681
1753
  }, [
1682
1754
  httpOperation,
@@ -1690,13 +1762,13 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1690
1762
  corsProxy,
1691
1763
  embeddedInMd,
1692
1764
  ]);
1693
- const handleClick = () => __awaiter(void 0, void 0, void 0, function* () {
1765
+ const handleSendRequest = () => __awaiter(void 0, void 0, void 0, function* () {
1694
1766
  setValidateParameters(true);
1695
1767
  if (hasRequiredButEmptyParameters)
1696
1768
  return;
1697
1769
  try {
1698
1770
  setLoading(true);
1699
- const mockData = getMockData(mockUrl, httpOperation, mockingOptions);
1771
+ const mockData = isMockingEnabled ? getMockData(mockUrl, httpOperation, mockingOptions) : undefined;
1700
1772
  const request = yield buildFetchRequest({
1701
1773
  parameterValues: parameterValuesWithDefaults,
1702
1774
  httpOperation,
@@ -1733,29 +1805,32 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1733
1805
  setLoading(false);
1734
1806
  }
1735
1807
  });
1736
- const serversSelect = (React.createElement(Select, { "aria-label": "Servers", options: servers.map(server => ({ value: server.description || '' })), value: (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.description) || '', onChange: (value) => {
1737
- const server = servers.find(server => server.description === value);
1738
- setChosenServer(server);
1739
- } }));
1740
- const serverDescription = (React.createElement(Tooltip, { renderTrigger: React.createElement(Box, { ml: 2, mr: 1, flexShrink: 0 }, (_d = servers[0]) === null || _d === void 0 ? void 0 : _d.description) },
1741
- "Server Host: ", (_e = servers[0]) === null || _e === void 0 ? void 0 :
1742
- _e.url));
1808
+ const isOnlySendButton = !((_d = httpOperation.security) === null || _d === void 0 ? void 0 : _d.length) && !allParameters.length && !formDataState.isFormDataBody && !mediaTypeContent;
1809
+ const tryItPanelContents = (React.createElement(React.Fragment, null,
1810
+ ((_e = httpOperation.security) === null || _e === void 0 ? void 0 : _e.length) ? (React.createElement(TryItAuth, { onChange: setOperationAuthValue, operationSecurityScheme: (_f = httpOperation.security) !== null && _f !== void 0 ? _f : [], value: operationAuthValue })) : null,
1811
+ allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
1812
+ formDataState.isFormDataBody ? (React.createElement(FormDataBody, { specification: formDataState.bodySpecification, values: bodyParameterValues, onChangeValues: setBodyParameterValues })) : mediaTypeContent ? (React.createElement(RequestBody, { examples: (_g = mediaTypeContent.examples) !== null && _g !== void 0 ? _g : [], requestBody: textRequestBody, onChange: setTextRequestBody })) : null,
1813
+ React.createElement(Panel.Content, { className: "SendButtonHolder", mt: 4, pt: !isOnlySendButton && !embeddedInMd ? 0 : undefined },
1814
+ React.createElement(HStack, { alignItems: "center", spacing: 2 },
1815
+ React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleSendRequest, size: "sm" }, "Send API Request"),
1816
+ servers.length > 1 && React.createElement(ServersDropdown, { servers: servers }),
1817
+ isMockingEnabled && (React.createElement(MockingButton, { options: mockingOptions, onOptionsChange: setMockingOptions, operation: httpOperation }))),
1818
+ validateParameters && hasRequiredButEmptyParameters && (React.createElement(Box, { mt: 4, color: "danger-light", fontSize: "sm" },
1819
+ React.createElement(Icon, { icon: faExclamationTriangle, className: "sl-mr-1" }),
1820
+ "You didn't provide all of the required parameters!")))));
1821
+ let tryItPanelElem;
1822
+ if (embeddedInMd) {
1823
+ tryItPanelElem = (React.createElement(Panel, { isCollapsible: false, p: 0, className: "TryItPanel" },
1824
+ React.createElement(Panel.Titlebar, { bg: "canvas-300" },
1825
+ React.createElement(Box, { fontWeight: "bold", color: !isDark ? HttpMethodColors[httpOperation.method] : undefined }, httpOperation.method.toUpperCase()),
1826
+ React.createElement(Box, { fontWeight: "medium", ml: 2, textOverflow: "truncate", overflowX: "hidden" }, `${(chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || ''}${httpOperation.path}`)),
1827
+ tryItPanelContents));
1828
+ }
1829
+ else {
1830
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
1831
+ }
1743
1832
  return (React.createElement(Box, { rounded: "lg", overflowY: "hidden" },
1744
- React.createElement(Panel, { isCollapsible: false, p: 0, className: "TryItPanel" },
1745
- React.createElement(Panel.Titlebar, { rightComponent: servers.length > 1 ? serversSelect : serverDescription, bg: "canvas-300" },
1746
- React.createElement("div", { role: "heading", className: "sl-font-bold" },
1747
- React.createElement(Text, { color: !isDark ? HttpMethodColors[httpOperation.method] : undefined }, httpOperation.method.toUpperCase()),
1748
- React.createElement(Text, { ml: 2 }, httpOperation.path))),
1749
- React.createElement(TryItAuth, { onChange: setOperationAuthValue, operationSecurityScheme: (_f = httpOperation.security) !== null && _f !== void 0 ? _f : [], value: operationAuthValue }),
1750
- allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
1751
- formDataState.isFormDataBody ? (React.createElement(FormDataBody, { specification: formDataState.bodySpecification, values: bodyParameterValues, onChangeValues: setBodyParameterValues })) : mediaTypeContent ? (React.createElement(RequestBody, { examples: (_g = mediaTypeContent.examples) !== null && _g !== void 0 ? _g : [], requestBody: textRequestBody, onChange: setTextRequestBody })) : null,
1752
- React.createElement(Panel.Content, { className: "SendButtonHolder" },
1753
- React.createElement(Flex, { alignItems: "center" },
1754
- React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleClick, size: "sm" }, "Send Request"),
1755
- mockUrl && (React.createElement(MockingButton, { options: mockingOptions, onOptionsChange: setMockingOptions, operation: httpOperation }))),
1756
- validateParameters && hasRequiredButEmptyParameters && (React.createElement(Box, { mt: 4, color: "danger-light", fontSize: "sm" },
1757
- React.createElement(Icon, { icon: faExclamationTriangle, className: "sl-mr-1" }),
1758
- "You didn't provide all of the required parameters!")))),
1833
+ tryItPanelElem,
1759
1834
  requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
1760
1835
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
1761
1836
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
@@ -1792,7 +1867,9 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
1792
1867
  const examplesSelect = userDefinedExamples && userDefinedExamples.length > 1 && (React__default.createElement(Select, { "aria-label": "Response Example", value: String(chosenExampleIndex), options: userDefinedExamples.map((example, index) => ({ value: index, label: example.key })), onChange: (value) => setChosenExampleIndex(parseInt(String(value), 10)), size: "sm", triggerTextPrefix: "Response Example: " }));
1793
1868
  return (React__default.createElement(Panel, { rounded: true, isCollapsible: false },
1794
1869
  React__default.createElement(Panel.Titlebar, null, examplesSelect || React__default.createElement(Text, { color: "body" }, "Response Example")),
1795
- React__default.createElement(Panel.Content, { p: 0 }, show || !exceedsSize(responseExample) ? (React__default.createElement(CodeViewer, { "aria-label": responseExample, noCopyButton: true, maxHeight: "400px", language: "json", value: responseExample, showLineNumbers: true })) : (React__default.createElement(LoadMore, { loading: loading, onClick: handleLoadMore })))));
1870
+ React__default.createElement(Panel.Content, { p: 0 }, show || !exceedsSize(responseExample) ? (React__default.createElement(CodeViewer, { "aria-label": responseExample, noCopyButton: true, maxHeight: "500px", language: "json", value: responseExample, showLineNumbers: true, style: {
1871
+ '--fs-code': 12,
1872
+ } })) : (React__default.createElement(LoadMore, { loading: loading, onClick: handleLoadMore })))));
1796
1873
  };
1797
1874
 
1798
1875
  const TryItWithRequestSamples = (_a) => {
@@ -1806,21 +1883,16 @@ const TryItWithRequestSamples = (_a) => {
1806
1883
  React.createElement(ResponseExamples, Object.assign({}, props))));
1807
1884
  };
1808
1885
 
1809
- const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(Box, { w: "full", className: className },
1886
+ const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(VStack, { w: "full", className: className, spacing: 8 },
1810
1887
  header,
1811
- React__default.createElement(Flex, { mt: header ? 12 : undefined },
1812
- React__default.createElement(Box, { style: { width: 0 }, flex: 1 }, left),
1888
+ React__default.createElement(Flex, null,
1889
+ React__default.createElement(Box, { w: 0, flex: 1 }, left),
1813
1890
  right && (React__default.createElement(Box, { ml: 16, pos: "relative", w: "2/5", style: { maxWidth: 500 } }, right)))));
1814
1891
 
1815
1892
  const DeprecatedBadge = () => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { intent: "warning", icon: faExclamationCircle, "data-testid": "badge-deprecated" }, "Deprecated") }, "This operation has been marked as deprecated, which means it could be removed at some point in the future."));
1816
- const InternalBadge = ({ isHttpService }) => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { icon: faEye, "data-testid": "badge-internal", className: "sl-bg-danger sl-ml-0" }, "Internal") }, `This ${isHttpService ? 'operation' : 'model'} is marked as internal and won't be visible in public docs.`));
1817
- const SecurityBadge = ({ scheme, httpServiceUri, includeKey }) => {
1818
- const badge = (React__default.createElement(Badge, { icon: faLock, "data-testid": "badge-security", className: "sl-truncate", style: { backgroundColor: badgeDefaultBackgroundColor, color: badgeDefaultColor } }, getReadableSecurityName(scheme, includeKey)));
1819
- return httpServiceUri ? (React__default.createElement(Link$1, { to: `${httpServiceUri}?security=${scheme.key}`, className: "sl-no-underline sl-block" }, badge)) : (badge);
1820
- };
1821
- const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", style: {
1893
+ const InternalBadge = ({ isHttpService }) => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { icon: faEye, "data-testid": "badge-internal", bg: "danger" }, "Internal") }, `This ${isHttpService ? 'operation' : 'model'} is marked as internal and won't be visible in public docs.`));
1894
+ const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", border: 0, style: {
1822
1895
  backgroundColor: backgroundColor || badgeDefaultBackgroundColor,
1823
- border: 'none',
1824
1896
  color: badgeDefaultColor,
1825
1897
  } }, enhanceVersionString(value)));
1826
1898
  const enhanceVersionString = (version) => {
@@ -1829,32 +1901,112 @@ const enhanceVersionString = (version) => {
1829
1901
  return `v${version}`;
1830
1902
  };
1831
1903
 
1832
- const SectionTitle = ({ title, children }) => {
1833
- return (React.createElement(Flex, { role: "heading", borderB: true, mb: 3, pb: 3, "aria-label": title, align: "baseline" },
1834
- React.createElement(Text, { size: "xl", fontWeight: "semibold", mr: 5 }, title),
1904
+ const oauthFlowNames = {
1905
+ implicit: 'Implicit',
1906
+ authorizationCode: 'Authorization Code',
1907
+ clientCredentials: 'Client Credentials',
1908
+ password: 'Password',
1909
+ };
1910
+ function getDefaultDescription(scheme) {
1911
+ switch (scheme.type) {
1912
+ case 'apiKey':
1913
+ return getApiKeyDescription(scheme.in, scheme.name);
1914
+ case 'http':
1915
+ switch (scheme.scheme) {
1916
+ case 'basic':
1917
+ return getBasicAuthDescription();
1918
+ case 'bearer':
1919
+ return getBearerAuthDescription();
1920
+ case 'digest':
1921
+ return getDigestAuthDescription();
1922
+ }
1923
+ case 'oauth2':
1924
+ return getOAuthDescription(scheme);
1925
+ }
1926
+ return '';
1927
+ }
1928
+ function getApiKeyDescription(inProperty, name) {
1929
+ return `An API key is a token that you provide when making API calls. Include the token in a ${inProperty} parameter called \`${name}\`.
1930
+
1931
+ Example: ${inProperty === 'query' ? `\`?${name}=123\`` : `\`${name}: 123\``}`;
1932
+ }
1933
+ function getBasicAuthDescription() {
1934
+ return `Basic authentication is a simple authentication scheme built into the HTTP protocol.
1935
+ To use it, send your HTTP requests with an Authorization header that contains the word Basic
1936
+ followed by a space and a base64-encoded string \`username:password\`.
1937
+
1938
+ Example: \`Authorization: Basic ZGVtbzpwQDU1dzByZA==\``;
1939
+ }
1940
+ function getBearerAuthDescription() {
1941
+ return `Provide your bearer token in the Authorization header when making requests to protected resources.
1942
+
1943
+ Example: \`Authorization: Bearer 123\``;
1944
+ }
1945
+ function getDigestAuthDescription() {
1946
+ return `Provide your encrypted digest scheme data in the Authorization header when making requests to protected resources.
1947
+
1948
+ Example: \`Authorization: Digest username=guest, realm="test", nonce="2", uri="/uri", response="123"\``;
1949
+ }
1950
+ function getOAuthDescription(scheme) {
1951
+ const flows = keys(scheme.flows);
1952
+ return flows.map(flow => getOAuthFlowDescription(oauthFlowNames[flow], scheme.flows[flow])).join('\n\n');
1953
+ }
1954
+ function getOAuthFlowDescription(title, flow) {
1955
+ let description = `**${title} OAuth Flow**`;
1956
+ description +=
1957
+ isOAuth2ImplicitFlow(flow) || isOauth2AuthorizationCodeFlow(flow)
1958
+ ? `\n\nAuthorize URL: ${flow.authorizationUrl}`
1959
+ : '';
1960
+ description +=
1961
+ isOauth2AuthorizationCodeFlow(flow) || isOauth2ClientCredentialsOrPasswordFlow(flow)
1962
+ ? `\n\nToken URL: ${flow.tokenUrl}`
1963
+ : '';
1964
+ description += flow.refreshUrl ? `\n\nRefresh URL: ${flow.refreshUrl}` : '';
1965
+ const scopes = entries(flow.scopes);
1966
+ if (scopes.length) {
1967
+ description += `\n\nScopes:
1968
+ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
1969
+ }
1970
+ return description;
1971
+ }
1972
+
1973
+ const SectionTitle = ({ title, id, size = 2, children }) => {
1974
+ return (React.createElement(HStack, { spacing: 6 },
1975
+ React.createElement(Box, { as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
1835
1976
  children));
1836
1977
  };
1837
- const SubSectionPanel = ({ title, children, hasContent, rightComponent }) => {
1838
- return (React.createElement(Panel, { appearance: "minimal", isCollapsible: hasContent, defaultIsOpen: true },
1978
+ const SectionSubtitle = props => {
1979
+ return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
1980
+ };
1981
+ const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
1982
+ return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
1839
1983
  React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
1840
1984
  React.createElement("div", { role: "heading" }, title)),
1841
- hasContent !== false && (React.createElement(Panel.Content, { pr: 3, className: "sl-py-0 sl-pl-0" }, children))));
1985
+ hasContent !== false && React.createElement(Panel.Content, null, children)));
1842
1986
  };
1843
1987
 
1844
- const Body = ({ body: { contents = [], description }, onChange }) => {
1988
+ const isBodyEmpty = (body) => {
1989
+ if (!body)
1990
+ return true;
1991
+ const { contents = [], description } = body;
1992
+ return contents.length === 0 && !(description === null || description === void 0 ? void 0 : description.trim());
1993
+ };
1994
+ const Body = ({ body, onChange }) => {
1845
1995
  var _a;
1846
1996
  const refResolver = useInlineRefResolver();
1847
1997
  const [chosenContent, setChosenContent] = React.useState(0);
1848
1998
  React.useEffect(() => {
1849
1999
  onChange(chosenContent);
1850
2000
  }, [chosenContent]);
1851
- if (contents.length === 0 && !description)
2001
+ if (isBodyEmpty(body))
1852
2002
  return null;
2003
+ const { contents = [], description } = body;
1853
2004
  const schema = (_a = contents[chosenContent]) === null || _a === void 0 ? void 0 : _a.schema;
1854
- return (React.createElement(SubSectionPanel, { title: "Body", rightComponent: contents.length > 0 && (React.createElement(Select, { "aria-label": "Request Body Content Type", value: String(chosenContent), onChange: (value) => setChosenContent(parseInt(String(value), 10)), options: contents.map((content, index) => ({ label: content.mediaType, value: index })), size: "sm" })) },
1855
- description && React.createElement(MarkdownViewer, { className: "sl-my-2", markdown: description }),
1856
- isJSONSchema(schema) && (React.createElement(Box, null,
1857
- React.createElement(JsonSchemaViewer, { resolveRef: refResolver, schema: getOriginalObject(schema), viewMode: "write", hideExamples: true })))));
2005
+ return (React.createElement(VStack, { spacing: 6 },
2006
+ React.createElement(SectionSubtitle, { title: "Body", id: "request-body" }, contents.length > 0 && (React.createElement(Flex, { flex: 1, justify: "end" },
2007
+ React.createElement(Select, { "aria-label": "Request Body Content Type", value: String(chosenContent), onChange: (value) => setChosenContent(parseInt(String(value), 10)), options: contents.map((content, index) => ({ label: content.mediaType, value: index })), size: "sm" })))),
2008
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2009
+ isJSONSchema(schema) && (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, schema: getOriginalObject(schema), viewMode: "write", hideExamples: true, renderRootTreeLines: true }))));
1858
2010
  };
1859
2011
  Body.displayName = 'HttpOperation.Body';
1860
2012
 
@@ -1878,68 +2030,81 @@ const defaultStyle = {
1878
2030
  cookie: HttpParamStyles.Form,
1879
2031
  };
1880
2032
  const Parameters = ({ parameters, parameterType }) => {
1881
- if (!parameters || !parameters.length)
2033
+ const schema = React.useMemo(() => httpOperationParamsToSchema({ parameters, parameterType }), [parameters, parameterType]);
2034
+ if (!schema)
1882
2035
  return null;
1883
- return (React.createElement(VStack, { spacing: 2, pl: 6, divider: React.createElement(Box, { borderT: true, borderColor: "light", w: "full" }) }, sortBy(parameters, ['required', 'name']).map(parameter => {
1884
- return React.createElement(Parameter, { key: parameter.name, parameter: parameter, parameterType: parameterType });
1885
- })));
2036
+ return React.createElement(JsonSchemaViewer, { schema: schema, disableCrumbs: true });
1886
2037
  };
1887
2038
  Parameters.displayName = 'HttpOperation.Parameters';
1888
- const Parameter = ({ parameter, parameterType }) => {
1889
- var _a, _b, _c, _d, _e;
1890
- if (!parameter)
2039
+ const httpOperationParamsToSchema = ({ parameters, parameterType }) => {
2040
+ var _a;
2041
+ if (!parameters || !parameters.length)
1891
2042
  return null;
1892
- const description = get(parameter, 'description') || get(parameter, 'schema.description');
1893
- const rootType = get(parameter, 'schema.type', 'unknown');
1894
- const type = ((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b['type']) && rootType === 'array' ? `array[${parameter.schema.items['type']}]` : rootType;
1895
- const format = (_c = parameter.schema) === null || _c === void 0 ? void 0 : _c.format;
1896
- const deprecated = get(parameter, 'deprecated') || get(parameter, 'schema.deprecated', false);
1897
- const parameterExamples = ((_d = parameter.examples) === null || _d === void 0 ? void 0 : _d.map(example => {
1898
- if (isNodeExample(example)) {
1899
- return example.value;
2043
+ const schema = {
2044
+ properties: {},
2045
+ required: [],
2046
+ };
2047
+ const sortedParams = sortBy(parameters, ['required', 'name']);
2048
+ for (const p of sortedParams) {
2049
+ if (!p.schema)
2050
+ continue;
2051
+ const { name, description, required, deprecated, examples, style } = p;
2052
+ const paramExamples = (examples === null || examples === void 0 ? void 0 : examples.map(example => {
2053
+ if (isNodeExample(example)) {
2054
+ return example.value;
2055
+ }
2056
+ return example.externalValue;
2057
+ })) || [];
2058
+ const schemaExamples = (_a = p.schema) === null || _a === void 0 ? void 0 : _a.examples;
2059
+ const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
2060
+ const paramDescription = description || p.schema.description;
2061
+ const paramDeprecated = deprecated || p.schema.deprecated;
2062
+ const paramStyle = style && defaultStyle[parameterType] !== style ? readableStyles[style] || style : undefined;
2063
+ schema.properties[p.name] = Object.assign(Object.assign({}, p.schema), { description: paramDescription, examples: [...paramExamples, ...schemaExamplesArray], deprecated: paramDeprecated, style: paramStyle });
2064
+ if (required) {
2065
+ schema.required.push(name);
1900
2066
  }
1901
- return example.externalValue;
1902
- })) || [];
1903
- const schemaExamples = (_e = parameter.schema) === null || _e === void 0 ? void 0 : _e.examples;
1904
- const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
1905
- const validations = omitBy(Object.assign(Object.assign(Object.assign(Object.assign({}, omit(parameter, ['name', 'required', 'deprecated', 'description', 'schema', 'style', 'examples'])), omit(get(parameter, 'schema'), ['description', 'type', 'deprecated'])), omit(get(parameter, 'schema.items'), ['description', 'type', 'deprecated'])), { examples: [...parameterExamples, ...schemaExamplesArray] }), value => (typeof value === 'object' && isEmpty(value)) || typeof value === 'undefined');
1906
- return (React.createElement("div", { className: "HttpOperation__Parameters" },
1907
- React.createElement("div", { className: "sl-flex sl-items-center sl-my-2" },
1908
- React.createElement("div", { className: "sl-flex sl-items-baseline sl-text-base sl-flex-1" },
1909
- React.createElement("div", { className: "sl-font-mono sl-font-bold" }, parameter.name),
1910
- React.createElement("div", { className: 'sl-ml-2 sl-text-muted' }, format ? `${type}<${format}>` : type)),
1911
- React.createElement("div", { className: "sl-text-sm sl-text-warning" },
1912
- deprecated && React.createElement("span", { className: "sl-ml-2" }, "deprecated"),
1913
- parameter.required && React.createElement("span", { className: "sl-ml-2" }, "required"))),
1914
- description && (React.createElement("div", { className: "sl-w-full sl-text-muted sl-text-sm sl-my-2" },
1915
- React.createElement(MarkdownViewer$1, { markdown: description }))),
1916
- React.createElement("div", { className: "sl-text-sm" },
1917
- React.createElement(Validations, { validations: validations })),
1918
- parameter.style && defaultStyle[parameterType] !== parameter.style && (React.createElement("div", { className: "sl-flex sl-my-2" },
1919
- React.createElement("span", { className: "sl-px-1 sl-text-muted sl-font-mono sl-border sl-rounded-lg sl-text-sm sl-capitalize", style: { backgroundColor: '#EDF2F7' } }, readableStyles[parameter.style] || parameter.style)))));
1920
- };
1921
- Parameter.displayName = 'HttpOperation.Parameter';
2067
+ }
2068
+ return schema;
2069
+ };
1922
2070
 
1923
- const Request = ({ operation: { path, method, request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
2071
+ const Request = ({ operation: { request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
1924
2072
  if (!request || typeof request !== 'object')
1925
2073
  return null;
1926
- const pathParamBlock = (React.createElement("div", null,
1927
- React.createElement(Text, { textTransform: "uppercase", mr: 1, color: HttpMethodColors[method] }, method),
1928
- ' ',
1929
- path));
1930
- return (React.createElement(Box, { mb: 10 },
2074
+ const bodyIsEmpty = isBodyEmpty(body);
2075
+ const securitySchemes = flatten(security);
2076
+ const hasRequestData = Boolean(securitySchemes.length ||
2077
+ pathParams.length ||
2078
+ queryParams.length ||
2079
+ headerParams.length ||
2080
+ cookieParams.length ||
2081
+ !bodyIsEmpty);
2082
+ if (!hasRequestData)
2083
+ return null;
2084
+ return (React.createElement(VStack, { spacing: 8 },
1931
2085
  React.createElement(SectionTitle, { title: "Request" }),
1932
- React.createElement(SubSectionPanel, { title: pathParamBlock, hasContent: pathParams.length > 0 },
1933
- React.createElement(Parameters, { parameterType: "path", parameters: pathParams })),
1934
- queryParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Query" },
2086
+ securitySchemes.length > 0 && (React.createElement(VStack, { spacing: 3 }, securitySchemes.map((scheme, i) => (React.createElement(SecurityPanel, { key: i, scheme: scheme, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))))),
2087
+ pathParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2088
+ React.createElement(SectionSubtitle, { title: "Path Parameters" }),
2089
+ React.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
2090
+ queryParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2091
+ React.createElement(SectionSubtitle, { title: "Query Parameters" }),
1935
2092
  React.createElement(Parameters, { parameterType: "query", parameters: queryParams }))),
1936
- headerParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Headers" },
2093
+ headerParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2094
+ React.createElement(SectionSubtitle, { title: "Headers", id: "request-headers" }),
1937
2095
  React.createElement(Parameters, { parameterType: "header", parameters: headerParams }))),
1938
- cookieParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Cookie" },
2096
+ cookieParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2097
+ React.createElement(SectionSubtitle, { title: "Cookies", id: "request-cookies" }),
1939
2098
  React.createElement(Parameters, { parameterType: "cookie", parameters: cookieParams }))),
1940
2099
  body && React.createElement(Body, { onChange: onChange, body: body })));
1941
2100
  };
1942
- Request.displayName = 'HttpOperation.Request';
2101
+ Request.displayName = 'HttpOperation.Request';
2102
+ const schemeExpandedState = atomWithStorage('HttpOperation_security_expanded', {});
2103
+ const SecurityPanel = ({ scheme, includeKey }) => {
2104
+ const [expandedState, setExpanded] = useAtom(schemeExpandedState);
2105
+ return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityName(scheme, includeKey)}`, defaultIsOpen: !!expandedState[scheme.key], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [scheme.key]: isOpen })) },
2106
+ React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })));
2107
+ };
1943
2108
 
1944
2109
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }) => {
1945
2110
  var _a, _b;
@@ -1950,15 +2115,15 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
1950
2115
  }, [activeResponseId]);
1951
2116
  if (!responses.length)
1952
2117
  return null;
1953
- return (React.createElement(Tabs, { selectedId: activeResponseId, onChange: setActiveResponseId },
1954
- React.createElement(Box, null,
1955
- React.createElement(SectionTitle, { title: "Responses" },
1956
- React.createElement(TabList, null, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code }, code))))),
1957
- React.createElement(Box, { as: TabPanels, mt: 4 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
1958
- React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2118
+ return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2119
+ React.createElement(SectionTitle, { title: "Responses" },
2120
+ React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2121
+ React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2122
+ React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
1959
2123
  };
1960
2124
  Responses.displayName = 'HttpOperation.Responses';
1961
- const Response = ({ response: { contents = [], headers = [], description }, onMediaTypeChange }) => {
2125
+ const Response = ({ response, onMediaTypeChange }) => {
2126
+ const { contents = [], headers = [], description } = response;
1962
2127
  const [chosenContent, setChosenContent] = React.useState(0);
1963
2128
  const refResolver = useInlineRefResolver();
1964
2129
  const responseContent = contents[chosenContent];
@@ -1966,16 +2131,33 @@ const Response = ({ response: { contents = [], headers = [], description }, onMe
1966
2131
  React.useEffect(() => {
1967
2132
  responseContent && onMediaTypeChange(responseContent.mediaType);
1968
2133
  }, [responseContent]);
1969
- return (React.createElement(Box, null,
1970
- description && React.createElement(MarkdownViewer, { className: "sl-ml-1 sl-mb-6", markdown: description }),
1971
- headers.length > 0 && (React.createElement(SubSectionPanel, { title: "Headers" },
2134
+ return (React.createElement(VStack, { spacing: 8, pt: 8 },
2135
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2136
+ headers.length > 0 && (React.createElement(VStack, { spacing: 5 },
2137
+ React.createElement(SectionSubtitle, { title: "Headers", id: "response-headers" }),
1972
2138
  React.createElement(Parameters, { parameterType: "header", parameters: headers }))),
1973
- contents.length > 0 && (React.createElement(SubSectionPanel, { title: "Body", rightComponent: React.createElement(Select, { "aria-label": "Response Body Content Type", value: String(chosenContent), onChange: (value) => setChosenContent(parseInt(String(value), 10)), options: contents.map((content, index) => ({ label: content.mediaType, value: index })), size: "sm" }) }, schema && (React.createElement(Box, null,
1974
- React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, viewMode: "read", hideExamples: true })))))));
2139
+ contents.length > 0 && (React.createElement(React.Fragment, null,
2140
+ React.createElement(SectionSubtitle, { title: "Body", id: "response-body" },
2141
+ React.createElement(Flex, { flex: 1, justify: "end" },
2142
+ React.createElement(Select, { "aria-label": "Response Body Content Type", value: String(chosenContent), onChange: (value) => setChosenContent(parseInt(String(value), 10)), options: contents.map((content, index) => ({ label: content.mediaType, value: index })), size: "sm" }))),
2143
+ schema && (React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, viewMode: "read", hideExamples: true, parentCrumbs: ['responses', response.code], renderRootTreeLines: true }))))));
1975
2144
  };
1976
- Response.displayName = 'HttpOperation.Response';
2145
+ Response.displayName = 'HttpOperation.Response';
2146
+ const codeToIntentVal = (code) => {
2147
+ const firstChar = code.charAt(0);
2148
+ switch (firstChar) {
2149
+ case '2':
2150
+ return 'success';
2151
+ case '4':
2152
+ return 'warning';
2153
+ case '5':
2154
+ return 'danger';
2155
+ default:
2156
+ return 'default';
2157
+ }
2158
+ };
1977
2159
 
1978
- const HttpOperationComponent = React.memo(({ className, data: unresolvedData, uri, allowRouting = false, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy, }) => {
2160
+ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
1979
2161
  const data = useResolvedObject(unresolvedData);
1980
2162
  const mocking = React.useContext(MockingContext);
1981
2163
  const isDeprecated = !!data.deprecated;
@@ -1983,32 +2165,50 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, ur
1983
2165
  const [responseMediaType, setResponseMediaType] = React.useState('');
1984
2166
  const [responseStatusCode, setResponseStatusCode] = React.useState('');
1985
2167
  const [requestBodyIndex, setTextRequestBodyIndex] = React.useState(0);
1986
- const httpServiceUri = uri && getServiceUriFromOperation(uri);
1987
- const securitySchemes = flatten(data.security);
1988
- const hasBadges = isDeprecated || securitySchemes.length > 0 || isInternal;
1989
- const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(React.Fragment, null,
1990
- !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && (React.createElement(Heading$1, { size: 1, mb: 4, fontWeight: "semibold" }, data.summary || data.iid || `${data.method} ${data.path}`)),
1991
- hasBadges && (React.createElement(HStack, { spacing: 2 },
1992
- isDeprecated && React.createElement(DeprecatedBadge, null),
1993
- sortBy(securitySchemes, 'type').map((scheme, i) => (React.createElement(SecurityBadge, { key: i, scheme: scheme, httpServiceUri: allowRouting ? httpServiceUri : undefined, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))),
1994
- isInternal && React.createElement(InternalBadge, { isHttpService: true })))));
1995
- const description = (React.createElement(React.Fragment, null,
1996
- data.description && (React.createElement(MarkdownViewer, { className: "HttpOperation__Description sl-mb-10", markdown: data.description })),
2168
+ const prettyName = (data.summary || data.iid || '').trim();
2169
+ const hasBadges = isDeprecated || isInternal;
2170
+ const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(VStack, { spacing: 5 },
2171
+ React.createElement(HStack, { spacing: 5 },
2172
+ !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && prettyName ? (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, prettyName)) : null,
2173
+ React.createElement(HStack, { spacing: 2 },
2174
+ isDeprecated && React.createElement(DeprecatedBadge, null),
2175
+ isInternal && React.createElement(InternalBadge, { isHttpService: true }))),
2176
+ React.createElement(MethodPath, { method: data.method, path: data.path })));
2177
+ const description = (React.createElement(VStack, { spacing: 10 },
2178
+ data.description && React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
1997
2179
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
1998
2180
  data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
1999
- const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React.createElement(Box, { className: "HttpOperation__gutter" },
2000
- React.createElement(TryItWithRequestSamples, { httpOperation: data, responseMediaType: responseMediaType, responseStatusCode: responseStatusCode, requestBodyIndex: requestBodyIndex, hideTryIt: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryIt, tryItCredentialsPolicy: tryItCredentialsPolicy, mockUrl: mocking.hideMocking ? undefined : mocking.mockUrl, corsProxy: tryItCorsProxy })));
2181
+ const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React.createElement(TryItWithRequestSamples, { httpOperation: data, responseMediaType: responseMediaType, responseStatusCode: responseStatusCode, requestBodyIndex: requestBodyIndex, hideTryIt: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryIt, tryItCredentialsPolicy: tryItCredentialsPolicy, mockUrl: mocking.hideMocking ? undefined : mocking.mockUrl, corsProxy: tryItCorsProxy }));
2001
2182
  return (React.createElement(TwoColumnLayout, { className: cn('HttpOperation', className), header: header, left: description, right: tryItPanel }));
2002
2183
  });
2003
2184
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2004
2185
  const HttpOperation = withErrorBoundary(HttpOperationComponent, {
2005
2186
  recoverableProps: ['data'],
2006
- });
2187
+ });
2188
+ function MethodPath({ method, path }) {
2189
+ const chosenServer = useAtomValue(chosenServerAtom);
2190
+ let chosenServerUrl = '';
2191
+ if (chosenServer) {
2192
+ chosenServerUrl = chosenServer.url.endsWith('/') ? chosenServer.url.slice(0, -1) : chosenServer.url;
2193
+ }
2194
+ return (React.createElement(Box, null,
2195
+ React.createElement(MethodPathInner, { method: method, path: path, chosenServerUrl: chosenServerUrl })));
2196
+ }
2197
+ function MethodPathInner({ method, path, chosenServerUrl }) {
2198
+ const isDark = useThemeIsDark();
2199
+ const fullUrl = `${chosenServerUrl}${path}`;
2200
+ const pathElem = (React.createElement(Flex, { overflowX: "hidden" },
2201
+ chosenServerUrl ? (React.createElement(Box, { dir: "rtl", color: "muted", fontSize: "lg", textOverflow: "truncate", overflowX: "hidden" }, chosenServerUrl)) : null,
2202
+ React.createElement(Box, { fontSize: "lg", fontWeight: "semibold", flex: 1 }, path)));
2203
+ return (React.createElement(HStack, { spacing: 3, pl: 2.5, pr: 4, py: 2, bg: "canvas-50", rounded: "lg", fontFamily: "mono", display: "inline-flex", maxW: "full", title: fullUrl },
2204
+ React.createElement(Box, { py: 1, px: 2.5, rounded: "lg", bg: !isDark ? HttpMethodColors[method] : 'canvas-100', color: !isDark ? 'on-primary' : 'body', fontSize: "lg", fontWeight: "semibold", textTransform: "uppercase" }, method),
2205
+ pathElem));
2206
+ }
2007
2207
 
2008
2208
  const PoweredByLink = ({ source, pathname, packageType, layout = 'sidebar' }) => {
2009
2209
  return (React.createElement(Flex, { as: "a", align: "center", borderT: layout === 'stacked' ? undefined : true, px: layout === 'stacked' ? 1 : 4, py: 3, justify: layout === 'stacked' ? 'end' : undefined, href: `https://stoplight.io/?utm_source=${packageType}&utm_medium=${source}&utm_campaign=powered_by&utm_content=${pathname}`, target: "_blank", rel: "noopener noreferrer" },
2010
- React.createElement(FontAwesomeIcon, { icon: faBolt, className: "sl-mr-1 fa-fw", style: { color: 'rgba(144, 97, 249, 1)' } }),
2011
- React.createElement("div", null,
2210
+ React.createElement(Box, { as: Icon, icon: faBolt, mr: 1, className: "fa-fw", style: { color: 'rgba(144, 97, 249, 1)' } }),
2211
+ React.createElement(Box, null,
2012
2212
  "powered by\u00A0",
2013
2213
  React.createElement("strong", null, "Stoplight"))));
2014
2214
  };
@@ -2039,91 +2239,28 @@ const ExportButton = ({ original, bundled }) => {
2039
2239
  return items;
2040
2240
  }, [original, bundled]);
2041
2241
  return (React.createElement(Box, null,
2042
- React.createElement(Menu, { "aria-label": "Export", items: menuItems, renderTrigger: ({ isOpen }) => (React.createElement(Button, { iconRight: "chevron-down", appearance: "default", ml: 2, active: isOpen, size: "sm" }, "Export")) })));
2242
+ React.createElement(Menu, { "aria-label": "Export", items: menuItems, placement: "bottom right", renderTrigger: ({ isOpen }) => (React.createElement(Button, { iconRight: "chevron-down", appearance: "default", ml: 2, active: isOpen, size: "sm" }, "Export")) })));
2043
2243
  };
2044
2244
 
2045
- const oauthFlowNames = {
2046
- implicit: 'Implicit',
2047
- authorizationCode: 'Authorization Code',
2048
- clientCredentials: 'Client Credentials',
2049
- password: 'Password',
2050
- };
2051
- const SecuritySchemes = ({ schemes, defaultScheme }) => {
2052
- return (React__default.createElement(Panel, { rounded: true, isCollapsible: false },
2245
+ const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2246
+ return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed },
2053
2247
  React__default.createElement(Panel.Titlebar, { bg: "canvas-300" },
2054
- React__default.createElement("span", { role: "heading" }, "Security")),
2055
- React__default.createElement(Panel.Content, { p: 0 }, sortBy(schemes, 'type').map((scheme, i) => (React__default.createElement(Panel, { key: i, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1 },
2056
- React__default.createElement(Panel.Titlebar, null,
2057
- React__default.createElement("span", { role: "heading" }, getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)))),
2058
- React__default.createElement(Panel.Content, null,
2059
- React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) }))))))));
2248
+ React__default.createElement(Box, { as: "span", role: "heading" }, "Security")),
2249
+ React__default.createElement(Panel.Content, { p: 0 }, sortBy(schemes, 'type').map((scheme, i) => (React__default.createElement(SecurityScheme, { key: i, scheme: scheme, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1, showSchemeKey: shouldIncludeKey(schemes, scheme.type) }))))));
2060
2250
  };
2061
- function getDefaultDescription(scheme) {
2062
- switch (scheme.type) {
2063
- case 'apiKey':
2064
- return getApiKeyDescription(scheme.in, scheme.name);
2065
- case 'http':
2066
- switch (scheme.scheme) {
2067
- case 'basic':
2068
- return getBasicAuthDescription();
2069
- case 'bearer':
2070
- return getBearerAuthDescription();
2071
- case 'digest':
2072
- return getDigestAuthDescription();
2073
- }
2074
- case 'oauth2':
2075
- return getOAuthDescription(scheme);
2076
- }
2077
- return '';
2078
- }
2079
- function getApiKeyDescription(inProperty, name) {
2080
- return `An API key is a token that you provide when making API calls. Include the token in a ${inProperty} parameter called \`${name}\`.
2081
-
2082
- Example: ${inProperty === 'query' ? `\`?${name}=123\`` : `\`${name}: 123\``}`;
2083
- }
2084
- function getBasicAuthDescription() {
2085
- return `Basic authentication is a simple authentication scheme built into the HTTP protocol.
2086
- To use it, send your HTTP requests with an Authorization header that contains the word Basic
2087
- followed by a space and a base64-encoded string \`username:password\`.
2088
-
2089
- Example: \`Authorization: Basic ZGVtbzpwQDU1dzByZA==\``;
2090
- }
2091
- function getBearerAuthDescription() {
2092
- return `Provide your bearer token in the Authorization header when making requests to protected resources.
2093
-
2094
- Example: \`Authorization: Bearer 123\``;
2095
- }
2096
- function getDigestAuthDescription() {
2097
- return `Provide your encrypted digest scheme data in the Authorization header when making requests to protected resources.
2098
-
2099
- Example: \`Authorization: Digest username=guest, realm="test", nonce="2", uri="/uri", response="123"\``;
2100
- }
2101
- function getOAuthDescription(scheme) {
2102
- const flows = keys(scheme.flows);
2103
- return flows.map(flow => getOAuthFlowDescription(oauthFlowNames[flow], scheme.flows[flow])).join('\n\n');
2104
- }
2105
- function getOAuthFlowDescription(title, flow) {
2106
- let description = `**${title} OAuth Flow**`;
2107
- description +=
2108
- isOAuth2ImplicitFlow(flow) || isOauth2AuthorizationCodeFlow(flow)
2109
- ? `\n\nAuthorize URL: ${flow.authorizationUrl}`
2110
- : '';
2111
- description +=
2112
- isOauth2AuthorizationCodeFlow(flow) || isOauth2ClientCredentialsOrPasswordFlow(flow)
2113
- ? `\n\nToken URL: ${flow.tokenUrl}`
2114
- : '';
2115
- description += flow.refreshUrl ? `\n\nRefresh URL: ${flow.refreshUrl}` : '';
2116
- description += `\n\nScopes:
2117
- ${entries(flow.scopes)
2118
- .map(([key, value]) => `- \`${key}\` - ${value}`)
2119
- .join('\n')}`;
2120
- return description;
2121
- }
2251
+ const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2252
+ return (React__default.createElement(Panel, { defaultIsOpen: defaultIsOpen, isCollapsible: isCollapsible },
2253
+ React__default.createElement(Panel.Titlebar, null,
2254
+ React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityName(scheme, showSchemeKey))),
2255
+ React__default.createElement(Panel.Content, null,
2256
+ React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) }))));
2257
+ };
2122
2258
 
2123
2259
  const ServerInfo = ({ servers, mockUrl }) => {
2124
2260
  const mocking = React.useContext(MockingContext);
2125
2261
  const showMocking = !mocking.hideMocking && mockUrl && isProperUrl(mockUrl);
2126
- const serversToDisplay = getServersToDisplay(servers);
2262
+ const $mockUrl = showMocking ? mockUrl || mocking.mockUrl : undefined;
2263
+ const serversToDisplay = getServersToDisplay(servers, $mockUrl);
2127
2264
  if (!showMocking && serversToDisplay.length === 0) {
2128
2265
  return null;
2129
2266
  }
@@ -2132,14 +2269,11 @@ const ServerInfo = ({ servers, mockUrl }) => {
2132
2269
  React.createElement(Panel.Titlebar, { whitespace: "nowrap" }, "API Base URL"),
2133
2270
  React.createElement(Box, { overflowX: "auto" },
2134
2271
  React.createElement(Panel.Content, { w: "full", className: "sl-flex sl-flex-col" },
2135
- serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { key: index })))),
2136
- showMocking && (React.createElement(React.Fragment, null,
2137
- React.createElement(Box, { borderT: 2, pt: 2, borderColor: "light", w: "full" }),
2138
- React.createElement(ServerUrl, { description: "Mock Server", url: mockUrl || '', marginBottom: false }))))))));
2272
+ React.createElement(VStack, { spacing: 1, divider: true }, serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { key: index }))))))))));
2139
2273
  };
2140
2274
  const ServerUrl = ({ description, url, marginBottom = true }) => {
2141
2275
  const { onCopy, hasCopied } = useClipboard(url);
2142
- return (React.createElement(Box, { whitespace: "nowrap", mb: marginBottom ? 2 : 0 },
2276
+ return (React.createElement(Box, { whitespace: "nowrap" },
2143
2277
  React.createElement(Text, { pr: 2, fontWeight: "bold" },
2144
2278
  description,
2145
2279
  ":"),
@@ -2188,14 +2322,13 @@ const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOpti
2188
2322
  };
2189
2323
  const examples = React.useMemo(() => generateExamplesFromJsonSchema(data), [data]);
2190
2324
  const shouldDisplayHeader = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && (title !== undefined || (exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport)));
2191
- const header = (shouldDisplayHeader || isInternal) && (React.createElement(React.Fragment, null,
2192
- shouldDisplayHeader && (React.createElement(Flex, { justifyContent: "between", alignItems: "center" },
2193
- React.createElement(Heading$1, { size: 1, mb: 4, fontWeight: "semibold" }, title),
2194
- exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport) && React.createElement(ExportButton, Object.assign({}, exportProps)))),
2195
- isInternal && (React.createElement(HStack, { spacing: 2, mb: 12 },
2196
- React.createElement(InternalBadge, null)))));
2197
- const description = (React.createElement(React.Fragment, null,
2198
- data.description && data.type === 'object' && (React.createElement(MarkdownViewer, { className: "sl-mb-6", role: "textbox", markdown: data.description })),
2325
+ const header = (shouldDisplayHeader || isInternal) && (React.createElement(Flex, { justifyContent: "between", alignItems: "center" },
2326
+ React.createElement(HStack, { spacing: 5 },
2327
+ title && (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, title)),
2328
+ React.createElement(HStack, { spacing: 2 }, isInternal && React.createElement(InternalBadge, null))),
2329
+ exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport) && React.createElement(ExportButton, Object.assign({}, exportProps))));
2330
+ const description = (React.createElement(VStack, { spacing: 10 },
2331
+ data.description && data.type === 'object' && React.createElement(MarkdownViewer, { role: "textbox", markdown: data.description }),
2199
2332
  React.createElement(JsonSchemaViewer, { resolveRef: resolveRef, schema: getOriginalObject(data) })));
2200
2333
  const examplesSelect = examples.length > 1 && (React.createElement(Select, { "aria-label": "Example", value: String(chosenExampleIndex), options: examples.map(({ label }, index) => ({ value: index, label })), onChange: (value) => setChosenExampleIndex(parseInt(String(value), 10)), size: "sm", triggerTextPrefix: "Example: " }));
2201
2334
  const modelExamples = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideModelExamples) && (React.createElement(Panel, { rounded: true, isCollapsible: false },
@@ -2284,7 +2417,7 @@ const SchemaAndDescription = ({ title: titleProp, schema }) => {
2284
2417
  const title = titleProp !== null && titleProp !== void 0 ? titleProp : schema.title;
2285
2418
  return (React__default.createElement(Box, { py: 2 },
2286
2419
  title && (React__default.createElement(Flex, { alignItems: "center", p: 2 },
2287
- React__default.createElement(FontAwesomeIcon, { icon: NodeTypeIconDefs[NodeType.Model], color: NodeTypeColors[NodeType.Model] }),
2420
+ React__default.createElement(Icon, { icon: NodeTypeIconDefs[NodeType.Model], color: NodeTypeColors[NodeType.Model] }),
2288
2421
  React__default.createElement(Box, { color: "muted", px: 2 }, title))),
2289
2422
  React__default.createElement(JsonSchemaViewer, { resolveRef: resolveRef, schema: getOriginalObject(schema) })));
2290
2423
  };
@@ -2338,6 +2471,15 @@ const MarkdownComponentsProvider = ({ value, children }) => {
2338
2471
  return React.createElement(MarkdownViewerProvider, { components: Object.assign({ code: CodeComponent }, value) }, children);
2339
2472
  };
2340
2473
 
2474
+ const externalRegex = new RegExp('^(?:[a-z]+:)?//', 'i');
2475
+ const ReactRouterMarkdownLink = ({ title, href, children }) => {
2476
+ const isExternal = href !== undefined && externalRegex.test(href);
2477
+ if (isExternal) {
2478
+ return (React__default.createElement("a", { target: "_blank", rel: "noreferrer noopener", href: href, title: title }, children));
2479
+ }
2480
+ return (React__default.createElement(HashLink, { to: href, title: title }, children));
2481
+ };
2482
+
2341
2483
  const NODE_TYPE_TITLE_ICON = {
2342
2484
  http_service: faCloud,
2343
2485
  };
@@ -2529,6 +2671,14 @@ function withPersistenceBoundary(WrappedComponent) {
2529
2671
 
2530
2672
  function withMosaicProvider(WrappedComponent) {
2531
2673
  const WithMosaicProvider = (props) => {
2674
+ try {
2675
+ const mosaicContext = useMosaicContext();
2676
+ if (mosaicContext === null || mosaicContext === void 0 ? void 0 : mosaicContext.providerId) {
2677
+ return React__default.createElement(WrappedComponent, Object.assign({}, props));
2678
+ }
2679
+ }
2680
+ catch (_a) {
2681
+ }
2532
2682
  return (React__default.createElement(Provider$1, { style: { height: '100%' } },
2533
2683
  React__default.createElement(WrappedComponent, Object.assign({}, props))));
2534
2684
  };
@@ -2546,6 +2696,12 @@ const queryClient = new QueryClient({
2546
2696
  });
2547
2697
  function withQueryClientProvider(WrappedComponent) {
2548
2698
  const WithQueryClientProvider = (props) => {
2699
+ try {
2700
+ useQueryClient();
2701
+ return React__default.createElement(WrappedComponent, Object.assign({}, props));
2702
+ }
2703
+ catch (_a) {
2704
+ }
2549
2705
  return (React__default.createElement(QueryClientProvider, { client: queryClient },
2550
2706
  React__default.createElement(WrappedComponent, Object.assign({}, props))));
2551
2707
  };
@@ -2553,23 +2709,15 @@ function withQueryClientProvider(WrappedComponent) {
2553
2709
  return WithQueryClientProvider;
2554
2710
  }
2555
2711
 
2556
- const externalRegex = new RegExp('^(?:[a-z]+:)?//', 'i');
2557
- const ReactRouterMarkdownLink = ({ title, href, children }) => {
2558
- const isExternal = href !== undefined && externalRegex.test(href);
2559
- if (isExternal) {
2560
- return (React__default.createElement("a", { target: "_blank", rel: "noreferrer noopener", href: href, title: title }, children));
2561
- }
2562
- return (React__default.createElement(HashLink, { to: href, title: title }, children));
2563
- };
2564
-
2565
2712
  const RouterComponent = {
2566
2713
  history: BrowserRouter,
2567
2714
  memory: MemoryRouter,
2568
2715
  hash: HashRouter,
2716
+ static: StaticRouter,
2569
2717
  };
2570
- const useRouter = (router, basePath) => {
2718
+ const useRouter = (router, basePath, staticRouterPath) => {
2571
2719
  const Router = RouterComponent[router];
2572
- const routerProps = Object.assign({}, (router !== 'memory' && { basename: basePath }));
2720
+ const routerProps = Object.assign(Object.assign({}, (router !== 'memory' && { basename: basePath })), (router === 'static' && { location: staticRouterPath }));
2573
2721
  return {
2574
2722
  Router,
2575
2723
  routerProps,
@@ -2578,9 +2726,10 @@ const useRouter = (router, basePath) => {
2578
2726
 
2579
2727
  function withRouter(WrappedComponent) {
2580
2728
  const WithRouter = (props) => {
2581
- var _a, _b;
2729
+ var _a, _b, _c;
2582
2730
  const basePath = (_a = props.basePath) !== null && _a !== void 0 ? _a : '/';
2583
- const { Router, routerProps } = useRouter((_b = props.router) !== null && _b !== void 0 ? _b : 'history', basePath);
2731
+ const staticRouterPath = (_b = props.staticRouterPath) !== null && _b !== void 0 ? _b : '';
2732
+ const { Router, routerProps } = useRouter((_c = props.router) !== null && _c !== void 0 ? _c : 'history', basePath, staticRouterPath);
2584
2733
  return (React.createElement(Router, Object.assign({}, routerProps, { key: basePath }),
2585
2734
  React.createElement(Route, { path: "/" },
2586
2735
  React.createElement(MarkdownComponentsProvider, { value: { link: ReactRouterMarkdownLink } },
@@ -2598,24 +2747,26 @@ function useBundleRefsIntoDocument(document, options) {
2598
2747
  setBundledData(document);
2599
2748
  return;
2600
2749
  }
2601
- let isActive = true;
2750
+ let isMounted = true;
2602
2751
  doBundle(document, baseUrl)
2603
2752
  .then(res => {
2604
- if (isActive) {
2753
+ if (isMounted) {
2605
2754
  setBundledData(Object.assign({}, res));
2606
2755
  }
2607
2756
  })
2608
2757
  .catch(reason => {
2609
2758
  var _a;
2610
2759
  if (typeof reason === 'object' && reason !== null && 'files' in reason) {
2611
- setBundledData(Object.assign({}, reason.files.schema));
2760
+ if (isMounted) {
2761
+ setBundledData(Object.assign({}, reason.files.schema));
2762
+ }
2612
2763
  }
2613
2764
  else {
2614
2765
  console.warn(`Could bundle: ${(_a = reason === null || reason === void 0 ? void 0 : reason.message) !== null && _a !== void 0 ? _a : 'Unknown error'}`);
2615
2766
  }
2616
2767
  });
2617
2768
  return () => {
2618
- isActive = false;
2769
+ isMounted = false;
2619
2770
  };
2620
2771
  }, [document, baseUrl]);
2621
2772
  return bundledData;
@@ -2752,4 +2903,4 @@ const createElementClass = (Component, propDescriptors) => {
2752
2903
  };
2753
2904
  };
2754
2905
 
2755
- export { DeprecatedBadge, Docs, ExportButton, HttpMethodColors, InlineRefResolverProvider, Logo, MarkdownComponentsProvider, MockingProvider, NodeTypeColors, NodeTypeIconDefs, NodeTypePrettyName, NonIdealState, ParsedDocs, PersistenceContextProvider, PoweredByLink, SidebarLayout, Styled, TableOfContents, TryIt, TryItWithRequestSamples, createElementClass, createResolvedObject, findFirstNode, isHttpOperation, isHttpService, useBundleRefsIntoDocument, useParsedData, useParsedValue, useRouter, withMosaicProvider, withPersistenceBoundary, withQueryClientProvider, withRouter, withStyles };
2906
+ export { DeprecatedBadge, Docs, ExportButton, HttpMethodColors, InlineRefResolverProvider, Logo, MarkdownComponentsProvider, MockingProvider, NodeTypeColors, NodeTypeIconDefs, NodeTypePrettyName, NonIdealState, ParsedDocs, PersistenceContextProvider, PoweredByLink, ReactRouterMarkdownLink, SidebarLayout, Styled, TableOfContents, TryIt, TryItWithRequestSamples, createElementClass, createResolvedObject, findFirstNode, isHttpOperation, isHttpService, slugify, useBundleRefsIntoDocument, useParsedData, useParsedValue, useRouter, withMosaicProvider, withPersistenceBoundary, withQueryClientProvider, withRouter, withStyles };