@stoplight/elements-core 7.4.1 → 7.5.0

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