@stoplight/elements-core 7.9.0 → 7.10.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.
@@ -3,9 +3,10 @@ interface ResponsesProps {
3
3
  responses: IHttpOperationResponse[];
4
4
  onMediaTypeChange(mediaType: string): void;
5
5
  onStatusCodeChange(statusCode: string): void;
6
+ isCompact?: boolean;
6
7
  }
7
8
  export declare const Responses: {
8
- ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }: ResponsesProps): JSX.Element | null;
9
+ ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }: ResponsesProps): JSX.Element | null;
9
10
  displayName: string;
10
11
  };
11
12
  export {};
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, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, Tabs, TabList, Tab, TabPanels, TabPanel, Heading, useClipboard, useBreakpoints, 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, 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';
@@ -486,6 +486,22 @@ function useChosenServerUrl(chosenServerUrl) {
486
486
  };
487
487
  }
488
488
 
489
+ const getBreakpoints = (compact) => {
490
+ if (!compact)
491
+ return undefined;
492
+ if (typeof compact === 'number') {
493
+ return [
494
+ ['compact', compact],
495
+ ['regular', Infinity],
496
+ ];
497
+ }
498
+ return [['compact', Infinity]];
499
+ };
500
+ function useIsCompact(layoutOptions) {
501
+ const { ref, breakpoint } = useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
502
+ return { ref: ref, isCompact: breakpoint === 'compact' };
503
+ }
504
+
489
505
  const chosenServerAtom = atom(undefined);
490
506
 
491
507
  function isValidServer(server) {
@@ -2410,20 +2426,41 @@ const SecuritySchemes$1 = ({ schemes }) => {
2410
2426
  React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) }))))));
2411
2427
  };
2412
2428
 
2413
- const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }) => {
2429
+ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
2414
2430
  var _a, _b;
2415
2431
  const responses = sortBy(uniqBy(unsortedResponses, r => r.code), r => r.code);
2416
2432
  const [activeResponseId, setActiveResponseId] = React.useState((_b = (_a = responses[0]) === null || _a === void 0 ? void 0 : _a.code) !== null && _b !== void 0 ? _b : '');
2433
+ const { isOpen, open, close } = useModalState();
2434
+ const onSelectionChange = React.useCallback(keys => {
2435
+ const selectedId = keys.values().next().value;
2436
+ const selectedResponse = responses === null || responses === void 0 ? void 0 : responses.find(response => response.id === selectedId);
2437
+ if (selectedResponse) {
2438
+ setActiveResponseId(selectedResponse.code);
2439
+ close();
2440
+ }
2441
+ }, [responses, setActiveResponseId, close]);
2417
2442
  React.useEffect(() => {
2418
2443
  onStatusCodeChange(activeResponseId);
2419
2444
  }, [activeResponseId]);
2420
2445
  if (!responses.length)
2421
2446
  return null;
2447
+ const response = responses.find(r => r.code === activeResponseId) || responses[0];
2448
+ const compactResponses = (React.createElement(React.Fragment, null,
2449
+ React.createElement(Button, { onPress: open, iconRight: React.createElement(Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2450
+ color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2451
+ } }, activeResponseId),
2452
+ React.createElement(Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React.createElement(HStack, { justifyContent: "end" },
2453
+ React.createElement(Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2454
+ React.createElement(ListBox, { "aria-label": "Response Code", overflowY: "auto", m: -5, items: responses, selectionMode: "single", onSelectionChange: onSelectionChange }, (response) => (React.createElement(ListBoxItem, { key: response.id },
2455
+ React.createElement(Box, { p: 3, bg: { hover: 'primary-tint' } },
2456
+ React.createElement(Flex, { w: "2xl", align: "center", justify: "end" },
2457
+ response.code === activeResponseId && React.createElement(Box, { as: Icon, icon: "check" }),
2458
+ React.createElement(Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2459
+ const tabResponses = (React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code)))));
2422
2460
  return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2423
- React.createElement(SectionTitle, { title: "Responses" },
2424
- React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2425
- React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2426
- React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
2461
+ React.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2462
+ 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 },
2463
+ React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2427
2464
  };
2428
2465
  Responses.displayName = 'HttpOperation.Responses';
2429
2466
  const Response = ({ response, onMediaTypeChange }) => {
@@ -2468,6 +2505,7 @@ const codeToIntentVal = (code) => {
2468
2505
  const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
2469
2506
  const { nodeHasChanged } = useOptionsCtx();
2470
2507
  const data = useResolvedObject(unresolvedData);
2508
+ const { ref: layoutRef, isCompact } = useIsCompact(layoutOptions);
2471
2509
  const mocking = React.useContext(MockingContext);
2472
2510
  const isDeprecated = !!data.deprecated;
2473
2511
  const isInternal = !!data.internal;
@@ -2477,15 +2515,16 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2477
2515
  const prettyName = (data.summary || data.iid || '').trim();
2478
2516
  const hasBadges = isDeprecated || isInternal;
2479
2517
  const header = (React.createElement(OperationHeader, { id: data.id, method: data.method, path: data.path, noHeading: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading, hasBadges: hasBadges, name: prettyName, isDeprecated: isDeprecated, isInternal: isInternal }));
2518
+ 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 }));
2480
2519
  const descriptionChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: data.id, attr: 'description' });
2481
2520
  const description = (React.createElement(VStack, { spacing: 10 },
2482
2521
  data.description && (React.createElement(Box, { pos: "relative" },
2483
2522
  React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2484
2523
  React.createElement(NodeAnnotation, { change: descriptionChanged }))),
2485
2524
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2486
- data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
2487
- 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 }));
2488
- return (React.createElement(TwoColumnLayout, { className: cn('HttpOperation', className), header: header, left: description, right: tryItPanel }));
2525
+ data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode, isCompact: isCompact })),
2526
+ isCompact && tryItPanel));
2527
+ return (React.createElement(TwoColumnLayout, { ref: layoutRef, className: cn('HttpOperation', className), header: header, left: description, right: !isCompact && tryItPanel }));
2489
2528
  });
2490
2529
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2491
2530
  const HttpOperation = withErrorBoundary(HttpOperationComponent, {
@@ -2717,22 +2756,6 @@ const HttpServiceComponent = React.memo(({ data: unresolvedData, location = {},
2717
2756
  HttpServiceComponent.displayName = 'HttpService.Component';
2718
2757
  const HttpService = withErrorBoundary(HttpServiceComponent, { recoverableProps: ['data'] });
2719
2758
 
2720
- const getBreakpoints = (compact) => {
2721
- if (!compact)
2722
- return undefined;
2723
- if (typeof compact === 'number') {
2724
- return [
2725
- ['compact', compact],
2726
- ['regular', Infinity],
2727
- ];
2728
- }
2729
- return [['compact', Infinity]];
2730
- };
2731
- function useIsCompact(layoutOptions) {
2732
- const { ref, breakpoint } = useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
2733
- return { ref: ref, isCompact: breakpoint === 'compact' };
2734
- }
2735
-
2736
2759
  const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOptions, exportProps, }) => {
2737
2760
  var _a, _b;
2738
2761
  const resolveRef = useSchemaInlineRefResolver();
package/index.js CHANGED
@@ -542,6 +542,22 @@ function useChosenServerUrl(chosenServerUrl) {
542
542
  };
543
543
  }
544
544
 
545
+ const getBreakpoints = (compact) => {
546
+ if (!compact)
547
+ return undefined;
548
+ if (typeof compact === 'number') {
549
+ return [
550
+ ['compact', compact],
551
+ ['regular', Infinity],
552
+ ];
553
+ }
554
+ return [['compact', Infinity]];
555
+ };
556
+ function useIsCompact(layoutOptions) {
557
+ const { ref, breakpoint } = mosaic.useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
558
+ return { ref: ref, isCompact: breakpoint === 'compact' };
559
+ }
560
+
545
561
  const chosenServerAtom = jotai.atom(undefined);
546
562
 
547
563
  function isValidServer(server) {
@@ -2466,20 +2482,41 @@ const SecuritySchemes$1 = ({ schemes }) => {
2466
2482
  React__namespace.createElement(mosaic.NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) }))))));
2467
2483
  };
2468
2484
 
2469
- const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }) => {
2485
+ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
2470
2486
  var _a, _b;
2471
2487
  const responses = sortBy__default["default"](uniqBy__default["default"](unsortedResponses, r => r.code), r => r.code);
2472
2488
  const [activeResponseId, setActiveResponseId] = React__namespace.useState((_b = (_a = responses[0]) === null || _a === void 0 ? void 0 : _a.code) !== null && _b !== void 0 ? _b : '');
2489
+ const { isOpen, open, close } = mosaic.useModalState();
2490
+ const onSelectionChange = React__namespace.useCallback(keys => {
2491
+ const selectedId = keys.values().next().value;
2492
+ const selectedResponse = responses === null || responses === void 0 ? void 0 : responses.find(response => response.id === selectedId);
2493
+ if (selectedResponse) {
2494
+ setActiveResponseId(selectedResponse.code);
2495
+ close();
2496
+ }
2497
+ }, [responses, setActiveResponseId, close]);
2473
2498
  React__namespace.useEffect(() => {
2474
2499
  onStatusCodeChange(activeResponseId);
2475
2500
  }, [activeResponseId]);
2476
2501
  if (!responses.length)
2477
2502
  return null;
2503
+ const response = responses.find(r => r.code === activeResponseId) || responses[0];
2504
+ const compactResponses = (React__namespace.createElement(React__namespace.Fragment, null,
2505
+ React__namespace.createElement(mosaic.Button, { onPress: open, iconRight: React__namespace.createElement(mosaic.Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2506
+ color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2507
+ } }, activeResponseId),
2508
+ React__namespace.createElement(mosaic.Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React__namespace.createElement(mosaic.HStack, { justifyContent: "end" },
2509
+ React__namespace.createElement(mosaic.Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2510
+ 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 },
2511
+ React__namespace.createElement(mosaic.Box, { p: 3, bg: { hover: 'primary-tint' } },
2512
+ React__namespace.createElement(mosaic.Flex, { w: "2xl", align: "center", justify: "end" },
2513
+ response.code === activeResponseId && React__namespace.createElement(mosaic.Box, { as: mosaic.Icon, icon: "check" }),
2514
+ React__namespace.createElement(mosaic.Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2515
+ 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)))));
2478
2516
  return (React__namespace.createElement(mosaic.VStack, { spacing: 8, as: mosaic.Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2479
- React__namespace.createElement(SectionTitle, { title: "Responses" },
2480
- React__namespace.createElement(mosaic.TabList, { density: "compact" }, responses.map(({ code }) => (React__namespace.createElement(mosaic.Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2481
- React__namespace.createElement(mosaic.TabPanels, { p: 0 }, responses.map(response => (React__namespace.createElement(mosaic.TabPanel, { key: response.code, id: response.code },
2482
- React__namespace.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
2517
+ React__namespace.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2518
+ 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 },
2519
+ React__namespace.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2483
2520
  };
2484
2521
  Responses.displayName = 'HttpOperation.Responses';
2485
2522
  const Response = ({ response, onMediaTypeChange }) => {
@@ -2524,6 +2561,7 @@ const codeToIntentVal = (code) => {
2524
2561
  const HttpOperationComponent = React__namespace.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
2525
2562
  const { nodeHasChanged } = useOptionsCtx();
2526
2563
  const data = useResolvedObject(unresolvedData);
2564
+ const { ref: layoutRef, isCompact } = useIsCompact(layoutOptions);
2527
2565
  const mocking = React__namespace.useContext(MockingContext);
2528
2566
  const isDeprecated = !!data.deprecated;
2529
2567
  const isInternal = !!data.internal;
@@ -2533,15 +2571,16 @@ const HttpOperationComponent = React__namespace.memo(({ className, data: unresol
2533
2571
  const prettyName = (data.summary || data.iid || '').trim();
2534
2572
  const hasBadges = isDeprecated || isInternal;
2535
2573
  const header = (React__namespace.createElement(OperationHeader, { id: data.id, method: data.method, path: data.path, noHeading: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading, hasBadges: hasBadges, name: prettyName, isDeprecated: isDeprecated, isInternal: isInternal }));
2574
+ const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React__namespace.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 }));
2536
2575
  const descriptionChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: data.id, attr: 'description' });
2537
2576
  const description = (React__namespace.createElement(mosaic.VStack, { spacing: 10 },
2538
2577
  data.description && (React__namespace.createElement(mosaic.Box, { pos: "relative" },
2539
2578
  React__namespace.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2540
2579
  React__namespace.createElement(mosaic.NodeAnnotation, { change: descriptionChanged }))),
2541
2580
  React__namespace.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2542
- data.responses && (React__namespace.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
2543
- const tryItPanel = !(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.hideTryItPanel) && (React__namespace.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 }));
2544
- return (React__namespace.createElement(TwoColumnLayout, { className: cn__default["default"]('HttpOperation', className), header: header, left: description, right: tryItPanel }));
2581
+ data.responses && (React__namespace.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode, isCompact: isCompact })),
2582
+ isCompact && tryItPanel));
2583
+ return (React__namespace.createElement(TwoColumnLayout, { ref: layoutRef, className: cn__default["default"]('HttpOperation', className), header: header, left: description, right: !isCompact && tryItPanel }));
2545
2584
  });
2546
2585
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2547
2586
  const HttpOperation = reactErrorBoundary.withErrorBoundary(HttpOperationComponent, {
@@ -2773,22 +2812,6 @@ const HttpServiceComponent = React__namespace.memo(({ data: unresolvedData, loca
2773
2812
  HttpServiceComponent.displayName = 'HttpService.Component';
2774
2813
  const HttpService = reactErrorBoundary.withErrorBoundary(HttpServiceComponent, { recoverableProps: ['data'] });
2775
2814
 
2776
- const getBreakpoints = (compact) => {
2777
- if (!compact)
2778
- return undefined;
2779
- if (typeof compact === 'number') {
2780
- return [
2781
- ['compact', compact],
2782
- ['regular', Infinity],
2783
- ];
2784
- }
2785
- return [['compact', Infinity]];
2786
- };
2787
- function useIsCompact(layoutOptions) {
2788
- const { ref, breakpoint } = mosaic.useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
2789
- return { ref: ref, isCompact: breakpoint === 'compact' };
2790
- }
2791
-
2792
2815
  const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOptions, exportProps, }) => {
2793
2816
  var _a, _b;
2794
2817
  const resolveRef = useSchemaInlineRefResolver();
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, Panel, CopyButton, Menu, Button, Text, Flex, Input, Icon, Select, FieldButton, Image, Link, useThemeIsDark, HStack, VStack, InvertTheme, Tooltip, Badge, LinkHeading as LinkHeading$1, NodeAnnotation, Tabs, TabList, Tab, TabPanels, TabPanel, Heading, useClipboard, useBreakpoints, 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, 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';
@@ -486,6 +486,22 @@ function useChosenServerUrl(chosenServerUrl) {
486
486
  };
487
487
  }
488
488
 
489
+ const getBreakpoints = (compact) => {
490
+ if (!compact)
491
+ return undefined;
492
+ if (typeof compact === 'number') {
493
+ return [
494
+ ['compact', compact],
495
+ ['regular', Infinity],
496
+ ];
497
+ }
498
+ return [['compact', Infinity]];
499
+ };
500
+ function useIsCompact(layoutOptions) {
501
+ const { ref, breakpoint } = useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
502
+ return { ref: ref, isCompact: breakpoint === 'compact' };
503
+ }
504
+
489
505
  const chosenServerAtom = atom(undefined);
490
506
 
491
507
  function isValidServer(server) {
@@ -2410,20 +2426,41 @@ const SecuritySchemes$1 = ({ schemes }) => {
2410
2426
  React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) }))))));
2411
2427
  };
2412
2428
 
2413
- const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange }) => {
2429
+ const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
2414
2430
  var _a, _b;
2415
2431
  const responses = sortBy(uniqBy(unsortedResponses, r => r.code), r => r.code);
2416
2432
  const [activeResponseId, setActiveResponseId] = React.useState((_b = (_a = responses[0]) === null || _a === void 0 ? void 0 : _a.code) !== null && _b !== void 0 ? _b : '');
2433
+ const { isOpen, open, close } = useModalState();
2434
+ const onSelectionChange = React.useCallback(keys => {
2435
+ const selectedId = keys.values().next().value;
2436
+ const selectedResponse = responses === null || responses === void 0 ? void 0 : responses.find(response => response.id === selectedId);
2437
+ if (selectedResponse) {
2438
+ setActiveResponseId(selectedResponse.code);
2439
+ close();
2440
+ }
2441
+ }, [responses, setActiveResponseId, close]);
2417
2442
  React.useEffect(() => {
2418
2443
  onStatusCodeChange(activeResponseId);
2419
2444
  }, [activeResponseId]);
2420
2445
  if (!responses.length)
2421
2446
  return null;
2447
+ const response = responses.find(r => r.code === activeResponseId) || responses[0];
2448
+ const compactResponses = (React.createElement(React.Fragment, null,
2449
+ React.createElement(Button, { onPress: open, iconRight: React.createElement(Icon, { icon: "chevron-down", color: "var(--color-border-button)" }), style: {
2450
+ color: `var(--color-${codeToIntentVal(activeResponseId)})`,
2451
+ } }, activeResponseId),
2452
+ React.createElement(Modal, { title: "Response Code", isOpen: isOpen, onClose: close, size: "sm", footer: React.createElement(HStack, { justifyContent: "end" },
2453
+ React.createElement(Button, { onPress: close, intent: "default", appearance: "primary" }, "Close")) },
2454
+ React.createElement(ListBox, { "aria-label": "Response Code", overflowY: "auto", m: -5, items: responses, selectionMode: "single", onSelectionChange: onSelectionChange }, (response) => (React.createElement(ListBoxItem, { key: response.id },
2455
+ React.createElement(Box, { p: 3, bg: { hover: 'primary-tint' } },
2456
+ React.createElement(Flex, { w: "2xl", align: "center", justify: "end" },
2457
+ response.code === activeResponseId && React.createElement(Box, { as: Icon, icon: "check" }),
2458
+ React.createElement(Text, { ml: 3, fontWeight: "medium" }, response.code)))))))));
2459
+ const tabResponses = (React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code)))));
2422
2460
  return (React.createElement(VStack, { spacing: 8, as: Tabs, selectedId: activeResponseId, onChange: setActiveResponseId, appearance: "pill" },
2423
- React.createElement(SectionTitle, { title: "Responses" },
2424
- React.createElement(TabList, { density: "compact" }, responses.map(({ code }) => (React.createElement(Tab, { key: code, id: code, intent: codeToIntentVal(code) }, code))))),
2425
- React.createElement(TabPanels, { p: 0 }, responses.map(response => (React.createElement(TabPanel, { key: response.code, id: response.code },
2426
- React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange })))))));
2461
+ React.createElement(SectionTitle, { title: "Responses" }, isCompact ? compactResponses : tabResponses),
2462
+ 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 },
2463
+ React.createElement(Response, { response: response, onMediaTypeChange: onMediaTypeChange }))))))));
2427
2464
  };
2428
2465
  Responses.displayName = 'HttpOperation.Responses';
2429
2466
  const Response = ({ response, onMediaTypeChange }) => {
@@ -2468,6 +2505,7 @@ const codeToIntentVal = (code) => {
2468
2505
  const HttpOperationComponent = React.memo(({ className, data: unresolvedData, layoutOptions, tryItCredentialsPolicy, tryItCorsProxy }) => {
2469
2506
  const { nodeHasChanged } = useOptionsCtx();
2470
2507
  const data = useResolvedObject(unresolvedData);
2508
+ const { ref: layoutRef, isCompact } = useIsCompact(layoutOptions);
2471
2509
  const mocking = React.useContext(MockingContext);
2472
2510
  const isDeprecated = !!data.deprecated;
2473
2511
  const isInternal = !!data.internal;
@@ -2477,15 +2515,16 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2477
2515
  const prettyName = (data.summary || data.iid || '').trim();
2478
2516
  const hasBadges = isDeprecated || isInternal;
2479
2517
  const header = (React.createElement(OperationHeader, { id: data.id, method: data.method, path: data.path, noHeading: layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.noHeading, hasBadges: hasBadges, name: prettyName, isDeprecated: isDeprecated, isInternal: isInternal }));
2518
+ 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 }));
2480
2519
  const descriptionChanged = nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: data.id, attr: 'description' });
2481
2520
  const description = (React.createElement(VStack, { spacing: 10 },
2482
2521
  data.description && (React.createElement(Box, { pos: "relative" },
2483
2522
  React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2484
2523
  React.createElement(NodeAnnotation, { change: descriptionChanged }))),
2485
2524
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2486
- data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode }))));
2487
- 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 }));
2488
- return (React.createElement(TwoColumnLayout, { className: cn('HttpOperation', className), header: header, left: description, right: tryItPanel }));
2525
+ data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode, isCompact: isCompact })),
2526
+ isCompact && tryItPanel));
2527
+ return (React.createElement(TwoColumnLayout, { ref: layoutRef, className: cn('HttpOperation', className), header: header, left: description, right: !isCompact && tryItPanel }));
2489
2528
  });
2490
2529
  HttpOperationComponent.displayName = 'HttpOperation.Component';
2491
2530
  const HttpOperation = withErrorBoundary(HttpOperationComponent, {
@@ -2717,22 +2756,6 @@ const HttpServiceComponent = React.memo(({ data: unresolvedData, location = {},
2717
2756
  HttpServiceComponent.displayName = 'HttpService.Component';
2718
2757
  const HttpService = withErrorBoundary(HttpServiceComponent, { recoverableProps: ['data'] });
2719
2758
 
2720
- const getBreakpoints = (compact) => {
2721
- if (!compact)
2722
- return undefined;
2723
- if (typeof compact === 'number') {
2724
- return [
2725
- ['compact', compact],
2726
- ['regular', Infinity],
2727
- ];
2728
- }
2729
- return [['compact', Infinity]];
2730
- };
2731
- function useIsCompact(layoutOptions) {
2732
- const { ref, breakpoint } = useBreakpoints(getBreakpoints(layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.compact));
2733
- return { ref: ref, isCompact: breakpoint === 'compact' };
2734
- }
2735
-
2736
2759
  const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOptions, exportProps, }) => {
2737
2760
  var _a, _b;
2738
2761
  const resolveRef = useSchemaInlineRefResolver();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "7.9.0",
3
+ "version": "7.10.0",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",