@stoplight/elements-core 7.4.1 → 7.5.3

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
@@ -8,14 +8,15 @@ import isPlainObject from 'lodash/isPlainObject.js';
8
8
  import { parse } from '@stoplight/markdown';
9
9
  import { NodeType, HttpParamStyles } from '@stoplight/types';
10
10
  import { parse as parse$1 } from '@stoplight/yaml';
11
- import { isArray as isArray$1, Box, Flex, Icon, Popover, Button, Panel, CopyButton, Menu, Text, Input, Select, Image, Link, useThemeIsDark, Tooltip, VStack, InvertTheme, Badge, Tabs, TabList, Tab, TabPanels, TabPanel, Heading as Heading$1, HStack, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
11
+ import { isArray as isArray$1, Box, Flex, Icon, Button, Popover, 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';
12
12
  import { withErrorBoundary } from '@stoplight/react-error-boundary';
13
13
  import { MarkdownViewer as MarkdownViewer$1, DefaultSMDComponents, MarkdownViewerProvider } from '@stoplight/markdown-viewer';
14
14
  export { DefaultSMDComponents } from '@stoplight/markdown-viewer';
15
- import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faExclamationTriangle, faEye, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
15
+ import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faServer, faExclamationTriangle, faEye, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
16
16
  import throttle from 'lodash/throttle.js';
17
17
  import { selectAll } from 'unist-util-select';
18
18
  import cn from 'classnames';
19
+ import { atomWithStorage, useAtomValue } from 'jotai/utils';
19
20
  import { atom, useAtom, Provider } from 'jotai';
20
21
  import URI from 'urijs';
21
22
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
@@ -38,15 +39,11 @@ import uniq from 'lodash/uniq.js';
38
39
  import orderBy from 'lodash/orderBy.js';
39
40
  import uniqBy from 'lodash/uniqBy.js';
40
41
  import formatXml from 'xml-formatter';
41
- import { atomWithStorage } from 'jotai/utils';
42
42
  import entries from 'lodash/entries.js';
43
43
  import keys from 'lodash/keys.js';
44
- import { JsonSchemaViewer, Validations } from '@stoplight/json-schema-viewer';
45
- import get from 'lodash/get.js';
46
- import isEmpty from 'lodash/isEmpty.js';
47
- import omitBy from 'lodash/omitBy.js';
44
+ import { JsonSchemaViewer } from '@stoplight/json-schema-viewer';
48
45
  import sortBy from 'lodash/sortBy.js';
49
- import { useLocation, BrowserRouter, MemoryRouter, HashRouter, Route } from 'react-router-dom';
46
+ import { useLocation, BrowserRouter, MemoryRouter, HashRouter, StaticRouter, Route } from 'react-router-dom';
50
47
  import { HashLink } from 'react-router-hash-link';
51
48
  import { QueryClient, useQueryClient, QueryClientProvider } from 'react-query';
52
49
  import $RefParser from '@stoplight/json-schema-ref-parser';
@@ -270,7 +267,7 @@ const findTitle = (parent) => {
270
267
  };
271
268
 
272
269
  function useLocationHash() {
273
- const isBrowser = typeof window !== undefined;
270
+ const isBrowser = typeof window !== 'undefined';
274
271
  const [locationHash, setLocationHash] = React.useState(isBrowser && window.location.hash);
275
272
  React.useEffect(() => {
276
273
  if (!isBrowser)
@@ -297,9 +294,10 @@ const Headings = ({ headings, className, title = 'On This Page', minimal, maxWid
297
294
  React.createElement(Box, { as: Icon, icon: faStream, mr: 2 }),
298
295
  title)),
299
296
  headings.map((heading, i) => (React.createElement(Heading, { key: i, item: heading, isSelected: locationHash === `#${heading.id}` })))));
297
+ const button = React.createElement(Button, { pos: "sticky", size: "sm", borderColor: "light", icon: faStream, style: { top: 10 } });
300
298
  if (minimal) {
301
- return (React.createElement(Box, { pos: "absolute", top: 0, right: 0, style: { top: 10 } },
302
- React.createElement(Popover, { renderTrigger: React.createElement(Button, { size: "sm", borderColor: "light", icon: faStream }), placement: "bottom" },
299
+ return (React.createElement(Box, { pos: "sticky", top: 0, right: 0, style: { top: 10 } },
300
+ React.createElement(Popover, { renderTrigger: button, placement: "bottom" },
303
301
  React.createElement(Box, { className: className }, component))));
304
302
  }
305
303
  return (React.createElement(Box, { pos: "sticky", pr: 4, pl: 16, h: "full", overflowX: "auto", overflowY: "auto", className: className, style: { top: 30 } },
@@ -321,20 +319,6 @@ const ArticleComponent = React.memo(({ data }) => {
321
319
  });
322
320
  const Article = withErrorBoundary(ArticleComponent, { recoverableProps: ['data'] });
323
321
 
324
- const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
325
- const MockingProvider = ({ mockUrl, hideMocking, children }) => {
326
- const info = {
327
- mockUrl,
328
- hideMocking: hideMocking || !mockUrl,
329
- };
330
- return React.createElement(MockingContext.Provider, { value: info }, children);
331
- };
332
- function createNamedContext(name, defaultValue) {
333
- const context = React.createContext(defaultValue);
334
- context.displayName = name;
335
- return context;
336
- }
337
-
338
322
  const NodeTypeColors = {
339
323
  http_operation: '#6a6acb',
340
324
  http_service: '#e056fd',
@@ -451,10 +435,36 @@ const HttpCodeDescriptions = {
451
435
  const badgeDefaultBackgroundColor = '#293742';
452
436
  const badgeDefaultColor = '#FFFFFF';
453
437
 
454
- const getServersToDisplay = (originalServers) => {
455
- return originalServers
456
- .map((server, i) => (Object.assign(Object.assign({}, server), { url: getServerUrlWithDefaultValues(server), description: server.description || `Server ${i + 1}` })))
438
+ const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
439
+ const MockingProvider = ({ mockUrl, hideMocking, children }) => {
440
+ const info = {
441
+ mockUrl,
442
+ hideMocking: hideMocking || !mockUrl,
443
+ };
444
+ return React.createElement(MockingContext.Provider, { value: info }, children);
445
+ };
446
+ function createNamedContext(name, defaultValue) {
447
+ const context = React.createContext(defaultValue);
448
+ context.displayName = name;
449
+ return context;
450
+ }
451
+
452
+ const chosenServerAtom = atom(undefined);
453
+
454
+ const getServersToDisplay = (originalServers, mockUrl) => {
455
+ const servers = originalServers
456
+ .map((server, i) => {
457
+ const fallbackDescription = originalServers.length === 1 ? 'Live Server' : `Server ${i + 1}`;
458
+ return Object.assign(Object.assign({}, server), { url: getServerUrlWithDefaultValues(server), description: server.description || fallbackDescription });
459
+ })
457
460
  .filter(server => isProperUrl(server.url));
461
+ if (mockUrl) {
462
+ servers.push({
463
+ description: 'Mock Server',
464
+ url: mockUrl,
465
+ });
466
+ }
467
+ return servers;
458
468
  };
459
469
  const getServerUrlWithDefaultValues = (server) => {
460
470
  var _a;
@@ -467,7 +477,8 @@ const getServerUrlWithDefaultValues = (server) => {
467
477
  if (url.is('relative') && typeof window !== 'undefined') {
468
478
  url = url.absoluteTo(window.location.origin);
469
479
  }
470
- return url.toString();
480
+ const stringifiedUrl = url.toString();
481
+ return stringifiedUrl.endsWith('/') ? stringifiedUrl.slice(0, -1) : stringifiedUrl;
471
482
  };
472
483
 
473
484
  const persistAtom = (key, atomInstance) => {
@@ -720,7 +731,12 @@ const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) =
720
731
  " ",
721
732
  selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
722
733
  React__default.createElement(Panel.Content, { p: 0 },
723
- React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText }))));
734
+ React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText, style: embeddedInMd
735
+ ? undefined
736
+ :
737
+ {
738
+ '--fs-code': 12,
739
+ } }))));
724
740
  });
725
741
 
726
742
  function getReadableSecurityName(securityScheme, includeKey = false) {
@@ -885,7 +901,14 @@ const SecuritySchemeComponent = (_a) => {
885
901
  };
886
902
  const securitySchemeKeys = ['apiKey', 'http', 'oauth2', 'openIdConnect'];
887
903
 
888
- const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
904
+ const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
905
+ function slugify(name) {
906
+ return name
907
+ .replace(/\/|{|}|\s/g, '-')
908
+ .replace(/-{2,}/, '-')
909
+ .replace(/^-/, '')
910
+ .replace(/-$/, '');
911
+ }
889
912
 
890
913
  const isApiKeySecurityScheme = (maybeIApiKey) => isObject(maybeIApiKey) && maybeIApiKey.type === 'apiKey';
891
914
  const isOAuth2SecurityScheme = (maybeIOAuth2) => isObject(maybeIOAuth2) && maybeIOAuth2.type === 'oauth2';
@@ -996,10 +1019,10 @@ function exampleValue(example) {
996
1019
  }
997
1020
  function getPlaceholderForParameter(parameter) {
998
1021
  var _a, _b;
999
- const parameterValue = getValueForParameter(parameter);
1022
+ const { value: parameterValue, isDefault } = getValueForParameter(parameter);
1000
1023
  if (parameterValue)
1001
- return `example: ${parameterValue}`;
1002
- return parameterValue || String((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '');
1024
+ return `${isDefault ? 'defaults to' : 'example'}: ${parameterValue}`;
1025
+ return String((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '');
1003
1026
  }
1004
1027
  function retrieveDefaultFromSchema(parameter) {
1005
1028
  var _a;
@@ -1008,22 +1031,25 @@ function retrieveDefaultFromSchema(parameter) {
1008
1031
  }
1009
1032
  const getValueForParameter = (parameter) => {
1010
1033
  var _a, _b, _c;
1011
- const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1012
- if (examples.length > 0)
1013
- return exampleValue(examples[0]);
1014
1034
  const defaultValue = retrieveDefaultFromSchema(parameter);
1015
- if (defaultValue)
1016
- return String(defaultValue);
1035
+ if (typeof defaultValue !== 'undefined') {
1036
+ return { value: String(defaultValue), isDefault: true };
1037
+ }
1038
+ const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1039
+ if (examples.length > 0) {
1040
+ return { value: exampleValue(examples[0]) };
1041
+ }
1017
1042
  const enums = (_c = (_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.enum) !== null && _c !== void 0 ? _c : [];
1018
- if (enums.length > 0)
1019
- return String(enums[0]);
1020
- return '';
1043
+ if (enums.length > 0) {
1044
+ return { value: String(enums[0]) };
1045
+ }
1046
+ return { value: '' };
1021
1047
  };
1022
1048
  const getInitialValueForParameter = (parameter) => {
1023
1049
  const isRequired = !!parameter.required;
1024
1050
  if (!isRequired)
1025
1051
  return '';
1026
- return getValueForParameter(parameter);
1052
+ return getValueForParameter(parameter).value;
1027
1053
  };
1028
1054
  const initialParameterValues = params => {
1029
1055
  const paramsByName = keyBy(params, (param) => param.name);
@@ -1168,7 +1194,9 @@ const RequestBody = ({ examples, requestBody, onChange }) => {
1168
1194
  return (React.createElement(Panel, { defaultIsOpen: true },
1169
1195
  React.createElement(Panel.Titlebar, { rightComponent: examples.length > 1 && React.createElement(ExampleMenu, { examples: examples, requestBody: requestBody, onChange: onChange }) }, "Body"),
1170
1196
  React.createElement(Panel.Content, { className: "TextRequestBody" },
1171
- React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0 }))));
1197
+ React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0, style: {
1198
+ fontSize: 12,
1199
+ } }))));
1172
1200
  };
1173
1201
  function ExampleMenu({ examples, requestBody, onChange }) {
1174
1202
  const handleClick = React.useCallback((example) => {
@@ -1426,8 +1454,8 @@ const formatMultiValueHeader = (...keyValuePairs) => {
1426
1454
  .join(', ');
1427
1455
  };
1428
1456
 
1429
- function getMockData(url, httpOperation, { isEnabled, code, dynamic, example }) {
1430
- return isEnabled && url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1457
+ function getMockData(url, httpOperation, { code, dynamic, example }) {
1458
+ return url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1431
1459
  }
1432
1460
  function buildPreferHeader({ code, example, dynamic }, httpOperation) {
1433
1461
  if (!code) {
@@ -1460,23 +1488,14 @@ function supportsExample(httpOperation, code, exampleKey) {
1460
1488
  return exampleKeys.includes(exampleKey);
1461
1489
  }
1462
1490
 
1463
- const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic }, onOptionsChange, }) => {
1464
- const toggleEnabled = React.useCallback(() => {
1465
- onOptionsChange({ isEnabled: !isEnabled });
1466
- }, [isEnabled, onOptionsChange]);
1491
+ const MockingButton = ({ operation, options: { code, example, dynamic }, onOptionsChange, }) => {
1467
1492
  const operationResponses = operation.responses;
1468
1493
  const setMockingOptions = React.useCallback(({ code, example, dynamic }) => {
1469
- onOptionsChange({ isEnabled, code, example, dynamic });
1470
- }, [isEnabled, onOptionsChange]);
1494
+ onOptionsChange({ code, example, dynamic });
1495
+ }, [onOptionsChange]);
1471
1496
  const menuItems = React.useMemo(() => {
1472
1497
  var _a;
1473
- const items = [
1474
- { id: 'mocking-enabled', title: 'Enabled', isChecked: isEnabled, onPress: toggleEnabled },
1475
- {
1476
- type: 'group',
1477
- 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),
1478
- },
1479
- ];
1498
+ 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);
1480
1499
  function generateOperationResponseMenu(operationResponse) {
1481
1500
  var _a;
1482
1501
  const menuId = `response-${operationResponse.code}`;
@@ -1510,7 +1529,6 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1510
1529
  ];
1511
1530
  const menuItem = {
1512
1531
  id: menuId,
1513
- isDisabled: !isEnabled,
1514
1532
  isChecked: isActive,
1515
1533
  title: operationResponse.code,
1516
1534
  onPress: () => {
@@ -1524,13 +1542,13 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1524
1542
  return menuItem;
1525
1543
  }
1526
1544
  return items;
1527
- }, [code, dynamic, example, isEnabled, operationResponses, setMockingOptions, toggleEnabled]);
1545
+ }, [code, dynamic, example, operationResponses, setMockingOptions]);
1528
1546
  return (React.createElement(Box, null,
1529
- 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")) })));
1547
+ React.createElement(Menu, { "aria-label": "Mock settings", items: menuItems, renderTrigger: ({ isOpen }) => (React.createElement(FieldButton, { active: isOpen, size: "sm" }, "Mock Settings")) })));
1530
1548
  };
1531
1549
 
1532
- const persistedMockingOptionsAtom = atom({ isEnabled: false });
1533
- const useMockingOptions = () => useAtom(persistedMockingOptionsAtom);
1550
+ const mockingOptionsAtom = atom({});
1551
+ const useMockingOptions = () => useAtom(mockingOptionsAtom);
1534
1552
 
1535
1553
  const OperationParameters = ({ parameters, values, onChangeValue, validate, }) => {
1536
1554
  return (React.createElement(Panel, { defaultIsOpen: true },
@@ -1659,7 +1677,32 @@ class NetworkError extends Error {
1659
1677
  }
1660
1678
  const isNetworkError = (error) => error instanceof NetworkError;
1661
1679
 
1662
- const chosenServerAtom = atom(undefined);
1680
+ const ServersDropdown = ({ servers }) => {
1681
+ const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1682
+ const serverItems = [
1683
+ {
1684
+ type: 'option_group',
1685
+ title: 'Servers',
1686
+ value: (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || '',
1687
+ onChange: url => {
1688
+ const server = servers.find(server => server.url === url);
1689
+ setChosenServer(server);
1690
+ },
1691
+ children: [
1692
+ ...servers.map((server, i) => ({
1693
+ id: server.url,
1694
+ title: server.name || server.description,
1695
+ description: server.name ? server.description || server.url : server.description ? server.url : undefined,
1696
+ value: server.url,
1697
+ })),
1698
+ ],
1699
+ },
1700
+ ];
1701
+ 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')) }));
1702
+ };
1703
+ ServersDropdown.displayName = 'ServersDropdown';
1704
+
1705
+ const defaultServers = [];
1663
1706
  const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embeddedInMd = false, tryItCredentialsPolicy, corsProxy, }) => {
1664
1707
  var _a, _b, _c, _d, _e, _f, _g;
1665
1708
  const isDark = useThemeIsDark();
@@ -1673,18 +1716,28 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1673
1716
  const [bodyParameterValues, setBodyParameterValues, formDataState] = useBodyParameterState(mediaTypeContent);
1674
1717
  const [textRequestBody, setTextRequestBody] = useTextRequestBodyState(mediaTypeContent);
1675
1718
  const [operationAuthValue, setOperationAuthValue] = usePersistedSecuritySchemeWithValues();
1676
- const servers = getServersToDisplay(httpOperation.servers || []);
1719
+ const servers = React.useMemo(() => {
1720
+ const toDisplay = getServersToDisplay(httpOperation.servers || defaultServers, mockUrl);
1721
+ return toDisplay;
1722
+ }, [httpOperation.servers, mockUrl]);
1723
+ const firstServer = servers[0] || null;
1677
1724
  const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1725
+ const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
1678
1726
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
1679
1727
  React.useEffect(() => {
1680
- if (!chosenServer) {
1681
- setChosenServer(servers[0]);
1728
+ const currentUrl = chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url;
1729
+ const exists = currentUrl && servers.find(s => s.url === currentUrl);
1730
+ if (!exists) {
1731
+ setChosenServer(firstServer);
1682
1732
  }
1683
- }, []);
1733
+ else if (exists !== chosenServer) {
1734
+ setChosenServer(exists);
1735
+ }
1736
+ }, [servers, firstServer, chosenServer, setChosenServer]);
1684
1737
  React.useEffect(() => {
1685
1738
  let isMounted = true;
1686
1739
  if (onRequestChange || embeddedInMd) {
1687
- buildHarRequest(Object.assign(Object.assign({ mediaTypeContent, parameterValues: parameterValuesWithDefaults, httpOperation, bodyInput: formDataState.isFormDataBody ? bodyParameterValues : textRequestBody, auth: operationAuthValue }, (mockingOptions.isEnabled && { mockData: getMockData(mockUrl, httpOperation, mockingOptions) })), { chosenServer,
1740
+ buildHarRequest(Object.assign(Object.assign({ mediaTypeContent, parameterValues: parameterValuesWithDefaults, httpOperation, bodyInput: formDataState.isFormDataBody ? bodyParameterValues : textRequestBody, auth: operationAuthValue }, (isMockingEnabled && { mockData: getMockData(mockUrl, httpOperation, mockingOptions) })), { chosenServer,
1688
1741
  corsProxy })).then(request => {
1689
1742
  if (isMounted) {
1690
1743
  if (onRequestChange) {
@@ -1711,13 +1764,13 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1711
1764
  corsProxy,
1712
1765
  embeddedInMd,
1713
1766
  ]);
1714
- const handleClick = () => __awaiter(void 0, void 0, void 0, function* () {
1767
+ const handleSendRequest = () => __awaiter(void 0, void 0, void 0, function* () {
1715
1768
  setValidateParameters(true);
1716
1769
  if (hasRequiredButEmptyParameters)
1717
1770
  return;
1718
1771
  try {
1719
1772
  setLoading(true);
1720
- const mockData = getMockData(mockUrl, httpOperation, mockingOptions);
1773
+ const mockData = isMockingEnabled ? getMockData(mockUrl, httpOperation, mockingOptions) : undefined;
1721
1774
  const request = yield buildFetchRequest({
1722
1775
  parameterValues: parameterValuesWithDefaults,
1723
1776
  httpOperation,
@@ -1754,29 +1807,32 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1754
1807
  setLoading(false);
1755
1808
  }
1756
1809
  });
1757
- 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) => {
1758
- const server = servers.find(server => server.description === value);
1759
- setChosenServer(server);
1760
- } }));
1761
- 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) },
1762
- "Server Host: ", (_e = servers[0]) === null || _e === void 0 ? void 0 :
1763
- _e.url));
1810
+ const isOnlySendButton = !((_d = httpOperation.security) === null || _d === void 0 ? void 0 : _d.length) && !allParameters.length && !formDataState.isFormDataBody && !mediaTypeContent;
1811
+ const tryItPanelContents = (React.createElement(React.Fragment, null,
1812
+ ((_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,
1813
+ allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
1814
+ 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,
1815
+ React.createElement(Panel.Content, { className: "SendButtonHolder", mt: 4, pt: !isOnlySendButton && !embeddedInMd ? 0 : undefined },
1816
+ React.createElement(HStack, { alignItems: "center", spacing: 2 },
1817
+ React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleSendRequest, size: "sm" }, "Send API Request"),
1818
+ servers.length > 1 && React.createElement(ServersDropdown, { servers: servers }),
1819
+ isMockingEnabled && (React.createElement(MockingButton, { options: mockingOptions, onOptionsChange: setMockingOptions, operation: httpOperation }))),
1820
+ validateParameters && hasRequiredButEmptyParameters && (React.createElement(Box, { mt: 4, color: "danger-light", fontSize: "sm" },
1821
+ React.createElement(Icon, { icon: faExclamationTriangle, className: "sl-mr-1" }),
1822
+ "You didn't provide all of the required parameters!")))));
1823
+ let tryItPanelElem;
1824
+ if (embeddedInMd) {
1825
+ tryItPanelElem = (React.createElement(Panel, { isCollapsible: false, p: 0, className: "TryItPanel" },
1826
+ React.createElement(Panel.Titlebar, { bg: "canvas-300" },
1827
+ React.createElement(Box, { fontWeight: "bold", color: !isDark ? HttpMethodColors[httpOperation.method] : undefined }, httpOperation.method.toUpperCase()),
1828
+ React.createElement(Box, { fontWeight: "medium", ml: 2, textOverflow: "truncate", overflowX: "hidden" }, `${(chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || ''}${httpOperation.path}`)),
1829
+ tryItPanelContents));
1830
+ }
1831
+ else {
1832
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
1833
+ }
1764
1834
  return (React.createElement(Box, { rounded: "lg", overflowY: "hidden" },
1765
- React.createElement(Panel, { isCollapsible: false, p: 0, className: "TryItPanel" },
1766
- React.createElement(Panel.Titlebar, { rightComponent: servers.length > 1 ? serversSelect : serverDescription, bg: "canvas-300" },
1767
- React.createElement("div", { role: "heading", className: "sl-font-bold" },
1768
- React.createElement(Text, { color: !isDark ? HttpMethodColors[httpOperation.method] : undefined }, httpOperation.method.toUpperCase()),
1769
- React.createElement(Text, { ml: 2 }, httpOperation.path))),
1770
- React.createElement(TryItAuth, { onChange: setOperationAuthValue, operationSecurityScheme: (_f = httpOperation.security) !== null && _f !== void 0 ? _f : [], value: operationAuthValue }),
1771
- allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
1772
- 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,
1773
- React.createElement(Panel.Content, { className: "SendButtonHolder" },
1774
- React.createElement(Flex, { alignItems: "center" },
1775
- React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleClick, size: "sm" }, "Send Request"),
1776
- mockUrl && (React.createElement(MockingButton, { options: mockingOptions, onOptionsChange: setMockingOptions, operation: httpOperation }))),
1777
- validateParameters && hasRequiredButEmptyParameters && (React.createElement(Box, { mt: 4, color: "danger-light", fontSize: "sm" },
1778
- React.createElement(Icon, { icon: faExclamationTriangle, className: "sl-mr-1" }),
1779
- "You didn't provide all of the required parameters!")))),
1835
+ tryItPanelElem,
1780
1836
  requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
1781
1837
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
1782
1838
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
@@ -1813,7 +1869,9 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
1813
1869
  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: " }));
1814
1870
  return (React__default.createElement(Panel, { rounded: true, isCollapsible: false },
1815
1871
  React__default.createElement(Panel.Titlebar, null, examplesSelect || React__default.createElement(Text, { color: "body" }, "Response Example")),
1816
- 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 })))));
1872
+ 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: {
1873
+ '--fs-code': 12,
1874
+ } })) : (React__default.createElement(LoadMore, { loading: loading, onClick: handleLoadMore })))));
1817
1875
  };
1818
1876
 
1819
1877
  const TryItWithRequestSamples = (_a) => {
@@ -1827,14 +1885,14 @@ const TryItWithRequestSamples = (_a) => {
1827
1885
  React.createElement(ResponseExamples, Object.assign({}, props))));
1828
1886
  };
1829
1887
 
1830
- const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(Box, { w: "full", className: className },
1888
+ const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(VStack, { w: "full", className: className, spacing: 8 },
1831
1889
  header,
1832
- React__default.createElement(Flex, { mt: header ? 12 : undefined },
1890
+ React__default.createElement(Flex, null,
1833
1891
  React__default.createElement(Box, { w: 0, flex: 1 }, left),
1834
1892
  right && (React__default.createElement(Box, { ml: 16, pos: "relative", w: "2/5", style: { maxWidth: 500 } }, right)))));
1835
1893
 
1836
1894
  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."));
1837
- const InternalBadge = ({ isHttpService }) => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { icon: faEye, "data-testid": "badge-internal", bg: "danger", ml: 0 }, "Internal") }, `This ${isHttpService ? 'operation' : 'model'} is marked as internal and won't be visible in public docs.`));
1895
+ 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.`));
1838
1896
  const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", border: 0, style: {
1839
1897
  backgroundColor: backgroundColor || badgeDefaultBackgroundColor,
1840
1898
  color: badgeDefaultColor,
@@ -1914,32 +1972,43 @@ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
1914
1972
  return description;
1915
1973
  }
1916
1974
 
1917
- const SectionTitle = ({ title, children }) => {
1918
- return (React.createElement(Flex, { role: "heading", borderB: true, mb: 3, pb: 3, "aria-label": title, align: "baseline" },
1919
- React.createElement(Text, { size: "xl", fontWeight: "semibold", mr: 5 }, title),
1975
+ const SectionTitle = ({ title, id, size = 2, children }) => {
1976
+ return (React.createElement(HStack, { spacing: 6 },
1977
+ React.createElement(Box, { as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
1920
1978
  children));
1921
1979
  };
1980
+ const SectionSubtitle = props => {
1981
+ return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
1982
+ };
1922
1983
  const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
1923
- return (React.createElement(Panel, { appearance: "minimal", isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange },
1984
+ return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
1924
1985
  React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
1925
1986
  React.createElement("div", { role: "heading" }, title)),
1926
- hasContent !== false && (React.createElement(Panel.Content, { pr: 3, pl: 6, p: 0 }, children))));
1987
+ hasContent !== false && React.createElement(Panel.Content, null, children)));
1927
1988
  };
1928
1989
 
1929
- const Body = ({ body: { contents = [], description }, onChange }) => {
1990
+ const isBodyEmpty = (body) => {
1991
+ if (!body)
1992
+ return true;
1993
+ const { contents = [], description } = body;
1994
+ return contents.length === 0 && !(description === null || description === void 0 ? void 0 : description.trim());
1995
+ };
1996
+ const Body = ({ body, onChange }) => {
1930
1997
  var _a;
1931
1998
  const refResolver = useInlineRefResolver();
1932
1999
  const [chosenContent, setChosenContent] = React.useState(0);
1933
2000
  React.useEffect(() => {
1934
2001
  onChange(chosenContent);
1935
2002
  }, [chosenContent]);
1936
- if (contents.length === 0 && !description)
2003
+ if (isBodyEmpty(body))
1937
2004
  return null;
2005
+ const { contents = [], description } = body;
1938
2006
  const schema = (_a = contents[chosenContent]) === null || _a === void 0 ? void 0 : _a.schema;
1939
- 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" })) },
1940
- description && React.createElement(MarkdownViewer, { className: "sl-my-2", markdown: description }),
1941
- isJSONSchema(schema) && (React.createElement(Box, null,
1942
- React.createElement(JsonSchemaViewer, { resolveRef: refResolver, schema: getOriginalObject(schema), viewMode: "write", hideExamples: true })))));
2007
+ return (React.createElement(VStack, { spacing: 6 },
2008
+ React.createElement(SectionSubtitle, { title: "Body", id: "request-body" }, contents.length > 0 && (React.createElement(Flex, { flex: 1, justify: "end" },
2009
+ 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" })))),
2010
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2011
+ isJSONSchema(schema) && (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, schema: getOriginalObject(schema), viewMode: "write", hideExamples: true, renderRootTreeLines: true }))));
1943
2012
  };
1944
2013
  Body.displayName = 'HttpOperation.Body';
1945
2014
 
@@ -1963,66 +2032,71 @@ const defaultStyle = {
1963
2032
  cookie: HttpParamStyles.Form,
1964
2033
  };
1965
2034
  const Parameters = ({ parameters, parameterType }) => {
1966
- if (!parameters || !parameters.length)
2035
+ const schema = React.useMemo(() => httpOperationParamsToSchema({ parameters, parameterType }), [parameters, parameterType]);
2036
+ if (!schema)
1967
2037
  return null;
1968
- return (React.createElement(VStack, { spacing: 2, divider: React.createElement(Box, { borderT: true, borderColor: "light", w: "full" }) }, sortBy(parameters, ['required', 'name']).map(parameter => {
1969
- return React.createElement(Parameter, { key: parameter.name, parameter: parameter, parameterType: parameterType });
1970
- })));
2038
+ return React.createElement(JsonSchemaViewer, { schema: schema, disableCrumbs: true });
1971
2039
  };
1972
2040
  Parameters.displayName = 'HttpOperation.Parameters';
1973
- const Parameter = ({ parameter, parameterType }) => {
1974
- var _a, _b, _c, _d, _e;
1975
- if (!parameter)
2041
+ const httpOperationParamsToSchema = ({ parameters, parameterType }) => {
2042
+ var _a;
2043
+ if (!parameters || !parameters.length)
1976
2044
  return null;
1977
- const description = get(parameter, 'description') || get(parameter, 'schema.description');
1978
- const rootType = get(parameter, 'schema.type', 'unknown');
1979
- 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;
1980
- const format = (_c = parameter.schema) === null || _c === void 0 ? void 0 : _c.format;
1981
- const deprecated = get(parameter, 'deprecated') || get(parameter, 'schema.deprecated', false);
1982
- const parameterExamples = ((_d = parameter.examples) === null || _d === void 0 ? void 0 : _d.map(example => {
1983
- if (isNodeExample(example)) {
1984
- return example.value;
2045
+ const schema = {
2046
+ properties: {},
2047
+ required: [],
2048
+ };
2049
+ const sortedParams = sortBy(parameters, ['required', 'name']);
2050
+ for (const p of sortedParams) {
2051
+ if (!p.schema)
2052
+ continue;
2053
+ const { name, description, required, deprecated, examples, style } = p;
2054
+ const paramExamples = (examples === null || examples === void 0 ? void 0 : examples.map(example => {
2055
+ if (isNodeExample(example)) {
2056
+ return example.value;
2057
+ }
2058
+ return example.externalValue;
2059
+ })) || [];
2060
+ const schemaExamples = (_a = p.schema) === null || _a === void 0 ? void 0 : _a.examples;
2061
+ const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
2062
+ const paramDescription = description || p.schema.description;
2063
+ const paramDeprecated = deprecated || p.schema.deprecated;
2064
+ const paramStyle = style && defaultStyle[parameterType] !== style ? readableStyles[style] || style : undefined;
2065
+ schema.properties[p.name] = Object.assign(Object.assign({}, p.schema), { description: paramDescription, examples: [...paramExamples, ...schemaExamplesArray], deprecated: paramDeprecated, style: paramStyle });
2066
+ if (required) {
2067
+ schema.required.push(name);
1985
2068
  }
1986
- return example.externalValue;
1987
- })) || [];
1988
- const schemaExamples = (_e = parameter.schema) === null || _e === void 0 ? void 0 : _e.examples;
1989
- const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
1990
- 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');
1991
- return (React.createElement(Box, { className: "HttpOperation__Parameters" },
1992
- React.createElement(Flex, { alignItems: "center", my: 2 },
1993
- React.createElement(Flex, { alignItems: "baseline", fontSize: "base", flex: 1 },
1994
- React.createElement(Box, { fontFamily: "mono", fontWeight: "bold" }, parameter.name),
1995
- React.createElement(Box, { ml: 2, color: "muted" }, format ? `${type}<${format}>` : type)),
1996
- React.createElement(Box, { fontSize: "sm", color: "warning" },
1997
- deprecated && (React.createElement(Box, { as: "span", ml: 2 }, "deprecated")),
1998
- parameter.required && (React.createElement(Box, { as: "span", ml: 2 }, "required")))),
1999
- description && (React.createElement(Box, { w: "full", color: "muted", fontSize: "sm", my: 2 },
2000
- React.createElement(MarkdownViewer$1, { markdown: description }))),
2001
- React.createElement(Box, { fontSize: "sm" },
2002
- React.createElement(Validations, { validations: validations })),
2003
- parameter.style && defaultStyle[parameterType] !== parameter.style && (React.createElement(Flex, { my: 2 },
2004
- React.createElement(Box, { as: "span", px: 1, color: "muted", fontFamily: "mono", rounded: "lg", fontSize: "sm", textTransform: "capitalize", style: { backgroundColor: '#EDF2F7' } }, readableStyles[parameter.style] || parameter.style)))));
2005
- };
2006
- Parameter.displayName = 'HttpOperation.Parameter';
2069
+ }
2070
+ return schema;
2071
+ };
2007
2072
 
2008
- const Request = ({ operation: { path, method, request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
2073
+ const Request = ({ operation: { request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
2009
2074
  if (!request || typeof request !== 'object')
2010
2075
  return null;
2076
+ const bodyIsEmpty = isBodyEmpty(body);
2011
2077
  const securitySchemes = flatten(security);
2012
- const pathParamBlock = (React.createElement(Box, null,
2013
- React.createElement(Text, { textTransform: "uppercase", mr: 1, color: HttpMethodColors[method] }, method),
2014
- ' ',
2015
- path));
2016
- return (React.createElement(Box, null,
2078
+ const hasRequestData = Boolean(securitySchemes.length ||
2079
+ pathParams.length ||
2080
+ queryParams.length ||
2081
+ headerParams.length ||
2082
+ cookieParams.length ||
2083
+ !bodyIsEmpty);
2084
+ if (!hasRequestData)
2085
+ return null;
2086
+ return (React.createElement(VStack, { spacing: 8 },
2017
2087
  React.createElement(SectionTitle, { title: "Request" }),
2018
- securitySchemes.map((scheme, i) => (React.createElement(SecurityPanel, { key: i, scheme: scheme, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))),
2019
- React.createElement(SubSectionPanel, { title: pathParamBlock, hasContent: pathParams.length > 0 },
2020
- React.createElement(Parameters, { parameterType: "path", parameters: pathParams })),
2021
- queryParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Query" },
2088
+ securitySchemes.length > 0 && (React.createElement(VStack, { spacing: 3 }, securitySchemes.map((scheme, i) => (React.createElement(SecurityPanel, { key: i, scheme: scheme, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))))),
2089
+ pathParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2090
+ React.createElement(SectionSubtitle, { title: "Path Parameters" }),
2091
+ React.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
2092
+ queryParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2093
+ React.createElement(SectionSubtitle, { title: "Query Parameters" }),
2022
2094
  React.createElement(Parameters, { parameterType: "query", parameters: queryParams }))),
2023
- headerParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Headers" },
2095
+ headerParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2096
+ React.createElement(SectionSubtitle, { title: "Headers", id: "request-headers" }),
2024
2097
  React.createElement(Parameters, { parameterType: "header", parameters: headerParams }))),
2025
- cookieParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Cookie" },
2098
+ cookieParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2099
+ React.createElement(SectionSubtitle, { title: "Cookies", id: "request-cookies" }),
2026
2100
  React.createElement(Parameters, { parameterType: "cookie", parameters: cookieParams }))),
2027
2101
  body && React.createElement(Body, { onChange: onChange, body: body })));
2028
2102
  };
@@ -2043,15 +2117,15 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2043
2117
  }, [activeResponseId]);
2044
2118
  if (!responses.length)
2045
2119
  return null;
2046
- return (React.createElement(Tabs, { selectedId: activeResponseId, onChange: setActiveResponseId },
2047
- React.createElement(Box, null,
2048
- React.createElement(SectionTitle, { title: "Responses" },
2049
- React.createElement(TabList, null, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code }, code))))),
2050
- React.createElement(Box, { as: TabPanels, mt: 4 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2051
- React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2120
+ return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2121
+ React.createElement(SectionTitle, { title: "Responses" },
2122
+ React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2123
+ React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2124
+ React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
2052
2125
  };
2053
2126
  Responses.displayName = 'HttpOperation.Responses';
2054
- const Response = ({ response: { contents = [], headers = [], description }, onMediaTypeChange }) => {
2127
+ const Response = ({ response, onMediaTypeChange }) => {
2128
+ const { contents = [], headers = [], description } = response;
2055
2129
  const [chosenContent, setChosenContent] = React.useState(0);
2056
2130
  const refResolver = useInlineRefResolver();
2057
2131
  const responseContent = contents[chosenContent];
@@ -2059,14 +2133,31 @@ const Response = ({ response: { contents = [], headers = [], description }, onMe
2059
2133
  React.useEffect(() => {
2060
2134
  responseContent && onMediaTypeChange(responseContent.mediaType);
2061
2135
  }, [responseContent]);
2062
- return (React.createElement(Box, null,
2063
- description && React.createElement(MarkdownViewer, { className: "sl-ml-1 sl-mb-6", markdown: description }),
2064
- headers.length > 0 && (React.createElement(SubSectionPanel, { title: "Headers" },
2136
+ return (React.createElement(VStack, { spacing: 8, pt: 8 },
2137
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2138
+ headers.length > 0 && (React.createElement(VStack, { spacing: 5 },
2139
+ React.createElement(SectionSubtitle, { title: "Headers", id: "response-headers" }),
2065
2140
  React.createElement(Parameters, { parameterType: "header", parameters: headers }))),
2066
- 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,
2067
- React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, viewMode: "read", hideExamples: true })))))));
2141
+ contents.length > 0 && (React.createElement(React.Fragment, null,
2142
+ React.createElement(SectionSubtitle, { title: "Body", id: "response-body" },
2143
+ React.createElement(Flex, { flex: 1, justify: "end" },
2144
+ 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" }))),
2145
+ schema && (React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, viewMode: "read", hideExamples: true, parentCrumbs: ['responses', response.code], renderRootTreeLines: true }))))));
2068
2146
  };
2069
- Response.displayName = 'HttpOperation.Response';
2147
+ Response.displayName = 'HttpOperation.Response';
2148
+ const codeToIntentVal = (code) => {
2149
+ const firstChar = code.charAt(0);
2150
+ switch (firstChar) {
2151
+ case '2':
2152
+ return 'success';
2153
+ case '4':
2154
+ return 'warning';
2155
+ case '5':
2156
+ return 'danger';
2157
+ default:
2158
+ return 'default';
2159
+ }
2160
+ };
2070
2161
 
2071
2162
  const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
2072
2163
  const data = useResolvedObject(unresolvedData);
@@ -2076,13 +2167,16 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2076
2167
  const [responseMediaType, setResponseMediaType] = React.useState('');
2077
2168
  const [responseStatusCode, setResponseStatusCode] = React.useState('');
2078
2169
  const [requestBodyIndex, setTextRequestBodyIndex] = React.useState(0);
2170
+ const prettyName = (data.summary || data.iid || '').trim();
2079
2171
  const hasBadges = isDeprecated || isInternal;
2080
- const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(React.Fragment, null,
2081
- !(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}`)),
2082
- hasBadges && (React.createElement(HStack, { spacing: 2 },
2083
- isDeprecated && React.createElement(DeprecatedBadge, null),
2084
- isInternal && React.createElement(InternalBadge, { isHttpService: true })))));
2085
- const description = (React.createElement(VStack, { spacing: 6 },
2172
+ const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(VStack, { spacing: 5 },
2173
+ React.createElement(HStack, { spacing: 5 },
2174
+ !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && prettyName ? (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, prettyName)) : null,
2175
+ React.createElement(HStack, { spacing: 2 },
2176
+ isDeprecated && React.createElement(DeprecatedBadge, null),
2177
+ isInternal && React.createElement(InternalBadge, { isHttpService: true }))),
2178
+ React.createElement(MethodPath, { method: data.method, path: data.path })));
2179
+ const description = (React.createElement(VStack, { spacing: 10 },
2086
2180
  data.description && React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2087
2181
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2088
2182
  data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
@@ -2092,7 +2186,26 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2092
2186
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2093
2187
  const HttpOperation = withErrorBoundary(HttpOperationComponent, {
2094
2188
  recoverableProps: ['data'],
2095
- });
2189
+ });
2190
+ function MethodPath({ method, path }) {
2191
+ const chosenServer = useAtomValue(chosenServerAtom);
2192
+ let chosenServerUrl = '';
2193
+ if (chosenServer) {
2194
+ chosenServerUrl = chosenServer.url.endsWith('/') ? chosenServer.url.slice(0, -1) : chosenServer.url;
2195
+ }
2196
+ return (React.createElement(Box, null,
2197
+ React.createElement(MethodPathInner, { method: method, path: path, chosenServerUrl: chosenServerUrl })));
2198
+ }
2199
+ function MethodPathInner({ method, path, chosenServerUrl }) {
2200
+ const isDark = useThemeIsDark();
2201
+ const fullUrl = `${chosenServerUrl}${path}`;
2202
+ const pathElem = (React.createElement(Flex, { overflowX: "hidden" },
2203
+ chosenServerUrl ? (React.createElement(Box, { dir: "rtl", color: "muted", fontSize: "lg", textOverflow: "truncate", overflowX: "hidden" }, chosenServerUrl)) : null,
2204
+ React.createElement(Box, { fontSize: "lg", fontWeight: "semibold", flex: 1 }, path)));
2205
+ 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 },
2206
+ 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),
2207
+ pathElem));
2208
+ }
2096
2209
 
2097
2210
  const PoweredByLink = ({ source, pathname, packageType, layout = 'sidebar' }) => {
2098
2211
  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" },
@@ -2128,7 +2241,7 @@ const ExportButton = ({ original, bundled }) => {
2128
2241
  return items;
2129
2242
  }, [original, bundled]);
2130
2243
  return (React.createElement(Box, null,
2131
- 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")) })));
2244
+ 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")) })));
2132
2245
  };
2133
2246
 
2134
2247
  const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
@@ -2148,7 +2261,8 @@ const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey })
2148
2261
  const ServerInfo = ({ servers, mockUrl }) => {
2149
2262
  const mocking = React.useContext(MockingContext);
2150
2263
  const showMocking = !mocking.hideMocking && mockUrl && isProperUrl(mockUrl);
2151
- const serversToDisplay = getServersToDisplay(servers);
2264
+ const $mockUrl = showMocking ? mockUrl || mocking.mockUrl : undefined;
2265
+ const serversToDisplay = getServersToDisplay(servers, $mockUrl);
2152
2266
  if (!showMocking && serversToDisplay.length === 0) {
2153
2267
  return null;
2154
2268
  }
@@ -2157,14 +2271,11 @@ const ServerInfo = ({ servers, mockUrl }) => {
2157
2271
  React.createElement(Panel.Titlebar, { whitespace: "nowrap" }, "API Base URL"),
2158
2272
  React.createElement(Box, { overflowX: "auto" },
2159
2273
  React.createElement(Panel.Content, { w: "full", className: "sl-flex sl-flex-col" },
2160
- serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { key: index })))),
2161
- showMocking && (React.createElement(React.Fragment, null,
2162
- React.createElement(Box, { borderT: 2, pt: 2, borderColor: "light", w: "full" }),
2163
- React.createElement(ServerUrl, { description: "Mock Server", url: mockUrl || '', marginBottom: false }))))))));
2274
+ React.createElement(VStack, { spacing: 1, divider: true }, serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { key: index }))))))))));
2164
2275
  };
2165
2276
  const ServerUrl = ({ description, url, marginBottom = true }) => {
2166
2277
  const { onCopy, hasCopied } = useClipboard(url);
2167
- return (React.createElement(Box, { whitespace: "nowrap", mb: marginBottom ? 2 : 0 },
2278
+ return (React.createElement(Box, { whitespace: "nowrap" },
2168
2279
  React.createElement(Text, { pr: 2, fontWeight: "bold" },
2169
2280
  description,
2170
2281
  ":"),
@@ -2213,14 +2324,13 @@ const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOpti
2213
2324
  };
2214
2325
  const examples = React.useMemo(() => generateExamplesFromJsonSchema(data), [data]);
2215
2326
  const shouldDisplayHeader = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && (title !== undefined || (exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport)));
2216
- const header = (shouldDisplayHeader || isInternal) && (React.createElement(React.Fragment, null,
2217
- shouldDisplayHeader && (React.createElement(Flex, { justifyContent: "between", alignItems: "center" },
2218
- React.createElement(Heading$1, { size: 1, mb: 4, fontWeight: "semibold" }, title),
2219
- exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport) && React.createElement(ExportButton, Object.assign({}, exportProps)))),
2220
- isInternal && (React.createElement(HStack, { spacing: 2, mb: 12 },
2221
- React.createElement(InternalBadge, null)))));
2222
- const description = (React.createElement(React.Fragment, null,
2223
- data.description && data.type === 'object' && (React.createElement(MarkdownViewer, { className: "sl-mb-6", role: "textbox", markdown: data.description })),
2327
+ const header = (shouldDisplayHeader || isInternal) && (React.createElement(Flex, { justifyContent: "between", alignItems: "center" },
2328
+ React.createElement(HStack, { spacing: 5 },
2329
+ title && (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, title)),
2330
+ React.createElement(HStack, { spacing: 2 }, isInternal && React.createElement(InternalBadge, null))),
2331
+ exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport) && React.createElement(ExportButton, Object.assign({}, exportProps))));
2332
+ const description = (React.createElement(VStack, { spacing: 10 },
2333
+ data.description && data.type === 'object' && React.createElement(MarkdownViewer, { role: "textbox", markdown: data.description }),
2224
2334
  React.createElement(JsonSchemaViewer, { resolveRef: resolveRef, schema: getOriginalObject(data) })));
2225
2335
  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: " }));
2226
2336
  const modelExamples = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideModelExamples) && (React.createElement(Panel, { rounded: true, isCollapsible: false },
@@ -2283,6 +2393,20 @@ const Logo = ({ logo }) => {
2283
2393
  React.createElement("img", { src: logo.url, height: "30px", width: "30px", alt: logo.altText }))) : (React.createElement("img", { src: logo.url, height: "30px", width: "30px", alt: logo.altText }))));
2284
2394
  };
2285
2395
 
2396
+ function getDisplayName(WrappedComponent) {
2397
+ return WrappedComponent.displayName || WrappedComponent.name || 'Component';
2398
+ }
2399
+
2400
+ const PersistenceContextProvider = Provider;
2401
+ function withPersistenceBoundary(WrappedComponent) {
2402
+ const WithPersistenceBoundary = props => {
2403
+ return (React.createElement(PersistenceContextProvider, null,
2404
+ React.createElement(WrappedComponent, Object.assign({}, props))));
2405
+ };
2406
+ WithPersistenceBoundary.displayName = `withPersistenceBoundary(${getDisplayName(WrappedComponent)})`;
2407
+ return WithPersistenceBoundary;
2408
+ }
2409
+
2286
2410
  function useParsedValue(value) {
2287
2411
  return React.useMemo(() => {
2288
2412
  let parsedValue = value;
@@ -2327,7 +2451,8 @@ const CodeComponent = props => {
2327
2451
  if (!isObject(parsedValue) || (!isPartialHttpRequest(parsedValue) && !isHttpOperation(parsedValue))) {
2328
2452
  return null;
2329
2453
  }
2330
- return (React__default.createElement(TryIt, { httpOperation: isHttpOperation(parsedValue) ? parsedValue : parseHttpRequest(parsedValue), embeddedInMd: true }));
2454
+ return (React__default.createElement(PersistenceContextProvider, null,
2455
+ React__default.createElement(TryIt, { httpOperation: isHttpOperation(parsedValue) ? parsedValue : parseHttpRequest(parsedValue), embeddedInMd: true })));
2331
2456
  }
2332
2457
  const DefaultCode = DefaultSMDComponents.code;
2333
2458
  return React__default.createElement(DefaultCode, Object.assign({}, props));
@@ -2547,20 +2672,6 @@ const NonIdealState = ({ description, icon, title }) => {
2547
2672
  React.createElement(Text, null, description)));
2548
2673
  };
2549
2674
 
2550
- function getDisplayName(WrappedComponent) {
2551
- return WrappedComponent.displayName || WrappedComponent.name || 'Component';
2552
- }
2553
-
2554
- const PersistenceContextProvider = Provider;
2555
- function withPersistenceBoundary(WrappedComponent) {
2556
- const WithPersistenceBoundary = props => {
2557
- return (React.createElement(PersistenceContextProvider, null,
2558
- React.createElement(WrappedComponent, Object.assign({}, props))));
2559
- };
2560
- WithPersistenceBoundary.displayName = `withPersistenceBoundary(${getDisplayName(WrappedComponent)})`;
2561
- return WithPersistenceBoundary;
2562
- }
2563
-
2564
2675
  function withMosaicProvider(WrappedComponent) {
2565
2676
  const WithMosaicProvider = (props) => {
2566
2677
  try {
@@ -2605,10 +2716,11 @@ const RouterComponent = {
2605
2716
  history: BrowserRouter,
2606
2717
  memory: MemoryRouter,
2607
2718
  hash: HashRouter,
2719
+ static: StaticRouter,
2608
2720
  };
2609
- const useRouter = (router, basePath) => {
2721
+ const useRouter = (router, basePath, staticRouterPath) => {
2610
2722
  const Router = RouterComponent[router];
2611
- const routerProps = Object.assign({}, (router !== 'memory' && { basename: basePath }));
2723
+ const routerProps = Object.assign(Object.assign({}, (router !== 'memory' && { basename: basePath })), (router === 'static' && { location: staticRouterPath }));
2612
2724
  return {
2613
2725
  Router,
2614
2726
  routerProps,
@@ -2617,9 +2729,10 @@ const useRouter = (router, basePath) => {
2617
2729
 
2618
2730
  function withRouter(WrappedComponent) {
2619
2731
  const WithRouter = (props) => {
2620
- var _a, _b;
2732
+ var _a, _b, _c;
2621
2733
  const basePath = (_a = props.basePath) !== null && _a !== void 0 ? _a : '/';
2622
- const { Router, routerProps } = useRouter((_b = props.router) !== null && _b !== void 0 ? _b : 'history', basePath);
2734
+ const staticRouterPath = (_b = props.staticRouterPath) !== null && _b !== void 0 ? _b : '';
2735
+ const { Router, routerProps } = useRouter((_c = props.router) !== null && _c !== void 0 ? _c : 'history', basePath, staticRouterPath);
2623
2736
  return (React.createElement(Router, Object.assign({}, routerProps, { key: basePath }),
2624
2737
  React.createElement(Route, { path: "/" },
2625
2738
  React.createElement(MarkdownComponentsProvider, { value: { link: ReactRouterMarkdownLink } },
@@ -2793,4 +2906,4 @@ const createElementClass = (Component, propDescriptors) => {
2793
2906
  };
2794
2907
  };
2795
2908
 
2796
- 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, useBundleRefsIntoDocument, useParsedData, useParsedValue, useRouter, withMosaicProvider, withPersistenceBoundary, withQueryClientProvider, withRouter, withStyles };
2909
+ 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 };