@stoplight/elements-core 7.3.11 → 7.4.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.mjs CHANGED
@@ -2,32 +2,56 @@ import { __rest, __awaiter } from 'tslib';
2
2
  import * as React from 'react';
3
3
  import React__default, { useContext, useMemo } from 'react';
4
4
  import { resolveInlineRef, isPlainObject as isPlainObject$1, safeParse, safeStringify } from '@stoplight/json';
5
- import _, { isObject, isPlainObject, isArray, throttle, filter, capitalize, flatten, curry, map, omit, pickBy, isString, compact, uniq, uniqBy, orderBy, sortBy, get, omitBy, isEmpty, keys, entries, mapValues, isEqual } from 'lodash';
5
+ import isArray from 'lodash/isArray.js';
6
+ import isObject from 'lodash/isObject.js';
7
+ import isPlainObject from 'lodash/isPlainObject.js';
6
8
  import { parse } from '@stoplight/markdown';
7
9
  import { NodeType, HttpParamStyles } from '@stoplight/types';
8
10
  import { parse as parse$1 } from '@stoplight/yaml';
9
- import { isArray as isArray$1, Flex, Box, Popover, Button, Panel, CopyButton, Menu, Text, Input, Icon, Select, Image, Link, useThemeIsDark, Tooltip, VStack, InvertTheme, Badge, Tabs, TabList, Tab, TabPanels, TabPanel, Heading as Heading$1, HStack, useClipboard, 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, 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';
10
12
  import { withErrorBoundary } from '@stoplight/react-error-boundary';
11
13
  import { MarkdownViewer as MarkdownViewer$1, DefaultSMDComponents, MarkdownViewerProvider } from '@stoplight/markdown-viewer';
12
14
  export { DefaultSMDComponents } from '@stoplight/markdown-viewer';
13
- import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faExclamationTriangle, faEye, faLock, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
14
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
15
+ import { faStream, faCrosshairs, faCloud, faBookOpen, faCube, faDatabase, faQuestionCircle, faExclamationCircle, faExclamationTriangle, faEye, faBolt, faCopy, faCheck } from '@fortawesome/free-solid-svg-icons';
16
+ import throttle from 'lodash/throttle.js';
15
17
  import { selectAll } from 'unist-util-select';
16
18
  import cn from 'classnames';
17
19
  import { atom, useAtom, Provider } from 'jotai';
18
20
  import URI from 'urijs';
19
21
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
20
22
  import HTTPSnippet from 'httpsnippet';
23
+ import flatten from 'lodash/flatten.js';
24
+ import capitalize from 'lodash/capitalize.js';
25
+ import filter from 'lodash/filter.js';
21
26
  import { nanoid } from 'nanoid';
27
+ import curry from 'lodash/curry.js';
28
+ import omit from 'lodash/omit.js';
29
+ import keyBy from 'lodash/keyBy.js';
30
+ import map from 'lodash/map.js';
31
+ import mapValues from 'lodash/mapValues.js';
32
+ import isString from 'lodash/isString.js';
33
+ import pickBy from 'lodash/pickBy.js';
22
34
  import { CodeEditor } from '@stoplight/mosaic-code-editor';
23
35
  import * as Sampler from '@stoplight/json-schema-sampler';
36
+ import compact from 'lodash/compact.js';
37
+ import uniq from 'lodash/uniq.js';
38
+ import orderBy from 'lodash/orderBy.js';
39
+ import uniqBy from 'lodash/uniqBy.js';
24
40
  import formatXml from 'xml-formatter';
25
- import { Link as Link$1, useLocation, BrowserRouter, MemoryRouter, HashRouter, Route } from 'react-router-dom';
41
+ import { atomWithStorage } from 'jotai/utils';
42
+ import entries from 'lodash/entries.js';
43
+ import keys from 'lodash/keys.js';
26
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';
48
+ import sortBy from 'lodash/sortBy.js';
49
+ import { useLocation, BrowserRouter, MemoryRouter, HashRouter, Route } from 'react-router-dom';
27
50
  import { HashLink } from 'react-router-hash-link';
28
51
  import { QueryClient, useQueryClient, QueryClientProvider } from 'react-query';
29
52
  import $RefParser from '@stoplight/json-schema-ref-parser';
30
53
  import * as PropTypes from 'prop-types';
54
+ import isEqual from 'lodash/isEqual.js';
31
55
  import * as ReactDOM from 'react-dom';
32
56
 
33
57
  const defaultResolver = (contextObject) => ({ pointer }, _, currentObject) => {
@@ -262,15 +286,15 @@ const ArticleHeadings = ({ tree, container }) => {
262
286
  const { width } = useComponentSize(container);
263
287
  const showHeadings = width >= 768;
264
288
  const headings = useComputeMarkdownHeadings(tree);
265
- return React.createElement(Headings, { className: "ArticleHeadings", headings: headings, minimal: !showHeadings });
289
+ return React.createElement(Headings, { className: "ArticleHeadings", headings: headings, minimal: !showHeadings, maxWidth: 300 });
266
290
  };
267
- const Headings = ({ headings, className, title = 'On This Page', minimal }) => {
291
+ const Headings = ({ headings, className, title = 'On This Page', minimal, maxWidth }) => {
268
292
  const locationHash = useLocationHash();
269
293
  if (!headings || !headings.length)
270
294
  return null;
271
- const component = (React.createElement("div", { style: { maxHeight: '85vh', overflow: 'auto' } },
295
+ const component = (React.createElement(Box, { overflowY: "auto", style: { maxHeight: '85vh', maxWidth } },
272
296
  title && (React.createElement(Flex, { py: 2, alignItems: "center", fontSize: "sm", fontWeight: "medium", color: "muted", style: { paddingLeft: 18 } },
273
- React.createElement(FontAwesomeIcon, { icon: faStream, className: "sl-mr-2" }),
297
+ React.createElement(Box, { as: Icon, icon: faStream, mr: 2 }),
274
298
  title)),
275
299
  headings.map((heading, i) => (React.createElement(Heading, { key: i, item: heading, isSelected: locationHash === `#${heading.id}` })))));
276
300
  if (minimal) {
@@ -290,7 +314,7 @@ const ArticleComponent = React.memo(({ data }) => {
290
314
  const tree = React.useMemo(() => (typeof data === 'object' ? data : parse(data)), [data]);
291
315
  if (tree === null)
292
316
  return null;
293
- return (React.createElement(Flex, { className: "sl-elements-article", w: "full", pos: "relative", ref: setContainer },
317
+ return (React.createElement(Flex, { className: "sl-elements-article", justifyContent: "evenly", w: "full", pos: "relative", ref: setContainer },
294
318
  React.createElement(Box, { className: "sl-elements-article-content", style: { width: 0 }, flex: 1 },
295
319
  React.createElement(MarkdownViewer, { markdown: tree })),
296
320
  React.createElement(ArticleHeadings, { tree: tree, container: container })));
@@ -311,38 +335,6 @@ function createNamedContext(name, defaultValue) {
311
335
  return context;
312
336
  }
313
337
 
314
- function getReadableSecurityName(securityScheme, includeKey = false) {
315
- let name = '';
316
- switch (securityScheme.type) {
317
- case 'apiKey':
318
- name = 'API Key';
319
- break;
320
- case 'http':
321
- name = `${capitalize(securityScheme.scheme)} Auth`;
322
- break;
323
- case 'oauth2':
324
- name = 'OAuth 2.0';
325
- break;
326
- case 'openIdConnect':
327
- name = 'OpenID Connect';
328
- break;
329
- case 'mutualTLS':
330
- name = 'Mutual TLS';
331
- break;
332
- }
333
- return includeKey ? `${name} (${securityScheme.key})` : name;
334
- }
335
- function getServiceUriFromOperation(uri) {
336
- const match = uri === null || uri === void 0 ? void 0 : uri.match(/(.*)\/(paths|operations)/);
337
- return match && match.length > 1 ? match[1] || '/' : undefined;
338
- }
339
- const isOAuth2ImplicitFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && !('tokenUrl' in maybeFlow);
340
- const isOauth2AuthorizationCodeFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && 'tokenUrl' in maybeFlow;
341
- const isOauth2ClientCredentialsOrPasswordFlow = (maybeFlow) => isObject(maybeFlow) && !('authorizationUrl' in maybeFlow) && 'tokenUrl' in maybeFlow;
342
- function shouldIncludeKey(schemes, type) {
343
- return filter(schemes, { type }).length > 1;
344
- }
345
-
346
338
  const NodeTypeColors = {
347
339
  http_operation: '#6a6acb',
348
340
  http_service: '#e056fd',
@@ -731,6 +723,34 @@ const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) =
731
723
  React__default.createElement(CodeViewer, { "aria-label": requestSample !== null && requestSample !== void 0 ? requestSample : fallbackText, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample || fallbackText }))));
732
724
  });
733
725
 
726
+ function getReadableSecurityName(securityScheme, includeKey = false) {
727
+ let name = '';
728
+ switch (securityScheme.type) {
729
+ case 'apiKey':
730
+ name = 'API Key';
731
+ break;
732
+ case 'http':
733
+ name = `${capitalize(securityScheme.scheme)} Auth`;
734
+ break;
735
+ case 'oauth2':
736
+ name = 'OAuth 2.0';
737
+ break;
738
+ case 'openIdConnect':
739
+ name = 'OpenID Connect';
740
+ break;
741
+ case 'mutualTLS':
742
+ name = 'Mutual TLS';
743
+ break;
744
+ }
745
+ return includeKey ? `${name} (${securityScheme.key})` : name;
746
+ }
747
+ const isOAuth2ImplicitFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && !('tokenUrl' in maybeFlow);
748
+ const isOauth2AuthorizationCodeFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && 'tokenUrl' in maybeFlow;
749
+ const isOauth2ClientCredentialsOrPasswordFlow = (maybeFlow) => isObject(maybeFlow) && !('authorizationUrl' in maybeFlow) && 'tokenUrl' in maybeFlow;
750
+ function shouldIncludeKey(schemes, type) {
751
+ return filter(schemes, { type }).length > 1;
752
+ }
753
+
734
754
  const useUniqueId = (prefix = 'id_') => React.useRef(`${prefix}${nanoid(8)}`).current;
735
755
 
736
756
  const AuthTokenInput = ({ type, name, value, onChange }) => {
@@ -1006,10 +1026,8 @@ const getInitialValueForParameter = (parameter) => {
1006
1026
  return getValueForParameter(parameter);
1007
1027
  };
1008
1028
  const initialParameterValues = params => {
1009
- return _.chain(params)
1010
- .keyBy((param) => param.name)
1011
- .mapValues(param => getInitialValueForParameter(param))
1012
- .value();
1029
+ const paramsByName = keyBy(params, (param) => param.name);
1030
+ return mapValues(paramsByName, param => getInitialValueForParameter(param));
1013
1031
  };
1014
1032
  function mapSchemaPropertiesToParameters(properties, required) {
1015
1033
  return Object.entries(properties).map(([name, schema]) => (Object.assign({ name, schema: typeof schema !== 'boolean' ? schema : undefined, examples: typeof schema !== 'boolean' && schema.examples ? [{ key: 'example', value: schema.examples }] : undefined }, ((required === null || required === void 0 ? void 0 : required.includes(name)) && { required: true }))));
@@ -1235,7 +1253,6 @@ const generateExamplesFromJsonSchema = (schema) => {
1235
1253
  : [{ label: 'default', data: '' }];
1236
1254
  }
1237
1255
  catch (e) {
1238
- console.error(e);
1239
1256
  return [{ label: '', data: `Example cannot be created for this schema\n${e}` }];
1240
1257
  }
1241
1258
  };
@@ -1611,7 +1628,7 @@ const TryItResponse = ({ response }) => {
1611
1628
  ? parseBody(response.bodyText, responseType)
1612
1629
  : response.bodyText })) : response.blob && responseType === 'image' ? (React.createElement(Flex, { justifyContent: "center" },
1613
1630
  React.createElement(Image, { src: URL.createObjectURL(response.blob), alt: "response image" }))) : (React.createElement("p", null,
1614
- React.createElement(FontAwesomeIcon, { icon: faExclamationCircle, className: "sl-mr-2" }),
1631
+ React.createElement(Box, { as: Icon, icon: faExclamationCircle, mr: 2 }),
1615
1632
  "No supported response body returned"))))));
1616
1633
  };
1617
1634
  const ResponseMenu = ({ types, type, onChange }) => {
@@ -1665,18 +1682,22 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
1665
1682
  }
1666
1683
  }, []);
1667
1684
  React.useEffect(() => {
1668
- let isActive = true;
1685
+ let isMounted = true;
1669
1686
  if (onRequestChange || embeddedInMd) {
1670
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,
1671
1688
  corsProxy })).then(request => {
1672
- if (onRequestChange && isActive)
1673
- onRequestChange(request);
1674
- if (embeddedInMd)
1675
- setRequestData(request);
1689
+ if (isMounted) {
1690
+ if (onRequestChange) {
1691
+ onRequestChange(request);
1692
+ }
1693
+ if (embeddedInMd) {
1694
+ setRequestData(request);
1695
+ }
1696
+ }
1676
1697
  });
1677
1698
  }
1678
1699
  return () => {
1679
- isActive = false;
1700
+ isMounted = false;
1680
1701
  };
1681
1702
  }, [
1682
1703
  httpOperation,
@@ -1809,18 +1830,13 @@ const TryItWithRequestSamples = (_a) => {
1809
1830
  const TwoColumnLayout = ({ header, right, left, className }) => (React__default.createElement(Box, { w: "full", className: className },
1810
1831
  header,
1811
1832
  React__default.createElement(Flex, { mt: header ? 12 : undefined },
1812
- React__default.createElement(Box, { style: { width: 0 }, flex: 1 }, left),
1833
+ React__default.createElement(Box, { w: 0, flex: 1 }, left),
1813
1834
  right && (React__default.createElement(Box, { ml: 16, pos: "relative", w: "2/5", style: { maxWidth: 500 } }, right)))));
1814
1835
 
1815
1836
  const DeprecatedBadge = () => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { intent: "warning", icon: faExclamationCircle, "data-testid": "badge-deprecated" }, "Deprecated") }, "This operation has been marked as deprecated, which means it could be removed at some point in the future."));
1816
- const InternalBadge = ({ isHttpService }) => (React__default.createElement(Tooltip, { renderTrigger: React__default.createElement(Badge, { icon: faEye, "data-testid": "badge-internal", className: "sl-bg-danger sl-ml-0" }, "Internal") }, `This ${isHttpService ? 'operation' : 'model'} is marked as internal and won't be visible in public docs.`));
1817
- const SecurityBadge = ({ scheme, httpServiceUri, includeKey }) => {
1818
- const badge = (React__default.createElement(Badge, { icon: faLock, "data-testid": "badge-security", className: "sl-truncate", style: { backgroundColor: badgeDefaultBackgroundColor, color: badgeDefaultColor } }, getReadableSecurityName(scheme, includeKey)));
1819
- return httpServiceUri ? (React__default.createElement(Link$1, { to: `${httpServiceUri}?security=${scheme.key}`, className: "sl-no-underline sl-block" }, badge)) : (badge);
1820
- };
1821
- const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", style: {
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.`));
1838
+ const VersionBadge = ({ value, backgroundColor }) => (React__default.createElement(Badge, { appearance: "solid", size: "sm", border: 0, style: {
1822
1839
  backgroundColor: backgroundColor || badgeDefaultBackgroundColor,
1823
- border: 'none',
1824
1840
  color: badgeDefaultColor,
1825
1841
  } }, enhanceVersionString(value)));
1826
1842
  const enhanceVersionString = (version) => {
@@ -1829,16 +1845,85 @@ const enhanceVersionString = (version) => {
1829
1845
  return `v${version}`;
1830
1846
  };
1831
1847
 
1848
+ const oauthFlowNames = {
1849
+ implicit: 'Implicit',
1850
+ authorizationCode: 'Authorization Code',
1851
+ clientCredentials: 'Client Credentials',
1852
+ password: 'Password',
1853
+ };
1854
+ function getDefaultDescription(scheme) {
1855
+ switch (scheme.type) {
1856
+ case 'apiKey':
1857
+ return getApiKeyDescription(scheme.in, scheme.name);
1858
+ case 'http':
1859
+ switch (scheme.scheme) {
1860
+ case 'basic':
1861
+ return getBasicAuthDescription();
1862
+ case 'bearer':
1863
+ return getBearerAuthDescription();
1864
+ case 'digest':
1865
+ return getDigestAuthDescription();
1866
+ }
1867
+ case 'oauth2':
1868
+ return getOAuthDescription(scheme);
1869
+ }
1870
+ return '';
1871
+ }
1872
+ function getApiKeyDescription(inProperty, name) {
1873
+ return `An API key is a token that you provide when making API calls. Include the token in a ${inProperty} parameter called \`${name}\`.
1874
+
1875
+ Example: ${inProperty === 'query' ? `\`?${name}=123\`` : `\`${name}: 123\``}`;
1876
+ }
1877
+ function getBasicAuthDescription() {
1878
+ return `Basic authentication is a simple authentication scheme built into the HTTP protocol.
1879
+ To use it, send your HTTP requests with an Authorization header that contains the word Basic
1880
+ followed by a space and a base64-encoded string \`username:password\`.
1881
+
1882
+ Example: \`Authorization: Basic ZGVtbzpwQDU1dzByZA==\``;
1883
+ }
1884
+ function getBearerAuthDescription() {
1885
+ return `Provide your bearer token in the Authorization header when making requests to protected resources.
1886
+
1887
+ Example: \`Authorization: Bearer 123\``;
1888
+ }
1889
+ function getDigestAuthDescription() {
1890
+ return `Provide your encrypted digest scheme data in the Authorization header when making requests to protected resources.
1891
+
1892
+ Example: \`Authorization: Digest username=guest, realm="test", nonce="2", uri="/uri", response="123"\``;
1893
+ }
1894
+ function getOAuthDescription(scheme) {
1895
+ const flows = keys(scheme.flows);
1896
+ return flows.map(flow => getOAuthFlowDescription(oauthFlowNames[flow], scheme.flows[flow])).join('\n\n');
1897
+ }
1898
+ function getOAuthFlowDescription(title, flow) {
1899
+ let description = `**${title} OAuth Flow**`;
1900
+ description +=
1901
+ isOAuth2ImplicitFlow(flow) || isOauth2AuthorizationCodeFlow(flow)
1902
+ ? `\n\nAuthorize URL: ${flow.authorizationUrl}`
1903
+ : '';
1904
+ description +=
1905
+ isOauth2AuthorizationCodeFlow(flow) || isOauth2ClientCredentialsOrPasswordFlow(flow)
1906
+ ? `\n\nToken URL: ${flow.tokenUrl}`
1907
+ : '';
1908
+ description += flow.refreshUrl ? `\n\nRefresh URL: ${flow.refreshUrl}` : '';
1909
+ const scopes = entries(flow.scopes);
1910
+ if (scopes.length) {
1911
+ description += `\n\nScopes:
1912
+ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
1913
+ }
1914
+ return description;
1915
+ }
1916
+
1832
1917
  const SectionTitle = ({ title, children }) => {
1833
1918
  return (React.createElement(Flex, { role: "heading", borderB: true, mb: 3, pb: 3, "aria-label": title, align: "baseline" },
1834
1919
  React.createElement(Text, { size: "xl", fontWeight: "semibold", mr: 5 }, title),
1835
1920
  children));
1836
1921
  };
1837
- const SubSectionPanel = ({ title, children, hasContent, rightComponent }) => {
1838
- return (React.createElement(Panel, { appearance: "minimal", isCollapsible: hasContent, defaultIsOpen: true },
1922
+ const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
1923
+ return (React.createElement(Panel, { appearance: "minimal", isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange },
1839
1924
  React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
1840
1925
  React.createElement("div", { role: "heading" }, title)),
1841
- hasContent !== false && (React.createElement(Panel.Content, { pr: 3, className: "sl-py-0 sl-pl-0" }, children))));
1926
+ hasContent !== false && (React.createElement(Panel.Content, { pr: 3, pl: 6, p: 0 }, children))));
1842
1927
  };
1843
1928
 
1844
1929
  const Body = ({ body: { contents = [], description }, onChange }) => {
@@ -1880,7 +1965,7 @@ const defaultStyle = {
1880
1965
  const Parameters = ({ parameters, parameterType }) => {
1881
1966
  if (!parameters || !parameters.length)
1882
1967
  return null;
1883
- return (React.createElement(VStack, { spacing: 2, pl: 6, divider: React.createElement(Box, { borderT: true, borderColor: "light", w: "full" }) }, sortBy(parameters, ['required', 'name']).map(parameter => {
1968
+ return (React.createElement(VStack, { spacing: 2, divider: React.createElement(Box, { borderT: true, borderColor: "light", w: "full" }) }, sortBy(parameters, ['required', 'name']).map(parameter => {
1884
1969
  return React.createElement(Parameter, { key: parameter.name, parameter: parameter, parameterType: parameterType });
1885
1970
  })));
1886
1971
  };
@@ -1903,32 +1988,34 @@ const Parameter = ({ parameter, parameterType }) => {
1903
1988
  const schemaExamples = (_e = parameter.schema) === null || _e === void 0 ? void 0 : _e.examples;
1904
1989
  const schemaExamplesArray = Array.isArray(schemaExamples) ? schemaExamples : [];
1905
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');
1906
- return (React.createElement("div", { className: "HttpOperation__Parameters" },
1907
- React.createElement("div", { className: "sl-flex sl-items-center sl-my-2" },
1908
- React.createElement("div", { className: "sl-flex sl-items-baseline sl-text-base sl-flex-1" },
1909
- React.createElement("div", { className: "sl-font-mono sl-font-bold" }, parameter.name),
1910
- React.createElement("div", { className: 'sl-ml-2 sl-text-muted' }, format ? `${type}<${format}>` : type)),
1911
- React.createElement("div", { className: "sl-text-sm sl-text-warning" },
1912
- deprecated && React.createElement("span", { className: "sl-ml-2" }, "deprecated"),
1913
- parameter.required && React.createElement("span", { className: "sl-ml-2" }, "required"))),
1914
- description && (React.createElement("div", { className: "sl-w-full sl-text-muted sl-text-sm sl-my-2" },
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 },
1915
2000
  React.createElement(MarkdownViewer$1, { markdown: description }))),
1916
- React.createElement("div", { className: "sl-text-sm" },
2001
+ React.createElement(Box, { fontSize: "sm" },
1917
2002
  React.createElement(Validations, { validations: validations })),
1918
- parameter.style && defaultStyle[parameterType] !== parameter.style && (React.createElement("div", { className: "sl-flex sl-my-2" },
1919
- React.createElement("span", { className: "sl-px-1 sl-text-muted sl-font-mono sl-border sl-rounded-lg sl-text-sm sl-capitalize", style: { backgroundColor: '#EDF2F7' } }, readableStyles[parameter.style] || parameter.style)))));
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)))));
1920
2005
  };
1921
2006
  Parameter.displayName = 'HttpOperation.Parameter';
1922
2007
 
1923
2008
  const Request = ({ operation: { path, method, request, request: { path: pathParams = [], headers: headerParams = [], cookie: cookieParams = [], body, query: queryParams = [], } = {}, security, }, onChange, }) => {
1924
2009
  if (!request || typeof request !== 'object')
1925
2010
  return null;
1926
- const pathParamBlock = (React.createElement("div", null,
2011
+ const securitySchemes = flatten(security);
2012
+ const pathParamBlock = (React.createElement(Box, null,
1927
2013
  React.createElement(Text, { textTransform: "uppercase", mr: 1, color: HttpMethodColors[method] }, method),
1928
2014
  ' ',
1929
2015
  path));
1930
- return (React.createElement(Box, { mb: 10 },
2016
+ return (React.createElement(Box, null,
1931
2017
  React.createElement(SectionTitle, { title: "Request" }),
2018
+ securitySchemes.map((scheme, i) => (React.createElement(SecurityPanel, { key: i, scheme: scheme, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))),
1932
2019
  React.createElement(SubSectionPanel, { title: pathParamBlock, hasContent: pathParams.length > 0 },
1933
2020
  React.createElement(Parameters, { parameterType: "path", parameters: pathParams })),
1934
2021
  queryParams.length > 0 && (React.createElement(SubSectionPanel, { title: "Query" },
@@ -1939,7 +2026,13 @@ const Request = ({ operation: { path, method, request, request: { path: pathPara
1939
2026
  React.createElement(Parameters, { parameterType: "cookie", parameters: cookieParams }))),
1940
2027
  body && React.createElement(Body, { onChange: onChange, body: body })));
1941
2028
  };
1942
- Request.displayName = 'HttpOperation.Request';
2029
+ Request.displayName = 'HttpOperation.Request';
2030
+ const schemeExpandedState = atomWithStorage('HttpOperation_security_expanded', {});
2031
+ const SecurityPanel = ({ scheme, includeKey }) => {
2032
+ const [expandedState, setExpanded] = useAtom(schemeExpandedState);
2033
+ return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityName(scheme, includeKey)}`, defaultIsOpen: !!expandedState[scheme.key], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [scheme.key]: isOpen })) },
2034
+ React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })));
2035
+ };
1943
2036
 
1944
2037
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }) => {
1945
2038
  var _a, _b;
@@ -1975,7 +2068,7 @@ const Response = ({ response: { contents = [], headers = [], description }, onMe
1975
2068
  };
1976
2069
  Response.displayName = 'HttpOperation.Response';
1977
2070
 
1978
- const HttpOperationComponent = React.memo(({ className, data: unresolvedData, uri, allowRouting = false, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy, }) => {
2071
+ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
1979
2072
  const data = useResolvedObject(unresolvedData);
1980
2073
  const mocking = React.useContext(MockingContext);
1981
2074
  const isDeprecated = !!data.deprecated;
@@ -1983,21 +2076,17 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, ur
1983
2076
  const [responseMediaType, setResponseMediaType] = React.useState('');
1984
2077
  const [responseStatusCode, setResponseStatusCode] = React.useState('');
1985
2078
  const [requestBodyIndex, setTextRequestBodyIndex] = React.useState(0);
1986
- const httpServiceUri = uri && getServiceUriFromOperation(uri);
1987
- const securitySchemes = flatten(data.security);
1988
- const hasBadges = isDeprecated || securitySchemes.length > 0 || isInternal;
2079
+ const hasBadges = isDeprecated || isInternal;
1989
2080
  const header = (!(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading) || hasBadges) && (React.createElement(React.Fragment, null,
1990
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}`)),
1991
2082
  hasBadges && (React.createElement(HStack, { spacing: 2 },
1992
2083
  isDeprecated && React.createElement(DeprecatedBadge, null),
1993
- sortBy(securitySchemes, 'type').map((scheme, i) => (React.createElement(SecurityBadge, { key: i, scheme: scheme, httpServiceUri: allowRouting ? httpServiceUri : undefined, includeKey: shouldIncludeKey(securitySchemes, scheme.type) }))),
1994
2084
  isInternal && React.createElement(InternalBadge, { isHttpService: true })))));
1995
- const description = (React.createElement(React.Fragment, null,
1996
- data.description && (React.createElement(MarkdownViewer, { className: "HttpOperation__Description sl-mb-10", markdown: data.description })),
2085
+ const description = (React.createElement(VStack, { spacing: 6 },
2086
+ data.description && React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
1997
2087
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
1998
2088
  data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
1999
- const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React.createElement(Box, { className: "HttpOperation__gutter" },
2000
- React.createElement(TryItWithRequestSamples, { httpOperation: data, responseMediaType: responseMediaType, responseStatusCode: responseStatusCode, requestBodyIndex: requestBodyIndex, hideTryIt: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryIt, tryItCredentialsPolicy: tryItCredentialsPolicy, mockUrl: mocking.hideMocking ? undefined : mocking.mockUrl, corsProxy: tryItCorsProxy })));
2089
+ const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React.createElement(TryItWithRequestSamples, { httpOperation: data, responseMediaType: responseMediaType, responseStatusCode: responseStatusCode, requestBodyIndex: requestBodyIndex, hideTryIt: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryIt, tryItCredentialsPolicy: tryItCredentialsPolicy, mockUrl: mocking.hideMocking ? undefined : mocking.mockUrl, corsProxy: tryItCorsProxy }));
2001
2090
  return (React.createElement(TwoColumnLayout, { className: cn('HttpOperation', className), header: header, left: description, right: tryItPanel }));
2002
2091
  });
2003
2092
  HttpOperationComponent.displayName = 'HttpOperation.Component';
@@ -2007,8 +2096,8 @@ const HttpOperation = withErrorBoundary(HttpOperationComponent, {
2007
2096
 
2008
2097
  const PoweredByLink = ({ source, pathname, packageType, layout = 'sidebar' }) => {
2009
2098
  return (React.createElement(Flex, { as: "a", align: "center", borderT: layout === 'stacked' ? undefined : true, px: layout === 'stacked' ? 1 : 4, py: 3, justify: layout === 'stacked' ? 'end' : undefined, href: `https://stoplight.io/?utm_source=${packageType}&utm_medium=${source}&utm_campaign=powered_by&utm_content=${pathname}`, target: "_blank", rel: "noopener noreferrer" },
2010
- React.createElement(FontAwesomeIcon, { icon: faBolt, className: "sl-mr-1 fa-fw", style: { color: 'rgba(144, 97, 249, 1)' } }),
2011
- React.createElement("div", null,
2099
+ React.createElement(Box, { as: Icon, icon: faBolt, mr: 1, className: "fa-fw", style: { color: 'rgba(144, 97, 249, 1)' } }),
2100
+ React.createElement(Box, null,
2012
2101
  "powered by\u00A0",
2013
2102
  React.createElement("strong", null, "Stoplight"))));
2014
2103
  };
@@ -2042,83 +2131,19 @@ const ExportButton = ({ original, bundled }) => {
2042
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")) })));
2043
2132
  };
2044
2133
 
2045
- const oauthFlowNames = {
2046
- implicit: 'Implicit',
2047
- authorizationCode: 'Authorization Code',
2048
- clientCredentials: 'Client Credentials',
2049
- password: 'Password',
2050
- };
2051
- const SecuritySchemes = ({ schemes, defaultScheme }) => {
2052
- return (React__default.createElement(Panel, { rounded: true, isCollapsible: false },
2134
+ const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2135
+ return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed },
2053
2136
  React__default.createElement(Panel.Titlebar, { bg: "canvas-300" },
2054
- React__default.createElement("span", { role: "heading" }, "Security")),
2055
- React__default.createElement(Panel.Content, { p: 0 }, sortBy(schemes, 'type').map((scheme, i) => (React__default.createElement(Panel, { key: i, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1 },
2056
- React__default.createElement(Panel.Titlebar, null,
2057
- React__default.createElement("span", { role: "heading" }, getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)))),
2058
- React__default.createElement(Panel.Content, null,
2059
- React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) }))))))));
2137
+ React__default.createElement(Box, { as: "span", role: "heading" }, "Security")),
2138
+ React__default.createElement(Panel.Content, { p: 0 }, sortBy(schemes, 'type').map((scheme, i) => (React__default.createElement(SecurityScheme, { key: i, scheme: scheme, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1, showSchemeKey: shouldIncludeKey(schemes, scheme.type) }))))));
2060
2139
  };
2061
- function getDefaultDescription(scheme) {
2062
- switch (scheme.type) {
2063
- case 'apiKey':
2064
- return getApiKeyDescription(scheme.in, scheme.name);
2065
- case 'http':
2066
- switch (scheme.scheme) {
2067
- case 'basic':
2068
- return getBasicAuthDescription();
2069
- case 'bearer':
2070
- return getBearerAuthDescription();
2071
- case 'digest':
2072
- return getDigestAuthDescription();
2073
- }
2074
- case 'oauth2':
2075
- return getOAuthDescription(scheme);
2076
- }
2077
- return '';
2078
- }
2079
- function getApiKeyDescription(inProperty, name) {
2080
- return `An API key is a token that you provide when making API calls. Include the token in a ${inProperty} parameter called \`${name}\`.
2081
-
2082
- Example: ${inProperty === 'query' ? `\`?${name}=123\`` : `\`${name}: 123\``}`;
2083
- }
2084
- function getBasicAuthDescription() {
2085
- return `Basic authentication is a simple authentication scheme built into the HTTP protocol.
2086
- To use it, send your HTTP requests with an Authorization header that contains the word Basic
2087
- followed by a space and a base64-encoded string \`username:password\`.
2088
-
2089
- Example: \`Authorization: Basic ZGVtbzpwQDU1dzByZA==\``;
2090
- }
2091
- function getBearerAuthDescription() {
2092
- return `Provide your bearer token in the Authorization header when making requests to protected resources.
2093
-
2094
- Example: \`Authorization: Bearer 123\``;
2095
- }
2096
- function getDigestAuthDescription() {
2097
- return `Provide your encrypted digest scheme data in the Authorization header when making requests to protected resources.
2098
-
2099
- Example: \`Authorization: Digest username=guest, realm="test", nonce="2", uri="/uri", response="123"\``;
2100
- }
2101
- function getOAuthDescription(scheme) {
2102
- const flows = keys(scheme.flows);
2103
- return flows.map(flow => getOAuthFlowDescription(oauthFlowNames[flow], scheme.flows[flow])).join('\n\n');
2104
- }
2105
- function getOAuthFlowDescription(title, flow) {
2106
- let description = `**${title} OAuth Flow**`;
2107
- description +=
2108
- isOAuth2ImplicitFlow(flow) || isOauth2AuthorizationCodeFlow(flow)
2109
- ? `\n\nAuthorize URL: ${flow.authorizationUrl}`
2110
- : '';
2111
- description +=
2112
- isOauth2AuthorizationCodeFlow(flow) || isOauth2ClientCredentialsOrPasswordFlow(flow)
2113
- ? `\n\nToken URL: ${flow.tokenUrl}`
2114
- : '';
2115
- description += flow.refreshUrl ? `\n\nRefresh URL: ${flow.refreshUrl}` : '';
2116
- description += `\n\nScopes:
2117
- ${entries(flow.scopes)
2118
- .map(([key, value]) => `- \`${key}\` - ${value}`)
2119
- .join('\n')}`;
2120
- return description;
2121
- }
2140
+ const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2141
+ return (React__default.createElement(Panel, { defaultIsOpen: defaultIsOpen, isCollapsible: isCollapsible },
2142
+ React__default.createElement(Panel.Titlebar, null,
2143
+ React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityName(scheme, showSchemeKey))),
2144
+ React__default.createElement(Panel.Content, null,
2145
+ React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) }))));
2146
+ };
2122
2147
 
2123
2148
  const ServerInfo = ({ servers, mockUrl }) => {
2124
2149
  const mocking = React.useContext(MockingContext);
@@ -2284,7 +2309,7 @@ const SchemaAndDescription = ({ title: titleProp, schema }) => {
2284
2309
  const title = titleProp !== null && titleProp !== void 0 ? titleProp : schema.title;
2285
2310
  return (React__default.createElement(Box, { py: 2 },
2286
2311
  title && (React__default.createElement(Flex, { alignItems: "center", p: 2 },
2287
- React__default.createElement(FontAwesomeIcon, { icon: NodeTypeIconDefs[NodeType.Model], color: NodeTypeColors[NodeType.Model] }),
2312
+ React__default.createElement(Icon, { icon: NodeTypeIconDefs[NodeType.Model], color: NodeTypeColors[NodeType.Model] }),
2288
2313
  React__default.createElement(Box, { color: "muted", px: 2 }, title))),
2289
2314
  React__default.createElement(JsonSchemaViewer, { resolveRef: resolveRef, schema: getOriginalObject(schema) })));
2290
2315
  };
@@ -2612,24 +2637,26 @@ function useBundleRefsIntoDocument(document, options) {
2612
2637
  setBundledData(document);
2613
2638
  return;
2614
2639
  }
2615
- let isActive = true;
2640
+ let isMounted = true;
2616
2641
  doBundle(document, baseUrl)
2617
2642
  .then(res => {
2618
- if (isActive) {
2643
+ if (isMounted) {
2619
2644
  setBundledData(Object.assign({}, res));
2620
2645
  }
2621
2646
  })
2622
2647
  .catch(reason => {
2623
2648
  var _a;
2624
2649
  if (typeof reason === 'object' && reason !== null && 'files' in reason) {
2625
- setBundledData(Object.assign({}, reason.files.schema));
2650
+ if (isMounted) {
2651
+ setBundledData(Object.assign({}, reason.files.schema));
2652
+ }
2626
2653
  }
2627
2654
  else {
2628
2655
  console.warn(`Could bundle: ${(_a = reason === null || reason === void 0 ? void 0 : reason.message) !== null && _a !== void 0 ? _a : 'Unknown error'}`);
2629
2656
  }
2630
2657
  });
2631
2658
  return () => {
2632
- isActive = false;
2659
+ isMounted = false;
2633
2660
  };
2634
2661
  }, [document, baseUrl]);
2635
2662
  return bundledData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "7.3.11",
3
+ "version": "7.4.0",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",
@@ -24,9 +24,7 @@
24
24
  "react-dom": ">=16.8"
25
25
  },
26
26
  "dependencies": {
27
- "@fortawesome/fontawesome-svg-core": "^1.2.31",
28
27
  "@fortawesome/free-solid-svg-icons": "^5.14.0",
29
- "@fortawesome/react-fontawesome": "^0.1.11",
30
28
  "@stoplight/json": "^3.10.0",
31
29
  "@stoplight/json-schema-ref-parser": "^9.0.5",
32
30
  "@stoplight/json-schema-sampler": "0.2.2",
@@ -40,14 +38,12 @@
40
38
  "@stoplight/react-error-boundary": "^2.0.0",
41
39
  "@stoplight/types": "^12.0.0",
42
40
  "@stoplight/yaml": "^4.2.2",
43
- "axios": "^0.21.1",
44
41
  "classnames": "^2.2.6",
45
42
  "httpsnippet": "^1.24.0",
46
- "jotai": "1.2.2",
47
- "json-schema": "^0.3.0",
43
+ "jotai": "1.3.9",
44
+ "json-schema": "^0.4.0",
48
45
  "lodash": "^4.17.19",
49
46
  "nanoid": "^3.1.20",
50
- "process": "0.11.10",
51
47
  "prop-types": "^15.7.2",
52
48
  "react-query": "^3.15.2",
53
49
  "react-router-dom": "^5.2.0",