@stoplight/elements-core 7.4.0 → 7.5.2

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.mjs 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;
@@ -720,7 +730,12 @@ const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) =
720
730
  " ",
721
731
  selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
722
732
  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 }))));
733
+ React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText, style: embeddedInMd
734
+ ? undefined
735
+ :
736
+ {
737
+ '--fs-code': 12,
738
+ } }))));
724
739
  });
725
740
 
726
741
  function getReadableSecurityName(securityScheme, includeKey = false) {
@@ -885,7 +900,14 @@ const SecuritySchemeComponent = (_a) => {
885
900
  };
886
901
  const securitySchemeKeys = ['apiKey', 'http', 'oauth2', 'openIdConnect'];
887
902
 
888
- const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
903
+ const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
904
+ function slugify(name) {
905
+ return name
906
+ .replace(/\/|{|}|\s/g, '-')
907
+ .replace(/-{2,}/, '-')
908
+ .replace(/^-/, '')
909
+ .replace(/-$/, '');
910
+ }
889
911
 
890
912
  const isApiKeySecurityScheme = (maybeIApiKey) => isObject(maybeIApiKey) && maybeIApiKey.type === 'apiKey';
891
913
  const isOAuth2SecurityScheme = (maybeIOAuth2) => isObject(maybeIOAuth2) && maybeIOAuth2.type === 'oauth2';
@@ -996,10 +1018,10 @@ function exampleValue(example) {
996
1018
  }
997
1019
  function getPlaceholderForParameter(parameter) {
998
1020
  var _a, _b;
999
- const parameterValue = getValueForParameter(parameter);
1021
+ const { value: parameterValue, isDefault } = getValueForParameter(parameter);
1000
1022
  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 : '');
1023
+ return `${isDefault ? 'defaults to' : 'example'}: ${parameterValue}`;
1024
+ return String((_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '');
1003
1025
  }
1004
1026
  function retrieveDefaultFromSchema(parameter) {
1005
1027
  var _a;
@@ -1008,22 +1030,25 @@ function retrieveDefaultFromSchema(parameter) {
1008
1030
  }
1009
1031
  const getValueForParameter = (parameter) => {
1010
1032
  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
1033
  const defaultValue = retrieveDefaultFromSchema(parameter);
1015
- if (defaultValue)
1016
- return String(defaultValue);
1034
+ if (typeof defaultValue !== 'undefined') {
1035
+ return { value: String(defaultValue), isDefault: true };
1036
+ }
1037
+ const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1038
+ if (examples.length > 0) {
1039
+ return { value: exampleValue(examples[0]) };
1040
+ }
1017
1041
  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 '';
1042
+ if (enums.length > 0) {
1043
+ return { value: String(enums[0]) };
1044
+ }
1045
+ return { value: '' };
1021
1046
  };
1022
1047
  const getInitialValueForParameter = (parameter) => {
1023
1048
  const isRequired = !!parameter.required;
1024
1049
  if (!isRequired)
1025
1050
  return '';
1026
- return getValueForParameter(parameter);
1051
+ return getValueForParameter(parameter).value;
1027
1052
  };
1028
1053
  const initialParameterValues = params => {
1029
1054
  const paramsByName = keyBy(params, (param) => param.name);
@@ -1168,7 +1193,9 @@ const RequestBody = ({ examples, requestBody, onChange }) => {
1168
1193
  return (React.createElement(Panel, { defaultIsOpen: true },
1169
1194
  React.createElement(Panel.Titlebar, { rightComponent: examples.length > 1 && React.createElement(ExampleMenu, { examples: examples, requestBody: requestBody, onChange: onChange }) }, "Body"),
1170
1195
  React.createElement(Panel.Content, { className: "TextRequestBody" },
1171
- React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0 }))));
1196
+ React.createElement(CodeEditor, { onChange: onChange, language: "json", value: requestBody, showLineNumbers: true, padding: 0, style: {
1197
+ fontSize: 12,
1198
+ } }))));
1172
1199
  };
1173
1200
  function ExampleMenu({ examples, requestBody, onChange }) {
1174
1201
  const handleClick = React.useCallback((example) => {
@@ -1426,8 +1453,8 @@ const formatMultiValueHeader = (...keyValuePairs) => {
1426
1453
  .join(', ');
1427
1454
  };
1428
1455
 
1429
- function getMockData(url, httpOperation, { isEnabled, code, dynamic, example }) {
1430
- return isEnabled && url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1456
+ function getMockData(url, httpOperation, { code, dynamic, example }) {
1457
+ return url ? { url, header: buildPreferHeader({ code, dynamic, example }, httpOperation) } : undefined;
1431
1458
  }
1432
1459
  function buildPreferHeader({ code, example, dynamic }, httpOperation) {
1433
1460
  if (!code) {
@@ -1460,23 +1487,14 @@ function supportsExample(httpOperation, code, exampleKey) {
1460
1487
  return exampleKeys.includes(exampleKey);
1461
1488
  }
1462
1489
 
1463
- const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic }, onOptionsChange, }) => {
1464
- const toggleEnabled = React.useCallback(() => {
1465
- onOptionsChange({ isEnabled: !isEnabled });
1466
- }, [isEnabled, onOptionsChange]);
1490
+ const MockingButton = ({ operation, options: { code, example, dynamic }, onOptionsChange, }) => {
1467
1491
  const operationResponses = operation.responses;
1468
1492
  const setMockingOptions = React.useCallback(({ code, example, dynamic }) => {
1469
- onOptionsChange({ isEnabled, code, example, dynamic });
1470
- }, [isEnabled, onOptionsChange]);
1493
+ onOptionsChange({ code, example, dynamic });
1494
+ }, [onOptionsChange]);
1471
1495
  const menuItems = React.useMemo(() => {
1472
1496
  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
- ];
1497
+ 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
1498
  function generateOperationResponseMenu(operationResponse) {
1481
1499
  var _a;
1482
1500
  const menuId = `response-${operationResponse.code}`;
@@ -1510,7 +1528,6 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1510
1528
  ];
1511
1529
  const menuItem = {
1512
1530
  id: menuId,
1513
- isDisabled: !isEnabled,
1514
1531
  isChecked: isActive,
1515
1532
  title: operationResponse.code,
1516
1533
  onPress: () => {
@@ -1524,13 +1541,13 @@ const MockingButton = ({ operation, options: { isEnabled, code, example, dynamic
1524
1541
  return menuItem;
1525
1542
  }
1526
1543
  return items;
1527
- }, [code, dynamic, example, isEnabled, operationResponses, setMockingOptions, toggleEnabled]);
1544
+ }, [code, dynamic, example, operationResponses, setMockingOptions]);
1528
1545
  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")) })));
1546
+ React.createElement(Menu, { "aria-label": "Mock settings", items: menuItems, renderTrigger: ({ isOpen }) => (React.createElement(FieldButton, { active: isOpen, size: "sm" }, "Mock Settings")) })));
1530
1547
  };
1531
1548
 
1532
- const persistedMockingOptionsAtom = atom({ isEnabled: false });
1533
- const useMockingOptions = () => useAtom(persistedMockingOptionsAtom);
1549
+ const mockingOptionsAtom = atom({});
1550
+ const useMockingOptions = () => useAtom(mockingOptionsAtom);
1534
1551
 
1535
1552
  const OperationParameters = ({ parameters, values, onChangeValue, validate, }) => {
1536
1553
  return (React.createElement(Panel, { defaultIsOpen: true },
@@ -1659,7 +1676,32 @@ class NetworkError extends Error {
1659
1676
  }
1660
1677
  const isNetworkError = (error) => error instanceof NetworkError;
1661
1678
 
1662
- const chosenServerAtom = atom(undefined);
1679
+ const ServersDropdown = ({ servers }) => {
1680
+ const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1681
+ const serverItems = [
1682
+ {
1683
+ type: 'option_group',
1684
+ title: 'Servers',
1685
+ value: (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || '',
1686
+ onChange: url => {
1687
+ const server = servers.find(server => server.url === url);
1688
+ setChosenServer(server);
1689
+ },
1690
+ children: [
1691
+ ...servers.map((server, i) => ({
1692
+ id: server.url,
1693
+ title: server.name || server.description,
1694
+ description: server.name ? server.description || server.url : server.description ? server.url : undefined,
1695
+ value: server.url,
1696
+ })),
1697
+ ],
1698
+ },
1699
+ ];
1700
+ 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')) }));
1701
+ };
1702
+ ServersDropdown.displayName = 'ServersDropdown';
1703
+
1704
+ const defaultServers = [];
1663
1705
  const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embeddedInMd = false, tryItCredentialsPolicy, corsProxy, }) => {
1664
1706
  var _a, _b, _c, _d, _e, _f, _g;
1665
1707
  const isDark = useThemeIsDark();
@@ -1673,18 +1715,28 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1673
1715
  const [bodyParameterValues, setBodyParameterValues, formDataState] = useBodyParameterState(mediaTypeContent);
1674
1716
  const [textRequestBody, setTextRequestBody] = useTextRequestBodyState(mediaTypeContent);
1675
1717
  const [operationAuthValue, setOperationAuthValue] = usePersistedSecuritySchemeWithValues();
1676
- const servers = getServersToDisplay(httpOperation.servers || []);
1718
+ const servers = React.useMemo(() => {
1719
+ const toDisplay = getServersToDisplay(httpOperation.servers || defaultServers, mockUrl);
1720
+ return toDisplay;
1721
+ }, [httpOperation.servers, mockUrl]);
1722
+ const firstServer = servers[0] || null;
1677
1723
  const [chosenServer, setChosenServer] = useAtom(chosenServerAtom);
1724
+ const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
1678
1725
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
1679
1726
  React.useEffect(() => {
1680
- if (!chosenServer) {
1681
- setChosenServer(servers[0]);
1727
+ const currentUrl = chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url;
1728
+ const exists = currentUrl && servers.find(s => s.url === currentUrl);
1729
+ if (!exists) {
1730
+ setChosenServer(firstServer);
1682
1731
  }
1683
- }, []);
1732
+ else if (exists !== chosenServer) {
1733
+ setChosenServer(exists);
1734
+ }
1735
+ }, [servers, firstServer, chosenServer, setChosenServer]);
1684
1736
  React.useEffect(() => {
1685
1737
  let isMounted = true;
1686
1738
  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,
1739
+ buildHarRequest(Object.assign(Object.assign({ mediaTypeContent, parameterValues: parameterValuesWithDefaults, httpOperation, bodyInput: formDataState.isFormDataBody ? bodyParameterValues : textRequestBody, auth: operationAuthValue }, (isMockingEnabled && { mockData: getMockData(mockUrl, httpOperation, mockingOptions) })), { chosenServer,
1688
1740
  corsProxy })).then(request => {
1689
1741
  if (isMounted) {
1690
1742
  if (onRequestChange) {
@@ -1711,13 +1763,13 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1711
1763
  corsProxy,
1712
1764
  embeddedInMd,
1713
1765
  ]);
1714
- const handleClick = () => __awaiter(void 0, void 0, void 0, function* () {
1766
+ const handleSendRequest = () => __awaiter(void 0, void 0, void 0, function* () {
1715
1767
  setValidateParameters(true);
1716
1768
  if (hasRequiredButEmptyParameters)
1717
1769
  return;
1718
1770
  try {
1719
1771
  setLoading(true);
1720
- const mockData = getMockData(mockUrl, httpOperation, mockingOptions);
1772
+ const mockData = isMockingEnabled ? getMockData(mockUrl, httpOperation, mockingOptions) : undefined;
1721
1773
  const request = yield buildFetchRequest({
1722
1774
  parameterValues: parameterValuesWithDefaults,
1723
1775
  httpOperation,
@@ -1754,29 +1806,32 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1754
1806
  setLoading(false);
1755
1807
  }
1756
1808
  });
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));
1809
+ const isOnlySendButton = !((_d = httpOperation.security) === null || _d === void 0 ? void 0 : _d.length) && !allParameters.length && !formDataState.isFormDataBody && !mediaTypeContent;
1810
+ const tryItPanelContents = (React.createElement(React.Fragment, null,
1811
+ ((_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,
1812
+ allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
1813
+ 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,
1814
+ React.createElement(Panel.Content, { className: "SendButtonHolder", mt: 4, pt: !isOnlySendButton && !embeddedInMd ? 0 : undefined },
1815
+ React.createElement(HStack, { alignItems: "center", spacing: 2 },
1816
+ React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleSendRequest, size: "sm" }, "Send API Request"),
1817
+ servers.length > 1 && React.createElement(ServersDropdown, { servers: servers }),
1818
+ isMockingEnabled && (React.createElement(MockingButton, { options: mockingOptions, onOptionsChange: setMockingOptions, operation: httpOperation }))),
1819
+ validateParameters && hasRequiredButEmptyParameters && (React.createElement(Box, { mt: 4, color: "danger-light", fontSize: "sm" },
1820
+ React.createElement(Icon, { icon: faExclamationTriangle, className: "sl-mr-1" }),
1821
+ "You didn't provide all of the required parameters!")))));
1822
+ let tryItPanelElem;
1823
+ if (embeddedInMd) {
1824
+ tryItPanelElem = (React.createElement(Panel, { isCollapsible: false, p: 0, className: "TryItPanel" },
1825
+ React.createElement(Panel.Titlebar, { bg: "canvas-300" },
1826
+ React.createElement(Box, { fontWeight: "bold", color: !isDark ? HttpMethodColors[httpOperation.method] : undefined }, httpOperation.method.toUpperCase()),
1827
+ React.createElement(Box, { fontWeight: "medium", ml: 2, textOverflow: "truncate", overflowX: "hidden" }, `${(chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) || ''}${httpOperation.path}`)),
1828
+ tryItPanelContents));
1829
+ }
1830
+ else {
1831
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
1832
+ }
1764
1833
  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!")))),
1834
+ tryItPanelElem,
1780
1835
  requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
1781
1836
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
1782
1837
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
@@ -1813,7 +1868,9 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
1813
1868
  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
1869
  return (React__default.createElement(Panel, { rounded: true, isCollapsible: false },
1815
1870
  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 })))));
1871
+ 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: {
1872
+ '--fs-code': 12,
1873
+ } })) : (React__default.createElement(LoadMore, { loading: loading, onClick: handleLoadMore })))));
1817
1874
  };
1818
1875
 
1819
1876
  const TryItWithRequestSamples = (_a) => {
@@ -1827,14 +1884,14 @@ const TryItWithRequestSamples = (_a) => {
1827
1884
  React.createElement(ResponseExamples, Object.assign({}, props))));
1828
1885
  };
1829
1886
 
1830
- const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(Box, { w: "full", className: className },
1887
+ const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(VStack, { w: "full", className: className, spacing: 8 },
1831
1888
  header,
1832
- React__default.createElement(Flex, { mt: header ? 12 : undefined },
1889
+ React__default.createElement(Flex, null,
1833
1890
  React__default.createElement(Box, { w: 0, flex: 1 }, left),
1834
1891
  right && (React__default.createElement(Box, { ml: 16, pos: "relative", w: "2/5", style: { maxWidth: 500 } }, right)))));
1835
1892
 
1836
1893
  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.`));
1894
+ 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
1895
  const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", border: 0, style: {
1839
1896
  backgroundColor: backgroundColor || badgeDefaultBackgroundColor,
1840
1897
  color: badgeDefaultColor,
@@ -1914,32 +1971,43 @@ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
1914
1971
  return description;
1915
1972
  }
1916
1973
 
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),
1974
+ const SectionTitle = ({ title, id, size = 2, children }) => {
1975
+ return (React.createElement(HStack, { spacing: 6 },
1976
+ React.createElement(Box, { as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
1920
1977
  children));
1921
1978
  };
1979
+ const SectionSubtitle = props => {
1980
+ return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
1981
+ };
1922
1982
  const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
1923
- return (React.createElement(Panel, { appearance: "minimal", isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange },
1983
+ return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
1924
1984
  React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
1925
1985
  React.createElement("div", { role: "heading" }, title)),
1926
- hasContent !== false && (React.createElement(Panel.Content, { pr: 3, pl: 6, p: 0 }, children))));
1986
+ hasContent !== false && React.createElement(Panel.Content, null, children)));
1927
1987
  };
1928
1988
 
1929
- const Body = ({ body: { contents = [], description }, onChange }) => {
1989
+ const isBodyEmpty = (body) => {
1990
+ if (!body)
1991
+ return true;
1992
+ const { contents = [], description } = body;
1993
+ return contents.length === 0 && !(description === null || description === void 0 ? void 0 : description.trim());
1994
+ };
1995
+ const Body = ({ body, onChange }) => {
1930
1996
  var _a;
1931
1997
  const refResolver = useInlineRefResolver();
1932
1998
  const [chosenContent, setChosenContent] = React.useState(0);
1933
1999
  React.useEffect(() => {
1934
2000
  onChange(chosenContent);
1935
2001
  }, [chosenContent]);
1936
- if (contents.length === 0 && !description)
2002
+ if (isBodyEmpty(body))
1937
2003
  return null;
2004
+ const { contents = [], description } = body;
1938
2005
  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 })))));
2006
+ return (React.createElement(VStack, { spacing: 6 },
2007
+ React.createElement(SectionSubtitle, { title: "Body", id: "request-body" }, contents.length > 0 && (React.createElement(Flex, { flex: 1, justify: "end" },
2008
+ 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" })))),
2009
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2010
+ isJSONSchema(schema) && (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, schema: getOriginalObject(schema), viewMode: "write", hideExamples: true, renderRootTreeLines: true }))));
1943
2011
  };
1944
2012
  Body.displayName = 'HttpOperation.Body';
1945
2013
 
@@ -1963,66 +2031,71 @@ const defaultStyle = {
1963
2031
  cookie: HttpParamStyles.Form,
1964
2032
  };
1965
2033
  const Parameters = ({ parameters, parameterType }) => {
1966
- if (!parameters || !parameters.length)
2034
+ const schema = React.useMemo(() => httpOperationParamsToSchema({ parameters, parameterType }), [parameters, parameterType]);
2035
+ if (!schema)
1967
2036
  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
- })));
2037
+ return React.createElement(JsonSchemaViewer, { schema: schema, disableCrumbs: true });
1971
2038
  };
1972
2039
  Parameters.displayName = 'HttpOperation.Parameters';
1973
- const Parameter = ({ parameter, parameterType }) => {
1974
- var _a, _b, _c, _d, _e;
1975
- if (!parameter)
2040
+ const httpOperationParamsToSchema = ({ parameters, parameterType }) => {
2041
+ var _a;
2042
+ if (!parameters || !parameters.length)
1976
2043
  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;
2044
+ const schema = {
2045
+ properties: {},
2046
+ required: [],
2047
+ };
2048
+ const sortedParams = sortBy(parameters, ['required', 'name']);
2049
+ for (const p of sortedParams) {
2050
+ if (!p.schema)
2051
+ continue;
2052
+ const { name, description, required, deprecated, examples, style } = p;
2053
+ const paramExamples = (examples === null || examples === void 0 ? void 0 : examples.map(example => {
2054
+ if (isNodeExample(example)) {
2055
+ return example.value;
2056
+ }
2057
+ return example.externalValue;
2058
+ })) || [];
2059
+ const schemaExamples = (_a = p.schema) === null || _a === void 0 ? void 0 : _a.examples;
2060
+ const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
2061
+ const paramDescription = description || p.schema.description;
2062
+ const paramDeprecated = deprecated || p.schema.deprecated;
2063
+ const paramStyle = style && defaultStyle[parameterType] !== style ? readableStyles[style] || style : undefined;
2064
+ schema.properties[p.name] = Object.assign(Object.assign({}, p.schema), { description: paramDescription, examples: [...paramExamples, ...schemaExamplesArray], deprecated: paramDeprecated, style: paramStyle });
2065
+ if (required) {
2066
+ schema.required.push(name);
1985
2067
  }
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';
2068
+ }
2069
+ return schema;
2070
+ };
2007
2071
 
2008
- const Request = ({ operation: { path, method, request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
2072
+ const Request = ({ operation: { request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
2009
2073
  if (!request || typeof request !== 'object')
2010
2074
  return null;
2075
+ const bodyIsEmpty = isBodyEmpty(body);
2011
2076
  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,
2077
+ const hasRequestData = Boolean(securitySchemes.length ||
2078
+ pathParams.length ||
2079
+ queryParams.length ||
2080
+ headerParams.length ||
2081
+ cookieParams.length ||
2082
+ !bodyIsEmpty);
2083
+ if (!hasRequestData)
2084
+ return null;
2085
+ return (React.createElement(VStack, { spacing: 8 },
2017
2086
  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" },
2087
+ securitySchemes.length > 0 && (React.createElement(VStack, { spacing: 3 }, securitySchemes.map((scheme, i) => (React.createElement(SecurityPanel, { key: i, scheme: scheme, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))))),
2088
+ pathParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2089
+ React.createElement(SectionSubtitle, { title: "Path Parameters" }),
2090
+ React.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
2091
+ queryParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2092
+ React.createElement(SectionSubtitle, { title: "Query Parameters" }),
2022
2093
  React.createElement(Parameters, { parameterType: "query", parameters: queryParams }))),
2023
- headerParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Headers" },
2094
+ headerParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2095
+ React.createElement(SectionSubtitle, { title: "Headers", id: "request-headers" }),
2024
2096
  React.createElement(Parameters, { parameterType: "header", parameters: headerParams }))),
2025
- cookieParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Cookie" },
2097
+ cookieParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2098
+ React.createElement(SectionSubtitle, { title: "Cookies", id: "request-cookies" }),
2026
2099
  React.createElement(Parameters, { parameterType: "cookie", parameters: cookieParams }))),
2027
2100
  body && React.createElement(Body, { onChange: onChange, body: body })));
2028
2101
  };
@@ -2043,15 +2116,15 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2043
2116
  }, [activeResponseId]);
2044
2117
  if (!responses.length)
2045
2118
  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 }))))))));
2119
+ return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2120
+ React.createElement(SectionTitle, { title: "Responses" },
2121
+ React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2122
+ React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2123
+ React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
2052
2124
  };
2053
2125
  Responses.displayName = 'HttpOperation.Responses';
2054
- const Response = ({ response: { contents = [], headers = [], description }, onMediaTypeChange }) => {
2126
+ const Response = ({ response, onMediaTypeChange }) => {
2127
+ const { contents = [], headers = [], description } = response;
2055
2128
  const [chosenContent, setChosenContent] = React.useState(0);
2056
2129
  const refResolver = useInlineRefResolver();
2057
2130
  const responseContent = contents[chosenContent];
@@ -2059,14 +2132,31 @@ const Response = ({ response: { contents = [], headers = [], description }, onMe
2059
2132
  React.useEffect(() => {
2060
2133
  responseContent && onMediaTypeChange(responseContent.mediaType);
2061
2134
  }, [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" },
2135
+ return (React.createElement(VStack, { spacing: 8, pt: 8 },
2136
+ description && React.createElement(MarkdownViewer, { markdown: description }),
2137
+ headers.length > 0 && (React.createElement(VStack, { spacing: 5 },
2138
+ React.createElement(SectionSubtitle, { title: "Headers", id: "response-headers" }),
2065
2139
  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 })))))));
2140
+ contents.length > 0 && (React.createElement(React.Fragment, null,
2141
+ React.createElement(SectionSubtitle, { title: "Body", id: "response-body" },
2142
+ React.createElement(Flex, { flex: 1, justify: "end" },
2143
+ 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" }))),
2144
+ schema && (React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, viewMode: "read", hideExamples: true, parentCrumbs: ['responses', response.code], renderRootTreeLines: true }))))));
2068
2145
  };
2069
- Response.displayName = 'HttpOperation.Response';
2146
+ Response.displayName = 'HttpOperation.Response';
2147
+ const codeToIntentVal = (code) => {
2148
+ const firstChar = code.charAt(0);
2149
+ switch (firstChar) {
2150
+ case '2':
2151
+ return 'success';
2152
+ case '4':
2153
+ return 'warning';
2154
+ case '5':
2155
+ return 'danger';
2156
+ default:
2157
+ return 'default';
2158
+ }
2159
+ };
2070
2160
 
2071
2161
  const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
2072
2162
  const data = useResolvedObject(unresolvedData);
@@ -2076,13 +2166,16 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2076
2166
  const [responseMediaType, setResponseMediaType] = React.useState('');
2077
2167
  const [responseStatusCode, setResponseStatusCode] = React.useState('');
2078
2168
  const [requestBodyIndex, setTextRequestBodyIndex] = React.useState(0);
2169
+ const prettyName = (data.summary || data.iid || '').trim();
2079
2170
  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 },
2171
+ const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(VStack, { spacing: 5 },
2172
+ React.createElement(HStack, { spacing: 5 },
2173
+ !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) && prettyName ? (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, prettyName)) : null,
2174
+ React.createElement(HStack, { spacing: 2 },
2175
+ isDeprecated && React.createElement(DeprecatedBadge, null),
2176
+ isInternal && React.createElement(InternalBadge, { isHttpService: true }))),
2177
+ React.createElement(MethodPath, { method: data.method, path: data.path })));
2178
+ const description = (React.createElement(VStack, { spacing: 10 },
2086
2179
  data.description && React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2087
2180
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2088
2181
  data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
@@ -2092,7 +2185,26 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2092
2185
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2093
2186
  const HttpOperation = withErrorBoundary(HttpOperationComponent, {
2094
2187
  recoverableProps: ['data'],
2095
- });
2188
+ });
2189
+ function MethodPath({ method, path }) {
2190
+ const chosenServer = useAtomValue(chosenServerAtom);
2191
+ let chosenServerUrl = '';
2192
+ if (chosenServer) {
2193
+ chosenServerUrl = chosenServer.url.endsWith('/') ? chosenServer.url.slice(0, -1) : chosenServer.url;
2194
+ }
2195
+ return (React.createElement(Box, null,
2196
+ React.createElement(MethodPathInner, { method: method, path: path, chosenServerUrl: chosenServerUrl })));
2197
+ }
2198
+ function MethodPathInner({ method, path, chosenServerUrl }) {
2199
+ const isDark = useThemeIsDark();
2200
+ const fullUrl = `${chosenServerUrl}${path}`;
2201
+ const pathElem = (React.createElement(Flex, { overflowX: "hidden" },
2202
+ chosenServerUrl ? (React.createElement(Box, { dir: "rtl", color: "muted", fontSize: "lg", textOverflow: "truncate", overflowX: "hidden" }, chosenServerUrl)) : null,
2203
+ React.createElement(Box, { fontSize: "lg", fontWeight: "semibold", flex: 1 }, path)));
2204
+ 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 },
2205
+ 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),
2206
+ pathElem));
2207
+ }
2096
2208
 
2097
2209
  const PoweredByLink = ({ source, pathname, packageType, layout = 'sidebar' }) => {
2098
2210
  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 +2240,7 @@ const ExportButton = ({ original, bundled }) => {
2128
2240
  return items;
2129
2241
  }, [original, bundled]);
2130
2242
  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")) })));
2243
+ 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
2244
  };
2133
2245
 
2134
2246
  const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
@@ -2148,7 +2260,8 @@ const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey })
2148
2260
  const ServerInfo = ({ servers, mockUrl }) => {
2149
2261
  const mocking = React.useContext(MockingContext);
2150
2262
  const showMocking = !mocking.hideMocking && mockUrl && isProperUrl(mockUrl);
2151
- const serversToDisplay = getServersToDisplay(servers);
2263
+ const $mockUrl = showMocking ? mockUrl || mocking.mockUrl : undefined;
2264
+ const serversToDisplay = getServersToDisplay(servers, $mockUrl);
2152
2265
  if (!showMocking && serversToDisplay.length === 0) {
2153
2266
  return null;
2154
2267
  }
@@ -2157,14 +2270,11 @@ const ServerInfo = ({ servers, mockUrl }) => {
2157
2270
  React.createElement(Panel.Titlebar, { whitespace: "nowrap" }, "API Base URL"),
2158
2271
  React.createElement(Box, { overflowX: "auto" },
2159
2272
  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 }))))))));
2273
+ React.createElement(VStack, { spacing: 1, divider: true }, serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { key: index }))))))))));
2164
2274
  };
2165
2275
  const ServerUrl = ({ description, url, marginBottom = true }) => {
2166
2276
  const { onCopy, hasCopied } = useClipboard(url);
2167
- return (React.createElement(Box, { whitespace: "nowrap", mb: marginBottom ? 2 : 0 },
2277
+ return (React.createElement(Box, { whitespace: "nowrap" },
2168
2278
  React.createElement(Text, { pr: 2, fontWeight: "bold" },
2169
2279
  description,
2170
2280
  ":"),
@@ -2213,14 +2323,13 @@ const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOpti
2213
2323
  };
2214
2324
  const examples = React.useMemo(() => generateExamplesFromJsonSchema(data), [data]);
2215
2325
  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 })),
2326
+ const header = (shouldDisplayHeader || isInternal) && (React.createElement(Flex, { justifyContent: "between", alignItems: "center" },
2327
+ React.createElement(HStack, { spacing: 5 },
2328
+ title && (React.createElement(Heading$1, { size: 1, fontWeight: "semibold" }, title)),
2329
+ React.createElement(HStack, { spacing: 2 }, isInternal && React.createElement(InternalBadge, null))),
2330
+ exportProps && !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideExport) && React.createElement(ExportButton, Object.assign({}, exportProps))));
2331
+ const description = (React.createElement(VStack, { spacing: 10 },
2332
+ data.description && data.type === 'object' && React.createElement(MarkdownViewer, { role: "textbox", markdown: data.description }),
2224
2333
  React.createElement(JsonSchemaViewer, { resolveRef: resolveRef, schema: getOriginalObject(data) })));
2225
2334
  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
2335
  const modelExamples = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideModelExamples) && (React.createElement(Panel, { rounded: true, isCollapsible: false },
@@ -2605,10 +2714,11 @@ const RouterComponent = {
2605
2714
  history: BrowserRouter,
2606
2715
  memory: MemoryRouter,
2607
2716
  hash: HashRouter,
2717
+ static: StaticRouter,
2608
2718
  };
2609
- const useRouter = (router, basePath) => {
2719
+ const useRouter = (router, basePath, staticRouterPath) => {
2610
2720
  const Router = RouterComponent[router];
2611
- const routerProps = Object.assign({}, (router !== 'memory' && { basename: basePath }));
2721
+ const routerProps = Object.assign(Object.assign({}, (router !== 'memory' && { basename: basePath })), (router === 'static' && { location: staticRouterPath }));
2612
2722
  return {
2613
2723
  Router,
2614
2724
  routerProps,
@@ -2617,9 +2727,10 @@ const useRouter = (router, basePath) => {
2617
2727
 
2618
2728
  function withRouter(WrappedComponent) {
2619
2729
  const WithRouter = (props) => {
2620
- var _a, _b;
2730
+ var _a, _b, _c;
2621
2731
  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);
2732
+ const staticRouterPath = (_b = props.staticRouterPath) !== null && _b !== void 0 ? _b : '';
2733
+ const { Router, routerProps } = useRouter((_c = props.router) !== null && _c !== void 0 ? _c : 'history', basePath, staticRouterPath);
2623
2734
  return (React.createElement(Router, Object.assign({}, routerProps, { key: basePath }),
2624
2735
  React.createElement(Route, { path: "/" },
2625
2736
  React.createElement(MarkdownComponentsProvider, { value: { link: ReactRouterMarkdownLink } },
@@ -2793,4 +2904,4 @@ const createElementClass = (Component, propDescriptors) => {
2793
2904
  };
2794
2905
  };
2795
2906
 
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 };
2907
+ 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 };