@stoplight/elements-core 7.13.1 → 7.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
1
  import { HttpSecurityScheme } from '@stoplight/types';
2
2
  import React from 'react';
3
3
  interface SecuritySchemesProps {
4
- schemes: HttpSecurityScheme[];
4
+ secSchemes: HttpSecurityScheme[][];
5
5
  defaultScheme?: string;
6
6
  defaultCollapsed?: boolean;
7
+ parentId: string;
7
8
  }
8
9
  export declare const SecuritySchemes: React.FC<SecuritySchemesProps>;
9
10
  export {};
@@ -4,6 +4,7 @@ export interface ISectionTitle {
4
4
  title: string;
5
5
  id?: string;
6
6
  size?: HeadingProps['size'];
7
+ isCompact?: boolean;
7
8
  }
8
9
  export declare const SectionTitle: React.FC<ISectionTitle>;
9
10
  export declare const SectionSubtitle: React.FC<ISectionTitle>;
@@ -0,0 +1,5 @@
1
+ import { HttpSecurityScheme } from '@stoplight/types';
2
+ import * as React from 'react';
3
+ export declare const PanelContent: React.FC<{
4
+ schemes: HttpSecurityScheme[];
5
+ }>;
@@ -0,0 +1 @@
1
+ export * from './PanelContent';
package/constants.d.ts CHANGED
@@ -88,3 +88,4 @@ export declare const HttpCodeDescriptions: {
88
88
  export declare const badgeDefaultBackgroundColor = "#293742";
89
89
  export declare const badgeDefaultColor = "#FFFFFF";
90
90
  export declare const CodeToIntentMap: Record<number, IntentVals>;
91
+ export declare const OptionalSecurityMessage = "Requiring authorization is optional. A user can access data without authorization or with authorization, if provided.";
package/index.esm.js CHANGED
@@ -7,7 +7,7 @@ import isArray from 'lodash/isArray.js';
7
7
  import isPlainObject from 'lodash/isPlainObject.js';
8
8
  import { NodeType, HttpParamStyles } from '@stoplight/types';
9
9
  import { parse } from '@stoplight/yaml';
10
- import { isArray as isArray$1, Box, useBreakpoints, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, useModalState, Modal, ListBox, ListBoxItem, TabList, Tab, Tabs, TabPanels, TabPanel, Heading, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
10
+ import { isArray as isArray$1, Box, useBreakpoints, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, Callout, useModalState, Modal, ListBox, ListBoxItem, TabList, Tab, Tabs, TabPanels, TabPanel, Heading, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
11
11
  import isObject from 'lodash/isObject.js';
12
12
  import { withErrorBoundary } from '@stoplight/react-error-boundary';
13
13
  import { useLocation, BrowserRouter, MemoryRouter, HashRouter, StaticRouter, Route } from 'react-router-dom';
@@ -19,6 +19,7 @@ import { atom, useAtom, Provider } from 'jotai';
19
19
  import URI from 'urijs';
20
20
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
21
21
  import { isValidTargetId, HTTPSnippet } from 'httpsnippet-lite';
22
+ import { hash } from '@stoplight/http-spec/hash';
22
23
  import capitalize from 'lodash/capitalize.js';
23
24
  import filter from 'lodash/filter.js';
24
25
  import flatten from 'lodash/flatten.js';
@@ -193,6 +194,9 @@ const parserMap = {
193
194
  [NodeType.SpectralRuleset]: parseUnknown,
194
195
  [NodeType.Styleguide]: parseUnknown,
195
196
  [NodeType.Image]: parseUnknown,
197
+ [NodeType.HttpCallback]: parseUnknown,
198
+ [NodeType.StoplightOverride]: parseUnknown,
199
+ [NodeType.StoplightResolutions]: parseUnknown,
196
200
  [NodeType.Unknown]: parseUnknown,
197
201
  };
198
202
  function parseArticleData(rawData) {
@@ -357,6 +361,9 @@ const NodeTypeColors = {
357
361
  spectral_ruleset: '',
358
362
  styleguide: '',
359
363
  image: '',
364
+ http_callback: '',
365
+ stoplight_override: '',
366
+ stoplight_resolutions: '',
360
367
  };
361
368
  const NodeTypePrettyName = {
362
369
  http_operation: 'Endpoint',
@@ -370,6 +377,9 @@ const NodeTypePrettyName = {
370
377
  spectral_ruleset: '',
371
378
  styleguide: '',
372
379
  image: '',
380
+ http_callback: '',
381
+ stoplight_override: '',
382
+ stoplight_resolutions: '',
373
383
  };
374
384
  const NodeTypeIconDefs = {
375
385
  http_operation: faCrosshairs,
@@ -383,6 +393,9 @@ const NodeTypeIconDefs = {
383
393
  spectral_ruleset: faQuestionCircle,
384
394
  styleguide: faQuestionCircle,
385
395
  image: faImage,
396
+ http_callback: faQuestionCircle,
397
+ stoplight_override: faQuestionCircle,
398
+ stoplight_resolutions: faQuestionCircle,
386
399
  };
387
400
  const HttpMethodColors = {
388
401
  get: 'success',
@@ -465,7 +478,8 @@ const HttpCodeDescriptions = {
465
478
  599: 'Network connect timeout error',
466
479
  };
467
480
  const badgeDefaultBackgroundColor = '#293742';
468
- const badgeDefaultColor = '#FFFFFF';
481
+ const badgeDefaultColor = '#FFFFFF';
482
+ const OptionalSecurityMessage = 'Requiring authorization is optional. A user can access data without authorization or with authorization, if provided.';
469
483
 
470
484
  const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
471
485
  const MockingProvider = ({ mockUrl, hideMocking, children }) => {
@@ -904,6 +918,9 @@ const shouldAddKey = (auth, operationSecuritySchemes) => {
904
918
  if (auth.length !== 1)
905
919
  return false;
906
920
  return shouldIncludeKey(flatten(operationSecuritySchemes.filter(scheme => scheme.length === 1)), auth[0].type);
921
+ };
922
+ const getSecurityGroupId = (id, position) => {
923
+ return hash(`http_security_group-${id}-${position}`);
907
924
  };
908
925
 
909
926
  const useUniqueId = (prefix = 'id_') => React.useRef(`${prefix}${nanoid(8)}`).current;
@@ -2252,6 +2269,51 @@ const enhanceVersionString = (version) => {
2252
2269
  return `v${version}`;
2253
2270
  };
2254
2271
 
2272
+ const operation = {
2273
+ id: '?http-operation-id?',
2274
+ iid: 'GET-simple',
2275
+ method: 'get',
2276
+ path: '/todos',
2277
+ summary: 'Get 200',
2278
+ responses: [
2279
+ {
2280
+ id: '?http-response-200?',
2281
+ code: '200',
2282
+ description: 'OK',
2283
+ },
2284
+ ],
2285
+ servers: [{ id: '?http-server-0?', url: 'https://todos.stoplight.io' }],
2286
+ };
2287
+
2288
+ const LinkHeading = React.memo(function LinkHeading(props) {
2289
+ const isUsingRouter = !!useRouterType();
2290
+ const Comp = isUsingRouter ? CustomLinkHeading : LinkHeading$1;
2291
+ return React.createElement(Comp, Object.assign({}, props));
2292
+ });
2293
+ const CustomLinkHeading = React.memo(function LinkHeading(_a) {
2294
+ var { id: _id } = _a, props = __rest(_a, ["id"]);
2295
+ const { pathname } = useLocation();
2296
+ const routerKind = React.useContext(RouterTypeContext);
2297
+ const route = pathname.split('#')[0];
2298
+ const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2299
+ return React.createElement(LinkHeading$1, Object.assign({ id: id }, props));
2300
+ });
2301
+
2302
+ const SectionTitle = ({ title, id, size = 2, isCompact = false, children }) => {
2303
+ return (React.createElement(Flex, { w: "full" },
2304
+ React.createElement(Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2305
+ React.createElement(Flex, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 }, justify: isCompact ? 'end' : undefined }, children)));
2306
+ };
2307
+ const SectionSubtitle = props => {
2308
+ return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2309
+ };
2310
+ const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2311
+ return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2312
+ React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2313
+ React.createElement("div", { role: "heading" }, title)),
2314
+ hasContent !== false && React.createElement(Panel.Content, null, children)));
2315
+ };
2316
+
2255
2317
  const oauthFlowNames = {
2256
2318
  implicit: 'Implicit',
2257
2319
  authorizationCode: 'Authorization Code',
@@ -2321,33 +2383,19 @@ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
2321
2383
  return description;
2322
2384
  }
2323
2385
 
2324
- const LinkHeading = React.memo(function LinkHeading(props) {
2325
- const isUsingRouter = !!useRouterType();
2326
- const Comp = isUsingRouter ? CustomLinkHeading : LinkHeading$1;
2327
- return React.createElement(Comp, Object.assign({}, props));
2328
- });
2329
- const CustomLinkHeading = React.memo(function LinkHeading(_a) {
2330
- var { id: _id } = _a, props = __rest(_a, ["id"]);
2331
- const { pathname } = useLocation();
2332
- const routerKind = React.useContext(RouterTypeContext);
2333
- const route = pathname.split('#')[0];
2334
- const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2335
- return React.createElement(LinkHeading$1, Object.assign({ id: id }, props));
2336
- });
2337
-
2338
- const SectionTitle = ({ title, id, size = 2, children }) => {
2339
- return (React.createElement(Flex, { w: "full" },
2340
- React.createElement(Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2341
- React.createElement(Box, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 } }, children)));
2342
- };
2343
- const SectionSubtitle = props => {
2344
- return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2345
- };
2346
- const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2347
- return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2348
- React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2349
- React.createElement("div", { role: "heading" }, title)),
2350
- hasContent !== false && React.createElement(Panel.Content, null, children)));
2386
+ const PanelContent = ({ schemes }) => {
2387
+ const { nodeHasChanged } = useOptionsCtx();
2388
+ if (!schemes || !schemes.length) {
2389
+ return null;
2390
+ }
2391
+ const collection = schemes.length > 1;
2392
+ return (React.createElement(Box, null, schemes.map(scheme => {
2393
+ var _a;
2394
+ return (React.createElement(Box, { key: scheme.key, p: 2, m: 2, border: true },
2395
+ collection && (React.createElement(MarkdownViewer$1, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2396
+ React.createElement(MarkdownViewer$1, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2397
+ React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2398
+ })));
2351
2399
  };
2352
2400
 
2353
2401
  const isBodyEmpty = (body) => {
@@ -2454,7 +2502,7 @@ const Request = ({ operation: { request, request: { path: pathParams = [], heade
2454
2502
  return null;
2455
2503
  return (React.createElement(VStack, { spacing: 8 },
2456
2504
  React.createElement(SectionTitle, { title: "Request" }),
2457
- React.createElement(SecuritySchemes$1, { schemes: securitySchemes }),
2505
+ React.createElement(SecuritySchemes$1, { schemes: securitySchemes, parentId: operation.id }),
2458
2506
  pathParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2459
2507
  React.createElement(SectionSubtitle, { title: "Path Parameters" }),
2460
2508
  React.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
@@ -2473,23 +2521,29 @@ Request.displayName = 'HttpOperation.Request';
2473
2521
  const schemeExpandedState = atomWithStorage('HttpOperation_security_expanded', {});
2474
2522
  const SecurityPanel = ({ schemes, includeKey }) => {
2475
2523
  const [expandedState, setExpanded] = useAtom(schemeExpandedState);
2476
- const { nodeHasChanged } = useOptionsCtx();
2477
- const collection = schemes.length > 1;
2478
2524
  return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityNames(schemes, includeKey)}`, defaultIsOpen: !!expandedState[getReadableSecurityNames(schemes)], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [getReadableSecurityNames(schemes)]: isOpen })) },
2479
- React.createElement(Box, { m: -2 }, schemes.map(scheme => {
2480
- var _a;
2481
- return (React.createElement(Box, { key: scheme.key, p: 2, m: 2, border: true },
2482
- collection && (React.createElement(MarkdownViewer, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2483
- React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2484
- React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2485
- }))));
2525
+ React.createElement(Box, { m: -2 },
2526
+ React.createElement(PanelContent, { schemes: schemes }))));
2486
2527
  };
2487
- const SecuritySchemes$1 = ({ schemes }) => {
2528
+ const SecuritySchemes$1 = ({ schemes, parentId }) => {
2529
+ const { nodeHasChanged } = useOptionsCtx();
2488
2530
  if (!schemes.length) {
2489
2531
  return null;
2490
2532
  }
2491
- return (React.createElement(VStack, { spacing: 3 }, schemes.map((scheme, i) => (React.createElement(Box, { pos: "relative", key: i, p: 0, "data-test": "security-row" },
2492
- React.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) }))))));
2533
+ const includeOptional = schemes.length > 1 && schemes.some(scheme => scheme.length === 0);
2534
+ return (React.createElement(VStack, { spacing: 3 },
2535
+ includeOptional && React.createElement(OptionalMessage$1, null),
2536
+ schemes
2537
+ .filter(scheme => scheme.length > 0)
2538
+ .map((scheme, i) => {
2539
+ const secGroupId = getSecurityGroupId(parentId, i);
2540
+ return (React.createElement(Box, { pos: "relative", key: secGroupId, p: 0, "data-test": "http-operation-security-row" },
2541
+ React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2542
+ React.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) })));
2543
+ })));
2544
+ };
2545
+ const OptionalMessage$1 = () => {
2546
+ return React.createElement(Callout, { appearance: "outline" }, OptionalSecurityMessage);
2493
2547
  };
2494
2548
 
2495
2549
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
@@ -2514,7 +2568,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2514
2568
  const compactResponses = (React.createElement(React.Fragment, null,
2515
2569
  React.createElement(Button, { "aria-label": "response-codes", onPress: open, iconRight: React.createElement(Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2516
2570
  color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2517
- } }, activeResponseId),
2571
+ }, appearance: "minimal" }, activeResponseId),
2518
2572
  React.createElement(Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React.createElement(HStack, { justifyContent: "end" },
2519
2573
  React.createElement(Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2520
2574
  React.createElement(ListBox, { "aria-label": "Response Code", overflowY: "auto", m: -5, items: responses, selectionMode: "single", onSelectionChange: onSelectionChange }, (response) => (React.createElement(ListBoxItem, { key: response.id },
@@ -2524,7 +2578,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2524
2578
  React.createElement(Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2525
2579
  const tabResponses = (React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code)))));
2526
2580
  return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2527
- React.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2581
+ React.createElement(SectionTitle, { title: "Responses", isCompact: isCompact }, isCompact ? compactResponses : tabResponses),
2528
2582
  isCompact ? (React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })) : (React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2529
2583
  React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2530
2584
  };
@@ -2678,21 +2732,33 @@ const ExportButton = ({ original, bundled }) => {
2678
2732
  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")) })));
2679
2733
  };
2680
2734
 
2681
- const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2735
+ const SecuritySchemes = ({ secSchemes, defaultScheme, defaultCollapsed = false, parentId, }) => {
2736
+ const includeOptional = secSchemes.length > 1 && secSchemes.some(schemes => schemes.length === 0);
2737
+ const { nodeHasChanged } = useOptionsCtx();
2682
2738
  return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed, "data-test": "security-row" },
2683
2739
  React__default.createElement(Panel.Titlebar, { bg: "canvas-300" },
2684
2740
  React__default.createElement(Box, { as: "span", role: "heading" }, "Security")),
2685
- 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) }))))));
2686
- };
2687
- const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2688
- const { nodeHasChanged } = useOptionsCtx();
2689
- const hasChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id });
2741
+ React__default.createElement(Panel.Content, { p: 0 },
2742
+ includeOptional && React__default.createElement(OptionalMessage, null),
2743
+ secSchemes
2744
+ .filter(scheme => scheme.length > 0)
2745
+ .map((schemes, i) => {
2746
+ const secGroupId = getSecurityGroupId(parentId, i);
2747
+ return (React__default.createElement(Box, { key: secGroupId, "data-test": "http-service-security-row" },
2748
+ React__default.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2749
+ React__default.createElement(SecurityScheme, { schemes: schemes, defaultIsOpen: defaultScheme ? schemes.length === 1 && schemes[0].key === defaultScheme : i === 0, isCollapsible: secSchemes.length > 1, showSchemeKey: shouldAddKey(schemes, secSchemes) })));
2750
+ }))));
2751
+ };
2752
+ const SecurityScheme = ({ schemes, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2690
2753
  return (React__default.createElement(Panel, { defaultIsOpen: defaultIsOpen, isCollapsible: isCollapsible, pos: "relative" },
2691
2754
  React__default.createElement(Panel.Titlebar, null,
2692
- React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityName(scheme, showSchemeKey))),
2755
+ React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityNames(schemes, showSchemeKey))),
2693
2756
  React__default.createElement(Panel.Content, null,
2694
- React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })),
2695
- React__default.createElement(NodeAnnotation, { change: hasChanged })));
2757
+ React__default.createElement(PanelContent, { schemes: schemes }))));
2758
+ };
2759
+ const OptionalMessage = () => {
2760
+ return (React__default.createElement(Box, { p: 2, pl: 6, border: true },
2761
+ React__default.createElement(Text, { fontSize: "base" }, OptionalSecurityMessage)));
2696
2762
  };
2697
2763
 
2698
2764
  const ServerInfo = ({ servers, mockUrl }) => {
@@ -2813,7 +2879,7 @@ const HttpServiceComponent = React.memo(({ data: unresolvedData, location = {},
2813
2879
  pathname && (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.showPoweredByLink) && (React.createElement(PoweredByLink, { source: (_a = data.name) !== null && _a !== void 0 ? _a : 'no-title', pathname: pathname, packageType: "elements", layout: "stacked" })),
2814
2880
  React.createElement(VStack, { spacing: 6 },
2815
2881
  React.createElement(ServerInfo, { servers: (_b = data.servers) !== null && _b !== void 0 ? _b : [], mockUrl: mocking.mockUrl }),
2816
- React.createElement(Box, { "data-test": "security" }, ((_c = data.securitySchemes) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { schemes: data.securitySchemes, defaultScheme: query.get('security') || undefined })) : null),
2882
+ React.createElement(Box, { "data-test": "security" }, ((_c = data.security) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { secSchemes: data.security, defaultScheme: query.get('security') || undefined, parentId: data.id })) : null),
2817
2883
  React.createElement(Box, { "data-test": "additional-info" }, (((_d = data.contact) === null || _d === void 0 ? void 0 : _d.email) || data.license || data.termsOfService) && (React.createElement(AdditionalInfo, { id: data.id, contact: data.contact, license: data.license, termsOfService: data.termsOfService })))),
2818
2884
  data.description && (React.createElement(Box, { pos: "relative" },
2819
2885
  React.createElement(MarkdownViewer, { className: "sl-my-5", markdown: data.description }),
package/index.js CHANGED
@@ -21,6 +21,7 @@ var jotai = require('jotai');
21
21
  var URI = require('urijs');
22
22
  var mosaicCodeViewer = require('@stoplight/mosaic-code-viewer');
23
23
  var httpsnippetLite = require('httpsnippet-lite');
24
+ var hash = require('@stoplight/http-spec/hash');
24
25
  var capitalize = require('lodash/capitalize.js');
25
26
  var filter = require('lodash/filter.js');
26
27
  var flatten = require('lodash/flatten.js');
@@ -249,6 +250,9 @@ const parserMap = {
249
250
  [types.NodeType.SpectralRuleset]: parseUnknown,
250
251
  [types.NodeType.Styleguide]: parseUnknown,
251
252
  [types.NodeType.Image]: parseUnknown,
253
+ [types.NodeType.HttpCallback]: parseUnknown,
254
+ [types.NodeType.StoplightOverride]: parseUnknown,
255
+ [types.NodeType.StoplightResolutions]: parseUnknown,
252
256
  [types.NodeType.Unknown]: parseUnknown,
253
257
  };
254
258
  function parseArticleData(rawData) {
@@ -413,6 +417,9 @@ const NodeTypeColors = {
413
417
  spectral_ruleset: '',
414
418
  styleguide: '',
415
419
  image: '',
420
+ http_callback: '',
421
+ stoplight_override: '',
422
+ stoplight_resolutions: '',
416
423
  };
417
424
  const NodeTypePrettyName = {
418
425
  http_operation: 'Endpoint',
@@ -426,6 +433,9 @@ const NodeTypePrettyName = {
426
433
  spectral_ruleset: '',
427
434
  styleguide: '',
428
435
  image: '',
436
+ http_callback: '',
437
+ stoplight_override: '',
438
+ stoplight_resolutions: '',
429
439
  };
430
440
  const NodeTypeIconDefs = {
431
441
  http_operation: faCrosshairs,
@@ -439,6 +449,9 @@ const NodeTypeIconDefs = {
439
449
  spectral_ruleset: faQuestionCircle,
440
450
  styleguide: faQuestionCircle,
441
451
  image: faImage,
452
+ http_callback: faQuestionCircle,
453
+ stoplight_override: faQuestionCircle,
454
+ stoplight_resolutions: faQuestionCircle,
442
455
  };
443
456
  const HttpMethodColors = {
444
457
  get: 'success',
@@ -521,7 +534,8 @@ const HttpCodeDescriptions = {
521
534
  599: 'Network connect timeout error',
522
535
  };
523
536
  const badgeDefaultBackgroundColor = '#293742';
524
- const badgeDefaultColor = '#FFFFFF';
537
+ const badgeDefaultColor = '#FFFFFF';
538
+ const OptionalSecurityMessage = 'Requiring authorization is optional. A user can access data without authorization or with authorization, if provided.';
525
539
 
526
540
  const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
527
541
  const MockingProvider = ({ mockUrl, hideMocking, children }) => {
@@ -960,6 +974,9 @@ const shouldAddKey = (auth, operationSecuritySchemes) => {
960
974
  if (auth.length !== 1)
961
975
  return false;
962
976
  return shouldIncludeKey(flatten__default["default"](operationSecuritySchemes.filter(scheme => scheme.length === 1)), auth[0].type);
977
+ };
978
+ const getSecurityGroupId = (id, position) => {
979
+ return hash.hash(`http_security_group-${id}-${position}`);
963
980
  };
964
981
 
965
982
  const useUniqueId = (prefix = 'id_') => React__namespace.useRef(`${prefix}${nanoid.nanoid(8)}`).current;
@@ -2308,6 +2325,51 @@ const enhanceVersionString = (version) => {
2308
2325
  return `v${version}`;
2309
2326
  };
2310
2327
 
2328
+ const operation = {
2329
+ id: '?http-operation-id?',
2330
+ iid: 'GET-simple',
2331
+ method: 'get',
2332
+ path: '/todos',
2333
+ summary: 'Get 200',
2334
+ responses: [
2335
+ {
2336
+ id: '?http-response-200?',
2337
+ code: '200',
2338
+ description: 'OK',
2339
+ },
2340
+ ],
2341
+ servers: [{ id: '?http-server-0?', url: 'https://todos.stoplight.io' }],
2342
+ };
2343
+
2344
+ const LinkHeading = React__namespace.memo(function LinkHeading(props) {
2345
+ const isUsingRouter = !!useRouterType();
2346
+ const Comp = isUsingRouter ? CustomLinkHeading : mosaic.LinkHeading;
2347
+ return React__namespace.createElement(Comp, Object.assign({}, props));
2348
+ });
2349
+ const CustomLinkHeading = React__namespace.memo(function LinkHeading(_a) {
2350
+ var { id: _id } = _a, props = tslib.__rest(_a, ["id"]);
2351
+ const { pathname } = reactRouterDom.useLocation();
2352
+ const routerKind = React__namespace.useContext(RouterTypeContext);
2353
+ const route = pathname.split('#')[0];
2354
+ const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2355
+ return React__namespace.createElement(mosaic.LinkHeading, Object.assign({ id: id }, props));
2356
+ });
2357
+
2358
+ const SectionTitle = ({ title, id, size = 2, isCompact = false, children }) => {
2359
+ return (React__namespace.createElement(mosaic.Flex, { w: "full" },
2360
+ React__namespace.createElement(mosaic.Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2361
+ React__namespace.createElement(mosaic.Flex, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 }, justify: isCompact ? 'end' : undefined }, children)));
2362
+ };
2363
+ const SectionSubtitle = props => {
2364
+ return React__namespace.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2365
+ };
2366
+ const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2367
+ return (React__namespace.createElement(mosaic.Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2368
+ React__namespace.createElement(mosaic.Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2369
+ React__namespace.createElement("div", { role: "heading" }, title)),
2370
+ hasContent !== false && React__namespace.createElement(mosaic.Panel.Content, null, children)));
2371
+ };
2372
+
2311
2373
  const oauthFlowNames = {
2312
2374
  implicit: 'Implicit',
2313
2375
  authorizationCode: 'Authorization Code',
@@ -2377,33 +2439,19 @@ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
2377
2439
  return description;
2378
2440
  }
2379
2441
 
2380
- const LinkHeading = React__namespace.memo(function LinkHeading(props) {
2381
- const isUsingRouter = !!useRouterType();
2382
- const Comp = isUsingRouter ? CustomLinkHeading : mosaic.LinkHeading;
2383
- return React__namespace.createElement(Comp, Object.assign({}, props));
2384
- });
2385
- const CustomLinkHeading = React__namespace.memo(function LinkHeading(_a) {
2386
- var { id: _id } = _a, props = tslib.__rest(_a, ["id"]);
2387
- const { pathname } = reactRouterDom.useLocation();
2388
- const routerKind = React__namespace.useContext(RouterTypeContext);
2389
- const route = pathname.split('#')[0];
2390
- const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2391
- return React__namespace.createElement(mosaic.LinkHeading, Object.assign({ id: id }, props));
2392
- });
2393
-
2394
- const SectionTitle = ({ title, id, size = 2, children }) => {
2395
- return (React__namespace.createElement(mosaic.Flex, { w: "full" },
2396
- React__namespace.createElement(mosaic.Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2397
- React__namespace.createElement(mosaic.Box, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 } }, children)));
2398
- };
2399
- const SectionSubtitle = props => {
2400
- return React__namespace.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2401
- };
2402
- const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2403
- return (React__namespace.createElement(mosaic.Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2404
- React__namespace.createElement(mosaic.Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2405
- React__namespace.createElement("div", { role: "heading" }, title)),
2406
- hasContent !== false && React__namespace.createElement(mosaic.Panel.Content, null, children)));
2442
+ const PanelContent = ({ schemes }) => {
2443
+ const { nodeHasChanged } = useOptionsCtx();
2444
+ if (!schemes || !schemes.length) {
2445
+ return null;
2446
+ }
2447
+ const collection = schemes.length > 1;
2448
+ return (React__namespace.createElement(mosaic.Box, null, schemes.map(scheme => {
2449
+ var _a;
2450
+ return (React__namespace.createElement(mosaic.Box, { key: scheme.key, p: 2, m: 2, border: true },
2451
+ collection && (React__namespace.createElement(markdownViewer.MarkdownViewer, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2452
+ React__namespace.createElement(markdownViewer.MarkdownViewer, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2453
+ React__namespace.createElement(mosaic.NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2454
+ })));
2407
2455
  };
2408
2456
 
2409
2457
  const isBodyEmpty = (body) => {
@@ -2510,7 +2558,7 @@ const Request = ({ operation: { request, request: { path: pathParams = [], heade
2510
2558
  return null;
2511
2559
  return (React__namespace.createElement(mosaic.VStack, { spacing: 8 },
2512
2560
  React__namespace.createElement(SectionTitle, { title: "Request" }),
2513
- React__namespace.createElement(SecuritySchemes$1, { schemes: securitySchemes }),
2561
+ React__namespace.createElement(SecuritySchemes$1, { schemes: securitySchemes, parentId: operation.id }),
2514
2562
  pathParams.length > 0 && (React__namespace.createElement(mosaic.VStack, { spacing: 5 },
2515
2563
  React__namespace.createElement(SectionSubtitle, { title: "Path Parameters" }),
2516
2564
  React__namespace.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
@@ -2529,23 +2577,29 @@ Request.displayName = 'HttpOperation.Request';
2529
2577
  const schemeExpandedState = utils.atomWithStorage('HttpOperation_security_expanded', {});
2530
2578
  const SecurityPanel = ({ schemes, includeKey }) => {
2531
2579
  const [expandedState, setExpanded] = jotai.useAtom(schemeExpandedState);
2532
- const { nodeHasChanged } = useOptionsCtx();
2533
- const collection = schemes.length > 1;
2534
2580
  return (React__namespace.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityNames(schemes, includeKey)}`, defaultIsOpen: !!expandedState[getReadableSecurityNames(schemes)], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [getReadableSecurityNames(schemes)]: isOpen })) },
2535
- React__namespace.createElement(mosaic.Box, { m: -2 }, schemes.map(scheme => {
2536
- var _a;
2537
- return (React__namespace.createElement(mosaic.Box, { key: scheme.key, p: 2, m: 2, border: true },
2538
- collection && (React__namespace.createElement(MarkdownViewer, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2539
- React__namespace.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2540
- React__namespace.createElement(mosaic.NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2541
- }))));
2581
+ React__namespace.createElement(mosaic.Box, { m: -2 },
2582
+ React__namespace.createElement(PanelContent, { schemes: schemes }))));
2542
2583
  };
2543
- const SecuritySchemes$1 = ({ schemes }) => {
2584
+ const SecuritySchemes$1 = ({ schemes, parentId }) => {
2585
+ const { nodeHasChanged } = useOptionsCtx();
2544
2586
  if (!schemes.length) {
2545
2587
  return null;
2546
2588
  }
2547
- return (React__namespace.createElement(mosaic.VStack, { spacing: 3 }, schemes.map((scheme, i) => (React__namespace.createElement(mosaic.Box, { pos: "relative", key: i, p: 0, "data-test": "security-row" },
2548
- React__namespace.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) }))))));
2589
+ const includeOptional = schemes.length > 1 && schemes.some(scheme => scheme.length === 0);
2590
+ return (React__namespace.createElement(mosaic.VStack, { spacing: 3 },
2591
+ includeOptional && React__namespace.createElement(OptionalMessage$1, null),
2592
+ schemes
2593
+ .filter(scheme => scheme.length > 0)
2594
+ .map((scheme, i) => {
2595
+ const secGroupId = getSecurityGroupId(parentId, i);
2596
+ return (React__namespace.createElement(mosaic.Box, { pos: "relative", key: secGroupId, p: 0, "data-test": "http-operation-security-row" },
2597
+ React__namespace.createElement(mosaic.NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2598
+ React__namespace.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) })));
2599
+ })));
2600
+ };
2601
+ const OptionalMessage$1 = () => {
2602
+ return React__namespace.createElement(mosaic.Callout, { appearance: "outline" }, OptionalSecurityMessage);
2549
2603
  };
2550
2604
 
2551
2605
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
@@ -2570,7 +2624,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2570
2624
  const compactResponses = (React__namespace.createElement(React__namespace.Fragment, null,
2571
2625
  React__namespace.createElement(mosaic.Button, { "aria-label": "response-codes", onPress: open, iconRight: React__namespace.createElement(mosaic.Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2572
2626
  color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2573
- } }, activeResponseId),
2627
+ }, appearance: "minimal" }, activeResponseId),
2574
2628
  React__namespace.createElement(mosaic.Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React__namespace.createElement(mosaic.HStack, { justifyContent: "end" },
2575
2629
  React__namespace.createElement(mosaic.Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2576
2630
  React__namespace.createElement(mosaic.ListBox, { "aria-label": "Response Code", overflowY: "auto", m: -5, items: responses, selectionMode: "single", onSelectionChange: onSelectionChange }, (response) => (React__namespace.createElement(mosaic.ListBoxItem, { key: response.id },
@@ -2580,7 +2634,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2580
2634
  React__namespace.createElement(mosaic.Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2581
2635
  const tabResponses = (React__namespace.createElement(mosaic.TabList, { density: "compact" }, responses.map(({ code }) => (React__namespace.createElement(mosaic.Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code)))));
2582
2636
  return (React__namespace.createElement(mosaic.VStack, { spacing: 8, as: mosaic.Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2583
- React__namespace.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2637
+ React__namespace.createElement(SectionTitle, { title: "Responses", isCompact: isCompact }, isCompact ? compactResponses : tabResponses),
2584
2638
  isCompact ? (React__namespace.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })) : (React__namespace.createElement(mosaic.TabPanels, { p: 0 }, responses.map(response => (React__namespace.createElement(mosaic.TabPanel, { key: response.code, id: response.code },
2585
2639
  React__namespace.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2586
2640
  };
@@ -2734,21 +2788,33 @@ const ExportButton = ({ original, bundled }) => {
2734
2788
  React__namespace.createElement(mosaic.Menu, { "aria-label": "Export", items: menuItems, placement: "bottom right", renderTrigger: ({ isOpen }) => (React__namespace.createElement(mosaic.Button, { iconRight: "chevron-down", appearance: "default", ml: 2, active: isOpen, size: "sm" }, "Export")) })));
2735
2789
  };
2736
2790
 
2737
- const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2791
+ const SecuritySchemes = ({ secSchemes, defaultScheme, defaultCollapsed = false, parentId, }) => {
2792
+ const includeOptional = secSchemes.length > 1 && secSchemes.some(schemes => schemes.length === 0);
2793
+ const { nodeHasChanged } = useOptionsCtx();
2738
2794
  return (React__default["default"].createElement(mosaic.Panel, { rounded: true, isCollapsible: defaultCollapsed, "data-test": "security-row" },
2739
2795
  React__default["default"].createElement(mosaic.Panel.Titlebar, { bg: "canvas-300" },
2740
2796
  React__default["default"].createElement(mosaic.Box, { as: "span", role: "heading" }, "Security")),
2741
- React__default["default"].createElement(mosaic.Panel.Content, { p: 0 }, sortBy__default["default"](schemes, 'type').map((scheme, i) => (React__default["default"].createElement(SecurityScheme, { key: i, scheme: scheme, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1, showSchemeKey: shouldIncludeKey(schemes, scheme.type) }))))));
2742
- };
2743
- const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2744
- const { nodeHasChanged } = useOptionsCtx();
2745
- const hasChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id });
2797
+ React__default["default"].createElement(mosaic.Panel.Content, { p: 0 },
2798
+ includeOptional && React__default["default"].createElement(OptionalMessage, null),
2799
+ secSchemes
2800
+ .filter(scheme => scheme.length > 0)
2801
+ .map((schemes, i) => {
2802
+ const secGroupId = getSecurityGroupId(parentId, i);
2803
+ return (React__default["default"].createElement(mosaic.Box, { key: secGroupId, "data-test": "http-service-security-row" },
2804
+ React__default["default"].createElement(mosaic.NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2805
+ React__default["default"].createElement(SecurityScheme, { schemes: schemes, defaultIsOpen: defaultScheme ? schemes.length === 1 && schemes[0].key === defaultScheme : i === 0, isCollapsible: secSchemes.length > 1, showSchemeKey: shouldAddKey(schemes, secSchemes) })));
2806
+ }))));
2807
+ };
2808
+ const SecurityScheme = ({ schemes, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2746
2809
  return (React__default["default"].createElement(mosaic.Panel, { defaultIsOpen: defaultIsOpen, isCollapsible: isCollapsible, pos: "relative" },
2747
2810
  React__default["default"].createElement(mosaic.Panel.Titlebar, null,
2748
- React__default["default"].createElement(mosaic.Box, { as: "span", role: "heading" }, getReadableSecurityName(scheme, showSchemeKey))),
2811
+ React__default["default"].createElement(mosaic.Box, { as: "span", role: "heading" }, getReadableSecurityNames(schemes, showSchemeKey))),
2749
2812
  React__default["default"].createElement(mosaic.Panel.Content, null,
2750
- React__default["default"].createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })),
2751
- React__default["default"].createElement(mosaic.NodeAnnotation, { change: hasChanged })));
2813
+ React__default["default"].createElement(PanelContent, { schemes: schemes }))));
2814
+ };
2815
+ const OptionalMessage = () => {
2816
+ return (React__default["default"].createElement(mosaic.Box, { p: 2, pl: 6, border: true },
2817
+ React__default["default"].createElement(mosaic.Text, { fontSize: "base" }, OptionalSecurityMessage)));
2752
2818
  };
2753
2819
 
2754
2820
  const ServerInfo = ({ servers, mockUrl }) => {
@@ -2869,7 +2935,7 @@ const HttpServiceComponent = React__namespace.memo(({ data: unresolvedData, loca
2869
2935
  pathname && (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.showPoweredByLink) && (React__namespace.createElement(PoweredByLink, { source: (_a = data.name) !== null && _a !== void 0 ? _a : 'no-title', pathname: pathname, packageType: "elements", layout: "stacked" })),
2870
2936
  React__namespace.createElement(mosaic.VStack, { spacing: 6 },
2871
2937
  React__namespace.createElement(ServerInfo, { servers: (_b = data.servers) !== null && _b !== void 0 ? _b : [], mockUrl: mocking.mockUrl }),
2872
- React__namespace.createElement(mosaic.Box, { "data-test": "security" }, ((_c = data.securitySchemes) === null || _c === void 0 ? void 0 : _c.length) ? (React__namespace.createElement(SecuritySchemes, { schemes: data.securitySchemes, defaultScheme: query.get('security') || undefined })) : null),
2938
+ React__namespace.createElement(mosaic.Box, { "data-test": "security" }, ((_c = data.security) === null || _c === void 0 ? void 0 : _c.length) ? (React__namespace.createElement(SecuritySchemes, { secSchemes: data.security, defaultScheme: query.get('security') || undefined, parentId: data.id })) : null),
2873
2939
  React__namespace.createElement(mosaic.Box, { "data-test": "additional-info" }, (((_d = data.contact) === null || _d === void 0 ? void 0 : _d.email) || data.license || data.termsOfService) && (React__namespace.createElement(AdditionalInfo, { id: data.id, contact: data.contact, license: data.license, termsOfService: data.termsOfService })))),
2874
2940
  data.description && (React__namespace.createElement(mosaic.Box, { pos: "relative" },
2875
2941
  React__namespace.createElement(MarkdownViewer, { className: "sl-my-5", markdown: data.description }),
package/index.mjs CHANGED
@@ -7,7 +7,7 @@ import isArray from 'lodash/isArray.js';
7
7
  import isPlainObject from 'lodash/isPlainObject.js';
8
8
  import { NodeType, HttpParamStyles } from '@stoplight/types';
9
9
  import { parse } from '@stoplight/yaml';
10
- import { isArray as isArray$1, Box, useBreakpoints, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, useModalState, Modal, ListBox, ListBoxItem, TabList, Tab, Tabs, TabPanels, TabPanel, Heading, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
10
+ import { isArray as isArray$1, Box, useBreakpoints, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, Callout, useModalState, Modal, ListBox, ListBoxItem, TabList, Tab, Tabs, TabPanels, TabPanel, Heading, useClipboard, useMosaicContext, Provider as Provider$1 } from '@stoplight/mosaic';
11
11
  import isObject from 'lodash/isObject.js';
12
12
  import { withErrorBoundary } from '@stoplight/react-error-boundary';
13
13
  import { useLocation, BrowserRouter, MemoryRouter, HashRouter, StaticRouter, Route } from 'react-router-dom';
@@ -19,6 +19,7 @@ import { atom, useAtom, Provider } from 'jotai';
19
19
  import URI from 'urijs';
20
20
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
21
21
  import { isValidTargetId, HTTPSnippet } from 'httpsnippet-lite';
22
+ import { hash } from '@stoplight/http-spec/hash';
22
23
  import capitalize from 'lodash/capitalize.js';
23
24
  import filter from 'lodash/filter.js';
24
25
  import flatten from 'lodash/flatten.js';
@@ -193,6 +194,9 @@ const parserMap = {
193
194
  [NodeType.SpectralRuleset]: parseUnknown,
194
195
  [NodeType.Styleguide]: parseUnknown,
195
196
  [NodeType.Image]: parseUnknown,
197
+ [NodeType.HttpCallback]: parseUnknown,
198
+ [NodeType.StoplightOverride]: parseUnknown,
199
+ [NodeType.StoplightResolutions]: parseUnknown,
196
200
  [NodeType.Unknown]: parseUnknown,
197
201
  };
198
202
  function parseArticleData(rawData) {
@@ -357,6 +361,9 @@ const NodeTypeColors = {
357
361
  spectral_ruleset: '',
358
362
  styleguide: '',
359
363
  image: '',
364
+ http_callback: '',
365
+ stoplight_override: '',
366
+ stoplight_resolutions: '',
360
367
  };
361
368
  const NodeTypePrettyName = {
362
369
  http_operation: 'Endpoint',
@@ -370,6 +377,9 @@ const NodeTypePrettyName = {
370
377
  spectral_ruleset: '',
371
378
  styleguide: '',
372
379
  image: '',
380
+ http_callback: '',
381
+ stoplight_override: '',
382
+ stoplight_resolutions: '',
373
383
  };
374
384
  const NodeTypeIconDefs = {
375
385
  http_operation: faCrosshairs,
@@ -383,6 +393,9 @@ const NodeTypeIconDefs = {
383
393
  spectral_ruleset: faQuestionCircle,
384
394
  styleguide: faQuestionCircle,
385
395
  image: faImage,
396
+ http_callback: faQuestionCircle,
397
+ stoplight_override: faQuestionCircle,
398
+ stoplight_resolutions: faQuestionCircle,
386
399
  };
387
400
  const HttpMethodColors = {
388
401
  get: 'success',
@@ -465,7 +478,8 @@ const HttpCodeDescriptions = {
465
478
  599: 'Network connect timeout error',
466
479
  };
467
480
  const badgeDefaultBackgroundColor = '#293742';
468
- const badgeDefaultColor = '#FFFFFF';
481
+ const badgeDefaultColor = '#FFFFFF';
482
+ const OptionalSecurityMessage = 'Requiring authorization is optional. A user can access data without authorization or with authorization, if provided.';
469
483
 
470
484
  const MockingContext = createNamedContext('MockingContext', { mockUrl: undefined, hideMocking: undefined });
471
485
  const MockingProvider = ({ mockUrl, hideMocking, children }) => {
@@ -904,6 +918,9 @@ const shouldAddKey = (auth, operationSecuritySchemes) => {
904
918
  if (auth.length !== 1)
905
919
  return false;
906
920
  return shouldIncludeKey(flatten(operationSecuritySchemes.filter(scheme => scheme.length === 1)), auth[0].type);
921
+ };
922
+ const getSecurityGroupId = (id, position) => {
923
+ return hash(`http_security_group-${id}-${position}`);
907
924
  };
908
925
 
909
926
  const useUniqueId = (prefix = 'id_') => React.useRef(`${prefix}${nanoid(8)}`).current;
@@ -2252,6 +2269,51 @@ const enhanceVersionString = (version) => {
2252
2269
  return `v${version}`;
2253
2270
  };
2254
2271
 
2272
+ const operation = {
2273
+ id: '?http-operation-id?',
2274
+ iid: 'GET-simple',
2275
+ method: 'get',
2276
+ path: '/todos',
2277
+ summary: 'Get 200',
2278
+ responses: [
2279
+ {
2280
+ id: '?http-response-200?',
2281
+ code: '200',
2282
+ description: 'OK',
2283
+ },
2284
+ ],
2285
+ servers: [{ id: '?http-server-0?', url: 'https://todos.stoplight.io' }],
2286
+ };
2287
+
2288
+ const LinkHeading = React.memo(function LinkHeading(props) {
2289
+ const isUsingRouter = !!useRouterType();
2290
+ const Comp = isUsingRouter ? CustomLinkHeading : LinkHeading$1;
2291
+ return React.createElement(Comp, Object.assign({}, props));
2292
+ });
2293
+ const CustomLinkHeading = React.memo(function LinkHeading(_a) {
2294
+ var { id: _id } = _a, props = __rest(_a, ["id"]);
2295
+ const { pathname } = useLocation();
2296
+ const routerKind = React.useContext(RouterTypeContext);
2297
+ const route = pathname.split('#')[0];
2298
+ const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2299
+ return React.createElement(LinkHeading$1, Object.assign({ id: id }, props));
2300
+ });
2301
+
2302
+ const SectionTitle = ({ title, id, size = 2, isCompact = false, children }) => {
2303
+ return (React.createElement(Flex, { w: "full" },
2304
+ React.createElement(Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2305
+ React.createElement(Flex, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 }, justify: isCompact ? 'end' : undefined }, children)));
2306
+ };
2307
+ const SectionSubtitle = props => {
2308
+ return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2309
+ };
2310
+ const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2311
+ return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2312
+ React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2313
+ React.createElement("div", { role: "heading" }, title)),
2314
+ hasContent !== false && React.createElement(Panel.Content, null, children)));
2315
+ };
2316
+
2255
2317
  const oauthFlowNames = {
2256
2318
  implicit: 'Implicit',
2257
2319
  authorizationCode: 'Authorization Code',
@@ -2321,33 +2383,19 @@ ${scopes.map(([key, value]) => `- \`${key}\` - ${value}`).join('\n')}`;
2321
2383
  return description;
2322
2384
  }
2323
2385
 
2324
- const LinkHeading = React.memo(function LinkHeading(props) {
2325
- const isUsingRouter = !!useRouterType();
2326
- const Comp = isUsingRouter ? CustomLinkHeading : LinkHeading$1;
2327
- return React.createElement(Comp, Object.assign({}, props));
2328
- });
2329
- const CustomLinkHeading = React.memo(function LinkHeading(_a) {
2330
- var { id: _id } = _a, props = __rest(_a, ["id"]);
2331
- const { pathname } = useLocation();
2332
- const routerKind = React.useContext(RouterTypeContext);
2333
- const route = pathname.split('#')[0];
2334
- const id = routerKind === 'hash' ? `${route}#${_id}` : _id;
2335
- return React.createElement(LinkHeading$1, Object.assign({ id: id }, props));
2336
- });
2337
-
2338
- const SectionTitle = ({ title, id, size = 2, children }) => {
2339
- return (React.createElement(Flex, { w: "full" },
2340
- React.createElement(Box, { py: 1, pr: 6, as: LinkHeading, size: size, "aria-label": title, id: id || slugify(title) }, title),
2341
- React.createElement(Box, { alignSelf: 'center', py: 1, flexGrow: true, style: { minWidth: 0 } }, children)));
2342
- };
2343
- const SectionSubtitle = props => {
2344
- return React.createElement(SectionTitle, Object.assign({}, props, { size: 3 }));
2345
- };
2346
- const SubSectionPanel = ({ title, children, hasContent, rightComponent, defaultIsOpen = true, onChange, }) => {
2347
- return (React.createElement(Panel, { isCollapsible: hasContent, defaultIsOpen: defaultIsOpen, onChange: onChange, appearance: "outlined" },
2348
- React.createElement(Panel.Titlebar, { fontWeight: "medium", rightComponent: rightComponent },
2349
- React.createElement("div", { role: "heading" }, title)),
2350
- hasContent !== false && React.createElement(Panel.Content, null, children)));
2386
+ const PanelContent = ({ schemes }) => {
2387
+ const { nodeHasChanged } = useOptionsCtx();
2388
+ if (!schemes || !schemes.length) {
2389
+ return null;
2390
+ }
2391
+ const collection = schemes.length > 1;
2392
+ return (React.createElement(Box, null, schemes.map(scheme => {
2393
+ var _a;
2394
+ return (React.createElement(Box, { key: scheme.key, p: 2, m: 2, border: true },
2395
+ collection && (React.createElement(MarkdownViewer$1, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2396
+ React.createElement(MarkdownViewer$1, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2397
+ React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2398
+ })));
2351
2399
  };
2352
2400
 
2353
2401
  const isBodyEmpty = (body) => {
@@ -2454,7 +2502,7 @@ const Request = ({ operation: { request, request: { path: pathParams = [], heade
2454
2502
  return null;
2455
2503
  return (React.createElement(VStack, { spacing: 8 },
2456
2504
  React.createElement(SectionTitle, { title: "Request" }),
2457
- React.createElement(SecuritySchemes$1, { schemes: securitySchemes }),
2505
+ React.createElement(SecuritySchemes$1, { schemes: securitySchemes, parentId: operation.id }),
2458
2506
  pathParams.length > 0 && (React.createElement(VStack, { spacing: 5 },
2459
2507
  React.createElement(SectionSubtitle, { title: "Path Parameters" }),
2460
2508
  React.createElement(Parameters, { parameterType: "path", parameters: pathParams }))),
@@ -2473,23 +2521,29 @@ Request.displayName = 'HttpOperation.Request';
2473
2521
  const schemeExpandedState = atomWithStorage('HttpOperation_security_expanded', {});
2474
2522
  const SecurityPanel = ({ schemes, includeKey }) => {
2475
2523
  const [expandedState, setExpanded] = useAtom(schemeExpandedState);
2476
- const { nodeHasChanged } = useOptionsCtx();
2477
- const collection = schemes.length > 1;
2478
2524
  return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityNames(schemes, includeKey)}`, defaultIsOpen: !!expandedState[getReadableSecurityNames(schemes)], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [getReadableSecurityNames(schemes)]: isOpen })) },
2479
- React.createElement(Box, { m: -2 }, schemes.map(scheme => {
2480
- var _a;
2481
- return (React.createElement(Box, { key: scheme.key, p: 2, m: 2, border: true },
2482
- collection && (React.createElement(MarkdownViewer, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2483
- React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2484
- React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2485
- }))));
2525
+ React.createElement(Box, { m: -2 },
2526
+ React.createElement(PanelContent, { schemes: schemes }))));
2486
2527
  };
2487
- const SecuritySchemes$1 = ({ schemes }) => {
2528
+ const SecuritySchemes$1 = ({ schemes, parentId }) => {
2529
+ const { nodeHasChanged } = useOptionsCtx();
2488
2530
  if (!schemes.length) {
2489
2531
  return null;
2490
2532
  }
2491
- return (React.createElement(VStack, { spacing: 3 }, schemes.map((scheme, i) => (React.createElement(Box, { pos: "relative", key: i, p: 0, "data-test": "security-row" },
2492
- React.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) }))))));
2533
+ const includeOptional = schemes.length > 1 && schemes.some(scheme => scheme.length === 0);
2534
+ return (React.createElement(VStack, { spacing: 3 },
2535
+ includeOptional && React.createElement(OptionalMessage$1, null),
2536
+ schemes
2537
+ .filter(scheme => scheme.length > 0)
2538
+ .map((scheme, i) => {
2539
+ const secGroupId = getSecurityGroupId(parentId, i);
2540
+ return (React.createElement(Box, { pos: "relative", key: secGroupId, p: 0, "data-test": "http-operation-security-row" },
2541
+ React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2542
+ React.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) })));
2543
+ })));
2544
+ };
2545
+ const OptionalMessage$1 = () => {
2546
+ return React.createElement(Callout, { appearance: "outline" }, OptionalSecurityMessage);
2493
2547
  };
2494
2548
 
2495
2549
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
@@ -2514,7 +2568,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2514
2568
  const compactResponses = (React.createElement(React.Fragment, null,
2515
2569
  React.createElement(Button, { "aria-label": "response-codes", onPress: open, iconRight: React.createElement(Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2516
2570
  color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2517
- } }, activeResponseId),
2571
+ }, appearance: "minimal" }, activeResponseId),
2518
2572
  React.createElement(Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React.createElement(HStack, { justifyContent: "end" },
2519
2573
  React.createElement(Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2520
2574
  React.createElement(ListBox, { "aria-label": "Response Code", overflowY: "auto", m: -5, items: responses, selectionMode: "single", onSelectionChange: onSelectionChange }, (response) => (React.createElement(ListBoxItem, { key: response.id },
@@ -2524,7 +2578,7 @@ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTy
2524
2578
  React.createElement(Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2525
2579
  const tabResponses = (React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code)))));
2526
2580
  return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2527
- React.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2581
+ React.createElement(SectionTitle, { title: "Responses", isCompact: isCompact }, isCompact ? compactResponses : tabResponses),
2528
2582
  isCompact ? (React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })) : (React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2529
2583
  React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2530
2584
  };
@@ -2678,21 +2732,33 @@ const ExportButton = ({ original, bundled }) => {
2678
2732
  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")) })));
2679
2733
  };
2680
2734
 
2681
- const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2735
+ const SecuritySchemes = ({ secSchemes, defaultScheme, defaultCollapsed = false, parentId, }) => {
2736
+ const includeOptional = secSchemes.length > 1 && secSchemes.some(schemes => schemes.length === 0);
2737
+ const { nodeHasChanged } = useOptionsCtx();
2682
2738
  return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed, "data-test": "security-row" },
2683
2739
  React__default.createElement(Panel.Titlebar, { bg: "canvas-300" },
2684
2740
  React__default.createElement(Box, { as: "span", role: "heading" }, "Security")),
2685
- 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) }))))));
2686
- };
2687
- const SecurityScheme = ({ scheme, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2688
- const { nodeHasChanged } = useOptionsCtx();
2689
- const hasChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id });
2741
+ React__default.createElement(Panel.Content, { p: 0 },
2742
+ includeOptional && React__default.createElement(OptionalMessage, null),
2743
+ secSchemes
2744
+ .filter(scheme => scheme.length > 0)
2745
+ .map((schemes, i) => {
2746
+ const secGroupId = getSecurityGroupId(parentId, i);
2747
+ return (React__default.createElement(Box, { key: secGroupId, "data-test": "http-service-security-row" },
2748
+ React__default.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: secGroupId }) }),
2749
+ React__default.createElement(SecurityScheme, { schemes: schemes, defaultIsOpen: defaultScheme ? schemes.length === 1 && schemes[0].key === defaultScheme : i === 0, isCollapsible: secSchemes.length > 1, showSchemeKey: shouldAddKey(schemes, secSchemes) })));
2750
+ }))));
2751
+ };
2752
+ const SecurityScheme = ({ schemes, defaultIsOpen, isCollapsible, showSchemeKey }) => {
2690
2753
  return (React__default.createElement(Panel, { defaultIsOpen: defaultIsOpen, isCollapsible: isCollapsible, pos: "relative" },
2691
2754
  React__default.createElement(Panel.Titlebar, null,
2692
- React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityName(scheme, showSchemeKey))),
2755
+ React__default.createElement(Box, { as: "span", role: "heading" }, getReadableSecurityNames(schemes, showSchemeKey))),
2693
2756
  React__default.createElement(Panel.Content, null,
2694
- React__default.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })),
2695
- React__default.createElement(NodeAnnotation, { change: hasChanged })));
2757
+ React__default.createElement(PanelContent, { schemes: schemes }))));
2758
+ };
2759
+ const OptionalMessage = () => {
2760
+ return (React__default.createElement(Box, { p: 2, pl: 6, border: true },
2761
+ React__default.createElement(Text, { fontSize: "base" }, OptionalSecurityMessage)));
2696
2762
  };
2697
2763
 
2698
2764
  const ServerInfo = ({ servers, mockUrl }) => {
@@ -2813,7 +2879,7 @@ const HttpServiceComponent = React.memo(({ data: unresolvedData, location = {},
2813
2879
  pathname && (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.showPoweredByLink) && (React.createElement(PoweredByLink, { source: (_a = data.name) !== null && _a !== void 0 ? _a : 'no-title', pathname: pathname, packageType: "elements", layout: "stacked" })),
2814
2880
  React.createElement(VStack, { spacing: 6 },
2815
2881
  React.createElement(ServerInfo, { servers: (_b = data.servers) !== null && _b !== void 0 ? _b : [], mockUrl: mocking.mockUrl }),
2816
- React.createElement(Box, { "data-test": "security" }, ((_c = data.securitySchemes) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { schemes: data.securitySchemes, defaultScheme: query.get('security') || undefined })) : null),
2882
+ React.createElement(Box, { "data-test": "security" }, ((_c = data.security) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { secSchemes: data.security, defaultScheme: query.get('security') || undefined, parentId: data.id })) : null),
2817
2883
  React.createElement(Box, { "data-test": "additional-info" }, (((_d = data.contact) === null || _d === void 0 ? void 0 : _d.email) || data.license || data.termsOfService) && (React.createElement(AdditionalInfo, { id: data.id, contact: data.contact, license: data.license, termsOfService: data.termsOfService })))),
2818
2884
  data.description && (React.createElement(Box, { pos: "relative" },
2819
2885
  React.createElement(MarkdownViewer, { className: "sl-my-5", markdown: data.description }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "7.13.1",
3
+ "version": "7.13.3",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",
@@ -24,7 +24,7 @@
24
24
  "react-dom": ">=16.8"
25
25
  },
26
26
  "dependencies": {
27
- "@stoplight/http-spec": "^5.1.4",
27
+ "@stoplight/http-spec": "^6.0.0",
28
28
  "@stoplight/json": "^3.18.1",
29
29
  "@stoplight/json-schema-ref-parser": "^9.0.5",
30
30
  "@stoplight/json-schema-sampler": "0.2.3",
@@ -35,7 +35,7 @@
35
35
  "@stoplight/mosaic-code-viewer": "^1.33.0",
36
36
  "@stoplight/path": "^1.3.2",
37
37
  "@stoplight/react-error-boundary": "^2.0.0",
38
- "@stoplight/types": "^13.7.0",
38
+ "@stoplight/types": "^14.0.0",
39
39
  "@stoplight/yaml": "^4.2.3",
40
40
  "classnames": "^2.2.6",
41
41
  "httpsnippet-lite": "^3.0.1",
@@ -7,3 +7,4 @@ export declare const isOauth2AuthorizationCodeFlow: (maybeFlow: IOauth2Flow) =>
7
7
  export declare const isOauth2ClientCredentialsOrPasswordFlow: (maybeFlow: IOauth2Flow) => maybeFlow is IOauth2ClientCredentialsFlow | IOauth2PasswordFlow;
8
8
  export declare function shouldIncludeKey(schemes: HttpSecurityScheme[], type: HttpSecurityScheme['type']): boolean;
9
9
  export declare const shouldAddKey: (auth: HttpSecurityScheme[], operationSecuritySchemes: HttpSecurityScheme[][]) => boolean;
10
+ export declare const getSecurityGroupId: (id: string, position: number) => string;
@@ -1,2 +1,3 @@
1
1
  import { HttpSecurityScheme } from '@stoplight/types';
2
2
  export declare function getDefaultDescription(scheme: HttpSecurityScheme): string;
3
+ export declare function getOptionalAuthDescription(): string;